-------------------------------------------------------------------------------- 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 unicode_categories src/lib.rs --error-format=json --json=diagnostic-rendered-ansi,artifacts,future-incompat --crate-type lib --emit=dep-info,metadata,link -C opt-level=3 -C embed-bitcode=no -C metadata=44fab5f29c4989ab -C extra-filename=-44fab5f29c4989ab --out-dir /usr/home/liquid/tmp/.tmpj8ifoR/target/release/deps -L dependency=/usr/home/liquid/tmp/.tmpj8ifoR/target/release/deps -Adeprecated -Aunknown-lints -Zincremental-verify-ich Data file: results/cgout-w-profiling-unicode_categories-0.1.1-Opt-Full Events recorded: Ir Events shown: Ir Event sort order: Ir Thresholds: 0.1 Include dirs: User annotated: Auto-annotation: on -------------------------------------------------------------------------------- Ir -------------------------------------------------------------------------------- 995,709,923 (100.0%) PROGRAM TOTALS -------------------------------------------------------------------------------- Ir file:function -------------------------------------------------------------------------------- 21,672,363 ( 2.18%) ./malloc/malloc.c:_int_malloc 15,486,218 ( 1.56%) ./malloc/malloc.c:_int_free 11,792,006 ( 1.18%) ./string/../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S:__memcpy_avx_unaligned_erms 10,846,950 ( 1.09%) ./malloc/malloc.c:malloc 10,309,110 ( 1.04%) ./elf/dl-lookup.c:_dl_lookup_symbol_x 9,360,987 ( 0.94%) ???:llvm::BitstreamCursor::readRecord(unsigned int, llvm::SmallVectorImpl&, llvm::StringRef*) 8,928,751 ( 0.90%) ???:(anonymous namespace)::ModuleBitcodeWriter::writeConstants(unsigned int, unsigned int, bool) 7,984,608 ( 0.80%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_lexer/src/unescape.rs:rustc_lexer::unescape::scan_escape 7,107,505 ( 0.71%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_parse/src/lexer/mod.rs:::next_token 5,800,246 ( 0.58%) ???:void llvm::BitstreamWriter::EmitRecordWithAbbrevImpl(unsigned int, llvm::ArrayRef, llvm::StringRef, llvm::Optional) 5,768,079 ( 0.58%) /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/hashbrown-0.12.0/src/raw/mod.rs:>>::from_key_hashed_nocheck:: 5,749,958 ( 0.58%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_const_eval/src/interpret/operand.rs:>::try_read_immediate 5,445,235 ( 0.55%) /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/hashbrown-0.12.0/src/raw/mod.rs:>>::insert 5,408,010 ( 0.54%) /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/hashbrown-0.12.0/src/raw/mod.rs:::intern 4,872,968 ( 0.49%) ./malloc/malloc.c:malloc_consolidate 4,845,521 ( 0.49%) ./elf/dl-lookup.c:do_lookup_x 4,603,016 ( 0.46%) /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/hashbrown-0.12.0/src/raw/mod.rs:>>::get:: 4,397,199 ( 0.44%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_parse/src/lexer/tokentrees.rs:::parse_token_tree 4,298,861 ( 0.43%) /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/hashbrown-0.12.0/src/raw/mod.rs:>::insert::>::{closure#0}> 4,279,101 ( 0.43%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_lexer/src/lib.rs:::advance_token 4,275,930 ( 0.43%) ./malloc/malloc.c:free 4,237,390 ( 0.43%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_span/src/caching_source_map_view.rs:::span_data_to_lines_and_cols 4,141,271 ( 0.42%) ./elf/../sysdeps/x86_64/dl-machine.h:_dl_relocate_object 4,057,780 ( 0.41%) /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/hashbrown-0.12.0/src/raw/mod.rs:>::reserve_rehash::>::{closure#0}> 3,847,578 ( 0.39%) /usr/home/liquid/rust/worktree-benchmarking/library/core/src/num/uint_macros.rs:::short_write_process_buffer:: 3,633,413 ( 0.36%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_parse/src/parser/mod.rs:::check 3,355,968 ( 0.34%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_middle/src/hir/map/mod.rs:::attrs 3,318,208 ( 0.33%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_span/src/lib.rs:>::hash_stable 3,290,626 ( 0.33%) /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/rustc-hash-1.1.0/src/lib.rs:<&str as core::hash::Hash>::hash:: 3,256,560 ( 0.33%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_parse/src/parser/mod.rs:::bump 3,197,341 ( 0.32%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_mir_build/src/thir/cx/expr.rs:::mirror_expr_inner 3,127,705 ( 0.31%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_middle/src/middle/region.rs:::temporary_scope 3,051,896 ( 0.31%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_middle/src/mir/interpret/allocation.rs:::read_scalar:: 2,979,318 ( 0.30%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs:rustc_const_eval::transform::check_consts::qualifs::in_operand::::qualif_local::{closure#0}> 2,970,001 ( 0.30%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_parse/src/parser/mod.rs:::next 2,955,460 ( 0.30%) /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/hashbrown-0.12.0/src/raw/mod.rs:::node_type_opt 2,826,233 ( 0.28%) ???:llvm::SHA1::hashBlock() 2,798,896 ( 0.28%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_serialize/src/opaque.rs:>::decode 2,785,952 ( 0.28%) /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/rustc-hash-1.1.0/src/lib.rs:::write 2,776,978 ( 0.28%) ./string/../sysdeps/x86_64/multiarch/memcmp-avx2-movbe.S:__memcmp_avx2_movbe 2,774,663 ( 0.28%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_ast/src/token.rs:::clone 2,725,007 ( 0.27%) ./malloc/malloc.c:unlink_chunk.constprop.0 2,662,278 ( 0.27%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_middle/src/ty/context.rs:::maybe_lint_level_root_bounded 2,580,984 ( 0.26%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_data_structures/src/sip128.rs:::short_write_process_buffer:: 2,573,768 ( 0.26%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_middle/src/mir/mod.rs:::check_static_ptr 2,527,986 ( 0.25%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_parse/src/parser/expr.rs:::parse_assoc_expr_with 2,520,316 ( 0.25%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_const_eval/src/interpret/memory.rs:>::get_global_alloc 2,490,713 ( 0.25%) /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/hashbrown-0.12.0/src/raw/mod.rs:>>::insert 2,480,759 ( 0.25%) /usr/home/liquid/rust/worktree-benchmarking/library/alloc/src/vec/mod.rs:>::decode 2,459,360 ( 0.25%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_const_eval/src/interpret/validity.rs:>::try_visit_primitive 2,396,014 ( 0.24%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_mir_build/src/thir/cx/expr.rs:::make_mirror_unadjusted 2,378,681 ( 0.24%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_mir_build/src/build/expr/as_operand.rs:::as_operand 2,350,511 ( 0.24%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_ast/src/tokenstream.rs:::next_with_spacing 2,348,960 ( 0.24%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_middle/src/mir/interpret/allocation.rs:::get_bytes_internal:: 2,338,528 ( 0.23%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_typeck/src/check/regionck.rs:::visit_expr 2,332,819 ( 0.23%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_span/src/lib.rs:>::decode 2,303,822 ( 0.23%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_data_structures/src/sip128.rs:>::hash_stable 2,296,875 ( 0.23%) /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/md-5-0.9.1/src/utils.rs:md5::utils::compress 2,278,376 ( 0.23%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_const_eval/src/interpret/validity.rs:>::aggregate_field_path_elem 2,259,210 ( 0.23%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_middle/src/hir/map/mod.rs:::find_parent_node 2,230,827 ( 0.22%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_lint/src/levels.rs:::push 2,227,256 ( 0.22%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_const_eval/src/interpret/memory.rs:>::get 2,220,796 ( 0.22%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_const_eval/src/interpret/operand.rs:>::read_scalar 2,220,112 ( 0.22%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_query_system/src/query/plumbing.rs:rustc_query_system::query::plumbing::get_query:: 2,189,143 ( 0.22%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_parse/src/lexer/tokentrees.rs:::push 2,139,033 ( 0.21%) ./elf/do-rel.h:_dl_relocate_object 2,138,942 ( 0.21%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_typeck/src/check/writeback.rs:::visit_node_id 2,124,990 ( 0.21%) /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/hashbrown-0.12.0/src/map.rs:>>::from_key_hashed_nocheck:: 2,123,836 ( 0.21%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_middle/src/middle/region.rs:>>::get:: 2,050,850 ( 0.21%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_middle/src/mir/interpret/allocation.rs:::get_relocations:: 2,034,490 ( 0.20%) /usr/home/liquid/rust/worktree-benchmarking/library/core/src/ops/bit.rs:::hash:: 2,009,000 ( 0.20%) /usr/home/liquid/rust/worktree-benchmarking/library/core/src/num/uint_macros.rs:md5::utils::compress 1,999,753 ( 0.20%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_parse/src/parser/expr.rs:::collect_tokens_for_expr::<::parse_dot_or_call_expr::{closure#0}>::{closure#0} 1,999,656 ( 0.20%) /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/hashbrown-0.12.0/src/raw/mod.rs:>::reserve_rehash::>::{closure#0}> 1,989,554 ( 0.20%) /usr/home/liquid/rust/worktree-benchmarking/library/core/src/str/validations.rs:::single_quoted_string 1,978,621 ( 0.20%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_typeck/src/check/expr.rs:::check_expr_with_expectation_and_args 1,967,388 ( 0.20%) /usr/home/liquid/rust/worktree-benchmarking/library/core/src/../../stdarch/crates/core_arch/src/x86/sse2.rs:>>::insert 1,965,336 ( 0.20%) /usr/home/liquid/rust/worktree-benchmarking/library/core/src/../../stdarch/crates/core_arch/src/x86/sse2.rs:::intern 1,964,519 ( 0.20%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_const_eval/src/interpret/place.rs:>::try_read_immediate 1,932,498 ( 0.19%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_target/src/abi/mod.rs:::read_scalar:: 1,930,808 ( 0.19%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_const_eval/src/interpret/operand.rs:>::const_val_to_op 1,927,794 ( 0.19%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_middle/src/mir/interpret/value.rs:::to_u32 1,927,503 ( 0.19%) ???:llvm::PassRegistry::enumerateWith(llvm::PassRegistrationListener*) 1,903,133 ( 0.19%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_const_eval/src/interpret/operand.rs:>::eval_operand 1,887,732 ( 0.19%) /usr/home/liquid/rust/worktree-benchmarking/library/core/src/cell.rs:::attrs 1,855,473 ( 0.19%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_borrowck/src/type_check/mod.rs:::visit_constant 1,843,123 ( 0.19%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_middle/src/ty/util.rs:::is_trivially_unpin 1,827,830 ( 0.18%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_ast/src/token.rs:::eq 1,811,144 ( 0.18%) /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/hashbrown-0.12.0/src/raw/mod.rs:)>>::remove_entry::>::{closure#0}> 1,794,924 ( 0.18%) /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/hashbrown-0.12.0/src/raw/mod.rs:, rustc_query_system::dep_graph::graph::DepNodeIndex))>>::reserve_rehash::, rustc_query_system::dep_graph::graph::DepNodeIndex), core::hash::BuildHasherDefault>::{closure#0}> 1,774,554 ( 0.18%) ???:SetImpliedBits(llvm::FeatureBitset&, llvm::FeatureBitset const&, llvm::ArrayRef) 1,755,100 ( 0.18%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_middle/src/ty/util.rs:::is_freeze 1,752,624 ( 0.18%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_typeck/src/check/coercion.rs:>::coerce 1,732,221 ( 0.17%) ./string/../sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S:__memset_avx2_erms 1,711,289 ( 0.17%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_passes/src/region.rs:::visit_expr 1,684,834 ( 0.17%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_middle/src/ty/flags.rs:::add_const 1,656,027 ( 0.17%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_typeck/src/mem_categorization.rs:::cat_expr_unadjusted 1,655,879 ( 0.17%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_middle/src/mir/interpret/value.rs:::hash:: 1,638,918 ( 0.16%) /usr/home/liquid/rust/worktree-benchmarking/library/core/src/ptr/mod.rs:>::truncate 1,635,846 ( 0.16%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_const_eval/src/interpret/place.rs:>::place_field 1,622,924 ( 0.16%) /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/hashbrown-0.12.0/src/raw/mod.rs:, ())>>::reserve_rehash::, rustc_middle::ty::context::Interned, (), core::hash::BuildHasherDefault>::{closure#0}> 1,612,607 ( 0.16%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_const_eval/src/interpret/place.rs:>::force_allocation_maybe_sized 1,603,733 ( 0.16%) /usr/home/liquid/rust/worktree-benchmarking/library/core/src/intrinsics.rs:::intern 1,599,092 ( 0.16%) ???:llvm::Type::getPrimitiveSizeInBits() const 1,594,826 ( 0.16%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_hir/src/intravisit.rs:rustc_hir::intravisit::walk_expr:: 1,584,090 ( 0.16%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_const_eval/src/interpret/place.rs:>::copy_op_no_validate 1,577,286 ( 0.16%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_middle/src/mir/interpret/pointer.rs:<&mut >::mplace_array_fields::{closure#0} as core::ops::function::FnOnce<(u64,)>>::call_once 1,575,742 ( 0.16%) /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/hashbrown-0.12.0/src/raw/bitmask.rs:::intern 1,554,801 ( 0.16%) /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/hashbrown-0.12.0/src/raw/bitmask.rs:>>::insert 1,538,969 ( 0.15%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_privacy/src/lib.rs:::check_expr_pat_type 1,538,167 ( 0.15%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_lexer/src/lib.rs:::single_quoted_string 1,528,640 ( 0.15%) /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/hashbrown-0.12.0/src/raw/mod.rs:, (core::result::Result, rustc_middle::ty::layout::LayoutError>, rustc_query_system::dep_graph::graph::DepNodeIndex), core::hash::BuildHasherDefault>>::from_key_hashed_nocheck::> 1,525,316 ( 0.15%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_expand/src/expand.rs:::filter_map_expr 1,524,416 ( 0.15%) /usr/home/liquid/rust/worktree-benchmarking/library/core/src/result.rs:>::try_read_immediate 1,524,012 ( 0.15%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_metadata/src/rmeta/encoder.rs:>::encode 1,522,367 ( 0.15%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_ast/src/token.rs:::ident 1,519,437 ( 0.15%) /usr/home/liquid/rust/worktree-benchmarking/library/core/src/../../stdarch/crates/core_arch/src/x86/sse2.rs:>>::from_key_hashed_nocheck:: 1,510,450 ( 0.15%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs:> as rustc_trait_selection::traits::query::type_op::TypeOp>::fully_perform 1,507,225 ( 0.15%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_parse/src/parser/mod.rs:::bump_with 1,505,072 ( 0.15%) /usr/home/liquid/rust/worktree-benchmarking/library/core/src/slice/iter/macros.rs:::next 1,494,131 ( 0.15%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_const_eval/src/interpret/place.rs:>::write_immediate_to_mplace_no_validate 1,475,541 ( 0.15%) /usr/home/liquid/rust/worktree-benchmarking/library/core/src/intrinsics.rs:>>::insert 1,459,872 ( 0.15%) /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/hashbrown-0.12.0/src/raw/mod.rs:)>>::remove_entry::>::{closure#0}> 1,444,079 ( 0.15%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_lint/src/early.rs: as rustc_ast::visit::Visitor>::visit_expr 1,434,084 ( 0.14%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_passes/src/check_attr.rs:::check_attributes 1,418,436 ( 0.14%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_middle/src/ty/context.rs:::node_type 1,414,656 ( 0.14%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_lint/src/early.rs: as rustc_ast::visit::Visitor>::visit_expr 1,406,107 ( 0.14%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_mir_build/src/build/scope.rs:::as_operand 1,405,872 ( 0.14%) /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/hashbrown-0.12.0/src/rustc_entry.rs:, rustc_middle::mir::interpret::allocation::Allocation), core::hash::BuildHasherDefault>>::rustc_entry 1,402,608 ( 0.14%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_const_eval/src/interpret/validity.rs:>::read_scalar 1,374,425 ( 0.14%) /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/hashbrown-0.12.0/src/raw/mod.rs:>::insert::>::{closure#0}> 1,359,642 ( 0.14%) /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/hashbrown-0.12.0/src/raw/mod.rs:>::insert::>::{closure#0}> 1,358,484 ( 0.14%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_middle/src/mir/interpret/allocation.rs:::find_bit 1,354,882 ( 0.14%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_parse/src/parser/expr.rs:::parse_dot_or_call_expr_with_ 1,350,480 ( 0.14%) /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/hashbrown-0.12.0/src/raw/mod.rs:, ())>>::insert_entry::, rustc_middle::ty::context::Interned, (), core::hash::BuildHasherDefault>::{closure#0}> 1,347,814 ( 0.14%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_mir_build/src/build/expr/as_constant.rs:::as_constant 1,346,450 ( 0.14%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_const_eval/src/interpret/visitor.rs: as rustc_const_eval::interpret::visitor::ValueVisitor>::walk_value 1,343,772 ( 0.13%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_const_eval/src/interpret/validity.rs: as rustc_const_eval::interpret::visitor::ValueVisitor>::visit_value 1,343,618 ( 0.13%) /usr/home/liquid/rust/worktree-benchmarking/library/core/src/option.rs: as rustc_const_eval::interpret::visitor::ValueVisitor>::walk_value 1,343,241 ( 0.13%) /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/hashbrown-0.12.0/src/raw/mod.rs:, rustc_query_system::dep_graph::graph::DepNodeIndex))>>::insert::, rustc_query_system::dep_graph::graph::DepNodeIndex), core::hash::BuildHasherDefault>::{closure#0}> 1,343,166 ( 0.13%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_ast/src/token.rs:::clone 1,336,839 ( 0.13%) /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/hashbrown-0.12.0/src/raw/mod.rs:::push 1,316,155 ( 0.13%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_ast/src/util/literal.rs:::from_lit_token 1,298,327 ( 0.13%) /usr/home/liquid/rust/worktree-benchmarking/library/core/src/str/mod.rs:::next_token 1,292,011 ( 0.13%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_span/src/lib.rs:::next_token 1,278,875 ( 0.13%) /usr/home/liquid/rust/worktree-benchmarking/library/core/src/slice/iter/macros.rs:::single_quoted_string 1,276,615 ( 0.13%) ???:llvm::ConstantDataSequential::getImpl(llvm::StringRef, llvm::Type*) 1,270,731 ( 0.13%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_typeck/src/check/writeback.rs:::visit_expr 1,264,068 ( 0.13%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_parse/src/parser/expr.rs:::parse_prefix_expr 1,257,438 ( 0.13%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_parse/src/parser/expr.rs:::parse_opt_lit 1,244,292 ( 0.12%) /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/hashbrown-0.12.0/src/raw/mod.rs:::get_global_alloc 1,240,681 ( 0.12%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_resolve/src/late.rs:::resolve_expr 1,238,888 ( 0.12%) /usr/home/liquid/rust/worktree-benchmarking/library/std/src/collections/hash/map.rs:>>::get:: 1,237,451 ( 0.12%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_typeck/src/check/expr.rs:::check_expr_kind 1,233,456 ( 0.12%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_ast/src/ptr.rs:>::map::<::parse_dot_or_call_expr_with::{closure#0}::{closure#0}> 1,233,425 ( 0.12%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_lint/src/late.rs:rustc_hir::intravisit::walk_expr::> 1,232,618 ( 0.12%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_data_structures/src/sorted_map.rs:>::range_slice_indices::> 1,230,510 ( 0.12%) /usr/home/liquid/rust/worktree-benchmarking/library/core/src/slice/index.rs:::get_relocations:: 1,230,138 ( 0.12%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_const_eval/src/interpret/memory.rs:>::get_mut 1,227,240 ( 0.12%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_parse/src/parser/expr.rs:::parse_lit_expr 1,220,712 ( 0.12%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_ast/src/ast.rs:::hash:: 1,214,368 ( 0.12%) /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/hashbrown-0.12.0/src/raw/bitmask.rs:>>::from_key_hashed_nocheck:: 1,206,256 ( 0.12%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_middle/src/ty/walk.rs:::next 1,205,018 ( 0.12%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_span/src/span_encoding.rs:::to 1,204,906 ( 0.12%) /usr/home/liquid/rust/worktree-benchmarking/library/alloc/src/vec/mod.rs:::check 1,198,600 ( 0.12%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_span/src/hygiene.rs:>::hash_stable 1,181,253 ( 0.12%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_ast_lowering/src/expr.rs:rustc_data_structures::stack::ensure_sufficient_stack::::lower_expr_mut::{closure#0}> 1,167,629 ( 0.12%) /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/hashbrown-0.12.0/src/map.rs:>>::insert 1,162,044 ( 0.12%) /usr/home/liquid/rust/worktree-benchmarking/library/core/src/slice/iter/macros.rs:rustc_ast::util::unicode::contains_text_flow_control_chars 1,154,612 ( 0.12%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_index/src/vec.rs:::mirror_expr_inner 1,153,161 ( 0.12%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_lint/src/builtin.rs:::check_heap_type 1,147,492 ( 0.12%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_lint/src/types.rs:::check_expr 1,144,104 ( 0.11%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_borrowck/src/type_check/canonical.rs:::fully_perform_op::<&rustc_middle::ty::TyS, rustc_middle::ty::ParamEnvAnd>> 1,139,151 ( 0.11%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_const_eval/src/interpret/place.rs:<&mut >::mplace_array_fields::{closure#0} as core::ops::function::FnOnce<(u64,)>>::call_once 1,128,804 ( 0.11%) /usr/home/liquid/rust/worktree-benchmarking/library/core/src/str/validations.rs:::next 1,122,578 ( 0.11%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_lint/src/types.rs:::inherent_atomic_method_call 1,114,046 ( 0.11%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_middle/src/mir/interpret/allocation.rs:::get_bytes_mut:: 1,112,982 ( 0.11%) /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/hashbrown-0.12.0/src/raw/mod.rs:, rustc_middle::mir::interpret::allocation::Allocation), core::hash::BuildHasherDefault>>::rustc_entry 1,109,942 ( 0.11%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_middle/src/mir/interpret/value.rs:::to_char 1,104,767 ( 0.11%) ???:llvm::FPPassManager::runOnFunction(llvm::Function&) 1,099,681 ( 0.11%) /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/stacker-0.1.14/src/lib.rs:stacker::remaining_stack 1,089,501 ( 0.11%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_parse/src/parser/mod.rs:::expect 1,085,656 ( 0.11%) /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/hashbrown-0.12.0/src/map.rs:>>::insert 1,084,903 ( 0.11%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_middle/src/mir/interpret/allocation.rs:::write_scalar:: 1,080,844 ( 0.11%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_mir_build/src/thir/constant.rs:rustc_mir_build::thir::constant::lit_to_const 1,073,975 ( 0.11%) /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,071,416 ( 0.11%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_parse/src/parser/attr.rs:::parse_outer_attributes 1,069,980 ( 0.11%) /usr/home/liquid/rust/worktree-benchmarking/library/core/src/slice/iter/macros.rs:::new_imported_source_file 1,067,020 ( 0.11%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_span/src/lib.rs:::new_imported_source_file 1,063,801 ( 0.11%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_privacy/src/lib.rs:::visit_expr 1,062,576 ( 0.11%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs:::warn_if_unreachable 1,062,388 ( 0.11%) /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/hashbrown-0.12.0/src/raw/bitmask.rs:>>::get:: 1,053,288 ( 0.11%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_const_eval/src/interpret/operand.rs:>::const_to_op 1,052,098 ( 0.11%) /usr/home/liquid/rust/worktree-benchmarking/library/core/src/option.rs:::attrs 1,044,995 ( 0.10%) /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/hashbrown-0.12.0/src/map.rs:, rustc_query_system::dep_graph::graph::DepNodeIndex), core::hash::BuildHasherDefault>>::insert 1,034,285 ( 0.10%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_lint/src/types.rs:::check_expr 1,033,725 ( 0.10%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_lint/src/passes.rs:::check_expr 1,028,225 ( 0.10%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_middle/src/mir/mod.rs:::ty 1,021,335 ( 0.10%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_typeck/src/check/coercion.rs:::try_find_coercion_lub:: 1,011,140 ( 0.10%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_mir_build/src/build/scope.rs:::pop_scope 1,003,534 ( 0.10%) /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/hashbrown-0.12.0/src/raw/mod.rs:>::reserve_rehash::>::{closure#0}> 1,000,066 ( 0.10%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_middle/src/ty/structural_impls.rs:<&rustc_middle::ty::consts::Const as rustc_middle::ty::fold::TypeFoldable>::super_fold_with:: 996,404 ( 0.10%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_const_eval/src/interpret/memory.rs:>::try_read_immediate 996,228 ( 0.10%) /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/hashbrown-0.12.0/src/raw/mod.rs:>::reserve_rehash::>::{closure#0}> -------------------------------------------------------------------------------- -- Auto-annotated source: /usr/home/liquid/rust/worktree-benchmarking/library/core/src/ops/bit.rs -------------------------------------------------------------------------------- Ir -- line 267 ---------------------------------------- . macro_rules! bitor_impl { . ($($t:ty)*) => ($( . #[stable(feature = "rust1", since = "1.0.0")] . #[rustc_const_unstable(feature = "const_ops", issue = "90080")] . impl const BitOr for $t { . type Output = $t; . . #[inline] 35 ( 0.00%) fn bitor(self, rhs: $t) -> $t { self | rhs } . } . . forward_ref_binop! { impl const BitOr, bitor for $t, $t } . )*) . } . . bitor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } . -- line 283 ---------------------------------------- -- line 368 ---------------------------------------- . macro_rules! bitxor_impl { . ($($t:ty)*) => ($( . #[stable(feature = "rust1", since = "1.0.0")] . #[rustc_const_unstable(feature = "const_ops", issue = "90080")] . impl const BitXor for $t { . type Output = $t; . . #[inline] 2,029,393 ( 0.20%) fn bitxor(self, other: $t) -> $t { self ^ other } . } . . forward_ref_binop! { impl const BitXor, bitxor for $t, $t } . )*) . } . . bitxor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } . -- line 384 ---------------------------------------- 1,646,055 ( 0.17%) -------------------------------------------------------------------------------- -- Auto-annotated source: /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_parse/src/lexer/tokentrees.rs -------------------------------------------------------------------------------- Ir -- line 8 ---------------------------------------- . }; . use rustc_ast_pretty::pprust::token_to_string; . use rustc_data_structures::fx::FxHashMap; . use rustc_errors::PResult; . use rustc_span::Span; . . impl<'a> StringReader<'a> { . pub(super) fn into_token_trees(self) -> (PResult<'a, TokenStream>, Vec) { 38 ( 0.00%) let mut tt_reader = TokenTreesReader { . string_reader: self, 2 ( 0.00%) token: Token::dummy(), . open_braces: Vec::new(), . unmatched_braces: Vec::new(), . matching_delim_spans: Vec::new(), . last_unclosed_found_span: None, . last_delim_empty_block_spans: FxHashMap::default(), . matching_block_spans: Vec::new(), . }; 2 ( 0.00%) let res = tt_reader.parse_all_token_trees(); 12 ( 0.00%) (res, tt_reader.unmatched_braces) . } . } . . struct TokenTreesReader<'a> { . string_reader: StringReader<'a>, . token: Token, . /// Stack of open delimiters and their spans. Used for error message. . open_braces: Vec<(token::DelimToken, Span)>, -- line 35 ---------------------------------------- -- line 43 ---------------------------------------- . last_delim_empty_block_spans: FxHashMap, . /// Collect the spans of braces (Open, Close). Used only . /// for detecting if blocks are empty and only braces. . matching_block_spans: Vec<(Span, Span)>, . } . . impl<'a> TokenTreesReader<'a> { . // Parse a stream of tokens into a list of `TokenTree`s, up to an `Eof`. 16 ( 0.00%) fn parse_all_token_trees(&mut self) -> PResult<'a, TokenStream> { . let mut buf = TokenStreamBuilder::default(); . . self.bump(); 712 ( 0.00%) while self.token != token::Eof { 2,832 ( 0.00%) buf.push(self.parse_token_tree()?); . } . . Ok(buf.into_token_stream()) 18 ( 0.00%) } . . // Parse a stream of tokens into a list of `TokenTree`s, up to a `CloseDelim`. . fn parse_token_trees_until_close_delim(&mut self) -> TokenStream { . let mut buf = TokenStreamBuilder::default(); . loop { 120,128 ( 0.01%) if let token::CloseDelim(..) = self.token.kind { . return buf.into_token_stream(); . } . 298,820 ( 0.03%) match self.parse_token_tree() { 537,876 ( 0.05%) Ok(tree) => buf.push(tree), . Err(mut e) => { . e.emit(); . return buf.into_token_stream(); . } . } . } . } . 541,062 ( 0.05%) fn parse_token_tree(&mut self) -> PResult<'a, TreeAndSpacing> { 120,236 ( 0.01%) let sm = self.string_reader.sess.source_map(); . 539,862 ( 0.05%) match self.token.kind { . token::Eof => { . let msg = "this file contains an unclosed delimiter"; . let mut err = . self.string_reader.sess.span_diagnostic.struct_span_err(self.token.span, msg); . for &(_, sp) in &self.open_braces { . err.span_label(sp, "unclosed delimiter"); . self.unmatched_braces.push(UnmatchedBrace { . expected_delim: token::DelimToken::Brace, -- line 91 ---------------------------------------- -- line 113 ---------------------------------------- . err.span_label( . *close_sp, . "...as it matches this but it has different indentation", . ); . } . } . Err(err) . } 300 ( 0.00%) token::OpenDelim(delim) => { . // The span for beginning of the delimited section 300 ( 0.00%) let pre_span = self.token.span; . . // Parse the open delimiter. 2,100 ( 0.00%) self.open_braces.push((delim, self.token.span)); . self.bump(); . . // Parse the token trees within the delimiters. . // We stop at any delimiter so we can try to recover if the user . // uses an incorrect delimiter. 300 ( 0.00%) let tts = self.parse_token_trees_until_close_delim(); . . // Expand to cover the entire delimited token tree 1,500 ( 0.00%) let delim_span = DelimSpan::from_pair(pre_span, self.token.span); . 600 ( 0.00%) match self.token.kind { . // Correct delimiter. 600 ( 0.00%) token::CloseDelim(d) if d == delim => { . let (open_brace, open_brace_span) = self.open_braces.pop().unwrap(); 600 ( 0.00%) let close_brace_span = self.token.span; . 900 ( 0.00%) if tts.is_empty() { 144 ( 0.00%) let empty_block_span = open_brace_span.to(close_brace_span); 192 ( 0.00%) if !sm.is_multiline(empty_block_span) { . // Only track if the block is in the form of `{}`, otherwise it is . // likely that it was written on purpose. . self.last_delim_empty_block_spans.insert(delim, empty_block_span); . } . } . . //only add braces 1,200 ( 0.00%) if let (DelimToken::Brace, DelimToken::Brace) = (open_brace, delim) { . self.matching_block_spans.push((open_brace_span, close_brace_span)); . } . 300 ( 0.00%) if self.open_braces.is_empty() { . // Clear up these spans to avoid suggesting them as we've found . // properly matched delimiters so far for an entire block. . self.matching_delim_spans.clear(); . } else { . self.matching_delim_spans.push(( . open_brace, . open_brace_span, . close_brace_span, -- line 165 ---------------------------------------- -- line 218 ---------------------------------------- . token::Eof => { . // Silently recover, the EOF token will be seen again . // and an error emitted then. Thus we don't pop from . // self.open_braces here. . } . _ => {} . } . 2,100 ( 0.00%) Ok(TokenTree::Delimited(delim_span, delim, tts).into()) . } . token::CloseDelim(delim) => { . // An unexpected closing delimiter (i.e., there is no . // matching opening delimiter). . let token_str = token_to_string(&self.token); . let msg = format!("unexpected closing delimiter: `{}`", token_str); . let mut err = . self.string_reader.sess.span_diagnostic.struct_span_err(self.token.span, &msg); -- line 234 ---------------------------------------- -- line 253 ---------------------------------------- . err.span_label(parent.1, "...matches this closing brace"); . } . } . . err.span_label(self.token.span, "unexpected closing delimiter"); . Err(err) . } . _ => { 299,090 ( 0.03%) let tt = TokenTree::Token(self.token.take()); . let mut spacing = self.bump(); 119,636 ( 0.01%) if !self.token.is_op() { . spacing = Alone; . } 358,908 ( 0.04%) Ok((tt, spacing)) . } . } 480,944 ( 0.05%) } . . fn bump(&mut self) -> Spacing { 542,274 ( 0.05%) let (spacing, token) = self.string_reader.next_token(); 300,608 ( 0.03%) self.token = token; . spacing . } . } . 300 ( 0.00%) #[derive(Default)] . struct TokenStreamBuilder { . buf: Vec, . } . . impl TokenStreamBuilder { 781,534 ( 0.08%) fn push(&mut self, (tree, joint): TreeAndSpacing) { 476,940 ( 0.05%) if let Some((TokenTree::Token(prev_token), Joint)) = self.buf.last() { 58,994 ( 0.01%) if let TokenTree::Token(token) = &tree { 89,091 ( 0.01%) if let Some(glued) = prev_token.glue(token) { . self.buf.pop(); 1,800 ( 0.00%) self.buf.push((TokenTree::Token(glued), joint)); . return; . } . } . } 299,840 ( 0.03%) self.buf.push((tree, joint)) 480,944 ( 0.05%) } . . fn into_token_stream(self) -> TokenStream { 3,018 ( 0.00%) TokenStream::new(self.buf) . } . } 123,351 ( 0.01%) -------------------------------------------------------------------------------- -- Auto-annotated source: /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_middle/src/mir/mod.rs -------------------------------------------------------------------------------- Ir -- line 90 ---------------------------------------- . &self.local_decls . } . } . . /// A streamlined trait that you can implement to create a pass; the . /// pass will be named after the type, and it will consist of a main . /// loop that goes over each available MIR and applies `run_pass`. . pub trait MirPass<'tcx> { 11,488 ( 0.00%) fn name(&self) -> Cow<'_, str> { . let name = std::any::type_name::(); 252 ( 0.00%) if let Some(tail) = name.rfind(':') { 1,412 ( 0.00%) Cow::from(&name[tail + 1..]) . } else { . Cow::from(name) . } 7,596 ( 0.00%) } . . /// Returns `true` if this pass is enabled with the current combination of compiler flags. . fn is_enabled(&self, _sess: &Session) -> bool { . true 2,984 ( 0.00%) } . . fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>); . . /// If this pass causes the MIR to enter a new phase, return that phase. . fn phase_change(&self) -> Option { . None 3,816 ( 0.00%) } . . fn is_mir_dump_enabled(&self) -> bool { . true 4,376 ( 0.00%) } . } . . /// The various "big phases" that MIR goes through. . /// . /// These phases all describe dialects of MIR. Since all MIR uses the same datastructures, the . /// dialects forbid certain variants or values in certain phases. . /// . /// Note: Each phase's validation checks all invariants of the *previous* phases' dialects. A phase . /// that changes the dialect documents what invariants must be upheld *after* that phase finishes. . /// . /// Warning: ordering of variants is significant. 1,820 ( 0.00%) #[derive(Copy, Clone, TyEncodable, TyDecodable, Debug, PartialEq, Eq, PartialOrd, Ord)] . #[derive(HashStable)] . pub enum MirPhase { . Build = 0, . // FIXME(oli-obk): it's unclear whether we still need this phase (and its corresponding query). . // We used to have this for pre-miri MIR based const eval. . Const = 1, . /// This phase checks the MIR for promotable elements and takes them out of the main MIR body . /// by creating a new MIR body per promoted element. After this phase (and thus the termination -- line 141 ---------------------------------------- -- line 157 ---------------------------------------- . impl MirPhase { . /// Gets the index of the current MirPhase within the set of all `MirPhase`s. . pub fn phase_index(&self) -> usize { . *self as usize . } . } . . /// Where a specific `mir::Body` comes from. 600 ( 0.00%) #[derive(Copy, Clone, Debug, PartialEq, Eq)] 534 ( 0.00%) #[derive(HashStable, TyEncodable, TyDecodable, TypeFoldable)] . pub struct MirSource<'tcx> { . pub instance: InstanceDef<'tcx>, . . /// If `Some`, this is a promoted rvalue within the parent function. . pub promoted: Option, . } . . impl<'tcx> MirSource<'tcx> { 64 ( 0.00%) pub fn item(def_id: DefId) -> Self { 320 ( 0.00%) MirSource { . instance: InstanceDef::Item(ty::WithOptConstParam::unknown(def_id)), . promoted: None, . } 64 ( 0.00%) } . . pub fn from_instance(instance: InstanceDef<'tcx>) -> Self { . MirSource { instance, promoted: None } . } . . pub fn with_opt_param(self) -> ty::WithOptConstParam { 156 ( 0.00%) self.instance.with_opt_param() 156 ( 0.00%) } . . #[inline] . pub fn def_id(&self) -> DefId { 6,931 ( 0.00%) self.instance.def_id() . } . } . . #[derive(Clone, TyEncodable, TyDecodable, Debug, HashStable, TypeFoldable)] . pub struct GeneratorInfo<'tcx> { . /// The yield type of the function, if it is a generator. . pub yield_ty: Option>, . -- line 200 ---------------------------------------- -- line 205 ---------------------------------------- . pub generator_layout: Option>, . . /// If this is a generator then record the type of source expression that caused this generator . /// to be created. . pub generator_kind: GeneratorKind, . } . . /// The lowered representation of a single function. 11,141 ( 0.00%) #[derive(Clone, TyEncodable, TyDecodable, Debug, HashStable, TypeFoldable)] . pub struct Body<'tcx> { . /// A list of basic blocks. References to basic block use a newtyped index type [`BasicBlock`] . /// that indexes into this vector. . basic_blocks: IndexVec>, . . /// Records how far through the "desugaring and optimization" process this particular . /// MIR has traversed. This is particularly useful when inlining, since in that context . /// we instantiate the promoted constants and add them to our promoted vector -- but those . /// promoted items have already been optimized, whereas ours have not. This field allows . /// us to see the difference and forego optimization on the inlined promoted items. 212 ( 0.00%) pub phase: MirPhase, . . pub source: MirSource<'tcx>, . . /// A list of source scopes; these are referenced by statements . /// and used for debuginfo. Indexed by a `SourceScope`. 240 ( 0.00%) pub source_scopes: IndexVec>, . 240 ( 0.00%) pub generator: Option>>, . . /// Declarations of locals. . /// . /// The first local is the return value pointer, followed by `arg_count` . /// locals for the function arguments, followed by any user-declared . /// variables and temporaries. . pub local_decls: LocalDecls<'tcx>, . -- line 240 ---------------------------------------- -- line 242 ---------------------------------------- . pub user_type_annotations: ty::CanonicalUserTypeAnnotations<'tcx>, . . /// The number of arguments this function takes. . /// . /// Starting at local 1, `arg_count` locals will be provided by the caller . /// and can be assumed to be initialized. . /// . /// If this MIR was built for a constant, this will be 0. 120 ( 0.00%) pub arg_count: usize, . . /// Mark an argument local (which must be a tuple) as getting passed as . /// its individual components at the LLVM level. . /// . /// This is used for the "rust-call" ABI. 240 ( 0.00%) pub spread_arg: Option, . . /// Debug information pertaining to user variables, including captures. 120 ( 0.00%) pub var_debug_info: Vec>, . . /// A span representing this MIR, for error reporting. . pub span: Span, . . /// Constants that are required to evaluate successfully for this MIR to be well-formed. . /// We hold in this field all the constants we are not able to evaluate yet. . pub required_consts: Vec>, . -- line 267 ---------------------------------------- -- line 275 ---------------------------------------- . /// fn test() { . /// let _ = [0; std::mem::size_of::<*mut T>()]; . /// } . /// ``` . /// . /// **WARNING**: Do not change this flags after the MIR was originally created, even if an optimization . /// removed the last mention of all generic params. We do not want to rely on optimizations and . /// potentially allow things like `[u8; std::mem::size_of::() * 0]` due to this. 120 ( 0.00%) pub is_polymorphic: bool, . . predecessor_cache: PredecessorCache, . is_cyclic: GraphIsCyclicCache, . } . . impl<'tcx> Body<'tcx> { 1,536 ( 0.00%) pub fn new( . source: MirSource<'tcx>, . basic_blocks: IndexVec>, . source_scopes: IndexVec>, . local_decls: LocalDecls<'tcx>, . user_type_annotations: ty::CanonicalUserTypeAnnotations<'tcx>, . arg_count: usize, . var_debug_info: Vec>, . span: Span, . generator_kind: Option, . ) -> Self { . // We need `arg_count` locals, and one for the return place. 128 ( 0.00%) assert!( 128 ( 0.00%) local_decls.len() > arg_count, . "expected at least {} locals, got {}", . arg_count + 1, . local_decls.len() . ); . 2,560 ( 0.00%) let mut body = Body { . phase: MirPhase::Build, . source, . basic_blocks, . source_scopes, . generator: generator_kind.map(|generator_kind| { . Box::new(GeneratorInfo { . yield_ty: None, . generator_drop: None, . generator_layout: None, . generator_kind, . }) . }), 512 ( 0.00%) local_decls, 512 ( 0.00%) user_type_annotations, . arg_count, . spread_arg: None, 512 ( 0.00%) var_debug_info, . span, . required_consts: Vec::new(), . is_polymorphic: false, . predecessor_cache: PredecessorCache::new(), . is_cyclic: GraphIsCyclicCache::new(), . }; 128 ( 0.00%) body.is_polymorphic = body.has_param_types_or_consts(); . body 1,152 ( 0.00%) } . . /// Returns a partially initialized MIR body containing only a list of basic blocks. . /// . /// The returned MIR contains no `LocalDecl`s (even for the return place) or source scopes. It . /// is only useful for testing but cannot be `#[cfg(test)]` because it is used in a different . /// crate. . pub fn new_cfg_only(basic_blocks: IndexVec>) -> Self { . let mut body = Body { -- line 343 ---------------------------------------- -- line 368 ---------------------------------------- . . #[inline] . pub fn basic_blocks_mut(&mut self) -> &mut IndexVec> { . // Because the user could mutate basic block terminators via this reference, we need to . // invalidate the caches. . // . // FIXME: Use a finer-grained API for this, so only transformations that alter terminators . // invalidate the caches. 624 ( 0.00%) self.predecessor_cache.invalidate(); . self.is_cyclic.invalidate(); . &mut self.basic_blocks . } . . #[inline] . pub fn basic_blocks_and_local_decls_mut( . &mut self, . ) -> (&mut IndexVec>, &mut LocalDecls<'tcx>) { -- line 384 ---------------------------------------- -- line 397 ---------------------------------------- . ) { . self.predecessor_cache.invalidate(); . self.is_cyclic.invalidate(); . (&mut self.basic_blocks, &mut self.local_decls, &mut self.var_debug_info) . } . . /// Returns `true` if a cycle exists in the control-flow graph that is reachable from the . /// `START_BLOCK`. 1,136 ( 0.00%) pub fn is_cfg_cyclic(&self) -> bool { . self.is_cyclic.is_cyclic(self) 1,704 ( 0.00%) } . . #[inline] . pub fn local_kind(&self, local: Local) -> LocalKind { . let index = local.as_usize(); 2,703 ( 0.00%) if index == 0 { . debug_assert!( . self.local_decls[local].mutability == Mutability::Mut, . "return place should be mutable" . ); . . LocalKind::ReturnPointer 8,540 ( 0.00%) } else if index < self.arg_count + 1 { . LocalKind::Arg . } else if self.local_decls[local].is_user_variable() { . LocalKind::Var . } else { . LocalKind::Temp . } . } . . /// Returns an iterator over all user-declared mutable locals. . #[inline] . pub fn mut_vars_iter<'a>(&'a self) -> impl Iterator + 'a { 192 ( 0.00%) (self.arg_count + 1..self.local_decls.len()).filter_map(move |index| { . let local = Local::new(index); . let decl = &self.local_decls[local]; 28 ( 0.00%) if decl.is_user_variable() && decl.mutability == Mutability::Mut { . Some(local) . } else { . None . } . }) . } . . /// Returns an iterator over all user-declared mutable arguments and locals. . #[inline] . pub fn mut_vars_and_args_iter<'a>(&'a self) -> impl Iterator + 'a { . (1..self.local_decls.len()).filter_map(move |index| { . let local = Local::new(index); . let decl = &self.local_decls[local]; 1,582 ( 0.00%) if (decl.is_user_variable() || index < self.arg_count + 1) . && decl.mutability == Mutability::Mut . { . Some(local) . } else { . None . } . }) . } . . /// Returns an iterator over all function arguments. . #[inline] . pub fn args_iter(&self) -> impl Iterator + ExactSizeIterator { 2,213 ( 0.00%) (1..self.arg_count + 1).map(Local::new) . } . . /// Returns an iterator over all user-defined variables and compiler-generated temporaries (all . /// locals that are neither arguments nor the return place). . #[inline] . pub fn vars_and_temps_iter( . &self, . ) -> impl DoubleEndedIterator + ExactSizeIterator { 39 ( 0.00%) (self.arg_count + 1..self.local_decls.len()).map(Local::new) . } . . #[inline] . pub fn drain_vars_and_temps<'a>(&'a mut self) -> impl Iterator> + 'a { . self.local_decls.drain(self.arg_count + 1..) . } . . /// Changes a statement to a nop. This is both faster than deleting instructions and avoids -- line 478 ---------------------------------------- -- line 479 ---------------------------------------- . /// invalidating statement indices in `Location`s. . pub fn make_statement_nop(&mut self, location: Location) { . let block = &mut self.basic_blocks[location.block]; . debug_assert!(location.statement_index < block.statements.len()); . block.statements[location.statement_index].make_nop() . } . . /// Returns the source info associated with `location`. 59,730 ( 0.01%) pub fn source_info(&self, location: Location) -> &SourceInfo { . let block = &self[location.block]; . let stmts = &block.statements; 29,865 ( 0.00%) let idx = location.statement_index; 149,325 ( 0.01%) if idx < stmts.len() { 88,680 ( 0.01%) &stmts[idx].source_info . } else { 610 ( 0.00%) assert_eq!(idx, stmts.len()); 610 ( 0.00%) &block.terminator().source_info . } 59,730 ( 0.01%) } . . /// Returns the return type; it always return first element from `local_decls` array. . #[inline] . pub fn return_ty(&self) -> Ty<'tcx> { 636 ( 0.00%) self.local_decls[RETURN_PLACE].ty . } . . /// Gets the location of the terminator for the given block. . #[inline] . pub fn terminator_loc(&self, bb: BasicBlock) -> Location { 1,746 ( 0.00%) Location { block: bb, statement_index: self[bb].statements.len() } . } . . pub fn stmt_at(&self, location: Location) -> Either<&Statement<'tcx>, &Terminator<'tcx>> { . let Location { block, statement_index } = location; . let block_data = &self.basic_blocks[block]; . block_data . .statements . .get(statement_index) -- line 516 ---------------------------------------- -- line 520 ---------------------------------------- . . #[inline] . pub fn predecessors(&self) -> &Predecessors { . self.predecessor_cache.compute(&self.basic_blocks) . } . . #[inline] . pub fn dominators(&self) -> Dominators { 282 ( 0.00%) dominators(self) . } . . #[inline] . pub fn yield_ty(&self) -> Option> { . self.generator.as_ref().and_then(|generator| generator.yield_ty) . } . . #[inline] -- line 536 ---------------------------------------- -- line 571 ---------------------------------------- . . impl<'tcx> IndexMut for Body<'tcx> { . #[inline] . fn index_mut(&mut self, index: BasicBlock) -> &mut BasicBlockData<'tcx> { . &mut self.basic_blocks_mut()[index] . } . } . 2,428 ( 0.00%) #[derive(Copy, Clone, Debug, HashStable, TypeFoldable)] . pub enum ClearCrossCrate { . Clear, . Set(T), . } . . impl ClearCrossCrate { . pub fn as_ref(&self) -> ClearCrossCrate<&T> { 118,151 ( 0.01%) match self { . ClearCrossCrate::Clear => ClearCrossCrate::Clear, . ClearCrossCrate::Set(v) => ClearCrossCrate::Set(v), . } . } . . pub fn assert_crate_local(self) -> T { 29,594 ( 0.00%) match self { . ClearCrossCrate::Clear => bug!("unwrapping cross-crate data"), . ClearCrossCrate::Set(v) => v, . } 62 ( 0.00%) } . } . . const TAG_CLEAR_CROSS_CRATE_CLEAR: u8 = 0; . const TAG_CLEAR_CROSS_CRATE_SET: u8 = 1; . . impl<'tcx, E: TyEncoder<'tcx>, T: Encodable> Encodable for ClearCrossCrate { . #[inline] . fn encode(&self, e: &mut E) -> Result<(), E::Error> { -- line 606 ---------------------------------------- -- line 637 ---------------------------------------- . } . } . . /// Grouped information about the source code origin of a MIR entity. . /// Intended to be inspected by diagnostics and debuginfo. . /// Most passes can work with it as a whole, within a single function. . // The unofficial Cranelift backend, at least as of #65828, needs `SourceInfo` to implement `Eq` and . // `Hash`. Please ping @bjorn3 if removing them. 14,122 ( 0.00%) #[derive(Copy, Clone, Debug, Eq, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)] . pub struct SourceInfo { . /// The source span for the AST pertaining to this MIR entity. . pub span: Span, . . /// The source scope, keeping track of which bindings can be . /// seen by debuginfo, active lint levels, `unsafe {...}`, etc. . pub scope: SourceScope, . } -- line 653 ---------------------------------------- -- line 657 ---------------------------------------- . pub fn outermost(span: Span) -> Self { . SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE } . } . } . . /////////////////////////////////////////////////////////////////////////// . // Borrow kinds . 1,814 ( 0.00%) #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, TyEncodable, TyDecodable)] . #[derive(Hash, HashStable)] . pub enum BorrowKind { . /// Data must be immutable and is aliasable. . Shared, . . /// The immediately borrowed place must be immutable, but projections from . /// it don't need to be. For example, a shallow borrow of `a.b` doesn't . /// conflict with a mutable borrow of `a.b.c`. -- line 673 ---------------------------------------- -- line 731 ---------------------------------------- . /// `true` if this borrow arose from method-call auto-ref . /// (i.e., `adjustment::Adjust::Borrow`). . allow_two_phase_borrow: bool, . }, . } . . impl BorrowKind { . pub fn allows_two_phase_borrow(&self) -> bool { 10 ( 0.00%) match *self { . BorrowKind::Shared | BorrowKind::Shallow | BorrowKind::Unique => false, . BorrowKind::Mut { allow_two_phase_borrow } => allow_two_phase_borrow, . } 2 ( 0.00%) } . . pub fn describe_mutability(&self) -> String { . match *self { . BorrowKind::Shared | BorrowKind::Shallow | BorrowKind::Unique => { . "immutable".to_string() . } . BorrowKind::Mut { .. } => "mutable".to_string(), . } -- line 751 ---------------------------------------- -- line 777 ---------------------------------------- . /// Compiler-introduced temporary. . Temp, . /// Function argument. . Arg, . /// Location of function's return value. . ReturnPointer, . } . 24 ( 0.00%) #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)] . pub struct VarBindingForm<'tcx> { . /// Is variable bound via `x`, `mut x`, `ref x`, or `ref mut x`? 6 ( 0.00%) pub binding_mode: ty::BindingMode, . /// If an explicit type was provided for this variable binding, . /// this holds the source Span of that type. . /// . /// NOTE: if you want to change this to a `HirId`, be wary that . /// doing so breaks incremental compilation (as of this writing), . /// while a `Span` does not cause our tests to fail. . pub opt_ty_info: Option, . /// Place of the RHS of the =, or the subject of the `match` where this -- line 796 ---------------------------------------- -- line 799 ---------------------------------------- . /// (a) the right-hand side isn't evaluated as a place expression. . /// (b) it gives a way to separate this case from the remaining cases . /// for diagnostics. . pub opt_match_place: Option<(Option>, Span)>, . /// The span of the pattern in which this variable was bound. . pub pat_span: Span, . } . 432 ( 0.00%) #[derive(Clone, Debug, TyEncodable, TyDecodable)] . pub enum BindingForm<'tcx> { . /// This is a binding for a non-`self` binding, or a `self` that has an explicit type. . Var(VarBindingForm<'tcx>), . /// Binding for a `self`/`&self`/`&mut self` binding where the type is implicit. 315 ( 0.00%) ImplicitSelf(ImplicitSelfKind), . /// Reference used in a guard expression to ensure immutability. . RefForGuard, . } . . /// Represents what type of implicit self a function has, if any. . #[derive(Clone, Copy, PartialEq, Debug, TyEncodable, TyDecodable, HashStable)] . pub enum ImplicitSelfKind { . /// Represents a `fn x(self);`. -- line 820 ---------------------------------------- -- line 853 ---------------------------------------- . /// `BlockTailInfo` is attached to the `LocalDecl` for temporaries . /// created during evaluation of expressions in a block tail . /// expression; that is, a block like `{ STMT_1; STMT_2; EXPR }`. . /// . /// It is used to improve diagnostics when such temporaries are . /// involved in borrow_check errors, e.g., explanations of where the . /// temporaries come from, when their destructors are run, and/or how . /// one might revise the code to satisfy the borrow checker's rules. 1,727 ( 0.00%) #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)] . pub struct BlockTailInfo { . /// If `true`, then the value resulting from evaluating this tail . /// expression is ignored by the block's expression context. . /// . /// Examples include `{ ...; tail };` and `let _ = { ...; tail };` . /// but not e.g., `let _x = { ...; tail };` . pub tail_result_is_ignored: bool, . -- line 869 ---------------------------------------- -- line 870 ---------------------------------------- . /// `Span` of the tail expression. . pub span: Span, . } . . /// A MIR local. . /// . /// This can be a binding declared by the user, a temporary inserted by the compiler, a function . /// argument, or the return place. 9,197 ( 0.00%) #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)] . pub struct LocalDecl<'tcx> { . /// Whether this is a mutable binding (i.e., `let x` or `let mut x`). . /// . /// Temporaries and the return place are always mutable. 2,214 ( 0.00%) pub mutability: Mutability, . . // FIXME(matthewjasper) Don't store in this in `Body` . pub local_info: Option>>, . . /// `true` if this is an internal local. . /// . /// These locals are not based on types in the source code and are only used . /// for a few desugarings at the moment. -- line 891 ---------------------------------------- -- line 894 ---------------------------------------- . /// across a suspension point against the type components of the generator . /// which type checking knows are live across a suspension point. We need to . /// flag drop flags to avoid triggering this check as they are introduced . /// after typeck. . /// . /// This should be sound because the drop flags are fully algebraic, and . /// therefore don't affect the auto-trait or outlives properties of the . /// generator. 1,761 ( 0.00%) pub internal: bool, . . /// If this local is a temporary and `is_block_tail` is `Some`, . /// then it is a temporary created for evaluation of some . /// subexpression of some block's tail expression (with no . /// intervening statement context). . // FIXME(matthewjasper) Don't store in this in `Body` . pub is_block_tail: Option, . . /// The type of this local. 1,761 ( 0.00%) pub ty: Ty<'tcx>, . . /// If the user manually ascribed a type to this variable, . /// e.g., via `let x: T`, then we carry that type here. The MIR . /// borrow checker needs this information since it can affect . /// region inference. . // FIXME(matthewjasper) Don't store in this in `Body` . pub user_ty: Option>, . -- line 920 ---------------------------------------- -- line 1005 ---------------------------------------- . static_assert_size!(LocalDecl<'_>, 56); . . /// Extra information about a some locals that's used for diagnostics and for . /// classifying variables into local variables, statics, etc, which is needed e.g. . /// for unsafety checking. . /// . /// Not used for non-StaticRef temporaries, the return place, or anonymous . /// function parameters. 3,679 ( 0.00%) #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)] . pub enum LocalInfo<'tcx> { . /// A user-defined local variable or function parameter . /// . /// The `BindingForm` is solely used for local diagnostics when generating . /// warnings/errors when compiling the current crate, and therefore it need . /// not be visible across crates. . User(ClearCrossCrate>), . /// A temporary created that references the static with the given `DefId`. 168 ( 0.00%) StaticRef { def_id: DefId, is_thread_local: bool }, . /// A temporary created that references the const with the given `DefId` . ConstRef { def_id: DefId }, . /// A temporary created during the creation of an aggregate . /// (e.g. a temporary for `foo` in `MyStruct { my_field: foo }`) . AggregateTemp, . } . . impl<'tcx> LocalDecl<'tcx> { -- line 1030 ---------------------------------------- -- line 1064 ---------------------------------------- . ))) . ) . } . . /// Returns `true` if this variable is a named variable or function . /// parameter declared by the user. . #[inline] . pub fn is_user_variable(&self) -> bool { 4,498 ( 0.00%) matches!(self.local_info, Some(box LocalInfo::User(_))) . } . . /// Returns `true` if this is a reference to a variable bound in a `match` . /// expression that is used to access said variable for the guard of the . /// match arm. . pub fn is_ref_for_guard(&self) -> bool { . matches!( . self.local_info, . Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::RefForGuard))) . ) . } . . /// Returns `Some` if this is a reference to a static item that is used to . /// access that static. . pub fn is_ref_to_static(&self) -> bool { 3,104 ( 0.00%) matches!(self.local_info, Some(box LocalInfo::StaticRef { .. })) 960 ( 0.00%) } . . /// Returns `Some` if this is a reference to a thread-local static item that is used to . /// access that static. . pub fn is_ref_to_thread_local(&self) -> bool { 528 ( 0.00%) match self.local_info { . Some(box LocalInfo::StaticRef { is_thread_local, .. }) => is_thread_local, . _ => false, . } 174 ( 0.00%) } . . /// Returns `true` is the local is from a compiler desugaring, e.g., . /// `__next` from a `for` loop. . #[inline] . pub fn from_compiler_desugaring(&self) -> bool { . self.source_info.span.desugaring_kind().is_some() . } . -- line 1106 ---------------------------------------- -- line 1108 ---------------------------------------- . #[inline] . pub fn new(ty: Ty<'tcx>, span: Span) -> Self { . Self::with_source_info(ty, SourceInfo::outermost(span)) . } . . /// Like `LocalDecl::new`, but takes a `SourceInfo` instead of a `Span`. . #[inline] . pub fn with_source_info(ty: Ty<'tcx>, source_info: SourceInfo) -> Self { 1,946 ( 0.00%) LocalDecl { . mutability: Mutability::Mut, . local_info: None, . internal: false, . is_block_tail: None, . ty, . user_ty: None, . source_info, . } -- line 1124 ---------------------------------------- -- line 1136 ---------------------------------------- . pub fn immutable(mut self) -> Self { . self.mutability = Mutability::Not; . self . } . . /// Converts `self` into same `LocalDecl` except tagged as internal temporary. . #[inline] . pub fn block_tail(mut self, info: BlockTailInfo) -> Self { 162 ( 0.00%) assert!(self.is_block_tail.is_none()); 486 ( 0.00%) self.is_block_tail = Some(info); 2,268 ( 0.00%) self . } . } . 645 ( 0.00%) #[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable)] . pub enum VarDebugInfoContents<'tcx> { . /// NOTE(eddyb) There's an unenforced invariant that this `Place` is . /// based on a `Local`, not a `Static`, and contains no indexing. . Place(Place<'tcx>), . Const(Constant<'tcx>), . } . . impl<'tcx> Debug for VarDebugInfoContents<'tcx> { -- line 1158 ---------------------------------------- -- line 1160 ---------------------------------------- . match self { . VarDebugInfoContents::Const(c) => write!(fmt, "{}", c), . VarDebugInfoContents::Place(p) => write!(fmt, "{:?}", p), . } . } . } . . /// Debug information pertaining to a user variable. 1,577 ( 0.00%) #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)] . pub struct VarDebugInfo<'tcx> { . pub name: Symbol, . . /// Source info of the user variable, including the scope . /// within which the variable is visible (to debuginfo) . /// (see `LocalDecl`'s `source_info` field for more details). . pub source_info: SourceInfo, . -- line 1176 ---------------------------------------- -- line 1209 ---------------------------------------- . DEBUG_FORMAT = "bb{}", . const START_BLOCK = 0, . } . } . . impl BasicBlock { . pub fn start_location(self) -> Location { . Location { block: self, statement_index: 0 } 1,581 ( 0.00%) } . } . . /////////////////////////////////////////////////////////////////////////// . // BasicBlockData and Terminator . . /// See [`BasicBlock`] for documentation on what basic blocks are at a high level. 17,394 ( 0.00%) #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)] . pub struct BasicBlockData<'tcx> { . /// List of statements in this block. 224 ( 0.00%) pub statements: Vec>, . . /// Terminator for this block. . /// . /// N.B., this should generally ONLY be `None` during construction. . /// Therefore, you should generally access it via the . /// `terminator()` or `terminator_mut()` methods. The only . /// exception is that certain passes, such as `simplify_cfg`, swap . /// out the terminator temporarily with `None` while they continue -- line 1235 ---------------------------------------- -- line 1239 ---------------------------------------- . /// If true, this block lies on an unwind path. This is used . /// during codegen where distinct kinds of basic blocks may be . /// generated (particularly for MSVC cleanup). Unwind blocks must . /// only branch to other unwind blocks. . pub is_cleanup: bool, . } . . /// Information about an assertion failure. 81 ( 0.00%) #[derive(Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq, PartialOrd)] . pub enum AssertKind { . BoundsCheck { len: O, index: O }, . Overflow(BinOp, O, O), . OverflowNeg(O), . DivisionByZero(O), . RemainderByZero(O), . ResumedAfterReturn(GeneratorKind), . ResumedAfterPanic(GeneratorKind), -- line 1255 ---------------------------------------- -- line 1287 ---------------------------------------- . pub type AssertMessage<'tcx> = AssertKind>; . . pub type Successors<'a> = . iter::Chain, slice::Iter<'a, BasicBlock>>; . pub type SuccessorsMut<'a> = . iter::Chain, slice::IterMut<'a, BasicBlock>>; . . impl<'tcx> BasicBlockData<'tcx> { 271 ( 0.00%) pub fn new(terminator: Option>) -> BasicBlockData<'tcx> { 4,336 ( 0.00%) BasicBlockData { statements: vec![], terminator, is_cleanup: false } 271 ( 0.00%) } . . /// Accessor for terminator. . /// . /// Terminator may not be None after construction of the basic block is complete. This accessor . /// provides a convenience way to reach the terminator. . #[inline] . pub fn terminator(&self) -> &Terminator<'tcx> { 6,028 ( 0.00%) self.terminator.as_ref().expect("invalid terminator state") . } . . #[inline] . pub fn terminator_mut(&mut self) -> &mut Terminator<'tcx> { 2,876 ( 0.00%) self.terminator.as_mut().expect("invalid terminator state") . } . . pub fn retain_statements(&mut self, mut f: F) . where . F: FnMut(&mut Statement<'_>) -> bool, . { . for s in &mut self.statements { . if !f(s) { . s.make_nop(); . } . } . } . 2,520 ( 0.00%) pub fn expand_statements(&mut self, mut f: F) . where . F: FnMut(&mut Statement<'tcx>) -> Option, . I: iter::TrustedLen>, . { . // Gather all the iterators we'll need to splice in, and their positions. . let mut splices: Vec<(usize, I)> = vec![]; . let mut extra_stmts = 0; . for (i, s) in self.statements.iter_mut().enumerate() { -- line 1332 ---------------------------------------- -- line 1348 ---------------------------------------- . } . . // Splice in the new statements, from the end of the block. . // FIXME(eddyb) This could be more efficient with a "gap buffer" . // where a range of elements ("gap") is left uninitialized, with . // splicing adding new elements to the end of that gap and moving . // existing elements from before the gap to the end of the gap. . // For now, this is safe code, emulating a gap but initializing it. 754 ( 0.00%) let mut gap = self.statements.len()..self.statements.len() + extra_stmts; 756 ( 0.00%) self.statements.resize( . gap.end, 1,008 ( 0.00%) Statement { source_info: SourceInfo::outermost(DUMMY_SP), kind: StatementKind::Nop }, . ); . for (splice_start, new_stmts) in splices.into_iter().rev() { . let splice_end = splice_start + new_stmts.size_hint().0; . while gap.end > splice_end { . gap.start -= 1; . gap.end -= 1; . self.statements.swap(gap.start, gap.end); . } . self.statements.splice(splice_start..splice_end, new_stmts); . gap.end = splice_start; . } 2,016 ( 0.00%) } . . pub fn visitable(&self, index: usize) -> &dyn MirVisitable<'tcx> { . if index < self.statements.len() { &self.statements[index] } else { &self.terminator } . } . } . . impl AssertKind { . /// Getting a description does not require `O` to be printable, and does not -- line 1379 ---------------------------------------- -- line 1501 ---------------------------------------- . _ => write!(f, "{}", self.description()), . } . } . } . . /////////////////////////////////////////////////////////////////////////// . // Statements . 28,248 ( 0.00%) #[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable)] . pub struct Statement<'tcx> { . pub source_info: SourceInfo, . pub kind: StatementKind<'tcx>, . } . . // `Statement` is used a lot. Make sure it doesn't unintentionally get bigger. . #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] . static_assert_size!(Statement<'_>, 32); . . impl Statement<'_> { . /// Changes a statement to a nop. This is both faster than deleting instructions and avoids . /// invalidating statement indices in `Location`s. 4 ( 0.00%) pub fn make_nop(&mut self) { 4 ( 0.00%) self.kind = StatementKind::Nop 4 ( 0.00%) } . . /// Changes a statement to a nop and returns the original statement. . #[must_use = "If you don't need the statement, use `make_nop` instead"] . pub fn replace_nop(&mut self) -> Self { . Statement { . source_info: self.source_info, . kind: mem::replace(&mut self.kind, StatementKind::Nop), . } . } . } . 31,276 ( 0.00%) #[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable)] . pub enum StatementKind<'tcx> { . /// Write the RHS Rvalue to the LHS Place. 668 ( 0.00%) Assign(Box<(Place<'tcx>, Rvalue<'tcx>)>), . . /// This represents all the reading that a pattern match may do . /// (e.g., inspecting constants and discriminant values), and the . /// kind of pattern it comes from. This is in order to adapt potential . /// error messages to these specific patterns. . /// . /// Note that this also is emitted for regular `let` bindings to ensure that locals that are . /// never accessed still get some sanity checks for, e.g., `let x: ! = ..;` 2 ( 0.00%) FakeRead(Box<(FakeReadCause, Place<'tcx>)>), . . /// Write the discriminant for a variant to the enum Place. . SetDiscriminant { place: Box>, variant_index: VariantIdx }, . . /// Start a live range for the storage of the local. 1,308 ( 0.00%) StorageLive(Local), . . /// End the current live range for the storage of the local. 1,308 ( 0.00%) StorageDead(Local), . . /// Retag references in the given place, ensuring they got fresh tags. This is . /// part of the Stacked Borrows model. These statements are currently only interpreted . /// by miri and only generated when "-Z mir-emit-retag" is passed. . /// See . /// for more details. . Retag(RetagKind, Box>), . -- line 1565 ---------------------------------------- -- line 1732 ---------------------------------------- . pub count: Operand<'tcx>, . } . . /////////////////////////////////////////////////////////////////////////// . // Places . . /// A path to a value; something that can be evaluated without . /// changing or disturbing program state. 2,025 ( 0.00%) #[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, HashStable)] . pub struct Place<'tcx> { 133 ( 0.00%) pub local: Local, . . /// projection out of a place (access a field, deref a pointer, etc) . pub projection: &'tcx List>, . } . . #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] . static_assert_size!(Place<'_>, 16); . 2,735 ( 0.00%) #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] 1,830 ( 0.00%) #[derive(TyEncodable, TyDecodable, HashStable)] . pub enum ProjectionElem { . Deref, 46 ( 0.00%) Field(Field, T), . Index(V), . . /// These indices are generated by slice patterns. Easiest to explain . /// by example: . /// . /// ``` . /// [X, _, .._, _, _] => { offset: 0, min_length: 4, from_end: false }, . /// [_, X, .._, _, _] => { offset: 1, min_length: 4, from_end: false }, -- line 1763 ---------------------------------------- -- line 1788 ---------------------------------------- . from_end: bool, . }, . . /// "Downcast" to a variant of an ADT. Currently, we only introduce . /// this for ADTs with more than one variant. It may be better to . /// just introduce it always, or always for enums. . /// . /// The included Symbol is the name of the variant, used for printing MIR. 2 ( 0.00%) Downcast(Option, VariantIdx), . } . . impl ProjectionElem { . /// Returns `true` if the target of this projection may refer to a different region of memory . /// than the base. . fn is_indirect(&self) -> bool { . match self { . Self::Deref => true, -- line 1804 ---------------------------------------- -- line 1838 ---------------------------------------- . pub struct Field { . derive [HashStable] . DEBUG_FORMAT = "field[{}]" . } . } . . #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] . pub struct PlaceRef<'tcx> { 352 ( 0.00%) pub local: Local, 88 ( 0.00%) pub projection: &'tcx [PlaceElem<'tcx>], . } . . impl<'tcx> Place<'tcx> { . // FIXME change this to a const fn by also making List::empty a const fn. . pub fn return_place() -> Place<'tcx> { . Place { local: RETURN_PLACE, projection: List::empty() } 339 ( 0.00%) } . . /// Returns `true` if this `Place` contains a `Deref` projection. . /// . /// If `Place::is_indirect` returns false, the caller knows that the `Place` refers to the . /// same region of memory as its base. . pub fn is_indirect(&self) -> bool { 194 ( 0.00%) self.projection.iter().any(|elem| elem.is_indirect()) 194 ( 0.00%) } . . /// Finds the innermost `Local` from this `Place`, *if* it is either a local itself or . /// a single deref of a local. . #[inline(always)] . pub fn local_or_deref_local(&self) -> Option { . self.as_ref().local_or_deref_local() . } . -- line 1870 ---------------------------------------- -- line 1872 ---------------------------------------- . /// projections, return `Some(_X)`. . #[inline(always)] . pub fn as_local(&self) -> Option { . self.as_ref().as_local() . } . . #[inline] . pub fn as_ref(&self) -> PlaceRef<'tcx> { 15,956 ( 0.00%) PlaceRef { local: self.local, projection: &self.projection } . } . . /// Iterate over the projections in evaluation order, i.e., the first element is the base with . /// its projection and then subsequently more projections are added. . /// As a concrete example, given the place a.b.c, this would yield: . /// - (a, .b) . /// - (a.b, .c) . /// -- line 1888 ---------------------------------------- -- line 1896 ---------------------------------------- . (base, proj) . }) . } . } . . impl From for Place<'_> { . fn from(local: Local) -> Self { . Place { local, projection: List::empty() } 8,412 ( 0.00%) } . } . . impl<'tcx> PlaceRef<'tcx> { . /// Finds the innermost `Local` from this `Place`, *if* it is either a local itself or . /// a single deref of a local. . pub fn local_or_deref_local(&self) -> Option { . match *self { . PlaceRef { local, projection: [] } -- line 1912 ---------------------------------------- -- line 1915 ---------------------------------------- . } . } . . /// If this place represents a local variable like `_X` with no . /// projections, return `Some(_X)`. . #[inline] . pub fn as_local(&self) -> Option { . match *self { 4,343 ( 0.00%) PlaceRef { local, projection: [] } => Some(local), . _ => None, . } . } . . #[inline] . pub fn last_projection(&self) -> Option<(PlaceRef<'tcx>, PlaceElem<'tcx>)> { 5,202 ( 0.00%) if let &[ref proj_base @ .., elem] = self.projection { 54 ( 0.00%) Some((PlaceRef { local: self.local, projection: proj_base }, elem)) . } else { . None . } . } . } . . impl Debug for Place<'_> { . fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { -- line 1939 ---------------------------------------- -- line 2024 ---------------------------------------- . trace!(?data); . match &data.local_data { . ClearCrossCrate::Set(data) => Some(data.lint_root), . ClearCrossCrate::Clear => None, . } . } . } . 3,147 ( 0.00%) #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)] . pub struct SourceScopeData<'tcx> { 28 ( 0.00%) pub span: Span, . pub parent_scope: Option, . . /// Whether this scope is the root of a scope tree of another body, . /// inlined into this body by the MIR inliner. . /// `ty::Instance` is the callee, and the `Span` is the call site. . pub inlined: Option<(ty::Instance<'tcx>, Span)>, . . /// Nearest (transitive) parent scope (if any) which is inlined. . /// This is an optimization over walking up `parent_scope` . /// until a scope with `inlined: Some(...)` is found. 84 ( 0.00%) pub inlined_parent_scope: Option, . . /// Crate-local information for this source scope, that can't (and . /// needn't) be tracked across crates. . pub local_data: ClearCrossCrate, . } . 632 ( 0.00%) #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)] . pub struct SourceScopeLocalData { . /// An `HirId` with lint levels equivalent to this scope's lint levels. . pub lint_root: hir::HirId, . /// The unsafe block that contains this node. . pub safety: Safety, . } . . /////////////////////////////////////////////////////////////////////////// . // Operands . . /// These are values that can appear inside an rvalue. They are intentionally . /// limited to prevent rvalues from being nested in one another. 772,761 ( 0.08%) #[derive(Clone, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)] . pub enum Operand<'tcx> { . /// Copy: The value must be available for use afterwards. . /// . /// This implies that the type of the place must be `Copy`; this is true . /// by construction during build, but also checked by the MIR type checker. 1,099 ( 0.00%) Copy(Place<'tcx>), . . /// Move: The value (including old borrows of it) will not be used again. . /// . /// Safe for values of all types (modulo future developments towards `?Move`). . /// Correct usage patterns are enforced by the borrow checker for safe code. . /// `Copy` may be converted to `Move` to enable "last-use" optimizations. 1,622 ( 0.00%) Move(Place<'tcx>), . . /// Synthesizes a constant value. 29,549 ( 0.00%) Constant(Box>), . } . . #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] . static_assert_size!(Operand<'_>, 24); . . impl<'tcx> Debug for Operand<'tcx> { . fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { . use self::Operand::*; -- line 2089 ---------------------------------------- -- line 2109 ---------------------------------------- . Operand::Constant(Box::new(Constant { . span, . user_ty: None, . literal: ConstantKind::Ty(ty::Const::zero_sized(tcx, ty)), . })) . } . . pub fn is_move(&self) -> bool { 88 ( 0.00%) matches!(self, Operand::Move(..)) 44 ( 0.00%) } . . /// Convenience helper to make a literal-like constant from a given scalar value. . /// Since this is used to synthesize MIR, assumes `user_ty` is None. . pub fn const_from_scalar( . tcx: TyCtxt<'tcx>, . ty: Ty<'tcx>, . val: Scalar, . span: Span, -- line 2126 ---------------------------------------- -- line 2149 ---------------------------------------- . Operand::Copy(_) | Operand::Constant(_) => self.clone(), . Operand::Move(place) => Operand::Copy(place), . } . } . . /// Returns the `Place` that is the target of this `Operand`, or `None` if this `Operand` is a . /// constant. . pub fn place(&self) -> Option> { 1,000 ( 0.00%) match self { . Operand::Copy(place) | Operand::Move(place) => Some(*place), . Operand::Constant(_) => None, . } 250 ( 0.00%) } . . /// Returns the `Constant` that is the target of this `Operand`, or `None` if this `Operand` is a . /// place. . pub fn constant(&self) -> Option<&Constant<'tcx>> { . match self { . Operand::Constant(x) => Some(&**x), . Operand::Copy(_) | Operand::Move(_) => None, . } . } . } . . /////////////////////////////////////////////////////////////////////////// . /// Rvalues . 13,640 ( 0.00%) #[derive(Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq)] . pub enum Rvalue<'tcx> { . /// x (either a move or copy, depending on type of x) . Use(Operand<'tcx>), . . /// [x; 32] . Repeat(Operand<'tcx>, &'tcx ty::Const<'tcx>), . . /// &x or &mut x 788 ( 0.00%) Ref(Region<'tcx>, BorrowKind, Place<'tcx>), . . /// Accessing a thread local static. This is inherently a runtime operation, even if llvm . /// treats it as an access to a static. This `Rvalue` yields a reference to the thread local . /// static. . ThreadLocalRef(DefId), . . /// Create a raw pointer to the given place . /// Can be generated by raw address of expressions (`&raw const x`), . /// or when casting a reference to a raw pointer. . AddressOf(Mutability, Place<'tcx>), . . /// length of a `[X]` or `[X;n]` value . Len(Place<'tcx>), . 168 ( 0.00%) Cast(CastKind, Operand<'tcx>, Ty<'tcx>), . 156 ( 0.00%) BinaryOp(BinOp, Box<(Operand<'tcx>, Operand<'tcx>)>), 12 ( 0.00%) CheckedBinaryOp(BinOp, Box<(Operand<'tcx>, Operand<'tcx>)>), . . NullaryOp(NullOp, Ty<'tcx>), . UnaryOp(UnOp, Operand<'tcx>), . . /// Read the discriminant of an ADT. . /// . /// Undefined (i.e., no effort is made to make it defined, but there’s no reason why it cannot . /// be defined to return, say, a 0) if ADT is not an enum. . Discriminant(Place<'tcx>), . . /// Creates an aggregate value, like a tuple or struct. This is . /// only needed because we want to distinguish `dest = Foo { x: . /// ..., y: ... }` from `dest.x = ...; dest.y = ...;` in the case . /// that `Foo` has a destructor. These rvalues can be optimized . /// away after type-checking and before lowering. 112 ( 0.00%) Aggregate(Box>, Vec>), . . /// Transmutes a `*mut u8` into shallow-initialized `Box`. . /// . /// This is different a normal transmute because dataflow analysis will treat the box . /// as initialized but its content as uninitialized. . ShallowInitBox(Operand<'tcx>, Ty<'tcx>), . } . . #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] . static_assert_size!(Rvalue<'_>, 40); . 340 ( 0.00%) #[derive(Clone, Copy, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)] . pub enum CastKind { . Misc, . Pointer(PointerCast), . } . 592 ( 0.00%) #[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)] . pub enum AggregateKind<'tcx> { . /// The type is of the element 84 ( 0.00%) Array(Ty<'tcx>), . Tuple, . . /// The second field is the variant index. It's equal to 0 for struct . /// and union expressions. The fourth field is . /// active field number and is present only for union expressions . /// -- e.g., for a union expression `SomeUnion { c: .. }`, the . /// active field index would identity the field `c` . Adt(DefId, VariantIdx, SubstsRef<'tcx>, Option, Option), -- line 2248 ---------------------------------------- -- line 2249 ---------------------------------------- . . Closure(DefId, SubstsRef<'tcx>), . Generator(DefId, SubstsRef<'tcx>, hir::Movability), . } . . #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] . static_assert_size!(AggregateKind<'_>, 48); . 178 ( 0.00%) #[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, TyEncodable, TyDecodable, Hash, HashStable)] . pub enum BinOp { . /// The `+` operator (addition) . Add, . /// The `-` operator (subtraction) . Sub, . /// The `*` operator (multiplication) . Mul, . /// The `/` operator (division) -- line 2265 ---------------------------------------- -- line 2485 ---------------------------------------- . . /////////////////////////////////////////////////////////////////////////// . /// Constants . /// . /// Two constants are equal if they are the same constant. Note that . /// this does not necessarily mean that they are `==` in Rust. In . /// particular, one must be wary of `NaN`! . 118,723 ( 0.01%) #[derive(Clone, Copy, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)] . pub struct Constant<'tcx> { . pub span: Span, . . /// Optional user-given type: for something like . /// `collect::>`, this would be present and would . /// indicate that `Vec<_>` was explicitly specified. . /// . /// Needed for NLL to impose user-given type constraints. . pub user_ty: Option, . . pub literal: ConstantKind<'tcx>, . } . 353,394 ( 0.04%) #[derive(Clone, Copy, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable, Debug)] . #[derive(Lift)] . pub enum ConstantKind<'tcx> { . /// This constant came from the type system 524 ( 0.00%) Ty(&'tcx ty::Const<'tcx>), . /// This constant cannot go back into the type system, as it represents . /// something the type system cannot handle (e.g. pointers). . Val(interpret::ConstValue<'tcx>, Ty<'tcx>), . } . . impl<'tcx> Constant<'tcx> { 584,890 ( 0.06%) pub fn check_static_ptr(&self, tcx: TyCtxt<'_>) -> Option { 584,890 ( 0.06%) match self.literal.const_for_ty()?.val.try_to_scalar() { . Some(Scalar::Ptr(ptr, _size)) => match tcx.global_alloc(ptr.provenance) { . GlobalAlloc::Static(def_id) => { 168 ( 0.00%) assert!(!tcx.is_thread_local_static(def_id)); . Some(def_id) . } . _ => None, . }, . _ => None, . } 935,824 ( 0.09%) } . #[inline] . pub fn ty(&self) -> Ty<'tcx> { 75 ( 0.00%) self.literal.ty() . } . } . . impl<'tcx> From<&'tcx ty::Const<'tcx>> for ConstantKind<'tcx> { . #[inline] . fn from(ct: &'tcx ty::Const<'tcx>) -> Self { . Self::Ty(ct) . } . } . . impl<'tcx> ConstantKind<'tcx> { . /// Returns `None` if the constant is not trivially safe for use in the type system. . pub fn const_for_ty(&self) -> Option<&'tcx ty::Const<'tcx>> { 526,330 ( 0.05%) match self { . ConstantKind::Ty(c) => Some(c), . ConstantKind::Val(..) => None, . } 146,187 ( 0.01%) } . . pub fn ty(&self) -> Ty<'tcx> { 411,290 ( 0.04%) match self { . ConstantKind::Ty(c) => c.ty, . ConstantKind::Val(_, ty) => ty, . } 205,645 ( 0.02%) } . . #[inline] . pub fn try_to_value(self) -> Option> { . match self { . ConstantKind::Ty(c) => c.val.try_to_value(), . ConstantKind::Val(val, _) => Some(val), . } . } -- line 2565 ---------------------------------------- -- line 2652 ---------------------------------------- . /// inferred region `'1`). The second will lead to the constraint `w: . /// &'static str`. . #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)] . pub struct UserTypeProjections { . pub contents: Vec<(UserTypeProjection, Span)>, . } . . impl<'tcx> UserTypeProjections { 13 ( 0.00%) pub fn none() -> Self { 13 ( 0.00%) UserTypeProjections { contents: vec![] } 13 ( 0.00%) } . . pub fn is_empty(&self) -> bool { . self.contents.is_empty() . } . . pub fn projections_and_spans( . &self, . ) -> impl Iterator + ExactSizeIterator { -- line 2670 ---------------------------------------- -- line 2870 ---------------------------------------- . fn start_node(&self) -> Self::Node { . START_BLOCK . } . } . . impl<'tcx> graph::WithSuccessors for Body<'tcx> { . #[inline] . fn successors(&self, node: Self::Node) -> >::Iter { 749 ( 0.00%) self.basic_blocks[node].terminator().successors().cloned() . } . } . . impl<'a, 'b> graph::GraphSuccessors<'b> for Body<'a> { . type Item = BasicBlock; . type Iter = iter::Cloned>; . } . -- line 2886 ---------------------------------------- -- line 2897 ---------------------------------------- . } . . /// `Location` represents the position of the start of the statement; or, if . /// `statement_index` equals the number of statements, then the start of the . /// terminator. . #[derive(Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd, HashStable)] . pub struct Location { . /// The block that the location is within. 72 ( 0.00%) pub block: BasicBlock, . 36 ( 0.00%) pub statement_index: usize, . } . . impl fmt::Debug for Location { . fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { . write!(fmt, "{:?}[{}]", self.block, self.statement_index) . } . } . -- line 2915 ---------------------------------------- -- line 2952 ---------------------------------------- . return true; . } . } . . false . } . . pub fn dominates(&self, other: Location, dominators: &Dominators) -> bool { 252 ( 0.00%) if self.block == other.block { 184 ( 0.00%) self.statement_index <= other.statement_index . } else { 136 ( 0.00%) dominators.is_dominated_by(other.block, self.block) . } 92 ( 0.00%) } . } 882,390 ( 0.09%) -------------------------------------------------------------------------------- -- Auto-annotated source: /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_lint/src/types.rs -------------------------------------------------------------------------------- Ir -- line 448 ---------------------------------------- . } . . fn lint_literal<'tcx>( . cx: &LateContext<'tcx>, . type_limits: &TypeLimits, . e: &'tcx hir::Expr<'tcx>, . lit: &hir::Lit, . ) { 350,904 ( 0.04%) match *cx.typeck_results().node_type(e.hir_id).kind() { . ty::Int(t) => { . match lit.node { . ast::LitKind::Int(v, ast::LitIntType::Signed(_) | ast::LitIntType::Unsuffixed) => { . lint_int_literal(cx, type_limits, e, lit, t, v) . } . _ => bug!(), . }; . } -- line 464 ---------------------------------------- -- line 487 ---------------------------------------- . }); . } . } . _ => {} . } . } . . impl<'tcx> LateLintPass<'tcx> for TypeLimits { 265,815 ( 0.03%) fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx hir::Expr<'tcx>) { 206,657 ( 0.02%) match e.kind { . hir::ExprKind::Unary(hir::UnOp::Neg, ref expr) => { . // propagate negation, if the negation itself isn't negated . if self.negated_expr_id != Some(e.hir_id) { . self.negated_expr_id = Some(expr.hir_id); . } . } 22 ( 0.00%) hir::ExprKind::Binary(binop, ref l, ref r) => { 22 ( 0.00%) if is_comparison(binop) && !check_limits(cx, binop, &l, &r) { . cx.struct_span_lint(UNUSED_COMPARISONS, e.span, |lint| { . lint.build("comparison is useless due to type limits").emit() . }); . } . } 58,484 ( 0.01%) hir::ExprKind::Lit(ref lit) => lint_literal(cx, self, e, lit), . _ => {} . }; . . fn is_valid(binop: hir::BinOp, v: T, min: T, max: T) -> bool { . match binop.node { . hir::BinOpKind::Lt => v > min && v <= max, . hir::BinOpKind::Le => v >= min && v < max, . hir::BinOpKind::Gt => v >= min && v < max, -- line 518 ---------------------------------------- -- line 575 ---------------------------------------- . }; . is_valid(norm_binop, lit_val, min, max) . } . _ => true, . } . } . . fn is_comparison(binop: hir::BinOp) -> bool { 44 ( 0.00%) matches!( 22 ( 0.00%) binop.node, . hir::BinOpKind::Eq . | hir::BinOpKind::Lt . | hir::BinOpKind::Le . | hir::BinOpKind::Ne . | hir::BinOpKind::Ge . | hir::BinOpKind::Gt . ) . } 236,280 ( 0.02%) } . } . . declare_lint! { . /// The `improper_ctypes` lint detects incorrect use of types in foreign . /// modules. . /// . /// ### Example . /// -- line 601 ---------------------------------------- -- line 1268 ---------------------------------------- . . fn check_foreign_static(&mut self, id: hir::HirId, span: Span) { . let def_id = self.cx.tcx.hir().local_def_id(id); . let ty = self.cx.tcx.type_of(def_id); . self.check_type_for_ffi_and_report_errors(span, ty, true, false); . } . . fn is_internal_abi(&self, abi: SpecAbi) -> bool { 72 ( 0.00%) matches!( . abi, . SpecAbi::Rust | SpecAbi::RustCall | SpecAbi::RustIntrinsic | SpecAbi::PlatformIntrinsic . ) . } . } . . impl<'tcx> LateLintPass<'tcx> for ImproperCTypesDeclarations { . fn check_foreign_item(&mut self, cx: &LateContext<'_>, it: &hir::ForeignItem<'_>) { -- line 1284 ---------------------------------------- -- line 1306 ---------------------------------------- . kind: hir::intravisit::FnKind<'tcx>, . decl: &'tcx hir::FnDecl<'_>, . _: &'tcx hir::Body<'_>, . _: Span, . hir_id: hir::HirId, . ) { . use hir::intravisit::FnKind; . 178 ( 0.00%) let abi = match kind { . FnKind::ItemFn(_, _, header, ..) => header.abi, 35 ( 0.00%) FnKind::Method(_, sig, ..) => sig.header.abi, . _ => return, . }; . 72 ( 0.00%) let mut vis = ImproperCTypesVisitor { cx, mode: CItemKind::Definition }; . if !vis.is_internal_abi(abi) { . vis.check_foreign_fn(hir_id, decl); . } . } . } . . declare_lint_pass!(VariantSizeDifferences => [VARIANT_SIZE_DIFFERENCES]); . . impl<'tcx> LateLintPass<'tcx> for VariantSizeDifferences { 238 ( 0.00%) fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) { 68 ( 0.00%) if let hir::ItemKind::Enum(ref enum_definition, _) = it.kind { . let t = cx.tcx.type_of(it.def_id); . let ty = cx.tcx.erase_regions(t); . let layout = match cx.layout_of(ty) { . Ok(layout) => layout, . Err( . ty::layout::LayoutError::Unknown(_) . | ty::layout::LayoutError::SizeOverflow(_) . | ty::layout::LayoutError::NormalizationFailure(_, _), -- line 1339 ---------------------------------------- -- line 1385 ---------------------------------------- . larger ({} bytes) than the next largest", . largest . )) . .emit() . }, . ); . } . } 272 ( 0.00%) } . } . . declare_lint! { . /// The `invalid_atomic_ordering` lint detects passing an `Ordering` . /// to an atomic operation that does not support that ordering. . /// . /// ### Example . /// -- line 1401 ---------------------------------------- -- line 1437 ---------------------------------------- . INVALID_ATOMIC_ORDERING, . Deny, . "usage of invalid atomic ordering in atomic operations and memory fences" . } . . declare_lint_pass!(InvalidAtomicOrdering => [INVALID_ATOMIC_ORDERING]); . . impl InvalidAtomicOrdering { 472,560 ( 0.05%) fn inherent_atomic_method_call<'hir>( . cx: &LateContext<'_>, . expr: &Expr<'hir>, . recognized_names: &[Symbol], // used for fast path calculation . ) -> Option<(Symbol, &'hir [Expr<'hir>])> { . const ATOMIC_TYPES: &[Symbol] = &[ . sym::AtomicBool, . sym::AtomicPtr, . sym::AtomicUsize, -- line 1453 ---------------------------------------- -- line 1459 ---------------------------------------- . sym::AtomicIsize, . sym::AtomicI8, . sym::AtomicI16, . sym::AtomicI32, . sym::AtomicI64, . sym::AtomicI128, . ]; . if_chain! { 118,140 ( 0.01%) if let ExprKind::MethodCall(ref method_path, args, _) = &expr.kind; 124 ( 0.00%) if recognized_names.contains(&method_path.ident.name); . if let Some(m_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id); . if let Some(impl_did) = cx.tcx.impl_of_method(m_def_id); . if let Some(adt) = cx.tcx.type_of(impl_did).ty_adt_def(); . // skip extension traits, only lint functions from the standard library . if cx.tcx.trait_id_of_impl(impl_did).is_none(); . . if let Some(parent) = cx.tcx.parent(adt.did); . if cx.tcx.is_diagnostic_item(sym::atomic_mod, parent); . if ATOMIC_TYPES.contains(&cx.tcx.item_name(adt.did)); . then { . return Some((method_path.ident.name, args)); . } . } 59,070 ( 0.01%) None 472,560 ( 0.05%) } . . fn matches_ordering(cx: &LateContext<'_>, did: DefId, orderings: &[Symbol]) -> bool { . let tcx = cx.tcx; . let atomic_ordering = tcx.get_diagnostic_item(sym::Ordering); . orderings.iter().any(|ordering| { . tcx.item_name(did) == *ordering && { . let parent = tcx.parent(did); . parent == atomic_ordering -- line 1491 ---------------------------------------- -- line 1502 ---------------------------------------- . None . } . } . . fn check_atomic_load_store(cx: &LateContext<'_>, expr: &Expr<'_>) { . use rustc_hir::def::{DefKind, Res}; . use rustc_hir::QPath; . if_chain! { 206,745 ( 0.02%) if let Some((method, args)) = Self::inherent_atomic_method_call(cx, expr, &[sym::load, sym::store]); . if let Some((ordering_arg, invalid_ordering)) = match method { . sym::load => Some((&args[1], sym::Release)), . sym::store => Some((&args[2], sym::Acquire)), . _ => None, . }; . . if let ExprKind::Path(QPath::Resolved(_, path)) = ordering_arg.kind; . if let Res::Def(DefKind::Ctor(..), ctor_id) = path.res; -- line 1518 ---------------------------------------- -- line 1531 ---------------------------------------- . } . }); . } . } . } . . fn check_memory_fence(cx: &LateContext<'_>, expr: &Expr<'_>) { . if_chain! { 59,070 ( 0.01%) if let ExprKind::Call(ref func, ref args) = expr.kind; 112 ( 0.00%) if let ExprKind::Path(ref func_qpath) = func.kind; 252 ( 0.00%) if let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id(); 168 ( 0.00%) if matches!(cx.tcx.get_diagnostic_name(def_id), Some(sym::fence | sym::compiler_fence)); . if let ExprKind::Path(ref ordering_qpath) = &args[0].kind; . if let Some(ordering_def_id) = cx.qpath_res(ordering_qpath, args[0].hir_id).opt_def_id(); . if Self::matches_ordering(cx, ordering_def_id, &[sym::Relaxed]); . then { . cx.struct_span_lint(INVALID_ATOMIC_ORDERING, args[0].span, |diag| { . diag.build("memory fences cannot have `Relaxed` ordering") . .help("consider using ordering modes `Acquire`, `Release`, `AcqRel` or `SeqCst`") . .emit(); . }); . } . } . } . . fn check_atomic_compare_exchange(cx: &LateContext<'_>, expr: &Expr<'_>) { . if_chain! { 265,815 ( 0.03%) if let Some((method, args)) = Self::inherent_atomic_method_call(cx, expr, &[sym::fetch_update, sym::compare_exchange, sym::compare_exchange_weak]); . if let Some((success_order_arg, failure_order_arg)) = match method { . sym::fetch_update => Some((&args[1], &args[2])), . sym::compare_exchange | sym::compare_exchange_weak => Some((&args[3], &args[4])), . _ => None, . }; . . if let Some(fail_ordering_def_id) = Self::opt_ordering_defid(cx, failure_order_arg); . then { -- line 1566 ---------------------------------------- -- line 1613 ---------------------------------------- . } . } . } . } . } . } . . impl<'tcx> LateLintPass<'tcx> for InvalidAtomicOrdering { 265,815 ( 0.03%) fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { . Self::check_atomic_load_store(cx, expr); . Self::check_memory_fence(cx, expr); . Self::check_atomic_compare_exchange(cx, expr); 236,280 ( 0.02%) } . } 29,538 ( 0.00%) -------------------------------------------------------------------------------- -- Auto-annotated source: /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_ast/src/tokenstream.rs -------------------------------------------------------------------------------- Ir -- line 32 ---------------------------------------- . /// . /// If the syntax extension is an MBE macro, it will attempt to match its . /// LHS token tree against the provided token tree, and if it finds a . /// match, will transcribe the RHS token tree, splicing in any captured . /// `macro_parser::matched_nonterminals` into the `SubstNt`s it finds. . /// . /// The RHS of an MBE macro is the only place `SubstNt`s are substituted. . /// Nothing special happens to misnamed or misplaced `SubstNt`s. 603,184 ( 0.06%) #[derive(Debug, Clone, PartialEq, Encodable, Decodable, HashStable_Generic)] . pub enum TokenTree { . /// A single token. 239,184 ( 0.02%) Token(Token), . /// A delimited sequence of token trees. 644 ( 0.00%) Delimited(DelimSpan, DelimToken, TokenStream), . } . . #[derive(Copy, Clone)] . pub enum CanSynthesizeMissingTokens { . Yes, . No, . } . -- line 53 ---------------------------------------- -- line 72 ---------------------------------------- . } . _ => false, . } . } . . /// Retrieves the `TokenTree`'s span. . pub fn span(&self) -> Span { . match self { 2 ( 0.00%) TokenTree::Token(token) => token.span, . TokenTree::Delimited(sp, ..) => sp.entire(), . } . } . . /// Modify the `TokenTree`'s span in-place. . pub fn set_span(&mut self, span: Span) { . match self { . TokenTree::Token(token) => token.span = span, . TokenTree::Delimited(dspan, ..) => *dspan = DelimSpan::from_single(span), . } . } . . pub fn token(kind: TokenKind, span: Span) -> TokenTree { 2,432 ( 0.00%) TokenTree::Token(Token::new(kind, span)) . } . . /// Returns the opening delimiter as a token tree. 305 ( 0.00%) pub fn open_tt(span: DelimSpan, delim: DelimToken) -> TokenTree { 915 ( 0.00%) TokenTree::token(token::OpenDelim(delim), span.open) 305 ( 0.00%) } . . /// Returns the closing delimiter as a token tree. 303 ( 0.00%) pub fn close_tt(span: DelimSpan, delim: DelimToken) -> TokenTree { 909 ( 0.00%) TokenTree::token(token::CloseDelim(delim), span.close) 303 ( 0.00%) } . 12 ( 0.00%) pub fn uninterpolate(self) -> TokenTree { 8 ( 0.00%) match self { 36 ( 0.00%) TokenTree::Token(token) => TokenTree::Token(token.uninterpolate().into_owned()), . tt => tt, . } 16 ( 0.00%) } . } . . impl HashStable for TokenStream . where . CTX: crate::HashStableContext, . { . fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { . for sub_tt in self.trees() { -- line 120 ---------------------------------------- -- line 188 ---------------------------------------- . Delimited(DelimSpan, DelimToken, AttrAnnotatedTokenStream), . /// Stores the attributes for an attribute target, . /// along with the tokens for that attribute target. . /// See `AttributesData` for more information . Attributes(AttributesData), . } . . impl AttrAnnotatedTokenStream { 604 ( 0.00%) pub fn new(tokens: Vec<(AttrAnnotatedTokenTree, Spacing)>) -> AttrAnnotatedTokenStream { . AttrAnnotatedTokenStream(Lrc::new(tokens)) 604 ( 0.00%) } . . /// Converts this `AttrAnnotatedTokenStream` to a plain `TokenStream . /// During conversion, `AttrAnnotatedTokenTree::Attributes` get 'flattened' . /// back to a `TokenStream` of the form `outer_attr attr_target`. . /// If there are inner attributes, they are inserted into the proper . /// place in the attribute target tokens. . pub fn to_tokenstream(&self) -> TokenStream { . let trees: Vec<_> = self -- line 206 ---------------------------------------- -- line 316 ---------------------------------------- . pub struct TokenStream(pub(crate) Lrc>); . . pub type TreeAndSpacing = (TokenTree, Spacing); . . // `TokenStream` is used a lot. Make sure it doesn't unintentionally get bigger. . #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] . rustc_data_structures::static_assert_size!(TokenStream, 8); . 60,425 ( 0.01%) #[derive(Clone, Copy, Debug, PartialEq, Encodable, Decodable)] . pub enum Spacing { . Alone, . Joint, . } . . impl TokenStream { . /// Given a `TokenStream` with a `Stream` of only two arguments, return a new `TokenStream` . /// separating the two arguments with a comma for diagnostic suggestions. -- line 332 ---------------------------------------- -- line 371 ---------------------------------------- . impl From<(AttrAnnotatedTokenTree, Spacing)> for AttrAnnotatedTokenStream { . fn from((tree, spacing): (AttrAnnotatedTokenTree, Spacing)) -> AttrAnnotatedTokenStream { . AttrAnnotatedTokenStream::new(vec![(tree, spacing)]) . } . } . . impl From for TokenStream { . fn from(tree: TokenTree) -> TokenStream { 10 ( 0.00%) TokenStream::new(vec![(tree, Spacing::Alone)]) . } . } . . impl From for TreeAndSpacing { . fn from(tree: TokenTree) -> TreeAndSpacing { 908 ( 0.00%) (tree, Spacing::Alone) . } . } . . impl iter::FromIterator for TokenStream { . fn from_iter>(iter: I) -> Self { . TokenStream::new(iter.into_iter().map(Into::into).collect::>()) . } . } -- line 393 ---------------------------------------- -- line 401 ---------------------------------------- . } . . impl TokenStream { . pub fn new(streams: Vec) -> TokenStream { . TokenStream(Lrc::new(streams)) . } . . pub fn is_empty(&self) -> bool { 300 ( 0.00%) self.0.is_empty() 300 ( 0.00%) } . . pub fn len(&self) -> usize { 60,765 ( 0.01%) self.0.len() . } . . pub fn from_streams(mut streams: SmallVec<[TokenStream; 2]>) -> TokenStream { . match streams.len() { . 0 => TokenStream::default(), . 1 => streams.pop().unwrap(), . _ => { . // We are going to extend the first stream in `streams` with -- line 421 ---------------------------------------- -- line 448 ---------------------------------------- . . // Create the final `TokenStream`. . TokenStream(first_stream_lrc) . } . } . } . . pub fn trees(&self) -> Cursor { 5 ( 0.00%) self.clone().into_trees() 10 ( 0.00%) } . 333 ( 0.00%) pub fn into_trees(self) -> Cursor { . Cursor::new(self) 666 ( 0.00%) } . . /// Compares two `TokenStream`s, checking equality without regarding span information. . pub fn eq_unspanned(&self, other: &TokenStream) -> bool { . let mut t1 = self.trees(); . let mut t2 = other.trees(); . for (t1, t2) in iter::zip(&mut t1, &mut t2) { . if !t1.eq_unspanned(&t2) { . return false; -- line 469 ---------------------------------------- -- line 572 ---------------------------------------- . pub struct Cursor { . pub stream: TokenStream, . index: usize, . } . . impl Iterator for Cursor { . type Item = TokenTree; . 273 ( 0.00%) fn next(&mut self) -> Option { 447 ( 0.00%) self.next_with_spacing().map(|(tree, _)| tree) 364 ( 0.00%) } . } . . impl Cursor { . fn new(stream: TokenStream) -> Self { . Cursor { stream, index: 0 } . } . 303,370 ( 0.03%) pub fn next_with_spacing(&mut self) -> Option { 182,295 ( 0.02%) if self.index < self.stream.len() { 120,232 ( 0.01%) self.index += 1; 420,378 ( 0.04%) Some(self.stream.0[self.index - 1].clone()) . } else { 1,240 ( 0.00%) None . } 364,044 ( 0.04%) } . . pub fn index(&self) -> usize { . self.index . } . . pub fn append(&mut self, new_stream: TokenStream) { . if new_stream.is_empty() { . return; . } . let index = self.index; . let stream = mem::take(&mut self.stream); . *self = TokenStream::from_streams(smallvec![stream, new_stream]).into_trees(); . self.index = index; . } . 59,660 ( 0.01%) pub fn look_ahead(&self, n: usize) -> Option<&TokenTree> { 119,320 ( 0.01%) self.stream.0[self.index..].get(n).map(|(tree, _)| tree) 119,320 ( 0.01%) } . } . 1,116 ( 0.00%) #[derive(Debug, Copy, Clone, PartialEq, Encodable, Decodable, HashStable_Generic)] . pub struct DelimSpan { . pub open: Span, . pub close: Span, . } . . impl DelimSpan { . pub fn from_single(sp: Span) -> Self { . DelimSpan { open: sp, close: sp } . } . 600 ( 0.00%) pub fn from_pair(open: Span, close: Span) -> Self { . DelimSpan { open, close } 300 ( 0.00%) } . . pub fn dummy() -> Self { . Self::from_single(DUMMY_SP) 18 ( 0.00%) } . 16 ( 0.00%) pub fn entire(self) -> Span { . self.open.with_hi(self.close.hi()) 12 ( 0.00%) } . } 193 ( 0.00%) -------------------------------------------------------------------------------- -- Auto-annotated source: /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_const_eval/src/interpret/place.rs -------------------------------------------------------------------------------- Ir -- line 14 ---------------------------------------- . use rustc_target::abi::{HasDataLayout, Size, VariantIdx, Variants}; . . use super::{ . alloc_range, mir_assign_valid_types, AllocId, AllocRef, AllocRefMut, CheckInAllocMsg, . ConstAlloc, ImmTy, Immediate, InterpCx, InterpResult, LocalValue, Machine, MemoryKind, OpTy, . Operand, Pointer, PointerArithmetic, Provenance, Scalar, ScalarMaybeUninit, . }; . 1,764 ( 0.00%) #[derive(Copy, Clone, Hash, PartialEq, Eq, HashStable, Debug)] . /// Information required for the sound usage of a `MemPlace`. . pub enum MemPlaceMeta { . /// The unsized payload (e.g. length for slices or vtable pointer for trait objects). . Meta(Scalar), . /// `Sized` types or unsized `extern type` . None, . /// The address of this place may not be taken. This protects the `MemPlace` from coming from . /// a ZST Operand without a backing allocation and being converted to an integer address. This -- line 30 ---------------------------------------- -- line 33 ---------------------------------------- . Poison, . } . . #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] . rustc_data_structures::static_assert_size!(MemPlaceMeta, 24); . . impl MemPlaceMeta { . pub fn unwrap_meta(self) -> Scalar { 168 ( 0.00%) match self { . Self::Meta(s) => s, . Self::None | Self::Poison => { . bug!("expected wide pointer extra data (e.g. slice length or trait object vtable)") . } . } . } . fn has_meta(self) -> bool { 87,933 ( 0.01%) match self { . Self::Meta(_) => true, . Self::None | Self::Poison => false, . } . } . } . . #[derive(Copy, Clone, Hash, PartialEq, Eq, HashStable, Debug)] . pub struct MemPlace { . /// The pointer can be a pure integer, with the `None` tag. 1 ( 0.00%) pub ptr: Pointer>, 2 ( 0.00%) pub align: Align, . /// Metadata for unsized places. Interpretation is up to the type. . /// Must not be present for sized types, but can be missing for unsized types . /// (e.g., `extern type`). . pub meta: MemPlaceMeta, . } . . #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] . rustc_data_structures::static_assert_size!(MemPlace, 48); -- line 68 ---------------------------------------- -- line 93 ---------------------------------------- . type Target = Place; . #[inline(always)] . fn deref(&self) -> &Place { . &self.place . } . } . . /// A MemPlace with its layout. Constructing it is only possible in this module. 7 ( 0.00%) #[derive(Copy, Clone, Hash, Eq, PartialEq, Debug)] . pub struct MPlaceTy<'tcx, Tag: Provenance = AllocId> { . mplace: MemPlace, . pub layout: TyAndLayout<'tcx>, . } . . #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] . rustc_data_structures::static_assert_size!(MPlaceTy<'_>, 64); . -- line 109 ---------------------------------------- -- line 113 ---------------------------------------- . fn deref(&self) -> &MemPlace { . &self.mplace . } . } . . impl<'tcx, Tag: Provenance> From> for PlaceTy<'tcx, Tag> { . #[inline(always)] . fn from(mplace: MPlaceTy<'tcx, Tag>) -> Self { 3,204 ( 0.00%) PlaceTy { place: Place::Ptr(mplace.mplace), layout: mplace.layout } . } . } . . impl MemPlace { . #[inline(always)] . pub fn from_ptr(ptr: Pointer>, align: Align) -> Self { . MemPlace { ptr, align, meta: MemPlaceMeta::None } . } -- line 129 ---------------------------------------- -- line 132 ---------------------------------------- . pub fn map_provenance(self, f: impl FnOnce(Option) -> Option) -> Self { . MemPlace { ptr: self.ptr.map_provenance(f), ..self } . } . . /// Turn a mplace into a (thin or wide) pointer, as a reference, pointing to the same space. . /// This is the inverse of `ref_to_mplace`. . #[inline(always)] . pub fn to_ref(self, cx: &impl HasDataLayout) -> Immediate { 860 ( 0.00%) match self.meta { 602 ( 0.00%) MemPlaceMeta::None => Immediate::from(Scalar::from_maybe_pointer(self.ptr, cx)), . MemPlaceMeta::Meta(meta) => { . Immediate::ScalarPair(Scalar::from_maybe_pointer(self.ptr, cx).into(), meta.into()) . } . MemPlaceMeta::Poison => bug!( . "MPlaceTy::dangling may never be used to produce a \ . place that will have the address of its pointee taken" . ), . } -- line 149 ---------------------------------------- -- line 177 ---------------------------------------- . #[inline] . pub fn offset( . &self, . offset: Size, . meta: MemPlaceMeta, . layout: TyAndLayout<'tcx>, . cx: &impl HasDataLayout, . ) -> InterpResult<'tcx, Self> { 730,267 ( 0.07%) Ok(MPlaceTy { mplace: self.mplace.offset(offset, meta, cx)?, layout }) . } . . #[inline] . pub fn from_aligned_ptr(ptr: Pointer>, layout: TyAndLayout<'tcx>) -> Self { 100 ( 0.00%) MPlaceTy { mplace: MemPlace::from_ptr(ptr, layout.align.abi), layout } . } . . #[inline] 84 ( 0.00%) pub(super) fn len(&self, cx: &impl HasDataLayout) -> InterpResult<'tcx, u64> { 336 ( 0.00%) if self.layout.is_unsized() { . // We need to consult `meta` metadata 168 ( 0.00%) match self.layout.ty.kind() { 28 ( 0.00%) ty::Slice(..) | ty::Str => self.mplace.meta.unwrap_meta().to_machine_usize(cx), . _ => bug!("len not supported on unsized type {:?}", self.layout.ty), . } . } else { . // Go through the layout. There are lots of types that support a length, . // e.g., SIMD types. (But not all repr(simd) types even have FieldsShape::Array!) 112 ( 0.00%) match self.layout.fields { 112 ( 0.00%) FieldsShape::Array { count, .. } => Ok(count), . _ => bug!("len not supported on sized type {:?}", self.layout.ty), . } . } 168 ( 0.00%) } . . #[inline] . pub(super) fn vtable(&self) -> Scalar { . match self.layout.ty.kind() { . ty::Dynamic(..) => self.mplace.meta.unwrap_meta(), . _ => bug!("vtable not supported on type {:?}", self.layout.ty), . } . } -- line 217 ---------------------------------------- -- line 218 ---------------------------------------- . } . . // These are defined here because they produce a place. . impl<'tcx, Tag: Provenance> OpTy<'tcx, Tag> { . #[inline(always)] . /// Note: do not call `as_ref` on the resulting place. This function should only be used to . /// read from the resulting mplace, not to get its address back. . pub fn try_as_mplace(&self) -> Result, ImmTy<'tcx, Tag>> { 176,638 ( 0.02%) match **self { 821,706 ( 0.08%) Operand::Indirect(mplace) => Ok(MPlaceTy { mplace, layout: self.layout }), . Operand::Immediate(_) if self.layout.is_zst() => Ok(MPlaceTy::dangling(self.layout)), 207,305 ( 0.02%) Operand::Immediate(imm) => Err(ImmTy::from_immediate(imm, self.layout)), . } . } . . #[inline(always)] . /// Note: do not call `as_ref` on the resulting place. This function should only be used to . /// read from the resulting mplace, not to get its address back. . pub fn assert_mem_place(&self) -> MPlaceTy<'tcx, Tag> { . self.try_as_mplace().unwrap() -- line 237 ---------------------------------------- -- line 263 ---------------------------------------- . M: Machine<'mir, 'tcx, PointerTag = Tag>, . { . /// Take a value, which represents a (thin or wide) reference, and make it a place. . /// Alignment is just based on the type. This is the inverse of `MemPlace::to_ref()`. . /// . /// Only call this if you are sure the place is "valid" (aligned and inbounds), or do not . /// want to ever use the place for memory access! . /// Generally prefer `deref_operand`. 2,000 ( 0.00%) pub fn ref_to_mplace( . &self, . val: &ImmTy<'tcx, M::PointerTag>, . ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> { . let pointee_type = 600 ( 0.00%) val.layout.ty.builtin_deref(true).expect("`ref_to_mplace` called on non-ptr type").ty; 600 ( 0.00%) let layout = self.layout_of(pointee_type)?; 1,000 ( 0.00%) let (ptr, meta) = match **val { 288 ( 0.00%) Immediate::Scalar(ptr) => (ptr, MemPlaceMeta::None), 392 ( 0.00%) Immediate::ScalarPair(ptr, meta) => (ptr, MemPlaceMeta::Meta(meta.check_init()?)), . }; . . let mplace = MemPlace { . ptr: self.scalar_to_ptr(ptr.check_init()?), . // We could use the run-time alignment here. For now, we do not, because . // the point of tracking the alignment here is to make sure that the *static* . // alignment information emitted with the loads is correct. The run-time . // alignment can only be more restrictive. 200 ( 0.00%) align: layout.align.abi, . meta, . }; 3,400 ( 0.00%) Ok(MPlaceTy { mplace, layout }) 1,800 ( 0.00%) } . . /// Take an operand, representing a pointer, and dereference it to a place -- that . /// will always be a MemPlace. Lives in `place.rs` because it creates a place. 924 ( 0.00%) pub fn deref_operand( . &self, . src: &OpTy<'tcx, M::PointerTag>, . ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> { 252 ( 0.00%) let val = self.read_immediate(src)?; . trace!("deref to {} on {:?}", val.layout.ty, *val); 168 ( 0.00%) let mplace = self.ref_to_mplace(&val)?; 420 ( 0.00%) self.check_mplace_access(mplace, CheckInAllocMsg::DerefTest)?; 924 ( 0.00%) Ok(mplace) 728 ( 0.00%) } . . #[inline] . pub(super) fn get_alloc( . &self, . place: &MPlaceTy<'tcx, M::PointerTag>, . ) -> InterpResult<'tcx, Option>> { . assert!(!place.layout.is_unsized()); 58,640 ( 0.01%) assert!(!place.meta.has_meta()); 58,640 ( 0.01%) let size = place.layout.size; 527,760 ( 0.05%) self.memory.get(place.ptr, size, place.align) . } . . #[inline] . pub(super) fn get_alloc_mut( . &mut self, . place: &MPlaceTy<'tcx, M::PointerTag>, . ) -> InterpResult<'tcx, Option>> { 29,289 ( 0.00%) assert!(!place.layout.is_unsized()); 29,289 ( 0.00%) assert!(!place.meta.has_meta()); 29,289 ( 0.00%) let size = place.layout.size; 175,734 ( 0.02%) self.memory.get_mut(place.ptr, size, place.align) . } . . /// Check if this mplace is dereferenceable and sufficiently aligned. . fn check_mplace_access( . &self, . mplace: MPlaceTy<'tcx, M::PointerTag>, . msg: CheckInAllocMsg, . ) -> InterpResult<'tcx> { . let (size, align) = self . .size_and_align_of_mplace(&mplace)? 84 ( 0.00%) .unwrap_or((mplace.layout.size, mplace.layout.align.abi)); 84 ( 0.00%) assert!(mplace.mplace.align <= align, "dynamic alignment less strict than static one?"); 84 ( 0.00%) let align = M::enforce_alignment(&self.memory.extra).then_some(align); 252 ( 0.00%) self.memory.check_ptr_access_align(mplace.ptr, size, align.unwrap_or(Align::ONE), msg)?; . Ok(()) . } . . /// Offset a pointer to project to a field of a struct/union. Unlike `place_field`, this is . /// always possible without allocating, so it can take `&self`. Also return the field's layout. . /// This supports both struct and array fields. . /// . /// This also works for arrays, but then the `usize` index type is restricting. . /// For indexing into arrays, use `mplace_index`. . #[inline(always)] . pub fn mplace_field( . &self, . base: &MPlaceTy<'tcx, M::PointerTag>, . field: usize, . ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> { 116,872 ( 0.01%) let offset = base.layout.fields.offset(field); 87,651 ( 0.01%) let field_layout = base.layout.field(self, field); . . // Offset may need adjustment for unsized fields. 146,095 ( 0.01%) let (meta, offset) = if field_layout.is_unsized() { . // Re-use parent metadata to determine dynamic field layout. . // With custom DSTS, this *will* execute user-defined code, but the same . // happens at run-time so that's okay. . match self.size_and_align_of(&base.meta, &field_layout)? { . Some((_, align)) => (base.meta, offset.align_to(align)), . None => { . // For unsized types with an extern type tail we perform no adjustments. . // NOTE: keep this in sync with `PlaceRef::project_field` in the codegen backend. -- line 369 ---------------------------------------- -- line 374 ---------------------------------------- . } else { . // base.meta could be present; we might be accessing a sized field of an unsized . // struct. . (MemPlaceMeta::None, offset) . }; . . // We do not look at `base.layout.align` nor `field_layout.align`, unlike . // codegen -- mostly to see if we can get away with that 8 ( 0.00%) base.offset(offset, meta, field_layout, self) . } . . /// Index into an array. . #[inline(always)] . pub fn mplace_index( . &self, . base: &MPlaceTy<'tcx, M::PointerTag>, . index: u64, -- line 390 ---------------------------------------- -- line 409 ---------------------------------------- . "`mplace_index` called on non-array type {:?}", . base.layout.ty . ), . } . } . . // Iterates over all fields of an array. Much more efficient than doing the . // same by repeatedly calling `mplace_array`. 840 ( 0.00%) pub(super) fn mplace_array_fields<'a>( . &self, . base: &'a MPlaceTy<'tcx, Tag>, . ) -> InterpResult<'tcx, impl Iterator>> + 'a> . { 336 ( 0.00%) let len = base.len(self)?; // also asserts that we have a type where this makes sense 252 ( 0.00%) let stride = match base.layout.fields { 84 ( 0.00%) FieldsShape::Array { stride, .. } => stride, . _ => span_bug!(self.cur_span(), "mplace_array_fields: expected an array layout"), . }; 168 ( 0.00%) let layout = base.layout.field(self, 0); 84 ( 0.00%) let dl = &self.tcx.data_layout; . // `Size` multiplication 526,350 ( 0.05%) Ok((0..len).map(move |i| base.offset(stride * i, MemPlaceMeta::None, layout, dl))) 756 ( 0.00%) } . . fn mplace_subslice( . &self, . base: &MPlaceTy<'tcx, M::PointerTag>, . from: u64, . to: u64, . from_end: bool, . ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> { -- line 439 ---------------------------------------- -- line 476 ---------------------------------------- . } . . pub(crate) fn mplace_downcast( . &self, . base: &MPlaceTy<'tcx, M::PointerTag>, . variant: VariantIdx, . ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> { . // Downcasts only change the layout 4 ( 0.00%) assert!(!base.meta.has_meta()); 18 ( 0.00%) Ok(MPlaceTy { layout: base.layout.for_variant(self, variant), ..*base }) . } . . /// Project into an mplace . pub(super) fn mplace_projection( . &self, . base: &MPlaceTy<'tcx, M::PointerTag>, . proj_elem: mir::PlaceElem<'tcx>, . ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> { -- line 493 ---------------------------------------- -- line 542 ---------------------------------------- . assert_eq!(layout.size, base.layout.size); . Ok((MPlaceTy { layout, ..*base }, len)) . } . . /// Gets the place of a field inside the place, and also the field's type. . /// Just a convenience function, but used quite a bit. . /// This is the only projection that might have a side-effect: We cannot project . /// into the field of a local `ScalarPair`, we have to first allocate it. 292,110 ( 0.03%) pub fn place_field( . &mut self, . base: &PlaceTy<'tcx, M::PointerTag>, . field: usize, . ) -> InterpResult<'tcx, PlaceTy<'tcx, M::PointerTag>> { . // FIXME: We could try to be smarter and avoid allocation for fields that span the . // entire place. 29,211 ( 0.00%) let mplace = self.force_allocation(base)?; 350,532 ( 0.04%) Ok(self.mplace_field(&mplace, field)?.into()) 233,688 ( 0.02%) } . . pub fn place_index( . &mut self, . base: &PlaceTy<'tcx, M::PointerTag>, . index: u64, . ) -> InterpResult<'tcx, PlaceTy<'tcx, M::PointerTag>> { . let mplace = self.force_allocation(base)?; . Ok(self.mplace_index(&mplace, index)?.into()) -- line 567 ---------------------------------------- -- line 586 ---------------------------------------- . . /// Projects into a place. . pub fn place_projection( . &mut self, . base: &PlaceTy<'tcx, M::PointerTag>, . &proj_elem: &mir::ProjectionElem>, . ) -> InterpResult<'tcx, PlaceTy<'tcx, M::PointerTag>> { . use rustc_middle::mir::ProjectionElem::*; 840 ( 0.00%) Ok(match proj_elem { . Field(field, _) => self.place_field(base, field.index())?, . Downcast(_, variant) => self.place_downcast(base, variant)?, 448 ( 0.00%) Deref => self.deref_operand(&self.place_to_op(base)?)?.into(), . // For the other variants, we have to force an allocation. . // This matches `operand_projection`. . Subslice { .. } | ConstantIndex { .. } | Index(_) => { . let mplace = self.force_allocation(base)?; . self.mplace_projection(&mplace, proj_elem)?.into() . } . }) . } -- line 605 ---------------------------------------- -- line 611 ---------------------------------------- . base: &PlaceTy<'tcx, M::PointerTag>, . ) -> InterpResult<'tcx, (MPlaceTy<'tcx, M::PointerTag>, u64)> { . let mplace = self.force_allocation(base)?; . self.mplace_to_simd(&mplace) . } . . /// Computes a place. You should only use this if you intend to write into this . /// place; for reading, a more efficient alternative is `eval_place_for_read`. 3,760 ( 0.00%) pub fn eval_place( . &mut self, . place: mir::Place<'tcx>, . ) -> InterpResult<'tcx, PlaceTy<'tcx, M::PointerTag>> { 2,205 ( 0.00%) let mut place_ty = PlaceTy { . // This works even for dead/uninitialized locals; we check further when writing . place: Place::Local { frame: self.frame_idx(), local: place.local }, . layout: self.layout_of_local(self.frame(), place.local, None)?, . }; . 112 ( 0.00%) for elem in place.projection.iter() { 56 ( 0.00%) place_ty = self.place_projection(&place_ty, &elem)? . } . . trace!("{:?}", self.dump_place(place_ty.place)); . // Sanity-check the type we ended up with. . debug_assert!(mir_assign_valid_types( . *self.tcx, . self.param_env, . self.layout_of(self.subst_from_current_frame_and_normalize_erasing_regions( . place.ty(&self.frame().body.local_decls, *self.tcx).ty . )?)?, . place_ty.layout, . )); 7,938 ( 0.00%) Ok(place_ty) 3,760 ( 0.00%) } . . /// Write an immediate to a place . #[inline(always)] . pub fn write_immediate( . &mut self, . src: Immediate, . dest: &PlaceTy<'tcx, M::PointerTag>, . ) -> InterpResult<'tcx> { 1,238 ( 0.00%) self.write_immediate_no_validate(src, dest)?; . . if M::enforce_validity(self) { . // Data got changed, better make sure it matches the type! . self.validate_operand(&self.place_to_op(dest)?)?; . } . . Ok(()) . } -- line 661 ---------------------------------------- -- line 678 ---------------------------------------- . dest: &PlaceTy<'tcx, M::PointerTag>, . ) -> InterpResult<'tcx> { . self.write_scalar(Scalar::from_maybe_pointer(ptr.into(), self), dest) . } . . /// Write an immediate to a place. . /// If you use this you are responsible for validating that things got copied at the . /// right type. 29,451 ( 0.00%) fn write_immediate_no_validate( . &mut self, . src: Immediate, . dest: &PlaceTy<'tcx, M::PointerTag>, . ) -> InterpResult<'tcx> { . if cfg!(debug_assertions) { . // This is a very common path, avoid some checks in release mode . assert!(!dest.layout.is_unsized(), "Cannot write unsized data"); . match src { -- line 694 ---------------------------------------- -- line 705 ---------------------------------------- . // FIXME: Can we check anything here? . } . } . } . trace!("write_immediate: {:?} <- {:?}: {}", *dest, src, dest.layout.ty); . . // See if we can avoid an allocation. This is the counterpart to `try_read_immediate`, . // but not factored as a separate function. 59,080 ( 0.01%) let mplace = match dest.place { 591 ( 0.00%) Place::Local { frame, local } => { 326 ( 0.00%) match M::access_local_mut(self, frame, local)? { . Ok(local) => { . // Local can be updated in-place. 2,286 ( 0.00%) *local = LocalValue::Live(Operand::Immediate(src)); . return Ok(()); . } . Err(mplace) => { . // The local is in memory, go on below. . mplace . } . } . } 175,734 ( 0.02%) Place::Ptr(mplace) => mplace, // already referring to memory . }; 263,601 ( 0.03%) let dest = MPlaceTy { mplace, layout: dest.layout }; . . // This is already in memory, write there. 322,179 ( 0.03%) self.write_immediate_to_mplace_no_validate(src, &dest) 58,902 ( 0.01%) } . . /// Write an immediate to memory. . /// If you use this you are responsible for validating that things got copied at the . /// right type. 292,890 ( 0.03%) fn write_immediate_to_mplace_no_validate( . &mut self, . value: Immediate, . dest: &MPlaceTy<'tcx, M::PointerTag>, . ) -> InterpResult<'tcx> { . // Note that it is really important that the type here is the right one, and matches the . // type things are read at. In case `src_val` is a `ScalarPair`, we don't do any magic here . // to handle padding properly, which is only correct if we never look at this data with the . // wrong type. . . // Invalid places are a thing: the return place of a diverging function 29,289 ( 0.00%) let tcx = *self.tcx; 58,578 ( 0.01%) let mut alloc = match self.get_alloc_mut(dest)? { 146,445 ( 0.01%) Some(a) => a, . None => return Ok(()), // zero-sized access . }; . . // FIXME: We should check that there are dest.layout.size many bytes available in . // memory. The code below is not sufficient, with enough padding it might not . // cover all the bytes! 58,578 ( 0.01%) match value { . Immediate::Scalar(scalar) => { 58,522 ( 0.01%) match dest.layout.abi { . Abi::Scalar(_) => {} // fine . _ => span_bug!( . self.cur_span(), . "write_immediate_to_mplace: invalid Scalar layout: {:#?}", . dest.layout . ), . } 263,349 ( 0.03%) alloc.write_scalar(alloc_range(Size::ZERO, dest.layout.size), scalar) . } . Immediate::ScalarPair(a_val, b_val) => { . // We checked `ptr_align` above, so all fields will have the alignment they need. . // We would anyway check against `ptr_align.restrict_for_offset(b_offset)`, . // which `ptr.offset(b_offset)` cannot possibly fail to satisfy. 56 ( 0.00%) let (a, b) = match dest.layout.abi { 84 ( 0.00%) Abi::ScalarPair(a, b) => (a.value, b.value), . _ => span_bug!( . self.cur_span(), . "write_immediate_to_mplace: invalid ScalarPair layout: {:#?}", . dest.layout . ), . }; . let (a_size, b_size) = (a.size(&tcx), b.size(&tcx)); . let b_offset = a_size.align_to(b.align(&tcx).abi); . . // It is tempting to verify `b_offset` against `layout.fields.offset(1)`, . // but that does not work: We could be a newtype around a pair, then the . // fields do not match the `ScalarPair` components. . 280 ( 0.00%) alloc.write_scalar(alloc_range(Size::ZERO, a_size), a_val)?; 224 ( 0.00%) alloc.write_scalar(alloc_range(b_offset, b_size), b_val) . } . } 234,312 ( 0.02%) } . . /// Copies the data from an operand to a place. This does not support transmuting! . /// Use `copy_op_transmute` if the layouts could disagree. . #[inline(always)] . pub fn copy_op( . &mut self, . src: &OpTy<'tcx, M::PointerTag>, . dest: &PlaceTy<'tcx, M::PointerTag>, . ) -> InterpResult<'tcx> { 176,196 ( 0.02%) self.copy_op_no_validate(src, dest)?; . . if M::enforce_validity(self) { . // Data got changed, better make sure it matches the type! . self.validate_operand(&self.place_to_op(dest)?)?; . } . . Ok(()) . } . . /// Copies the data from an operand to a place. This does not support transmuting! . /// Use `copy_op_transmute` if the layouts could disagree. . /// Also, if you use this you are responsible for validating that things get copied at the . /// right type. 234,680 ( 0.02%) fn copy_op_no_validate( . &mut self, . src: &OpTy<'tcx, M::PointerTag>, . dest: &PlaceTy<'tcx, M::PointerTag>, . ) -> InterpResult<'tcx> { . // We do NOT compare the types for equality, because well-typed code can . // actually "transmute" `&mut T` to `&T` in an assignment without a cast. 529,098 ( 0.05%) if !mir_assign_valid_types(*self.tcx, self.param_env, src.layout, dest.layout) { . span_bug!( . self.cur_span(), . "type mismatch when copying!\nsrc: {:?},\ndest: {:?}", . src.layout.ty, . dest.layout.ty, . ); . } . . // Let us see if the layout is simple so we take a shortcut, avoid force_allocation. 147,031 ( 0.01%) let src = match self.try_read_immediate(src)? { . Ok(src_val) => { 29,424 ( 0.00%) assert!(!src.layout.is_unsized(), "cannot have unsized immediates"); . // Yay, we got a value that we can write directly. . // FIXME: Add a check to make sure that if `src` is indirect, . // it does not overlap with `dest`. 381,355 ( 0.04%) return self.write_immediate_no_validate(*src_val, dest); . } . Err(mplace) => mplace, . }; . // Slow path, this does not fit into an immediate. Just memcpy. . trace!("copy_op: {:?} <- {:?}: {}", *dest, src, dest.layout.ty); . . // This interprets `src.meta` with the `dest` local's layout, if an unsized local . // is being initialized! -- line 848 ---------------------------------------- -- line 853 ---------------------------------------- . "Cannot copy into already initialized unsized place" . ); . dest.layout.size . }); . assert_eq!(src.meta, dest.meta, "Can only copy between equally-sized instances"); . . self.memory . .copy(src.ptr, src.align, dest.ptr, dest.align, size, /*nonoverlapping*/ true) 234,680 ( 0.02%) } . . /// Copies the data from an operand to a place. The layouts may disagree, but they must . /// have the same size. 624 ( 0.00%) pub fn copy_op_transmute( . &mut self, . src: &OpTy<'tcx, M::PointerTag>, . dest: &PlaceTy<'tcx, M::PointerTag>, . ) -> InterpResult<'tcx> { 1,404 ( 0.00%) if mir_assign_valid_types(*self.tcx, self.param_env, src.layout, dest.layout) { . // Fast path: Just use normal `copy_op` . return self.copy_op(src, dest); . } . // We still require the sizes to match. . if src.layout.size != dest.layout.size { . // FIXME: This should be an assert instead of an error, but if we transmute within an . // array length computation, `typeck` may not have yet been run and errored out. In fact . // most likey we *are* running `typeck` right now. Investigate whether we can bail out -- line 878 ---------------------------------------- -- line 916 ---------------------------------------- . /// Ensures that a place is in memory, and returns where it is. . /// If the place currently refers to a local that doesn't yet have a matching allocation, . /// create such an allocation. . /// This is essentially `force_to_memplace`. . /// . /// This supports unsized types and returns the computed size to avoid some . /// redundant computation when copying; use `force_allocation` for a simpler, sized-only . /// version. 263,673 ( 0.03%) pub fn force_allocation_maybe_sized( . &mut self, . place: &PlaceTy<'tcx, M::PointerTag>, . meta: MemPlaceMeta, . ) -> InterpResult<'tcx, (MPlaceTy<'tcx, M::PointerTag>, Option)> { 292,970 ( 0.03%) let (mplace, size) = match place.place { 29,241 ( 0.00%) Place::Local { frame, local } => { 58,482 ( 0.01%) match M::access_local_mut(self, frame, local)? { 270 ( 0.00%) Ok(&mut local_val) => { . // We need to make an allocation. . . // We need the layout of the local. We can NOT use the layout we got, . // that might e.g., be an inner field of a struct with `Scalar` layout, . // that has different alignment than the outer field. . let local_layout = 150 ( 0.00%) self.layout_of_local(&self.stack()[frame], local, None)?; . // We also need to support unsized types, and hence cannot use `allocate`. 120 ( 0.00%) let (size, align) = self . .size_and_align_of(&meta, &local_layout)? . .expect("Cannot allocate for non-dyn-sized type"); 210 ( 0.00%) let ptr = self.memory.allocate(size, align, MemoryKind::Stack)?; . let mplace = MemPlace { ptr: ptr.into(), align, meta }; 150 ( 0.00%) if let LocalValue::Live(Operand::Immediate(value)) = local_val { . // Preserve old value. . // We don't have to validate as we can assume the local . // was already valid for its type. . let mplace = MPlaceTy { mplace, layout: local_layout }; . self.write_immediate_to_mplace_no_validate(value, &mplace)?; . } . // Now we can call `access_mut` again, asserting it goes well, . // and actually overwrite things. 570 ( 0.00%) *M::access_local_mut(self, frame, local).unwrap().unwrap() = . LocalValue::Live(Operand::Indirect(mplace)); 210 ( 0.00%) (mplace, Some(size)) . } 292,110 ( 0.03%) Err(mplace) => (mplace, None), // this already was an indirect local . } . } 728 ( 0.00%) Place::Ptr(mplace) => (mplace, None), . }; . // Return with the original layout, so that the caller can go on 351,564 ( 0.04%) Ok((MPlaceTy { mplace, layout: place.layout }, size)) 234,376 ( 0.02%) } . . #[inline(always)] . pub fn force_allocation( . &mut self, . place: &PlaceTy<'tcx, M::PointerTag>, . ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> { 263,415 ( 0.03%) Ok(self.force_allocation_maybe_sized(place, MemPlaceMeta::None)?.0) . } . 288 ( 0.00%) pub fn allocate( . &mut self, . layout: TyAndLayout<'tcx>, . kind: MemoryKind, . ) -> InterpResult<'static, MPlaceTy<'tcx, M::PointerTag>> { 762 ( 0.00%) let ptr = self.memory.allocate(layout.size, layout.align.abi, kind)?; 216 ( 0.00%) Ok(MPlaceTy::from_aligned_ptr(ptr.into(), layout)) 252 ( 0.00%) } . . /// Returns a wide MPlace of type `&'static [mut] str` to a new 1-aligned allocation. . pub fn allocate_str( . &mut self, . str: &str, . kind: MemoryKind, . mutbl: Mutability, . ) -> MPlaceTy<'tcx, M::PointerTag> { -- line 991 ---------------------------------------- -- line 998 ---------------------------------------- . self.tcx.lifetimes.re_static, . ty::TypeAndMut { ty: self.tcx.types.str_, mutbl }, . ); . let layout = self.layout_of(ty).unwrap(); . MPlaceTy { mplace, layout } . } . . /// Writes the discriminant of the given variant. 22 ( 0.00%) pub fn write_discriminant( . &mut self, . variant_index: VariantIdx, . dest: &PlaceTy<'tcx, M::PointerTag>, . ) -> InterpResult<'tcx> { . // This must be an enum or generator. 8 ( 0.00%) match dest.layout.ty.kind() { 4 ( 0.00%) ty::Adt(adt, _) => assert!(adt.is_enum()), . ty::Generator(..) => {} . _ => span_bug!( . self.cur_span(), . "write_discriminant called on non-variant-type (neither enum nor generator)" . ), . } . // Layout computation excludes uninhabited variants from consideration . // therefore there's no way to represent those variants in the given layout. . // Essentially, uninhabited variants do not have a tag that corresponds to their . // discriminant, so we cannot do anything here. . // When evaluating we will always error before even getting here, but ConstProp 'executes' . // dead code, so we cannot ICE here. 4 ( 0.00%) if dest.layout.for_variant(self, variant_index).abi.is_uninhabited() { . throw_ub!(UninhabitedEnumVariantWritten) . } . 10 ( 0.00%) match dest.layout.variants { . Variants::Single { index } => { . assert_eq!(index, variant_index); . } . Variants::Multiple { . tag_encoding: TagEncoding::Direct, 6 ( 0.00%) tag: tag_layout, 4 ( 0.00%) tag_field, . .. . } => { . // No need to validate that the discriminant here because the . // `TyAndLayout::for_variant()` call earlier already checks the variant is valid. . . let discr_val = 8 ( 0.00%) dest.layout.ty.discriminant_for_variant(*self.tcx, variant_index).unwrap().val; . . // raw discriminants for enums are isize or bigger during . // their computation, but the in-memory tag is the smallest possible . // representation . let size = tag_layout.value.size(self); . let tag_val = size.truncate(discr_val); . 10 ( 0.00%) let tag_dest = self.place_field(dest, tag_field)?; . self.write_scalar(Scalar::from_uint(tag_val, size), &tag_dest)?; . } . Variants::Multiple { . tag_encoding: . TagEncoding::Niche { dataful_variant, ref niche_variants, niche_start }, . tag: tag_layout, . tag_field, . .. -- line 1060 ---------------------------------------- -- line 1082 ---------------------------------------- . // Write result. . let niche_dest = self.place_field(dest, tag_field)?; . self.write_immediate(*tag_val, &niche_dest)?; . } . } . } . . Ok(()) 16 ( 0.00%) } . 450 ( 0.00%) pub fn raw_const_to_mplace( . &self, . raw: ConstAlloc<'tcx>, . ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> { . // This must be an allocation in `tcx` 150 ( 0.00%) let _ = self.tcx.global_alloc(raw.alloc_id); . let ptr = self.global_base_pointer(Pointer::from(raw.alloc_id))?; 150 ( 0.00%) let layout = self.layout_of(raw.ty)?; 300 ( 0.00%) Ok(MPlaceTy::from_aligned_ptr(ptr.into(), layout)) 350 ( 0.00%) } . . /// Turn a place with a `dyn Trait` type into a place with the actual dynamic type. . /// Also return some more information so drop doesn't have to run the same code twice. . pub(super) fn unpack_dyn_trait( . &self, . mplace: &MPlaceTy<'tcx, M::PointerTag>, . ) -> InterpResult<'tcx, (ty::Instance<'tcx>, MPlaceTy<'tcx, M::PointerTag>)> { . let vtable = self.scalar_to_ptr(mplace.vtable()); // also sanity checks the type -- line 1109 ---------------------------------------- 354,450 ( 0.04%) -------------------------------------------------------------------------------- -- Auto-annotated source: /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/stacker-0.1.14/src/lib.rs -------------------------------------------------------------------------------- Ir -- line 42 ---------------------------------------- . /// `stack_size` bytes. . /// . /// The closure `f` is guaranteed to run on a stack with at least `red_zone` bytes, and it will be . /// run on the current stack if there's space available. . #[inline(always)] . pub fn maybe_grow R>(red_zone: usize, stack_size: usize, callback: F) -> R { . // if we can't guess the remaining stack (unsupported on some platforms) we immediately grow . // the stack and then cache the new stack size (which we do know now because we allocated it. 203,642 ( 0.02%) let enough_space = match remaining_stack() { . Some(remaining) => remaining >= red_zone, . None => false, . }; 299,913 ( 0.03%) if enough_space { 2,267 ( 0.00%) callback() . } else { . grow(stack_size, callback) . } . } . . /// Always creates a new stack for the passed closure to run on. . /// The closure will still be on the same thread as the caller of `grow`. . /// This will allocate a new stack with at least `stack_size` bytes. -- line 63 ---------------------------------------- -- line 82 ---------------------------------------- . _grow(stack_size, dyn_callback); . ret.unwrap() . } . . /// Queries the amount of remaining stack as interpreted by this library. . /// . /// This function will return the amount of stack space left which will be used . /// to determine whether a stack switch should be made or not. 199,942 ( 0.02%) pub fn remaining_stack() -> Option { . let current_ptr = current_stack_ptr(); 199,942 ( 0.02%) get_stack_limit().map(|limit| current_ptr - limit) 399,884 ( 0.04%) } . . psm_stack_information! ( . yes { . fn current_stack_ptr() -> usize { 199,942 ( 0.02%) psm::stack_pointer() as usize . } . } . no { . #[inline(always)] . fn current_stack_ptr() -> usize { . unsafe { . let mut x = std::mem::MaybeUninit::::uninit(); . // Unlikely to be ever exercised. As a fallback we execute a volatile read to a -- line 106 ---------------------------------------- -- line 111 ---------------------------------------- . x.as_ptr() as usize . } . } . } . ); . . thread_local! { . static STACK_LIMIT: Cell> = Cell::new(unsafe { 1 ( 0.00%) guess_os_stack_limit() . }) . } . . #[inline(always)] . fn get_stack_limit() -> Option { . STACK_LIMIT.with(|s| s.get()) . } . -- line 127 ---------------------------------------- -- line 403 ---------------------------------------- . VirtualQuery( . psm::stack_pointer() as *const _, . mi.as_mut_ptr(), . std::mem::size_of::() as SIZE_T, . ); . Some(mi.assume_init().AllocationBase as usize + get_thread_stack_guarantee() + 0x1000) . } . } else if #[cfg(any(target_os = "linux", target_os="solaris", target_os = "netbsd"))] { 2 ( 0.00%) unsafe fn guess_os_stack_limit() -> Option { . let mut attr = std::mem::MaybeUninit::::uninit(); 4 ( 0.00%) assert_eq!(libc::pthread_attr_init(attr.as_mut_ptr()), 0); 7 ( 0.00%) assert_eq!(libc::pthread_getattr_np(libc::pthread_self(), . attr.as_mut_ptr()), 0); 1 ( 0.00%) let mut stackaddr = std::ptr::null_mut(); 4 ( 0.00%) let mut stacksize = 0; 4 ( 0.00%) assert_eq!(libc::pthread_attr_getstack( . attr.as_ptr(), &mut stackaddr, &mut stacksize . ), 0); 4 ( 0.00%) assert_eq!(libc::pthread_attr_destroy(attr.as_mut_ptr()), 0); 1 ( 0.00%) Some(stackaddr as usize) 3 ( 0.00%) } . } else if #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] { . unsafe fn guess_os_stack_limit() -> Option { . let mut attr = std::mem::MaybeUninit::::uninit(); . assert_eq!(libc::pthread_attr_init(attr.as_mut_ptr()), 0); . assert_eq!(libc::pthread_attr_get_np(libc::pthread_self(), attr.as_mut_ptr()), 0); . let mut stackaddr = std::ptr::null_mut(); . let mut stacksize = 0; . assert_eq!(libc::pthread_attr_getstack( -- line 431 ---------------------------------------- 189,780 ( 0.02%) -------------------------------------------------------------------------------- -- Auto-annotated source: /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs -------------------------------------------------------------------------------- Ir -- line 40 ---------------------------------------- . . use std::collections::hash_map::Entry; . use std::iter; . use std::slice; . . impl<'a, 'tcx> FnCtxt<'a, 'tcx> { . /// Produces warning on the given node, if the current point in the . /// function is unreachable, and there hasn't been another warning. 531,288 ( 0.05%) pub(in super::super) fn warn_if_unreachable(&self, id: hir::HirId, span: Span, kind: &str) { . // FIXME: Combine these two 'if' expressions into one once . // let chains are implemented 118,182 ( 0.01%) if let Diverges::Always { span: orig_span, custom_note } = self.diverges.get() { . // If span arose from a desugaring of `if` or `while`, then it is the condition itself, . // which diverges, that we are about to lint on. This gives suboptimal diagnostics. . // Instead, stop here so that the `if`- or `while`-expression's block is linted instead. . if !span.is_desugaring(DesugaringKind::CondTemporary) . && !span.is_desugaring(DesugaringKind::Async) . && !orig_span.is_desugaring(DesugaringKind::Await) . { . self.diverges.set(Diverges::WarnedAlways); -- line 59 ---------------------------------------- -- line 68 ---------------------------------------- . orig_span, . custom_note . .unwrap_or("any code following this expression is unreachable"), . ) . .emit(); . }) . } . } 413,224 ( 0.04%) } . . /// Resolves type and const variables in `ty` if possible. Unlike the infcx . /// version (resolve_vars_if_possible), this version will . /// also select obligations if it seems useful, in an effort . /// to get more type information. 412,601 ( 0.04%) pub(in super::super) fn resolve_vars_with_obligations(&self, ty: Ty<'tcx>) -> Ty<'tcx> { . self.resolve_vars_with_obligations_and_mutate_fulfillment(ty, |_| {}) 471,544 ( 0.05%) } . . #[instrument(skip(self, mutate_fulfillment_errors), level = "debug")] . pub(in super::super) fn resolve_vars_with_obligations_and_mutate_fulfillment( . &self, . mut ty: Ty<'tcx>, . mutate_fulfillment_errors: impl Fn(&mut Vec>), . ) -> Ty<'tcx> { . // No Infer()? Nothing needs doing. 59,000 ( 0.01%) if !ty.has_infer_types_or_consts() { . debug!("no inference var, nothing needs doing"); . return ty; . } . . // If `ty` is a type variable, see whether we already know what it is. . ty = self.resolve_vars_if_possible(ty); 11 ( 0.00%) if !ty.has_infer_types_or_consts() { . debug!(?ty); . return ty; . } . . // If not, try resolving pending obligations as much as . // possible. This can help substantially when there are . // indirect dependencies that don't seem worth tracking . // precisely. -- line 108 ---------------------------------------- -- line 129 ---------------------------------------- . let mut deferred_call_resolutions = self.deferred_call_resolutions.borrow_mut(); . deferred_call_resolutions.remove(&closure_def_id).unwrap_or_default() . } . . pub fn tag(&self) -> String { . format!("{:p}", self) . } . 490 ( 0.00%) pub fn local_ty(&self, span: Span, nid: hir::HirId) -> LocalTy<'tcx> { . self.locals.borrow().get(&nid).cloned().unwrap_or_else(|| { . span_bug!(span, "no type for local variable {}", self.tcx.hir().node_to_string(nid)) . }) 588 ( 0.00%) } . . #[inline] 207,718 ( 0.02%) pub fn write_ty(&self, id: hir::HirId, ty: Ty<'tcx>) { . debug!("write_ty({:?}, {:?}) in fcx {}", id, self.resolve_vars_if_possible(ty), self.tag()); 59,494 ( 0.01%) self.typeck_results.borrow_mut().node_types_mut().insert(id, ty); . 29,747 ( 0.00%) if ty.references_error() { . self.has_errors.set(true); . self.set_tainted_by_errors(); . } 237,392 ( 0.02%) } . . pub fn write_field_index(&self, hir_id: hir::HirId, index: usize) { . self.typeck_results.borrow_mut().field_indices_mut().insert(hir_id, index); . } . . pub(in super::super) fn write_resolution( . &self, . hir_id: hir::HirId, . r: Result<(DefKind, DefId), ErrorReported>, . ) { 31 ( 0.00%) self.typeck_results.borrow_mut().type_dependent_defs_mut().insert(hir_id, r); . } . 279 ( 0.00%) pub fn write_method_call(&self, hir_id: hir::HirId, method: MethodCallee<'tcx>) { . debug!("write_method_call(hir_id={:?}, method={:?})", hir_id, method); 62 ( 0.00%) self.write_resolution(hir_id, Ok((DefKind::AssocFn, method.def_id))); 217 ( 0.00%) self.write_substs(hir_id, method.substs); . . // When the method is confirmed, the `method.substs` includes . // parameters from not just the method, but also the impl of . // the method -- in particular, the `Self` type will be fully . // resolved. However, those are not something that the "user . // specified" -- i.e., those types come from the inferred type . // of the receiver, not something the user wrote. So when we . // create the user-substs, we want to replace those earlier . // types with just the types that the user actually wrote -- . // that is, those that appear on the *method itself*. . // . // As an example, if the user wrote something like . // `foo.bar::(...)` -- the `Self` type here will be the . // type of `foo` (possibly adjusted), but we don't want to . // include that. We want just the `[_, u32]` part. 31 ( 0.00%) if !method.substs.is_empty() { 31 ( 0.00%) let method_generics = self.tcx.generics_of(method.def_id); 62 ( 0.00%) if !method_generics.params.is_empty() { . let user_type_annotation = self.infcx.probe(|_| { . let user_substs = UserSubsts { . substs: InternalSubsts::for_item(self.tcx, method.def_id, |param, _| { . let i = param.index as usize; . if i < method_generics.parent_count { . self.infcx.var_for_def(DUMMY_SP, param) . } else { . method.substs[i] -- line 195 ---------------------------------------- -- line 203 ---------------------------------------- . user_substs, . )) . }); . . debug!("write_method_call: user_type_annotation={:?}", user_type_annotation); . self.write_user_type_annotation(hir_id, user_type_annotation); . } . } 248 ( 0.00%) } . 522 ( 0.00%) pub fn write_substs(&self, node_id: hir::HirId, substs: SubstsRef<'tcx>) { 87 ( 0.00%) if !substs.is_empty() { . debug!("write_substs({:?}, {:?}) in fcx {}", node_id, substs, self.tag()); . 62 ( 0.00%) self.typeck_results.borrow_mut().node_substs_mut().insert(node_id, substs); . } 609 ( 0.00%) } . . /// Given the substs that we just converted from the HIR, try to . /// canonicalize them and store them as user-given substitutions . /// (i.e., substitutions that must be respected by the NLL check). . /// . /// This should be invoked **before any unifications have . /// occurred**, so that annotations like `Vec<_>` are preserved . /// properly. -- line 227 ---------------------------------------- -- line 258 ---------------------------------------- . .borrow_mut() . .user_provided_types_mut() . .insert(hir_id, canonical_user_type_annotation); . } else { . debug!("skipping identity substs"); . } . } . 4,930 ( 0.00%) #[instrument(skip(self, expr), level = "debug")] . pub fn apply_adjustments(&self, expr: &hir::Expr<'_>, adj: Vec>) { . debug!("expr = {:#?}", expr); . 290 ( 0.00%) if adj.is_empty() { . return; . } . . for a in &adj { 178 ( 0.00%) if let Adjust::NeverToAny = a.kind { . if a.target.is_ty_var() { . self.diverging_type_vars.borrow_mut().insert(a.target); . debug!("apply_adjustments: adding `{:?}` as diverging type var", a.target); . } . } . } . . let autoborrow_mut = adj.iter().any(|adj| { 364 ( 0.00%) matches!( 31 ( 0.00%) adj, . &Adjustment { . kind: Adjust::Borrow(AutoBorrow::Ref(_, AutoBorrowMutability::Mut { .. })), . .. . } . ) . }); . 186 ( 0.00%) match self.typeck_results.borrow_mut().adjustments_mut().entry(expr.hir_id) { . Entry::Vacant(entry) => { . entry.insert(adj); . } . Entry::Occupied(mut entry) => { . debug!(" - composing on top of {:?}", entry.get()); . match (&entry.get()[..], &adj[..]) { . // Applying any adjustment on top of a NeverToAny . // is a valid NeverToAny adjustment, because it can't -- line 301 ---------------------------------------- -- line 324 ---------------------------------------- . }; . *entry.get_mut() = adj; . } . } . . // If there is an mutable auto-borrow, it is equivalent to `&mut `. . // In this case implicit use of `Deref` and `Index` within `` should . // instead be `DerefMut` and `IndexMut`, so fix those up. 93 ( 0.00%) if autoborrow_mut { . self.convert_place_derefs_to_mutable(expr); . } . } . . /// Basically whenever we are converting from a type scheme into . /// the fn body space, we always want to normalize associated . /// types as well. This function combines the two. . fn instantiate_type_scheme(&self, span: Span, substs: SubstsRef<'tcx>, value: T) -> T . where . T: TypeFoldable<'tcx>, . { . debug!("instantiate_type_scheme(value={:?}, substs={:?})", value, substs); 56 ( 0.00%) let value = value.subst(self.tcx, substs); . let result = self.normalize_associated_types_in(span, value); . debug!("instantiate_type_scheme = {:?}", result); . result . } . . /// As `instantiate_type_scheme`, but for the bounds found in a . /// generic type scheme. . pub(in super::super) fn instantiate_bounds( . &self, . span: Span, . def_id: DefId, . substs: SubstsRef<'tcx>, . ) -> (ty::InstantiatedPredicates<'tcx>, Vec) { 56 ( 0.00%) let bounds = self.tcx.predicates_of(def_id); . let spans: Vec = bounds.predicates.iter().map(|(_, span)| *span).collect(); 224 ( 0.00%) let result = bounds.instantiate(self.tcx, substs); . let result = self.normalize_associated_types_in(span, result); . debug!( . "instantiate_bounds(bounds={:?}, substs={:?}) = {:?}, {:?}", . bounds, substs, result, spans, . ); 336 ( 0.00%) (result, spans) . } . . /// Replaces the opaque types from the given value with type variables, . /// and records the `OpaqueTypeMap` for later use during writeback. See . /// `InferCtxt::instantiate_opaque_types` for more details. 288 ( 0.00%) #[instrument(skip(self, value_span), level = "debug")] 252 ( 0.00%) pub(in super::super) fn instantiate_opaque_types_from_value>( . &self, . value: T, . value_span: Span, . ) -> T { . self.register_infer_ok_obligations(self.instantiate_opaque_types( 36 ( 0.00%) self.body_id, 36 ( 0.00%) self.param_env, . value, . value_span, . )) . } . . /// Convenience method which tracks extra diagnostic information for normalization . /// that occurs as a result of WF checking. The `hir_id` is the `HirId` of the hir item . /// whose type is being wf-checked - this is used to construct a more precise span if -- line 389 ---------------------------------------- -- line 395 ---------------------------------------- . &self, . span: Span, . value: T, . loc: WellFormedLoc, . ) -> T . where . T: TypeFoldable<'tcx>, . { 527 ( 0.00%) self.inh.normalize_associated_types_in_with_cause( 314 ( 0.00%) ObligationCause::new(span, self.body_id, ObligationCauseCode::WellFormed(Some(loc))), 572 ( 0.00%) self.param_env, . value, . ) . } . . pub(in super::super) fn normalize_associated_types_in(&self, span: Span, value: T) -> T . where . T: TypeFoldable<'tcx>, . { 6,878 ( 0.00%) self.inh.normalize_associated_types_in(span, self.body_id, self.param_env, value) . } . . pub(in super::super) fn normalize_associated_types_in_as_infer_ok( . &self, . span: Span, . value: T, . ) -> InferOk<'tcx, T> . where -- line 422 ---------------------------------------- -- line 431 ---------------------------------------- . . pub fn require_type_meets( . &self, . ty: Ty<'tcx>, . span: Span, . code: traits::ObligationCauseCode<'tcx>, . def_id: DefId, . ) { 2,371 ( 0.00%) self.register_bound(ty, def_id, traits::ObligationCause::new(span, self.body_id, code)); . } . 808 ( 0.00%) pub fn require_type_is_sized( . &self, . ty: Ty<'tcx>, . span: Span, . code: traits::ObligationCauseCode<'tcx>, . ) { 185 ( 0.00%) if !ty.references_error() { 925 ( 0.00%) let lang_item = self.tcx.require_lang_item(LangItem::Sized, None); . self.require_type_meets(ty, span, code, lang_item); . } 808 ( 0.00%) } . 420 ( 0.00%) pub fn require_type_is_sized_deferred( . &self, . ty: Ty<'tcx>, . span: Span, . code: traits::ObligationCauseCode<'tcx>, . ) { 84 ( 0.00%) if !ty.references_error() { 672 ( 0.00%) self.deferred_sized_obligations.borrow_mut().push((ty, span, code)); . } 420 ( 0.00%) } . 1,205 ( 0.00%) pub fn register_bound( . &self, . ty: Ty<'tcx>, . def_id: DefId, . cause: traits::ObligationCause<'tcx>, . ) { 241 ( 0.00%) if !ty.references_error() { 1,687 ( 0.00%) self.fulfillment_cx.borrow_mut().register_bound( . self, 241 ( 0.00%) self.param_env, . ty, . def_id, 964 ( 0.00%) cause, . ); . } 1,205 ( 0.00%) } . . pub fn to_ty(&self, ast_t: &hir::Ty<'_>) -> Ty<'tcx> { . let t = >::ast_ty_to_ty(self, ast_t); . self.register_wf_obligation(t.into(), ast_t.span, traits::MiscObligation); . t . } . . pub fn to_ty_saving_user_provided_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> { -- line 488 ---------------------------------------- -- line 543 ---------------------------------------- . // sufficiently enforced with erased regions. =) . fn can_contain_user_lifetime_bounds(t: T) -> bool . where . T: TypeFoldable<'tcx>, . { . t.has_free_regions() || t.has_projections() || t.has_infer_types() . } . 208,572 ( 0.02%) pub fn node_ty(&self, id: hir::HirId) -> Ty<'tcx> { 297,960 ( 0.03%) match self.typeck_results.borrow().node_types().get(id) { 59,592 ( 0.01%) Some(&t) => t, . None if self.is_tainted_by_errors() => self.tcx.ty_error(), . None => { . bug!( . "no type for node {}: {} in fcx {}", . id, . self.tcx.hir().node_to_string(id), . self.tag() . ); . } . } 178,776 ( 0.02%) } . . pub fn node_ty_opt(&self, id: hir::HirId) -> Option> { . match self.typeck_results.borrow().node_types().get(id) { . Some(&t) => Some(t), . None if self.is_tainted_by_errors() => Some(self.tcx.ty_error()), . None => None, . } . } . . /// Registers an obligation for checking later, during regionck, that `arg` is well-formed. 3,050 ( 0.00%) pub fn register_wf_obligation( . &self, . arg: subst::GenericArg<'tcx>, . span: Span, . code: traits::ObligationCauseCode<'tcx>, . ) { . // WF obligations never themselves fail, so no real need to give a detailed cause: 2,745 ( 0.00%) let cause = traits::ObligationCause::new(span, self.body_id, code); 305 ( 0.00%) self.register_predicate(traits::Obligation::new( 1,220 ( 0.00%) cause, 305 ( 0.00%) self.param_env, 1,220 ( 0.00%) ty::Binder::dummy(ty::PredicateKind::WellFormed(arg)).to_predicate(self.tcx), . )); 2,440 ( 0.00%) } . . /// Registers obligations that all `substs` are well-formed. . pub fn add_wf_bounds(&self, substs: SubstsRef<'tcx>, expr: &hir::Expr<'_>) { 740 ( 0.00%) for arg in substs.iter().filter(|arg| { . matches!(arg.unpack(), GenericArgKind::Type(..) | GenericArgKind::Const(..)) . }) { 192 ( 0.00%) self.register_wf_obligation(arg, expr.span, traits::MiscObligation); . } . } . . // FIXME(arielb1): use this instead of field.ty everywhere . // Only for fields! Returns for methods> . // Indifferent to privacy flags . pub fn field_ty( . &self, . span: Span, . field: &'tcx ty::FieldDef, . substs: SubstsRef<'tcx>, . ) -> Ty<'tcx> { . self.normalize_associated_types_in(span, &field.ty(self.tcx, substs)) . } . 576 ( 0.00%) pub(in super::super) fn resolve_generator_interiors(&self, def_id: DefId) { . let mut generators = self.deferred_generator_interiors.borrow_mut(); 448 ( 0.00%) for (body_id, interior, kind) in generators.drain(..) { . self.select_obligations_where_possible(false, |_| {}); . crate::check::generator_interior::resolve_interior( . self, def_id, body_id, interior, kind, . ); . } 512 ( 0.00%) } . 3,942 ( 0.00%) #[instrument(skip(self), level = "debug")] . pub(in super::super) fn select_all_obligations_or_error(&self) { 1,314 ( 0.00%) let errors = self.fulfillment_cx.borrow_mut().select_all_or_error(&self); . 438 ( 0.00%) if !errors.is_empty() { . self.report_fulfillment_errors(&errors, self.inh.body_id, false); . } . } . . /// Select as many obligations as we can at present. 320 ( 0.00%) pub(in super::super) fn select_obligations_where_possible( . &self, . fallback_has_occurred: bool, . mutate_fulfillment_errors: impl Fn(&mut Vec>), . ) { 620 ( 0.00%) let mut result = self.fulfillment_cx.borrow_mut().select_where_possible(self); 187 ( 0.00%) if !result.is_empty() { . mutate_fulfillment_errors(&mut result); . self.report_fulfillment_errors(&result, self.inh.body_id, fallback_has_occurred); . } 384 ( 0.00%) } . . /// For the overloaded place expressions (`*x`, `x[3]`), the trait . /// returns a type of `&T`, but the actual type we assign to the . /// *expression* is `T`. So this function just peels off the return . /// type by one layer to yield `T`. . pub(in super::super) fn make_overloaded_place_return_type( . &self, . method: MethodCallee<'tcx>, -- line 649 ---------------------------------------- -- line 739 ---------------------------------------- . #[instrument(skip(self, call_span), level = "debug")] . pub(in super::super) fn expected_inputs_for_expected_output( . &self, . call_span: Span, . expected_ret: Expectation<'tcx>, . formal_ret: Ty<'tcx>, . formal_args: &[Ty<'tcx>], . ) -> Vec> { 236 ( 0.00%) let formal_ret = self.resolve_vars_with_obligations(formal_ret); . let ret_ty = match expected_ret.only_has_type(self) { 58 ( 0.00%) Some(ret) => ret, . None => return Vec::new(), . }; 58 ( 0.00%) let expect_args = self 638 ( 0.00%) .fudge_inference_if_ok(|| { . // Attempt to apply a subtyping relationship between the formal . // return type (likely containing type variables if the function . // is polymorphic) and the expected return type. . // No argument expectations are produced if unification fails. 58 ( 0.00%) let origin = self.misc(call_span); 232 ( 0.00%) let ures = self.at(&origin, self.param_env).sup(ret_ty, &formal_ret); . . // FIXME(#27336) can't use ? here, Try::from_error doesn't default . // to identity so the resulting type is not constrained. 174 ( 0.00%) match ures { . Ok(ok) => { . // Process any obligations locally as much as . // we can. We don't care if some things turn . // out unconstrained or ambiguous, as we're . // just trying to get hints here. . let errors = self.save_and_restore_in_snapshot_flag(|_| { 348 ( 0.00%) let mut fulfill = >::new(self.tcx); 232 ( 0.00%) for obligation in ok.obligations { . fulfill.register_predicate_obligation(self, obligation); . } 116 ( 0.00%) fulfill.select_where_possible(self) . }); . 58 ( 0.00%) if !errors.is_empty() { . return Err(()); . } . } . Err(_) => return Err(()), . } . . // Record all the argument types, with the substitutions . // produced from the above subtyping unification. 174 ( 0.00%) Ok(formal_args.iter().map(|&ty| self.resolve_vars_if_possible(ty)).collect()) . }) . .unwrap_or_default(); . debug!(?formal_args, ?formal_ret, ?expect_args, ?expected_ret); 174 ( 0.00%) expect_args . } . . pub(in super::super) fn resolve_lang_item_path( . &self, . lang_item: hir::LangItem, . span: Span, . hir_id: hir::HirId, . expr_hir_id: Option, -- line 798 ---------------------------------------- -- line 826 ---------------------------------------- . _ => traits::ItemObligation(def_id), . }, . ); . (Res::Def(def_kind, def_id), ty) . } . . /// Resolves an associated value path into a base type and associated constant, or method . /// resolution. The newly resolved definition is written into `type_dependent_defs`. 1,170 ( 0.00%) pub fn resolve_ty_and_res_fully_qualified_call( . &self, . qpath: &'tcx QPath<'tcx>, . hir_id: hir::HirId, . span: Span, . ) -> (Res, Option>, &'tcx [hir::PathSegment<'tcx>]) { . debug!( . "resolve_ty_and_res_fully_qualified_call: qpath={:?} hir_id={:?} span={:?}", . qpath, hir_id, span . ); 351 ( 0.00%) let (ty, qself, item_segment) = match *qpath { . QPath::Resolved(ref opt_qself, ref path) => { 819 ( 0.00%) return ( 585 ( 0.00%) path.res, . opt_qself.as_ref().map(|qself| self.to_ty(qself)), 117 ( 0.00%) path.segments, . ); . } . QPath::TypeRelative(ref qself, ref segment) => { . // Don't use `self.to_ty`, since this will register a WF obligation. . // If we're trying to call a non-existent method on a trait . // (e.g. `MyTrait::missing_method`), then resolution will . // give us a `QPath::TypeRelative` with a trait object as . // `qself`. In that case, we want to avoid registering a WF obligation -- line 857 ---------------------------------------- -- line 910 ---------------------------------------- . . // Write back the new resolution. . self.write_resolution(hir_id, result); . ( . result.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)), . Some(ty), . slice::from_ref(&**item_segment), . ) 1,053 ( 0.00%) } . . /// Given a function `Node`, return its `FnDecl` if it exists, or `None` otherwise. . pub(in super::super) fn get_node_fn_decl( . &self, . node: Node<'tcx>, . ) -> Option<(&'tcx hir::FnDecl<'tcx>, Ident, bool)> { . match node { . Node::Item(&hir::Item { ident, kind: hir::ItemKind::Fn(ref sig, ..), .. }) => { -- line 926 ---------------------------------------- -- line 1115 ---------------------------------------- . } else { . last_stmt.span.with_lo(last_stmt.span.hi() - BytePos(1)) . }; . Some((span, needs_box)) . } . . // Instantiates the given path, which must refer to an item with the given . // number of type parameters and type. 936 ( 0.00%) #[instrument(skip(self, span), level = "debug")] 1,404 ( 0.00%) pub fn instantiate_value_path( . &self, . segments: &[hir::PathSegment<'_>], . self_ty: Option>, . res: Res, . span: Span, . hir_id: hir::HirId, . ) -> (Ty<'tcx>, Res) { 351 ( 0.00%) let tcx = self.tcx; . 697 ( 0.00%) let path_segs = match res { . Res::Local(_) | Res::SelfCtor(_) => vec![], 1,008 ( 0.00%) Res::Def(kind, def_id) => >::def_ids_for_value_path_segments( . self, segments, self_ty, kind, def_id, . ), . _ => bug!("instantiate_value_path on {:?}", res), . }; . . let mut user_self_ty = None; 234 ( 0.00%) let mut is_alias_variant_ctor = false; 570 ( 0.00%) match res { . Res::Def(DefKind::Ctor(CtorOf::Variant, _), _) . if let Some(self_ty) = self_ty => . { . let adt_def = self_ty.ty_adt_def().unwrap(); . user_self_ty = Some(UserSelfTy { impl_def_id: adt_def.did, self_ty }); . is_alias_variant_ctor = true; . } . Res::Def(DefKind::AssocFn | DefKind::AssocConst, def_id) => { -- line 1152 ---------------------------------------- -- line 1173 ---------------------------------------- . } . . // Now that we have categorized what space the parameters for each . // segment belong to, let's sort out the parameters that the user . // provided (if any) into their appropriate spaces. We'll also report . // errors if type parameters are provided in an inappropriate place. . . let generic_segs: FxHashSet<_> = path_segs.iter().map(|PathSeg(_, index)| index).collect(); 468 ( 0.00%) let generics_has_err = >::prohibit_generics( . self, 145 ( 0.00%) segments.iter().enumerate().filter_map(|(index, seg)| { 402 ( 0.00%) if !generic_segs.contains(&index) || is_alias_variant_ctor { . Some(seg) . } else { . None . } . }), . ); . 534 ( 0.00%) if let Res::Local(hid) = res { 122 ( 0.00%) let ty = self.local_ty(span, hid).decl_ty; . let ty = self.normalize_associated_types_in(span, ty); 244 ( 0.00%) self.write_ty(hir_id, ty); 366 ( 0.00%) return (ty, res); . } . 280 ( 0.00%) if generics_has_err { . // Don't try to infer type parameters when prohibited generic arguments were given. . user_self_ty = None; . } . . // Now we have to compare the types that the user *actually* . // provided against the types that were *expected*. If the user . // did not provide any types, then we want to substitute inference . // variables. If the user provided some types, we may still need . // to add defaults. If the user provided *too many* types, that's . // a problem. . . let mut infer_args_for_err = FxHashSet::default(); . . let mut explicit_late_bound = ExplicitLateBound::No; 56 ( 0.00%) for &PathSeg(def_id, index) in &path_segs { 504 ( 0.00%) let seg = &segments[index]; . let generics = tcx.generics_of(def_id); . . // Argument-position `impl Trait` is treated as a normal generic . // parameter internally, but we don't allow users to specify the . // parameter's value explicitly, so we have to do some error- . // checking here. 560 ( 0.00%) let arg_count = >::check_generic_arg_count_for_call( . tcx, . span, . def_id, . &generics, . seg, . IsMethodCall::No, . ); . 336 ( 0.00%) if let ExplicitLateBound::Yes = arg_count.explicit_late_bound { . explicit_late_bound = ExplicitLateBound::Yes; . } . 280 ( 0.00%) if let Err(GenericArgCountMismatch { reported: Some(_), .. }) = arg_count.correct { . infer_args_for_err.insert(index); . self.set_tainted_by_errors(); // See issue #53251. . } . } . . let has_self = path_segs . .last() 112 ( 0.00%) .map(|PathSeg(def_id, _)| tcx.generics_of(*def_id).has_self) . .unwrap_or(false); . 784 ( 0.00%) let (res, self_ctor_substs) = if let Res::SelfCtor(impl_def_id) = res { . let ty = self.normalize_ty(span, tcx.at(span).type_of(impl_def_id)); . match *ty.kind() { . ty::Adt(adt_def, substs) if adt_def.has_ctor() => { . let variant = adt_def.non_enum_variant(); . let ctor_def_id = variant.ctor_def_id.unwrap(); . ( . Res::Def(DefKind::Ctor(CtorOf::Struct, variant.ctor_kind), ctor_def_id), . Some(substs), -- line 1254 ---------------------------------------- -- line 1275 ---------------------------------------- . } . } . err.emit(); . . return (tcx.ty_error(), res); . } . } . } else { 560 ( 0.00%) (res, None) . }; . let def_id = res.def_id(); . . // The things we are substituting into the type should not contain . // escaping late-bound regions, and nor should the base type scheme. . let ty = tcx.type_of(def_id); . 280 ( 0.00%) let arg_count = GenericArgCountResult { 112 ( 0.00%) explicit_late_bound, 56 ( 0.00%) correct: if infer_args_for_err.is_empty() { . Ok(()) . } else { . Err(GenericArgCountMismatch::default()) . }, . }; . . struct CreateCtorSubstsContext<'a, 'tcx> { . fcx: &'a FnCtxt<'a, 'tcx>, -- line 1301 ---------------------------------------- -- line 1304 ---------------------------------------- . infer_args_for_err: &'a FxHashSet, . segments: &'a [hir::PathSegment<'a>], . } . impl<'tcx, 'a> CreateSubstsForGenericArgsCtxt<'a, 'tcx> for CreateCtorSubstsContext<'a, 'tcx> { . fn args_for_def_id( . &mut self, . def_id: DefId, . ) -> (Option<&'a hir::GenericArgs<'a>>, bool) { 112 ( 0.00%) if let Some(&PathSeg(_, index)) = 112 ( 0.00%) self.path_segs.iter().find(|&PathSeg(did, _)| *did == def_id) . { . // If we've encountered an `impl Trait`-related error, we're just . // going to infer the arguments for better error messages. 336 ( 0.00%) if !self.infer_args_for_err.contains(&index) { . // Check whether the user has provided generic arguments. 448 ( 0.00%) if let Some(ref data) = self.segments[index].args { . return (Some(data), self.segments[index].infer_args); . } . } 280 ( 0.00%) return (None, self.segments[index].infer_args); . } . . (None, true) . } . . fn provided_kind( . &mut self, . param: &ty::GenericParamDef, -- line 1331 ---------------------------------------- -- line 1392 ---------------------------------------- . self.fcx.var_for_def(self.span, param) . } . } . } . } . } . . let substs = self_ctor_substs.unwrap_or_else(|| { 728 ( 0.00%) >::create_substs_for_generic_args( . tcx, . def_id, . &[], . has_self, . self_ty, . &arg_count, 728 ( 0.00%) &mut CreateCtorSubstsContext { . fcx: self, . span, . path_segs: &path_segs, . infer_args_for_err: &infer_args_for_err, . segments, . }, . ) . }); . assert!(!substs.has_escaping_bound_vars()); 56 ( 0.00%) assert!(!ty.has_escaping_bound_vars()); . . // First, store the "user substs" for later. 224 ( 0.00%) self.write_user_type_annotation_from_substs(hir_id, def_id, substs, user_self_ty); . . self.add_required_obligations(span, def_id, &substs); . . // Substitute the values for the type parameters into the type of . // the referenced item. . let ty_substituted = self.instantiate_type_scheme(span, &substs, ty); . 168 ( 0.00%) if let Some(UserSelfTy { impl_def_id, self_ty }) = user_self_ty { . // In the case of `Foo::method` and `>::method`, if `method` . // is inherent, there is no `Self` parameter; instead, the impl needs . // type parameters, which we can infer by unifying the provided `Self` . // with the substituted impl type. . // This also occurs for an enum variant on a type alias. . let ty = tcx.type_of(impl_def_id); . . let impl_ty = self.instantiate_type_scheme(span, &substs, ty); -- line 1436 ---------------------------------------- -- line 1445 ---------------------------------------- . impl_ty, . ), . ); . } . } . } . . debug!("instantiate_value_path: type of {:?} is {:?}", hir_id, ty_substituted); 224 ( 0.00%) self.write_substs(hir_id, substs); . 336 ( 0.00%) (ty_substituted, res) . } . . /// Add all the obligations that are required, substituting and normalized appropriately. . crate fn add_required_obligations(&self, span: Span, def_id: DefId, substs: &SubstsRef<'tcx>) { 168 ( 0.00%) self.add_required_obligations_with_code( . span, . def_id, . substs, 336 ( 0.00%) traits::ItemObligation(def_id), . ) . } . 1,008 ( 0.00%) #[tracing::instrument(level = "debug", skip(self, span, def_id, substs))] . fn add_required_obligations_with_code( . &self, . span: Span, . def_id: DefId, . substs: &SubstsRef<'tcx>, . code: ObligationCauseCode<'tcx>, . ) { 168 ( 0.00%) let (bounds, _) = self.instantiate_bounds(span, def_id, &substs); . 1,008 ( 0.00%) for obligation in traits::predicates_for_generics( 504 ( 0.00%) traits::ObligationCause::new(span, self.body_id, code), 56 ( 0.00%) self.param_env, 504 ( 0.00%) bounds, . ) { . self.register_predicate(obligation); . } . } . . /// Resolves `typ` by a single level if `typ` is a type variable. . /// If no resolution is possible, then an error is reported. . /// Numeric inference variables may be left unresolved. 1,161 ( 0.00%) pub fn structurally_resolved_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> { 387 ( 0.00%) let ty = self.resolve_vars_with_obligations(ty); 129 ( 0.00%) if !ty.is_ty_var() { . ty . } else { . if !self.is_tainted_by_errors() { . self.emit_inference_failure_err((**self).body_id, sp, ty.into(), vec![], E0282) . .note("type must be known at this point") . .emit(); . } . let err = self.tcx.ty_error(); . self.demand_suptype(sp, err, ty); . err . } 1,161 ( 0.00%) } . . pub(in super::super) fn with_breakable_ctxt R, R>( . &self, . id: hir::HirId, . ctxt: BreakableCtxt<'tcx>, . f: F, . ) -> (BreakableCtxt<'tcx>, R) { . let index; . { . let mut enclosing_breakables = self.enclosing_breakables.borrow_mut(); 36 ( 0.00%) index = enclosing_breakables.stack.len(); . enclosing_breakables.by_id.insert(id, index); 288 ( 0.00%) enclosing_breakables.stack.push(ctxt); . } . let result = f(); . let ctxt = { . let mut enclosing_breakables = self.enclosing_breakables.borrow_mut(); . debug_assert!(enclosing_breakables.stack.len() == index + 1); . enclosing_breakables.by_id.remove(&id).expect("missing breakable context"); . enclosing_breakables.stack.pop().expect("missing breakable context") . }; 216 ( 0.00%) (ctxt, result) . } . . /// Instantiate a QueryResponse in a probe context, without a . /// good ObligationCause. 341 ( 0.00%) pub(in super::super) fn probe_instantiate_query_response( . &self, . span: Span, . original_values: &OriginalQueryValues<'tcx>, . query_result: &Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>, . ) -> InferResult<'tcx, Ty<'tcx>> { 186 ( 0.00%) self.instantiate_query_response_and_region_obligations( 217 ( 0.00%) &traits::ObligationCause::misc(span, self.body_id), 31 ( 0.00%) self.param_env, . original_values, . query_result, . ) 279 ( 0.00%) } . . /// Returns `true` if an expression is contained inside the LHS of an assignment expression. . pub(in super::super) fn expr_in_place(&self, mut expr_id: hir::HirId) -> bool { . let mut contained_in_place = false; . . while let hir::Node::Expr(parent_expr) = . self.tcx.hir().get(self.tcx.hir().get_parent_node(expr_id)) . { -- line 1551 ---------------------------------------- 33,384 ( 0.00%) -------------------------------------------------------------------------------- -- Auto-annotated source: /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_mir_build/src/thir/cx/expr.rs -------------------------------------------------------------------------------- Ir -- line 18 ---------------------------------------- . use rustc_middle::ty::{self, AdtKind, Ty, UpvarSubsts, UserType}; . use rustc_span::def_id::DefId; . use rustc_span::Span; . use rustc_target::abi::VariantIdx; . . impl<'tcx> Cx<'tcx> { . crate fn mirror_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) -> ExprId { . // `mirror_expr` is recursing very deep. Make sure the stack doesn't overflow. 1,092 ( 0.00%) ensure_sufficient_stack(|| self.mirror_expr_inner(expr)) . } . 56 ( 0.00%) crate fn mirror_exprs(&mut self, exprs: &'tcx [hir::Expr<'tcx>]) -> Box<[ExprId]> { 87,891 ( 0.01%) exprs.iter().map(|expr| self.mirror_expr_inner(expr)).collect() 112 ( 0.00%) } . 265,617 ( 0.03%) pub(super) fn mirror_expr_inner(&mut self, hir_expr: &'tcx hir::Expr<'tcx>) -> ExprId { 206,591 ( 0.02%) let temp_lifetime = self.region_scope_tree.temporary_scope(hir_expr.hir_id.local_id); . let expr_scope = . region::Scope { id: hir_expr.hir_id.local_id, data: region::ScopeData::Node }; . . debug!("Expr::make_mirror(): id={}, span={:?}", hir_expr.hir_id, hir_expr.span); . 118,052 ( 0.01%) let mut expr = self.make_mirror_unadjusted(hir_expr); . 177,078 ( 0.02%) let adjustment_span = match self.adjustment_span { 225 ( 0.00%) Some((hir_id, span)) if hir_id == hir_expr.hir_id => Some(span), . _ => None, . }; . . // Now apply adjustments, if any. 118,052 ( 0.01%) for adjustment in self.typeck_results.expr_adjustments(hir_expr) { . debug!("make_mirror: expr={:?} applying adjustment={:?}", expr, adjustment); 124 ( 0.00%) let span = expr.span; 623 ( 0.00%) expr = 1,602 ( 0.00%) self.apply_adjustment(hir_expr, expr, adjustment, adjustment_span.unwrap_or(span)); . } . . // Next, wrap this up in the expr's scope. 383,669 ( 0.04%) expr = Expr { . temp_lifetime, 29,482 ( 0.00%) ty: expr.ty, 29,513 ( 0.00%) span: hir_expr.span, . kind: ExprKind::Scope { . region_scope: expr_scope, 531,234 ( 0.05%) value: self.thir.exprs.push(expr), 59,026 ( 0.01%) lint_level: LintLevel::Explicit(hir_expr.hir_id), . }, . }; . . // Finally, create a destruction scope, if any. 88,539 ( 0.01%) if let Some(region_scope) = 59,026 ( 0.01%) self.region_scope_tree.opt_destruction_scope(hir_expr.hir_id.local_id) . { 1,188 ( 0.00%) expr = Expr { . temp_lifetime, . ty: expr.ty, 99 ( 0.00%) span: hir_expr.span, . kind: ExprKind::Scope { . region_scope, 1,386 ( 0.00%) value: self.thir.exprs.push(expr), . lint_level: LintLevel::Inherited, . }, . }; . } . . // OK, all done! 649,286 ( 0.07%) self.thir.exprs.push(expr) 265,617 ( 0.03%) } . . fn apply_adjustment( . &mut self, . hir_expr: &'tcx hir::Expr<'tcx>, . mut expr: Expr<'tcx>, . adjustment: &Adjustment<'tcx>, . mut span: Span, . ) -> Expr<'tcx> { 178 ( 0.00%) let Expr { temp_lifetime, .. } = expr; . . // Adjust the span from the block, to the last expression of the . // block. This is a better span when returning a mutable reference . // with too short a lifetime. The error message will use the span . // from the assignment to the return place, which should only point . // at the returned value, not the entire function body. . // . // fn return_short_lived<'a>(x: &'a mut i32) -> &'static mut i32 { . // x . // // ^ error message points at this expression. . // } . let mut adjust_span = |expr: &mut Expr<'tcx>| { 116 ( 0.00%) if let ExprKind::Block { body } = &expr.kind { . if let Some(last_expr) = body.expr { . span = self.thir[last_expr].span; . expr.span = span; . } . } . }; . 829 ( 0.00%) let kind = match adjustment.kind { . Adjust::Pointer(PointerCast::Unsize) => { . adjust_span(&mut expr); 476 ( 0.00%) ExprKind::Pointer { cast: PointerCast::Unsize, source: self.thir.exprs.push(expr) } . } . Adjust::Pointer(cast) => ExprKind::Pointer { cast, source: self.thir.exprs.push(expr) }, . Adjust::NeverToAny => ExprKind::NeverToAny { source: self.thir.exprs.push(expr) }, . Adjust::Deref(None) => { . adjust_span(&mut expr); 510 ( 0.00%) ExprKind::Deref { arg: self.thir.exprs.push(expr) } . } . Adjust::Deref(Some(deref)) => { . // We don't need to do call adjust_span here since . // deref coercions always start with a built-in deref. . let call = deref.method_call(self.tcx(), expr.ty); . . expr = Expr { . temp_lifetime, -- line 132 ---------------------------------------- -- line 139 ---------------------------------------- . arg: self.thir.exprs.push(expr), . }, . }; . . let expr = Box::new([self.thir.exprs.push(expr)]); . . self.overloaded_place(hir_expr, adjustment.target, Some(call), expr, deref.span) . } 124 ( 0.00%) Adjust::Borrow(AutoBorrow::Ref(_, m)) => ExprKind::Borrow { . borrow_kind: m.to_borrow_kind(), 434 ( 0.00%) arg: self.thir.exprs.push(expr), . }, . Adjust::Borrow(AutoBorrow::RawPtr(mutability)) => { . ExprKind::AddressOf { mutability, arg: self.thir.exprs.push(expr) } . } . }; . 1,691 ( 0.00%) Expr { temp_lifetime, ty: adjustment.target, span, kind } . } . 295,130 ( 0.03%) fn make_mirror_unadjusted(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Expr<'tcx> { 118,052 ( 0.01%) let expr_ty = self.typeck_results().expr_ty(expr); 29,513 ( 0.00%) let expr_span = expr.span; 147,565 ( 0.01%) let temp_lifetime = self.region_scope_tree.temporary_scope(expr.hir_id.local_id); . 177,136 ( 0.02%) let kind = match expr.kind { . // Here comes the interesting stuff: 93 ( 0.00%) hir::ExprKind::MethodCall(segment, ref args, fn_span) => { . // Rewrite a.b(c) into UFCS form like Trait::b(a, c) 217 ( 0.00%) let expr = self.method_callee(expr, segment.ident.span, None); . // When we apply adjustments to the receiver, use the span of . // the overall method call for better diagnostics. args[0] . // is guaranteed to exist, since a method call always has a receiver. 124 ( 0.00%) let old_adjustment_span = self.adjustment_span.replace((args[0].hir_id, expr_span)); . tracing::info!("Using method span: {:?}", expr.span); 31 ( 0.00%) let args = self.mirror_exprs(args); 62 ( 0.00%) self.adjustment_span = old_adjustment_span; 217 ( 0.00%) ExprKind::Call { 31 ( 0.00%) ty: expr.ty, 434 ( 0.00%) fun: self.thir.exprs.push(expr), . args, . from_hir_call: true, . fn_span, . } . } . . hir::ExprKind::Call(ref fun, ref args) => { 112 ( 0.00%) if self.typeck_results().is_method_call(expr) { . // The callee is something implementing Fn, FnMut, or FnOnce. . // Find the actual method implementation being called and . // build the appropriate UFCS call expression with the . // callee-object as expr parameter. . . // rewrite f(u, v) into FnOnce::call_once(f, (u, v)) . . let method = self.method_callee(expr, fun.span, None); -- line 194 ---------------------------------------- -- line 206 ---------------------------------------- . ty: method.ty, . fun: self.thir.exprs.push(method), . args: Box::new([self.mirror_expr(fun), tupled_args]), . from_hir_call: true, . fn_span: expr.span, . } . } else { . let adt_data = 140 ( 0.00%) if let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) = fun.kind { . // Tuple-like ADTs are represented as ExprKind::Call. We convert them here. 56 ( 0.00%) expr_ty.ty_adt_def().and_then(|adt_def| match path.res { . Res::Def(DefKind::Ctor(_, CtorKind::Fn), ctor_id) => { . Some((adt_def, adt_def.variant_index_with_ctor_id(ctor_id))) . } . Res::SelfCtor(..) => Some((adt_def, VariantIdx::new(0))), . _ => None, . }) . } else { . None . }; 56 ( 0.00%) if let Some((adt_def, index)) = adt_data { . let substs = self.typeck_results().node_substs(fun.hir_id); . let user_provided_types = self.typeck_results().user_provided_types(); . let user_ty = . user_provided_types.get(fun.hir_id).copied().map(|mut u_ty| { . if let UserType::TypeOf(ref mut did, _) = &mut u_ty.value { . *did = adt_def.did; . } . u_ty -- line 234 ---------------------------------------- -- line 247 ---------------------------------------- . adt_def, . substs, . variant_index: index, . fields: field_refs, . user_ty, . base: None, . })) . } else { 112 ( 0.00%) ExprKind::Call { 168 ( 0.00%) ty: self.typeck_results().node_type(fun.hir_id), 28 ( 0.00%) fun: self.mirror_expr(fun), 112 ( 0.00%) args: self.mirror_exprs(args), . from_hir_call: true, 28 ( 0.00%) fn_span: expr.span, . } . } . } . } . . hir::ExprKind::AddrOf(hir::BorrowKind::Ref, mutbl, ref arg) => { 145 ( 0.00%) ExprKind::Borrow { borrow_kind: mutbl.to_borrow_kind(), arg: self.mirror_expr(arg) } . } . . hir::ExprKind::AddrOf(hir::BorrowKind::Raw, mutability, ref arg) => { . ExprKind::AddressOf { mutability, arg: self.mirror_expr(arg) } . } . 504 ( 0.00%) hir::ExprKind::Block(ref blk, _) => ExprKind::Block { body: self.mirror_block(blk) }, . . hir::ExprKind::Assign(ref lhs, ref rhs, _) => { . ExprKind::Assign { lhs: self.mirror_expr(lhs), rhs: self.mirror_expr(rhs) } . } . . hir::ExprKind::AssignOp(op, ref lhs, ref rhs) => { . if self.typeck_results().is_method_call(expr) { . let lhs = self.mirror_expr(lhs); -- line 282 ---------------------------------------- -- line 286 ---------------------------------------- . ExprKind::AssignOp { . op: bin_op(op.node), . lhs: self.mirror_expr(lhs), . rhs: self.mirror_expr(rhs), . } . } . } . 29,220 ( 0.00%) hir::ExprKind::Lit(ref lit) => ExprKind::Literal { 116,880 ( 0.01%) literal: self.const_eval_literal(&lit.node, expr_ty, lit.span, false), . user_ty: None, . const_id: None, . }, . 22 ( 0.00%) hir::ExprKind::Binary(op, ref lhs, ref rhs) => { 88 ( 0.00%) if self.typeck_results().is_method_call(expr) { . let lhs = self.mirror_expr(lhs); . let rhs = self.mirror_expr(rhs); . self.overloaded_operator(expr, Box::new([lhs, rhs])) . } else { . // FIXME overflow 88 ( 0.00%) match op.node { . hir::BinOpKind::And => ExprKind::LogicalOp { . op: LogicalOp::And, . lhs: self.mirror_expr(lhs), . rhs: self.mirror_expr(rhs), . }, 88 ( 0.00%) hir::BinOpKind::Or => ExprKind::LogicalOp { . op: LogicalOp::Or, 22 ( 0.00%) lhs: self.mirror_expr(lhs), 22 ( 0.00%) rhs: self.mirror_expr(rhs), . }, . _ => { . let op = bin_op(op.node); . ExprKind::Binary { . op, . lhs: self.mirror_expr(lhs), . rhs: self.mirror_expr(rhs), . } -- line 324 ---------------------------------------- -- line 454 ---------------------------------------- . }) . .collect(), . None => Vec::new(), . }; . . ExprKind::Closure { closure_id: def_id, substs, upvars, movability, fake_reads } . } . 117 ( 0.00%) hir::ExprKind::Path(ref qpath) => { 468 ( 0.00%) let res = self.typeck_results().qpath_res(qpath, expr.hir_id); 468 ( 0.00%) self.convert_path_expr(expr, res) . } . . hir::ExprKind::InlineAsm(ref asm) => ExprKind::InlineAsm { . template: asm.template, . operands: asm . .operands . .iter() . .map(|(op, _op_sp)| { -- line 472 ---------------------------------------- -- line 609 ---------------------------------------- . if_then_scope: region::Scope { . id: then.hir_id.local_id, . data: region::ScopeData::IfThen, . }, . cond: self.mirror_expr(cond), . then: self.mirror_expr(then), . else_opt: else_opt.map(|el| self.mirror_expr(el)), . }, 10 ( 0.00%) hir::ExprKind::Match(ref discr, ref arms, _) => ExprKind::Match { 2 ( 0.00%) scrutinee: self.mirror_expr(discr), 41 ( 0.00%) arms: arms.iter().map(|a| self.convert_arm(a)).collect(), . }, . hir::ExprKind::Loop(ref body, ..) => { . let block_ty = self.typeck_results().node_type(body.hir_id); . let temp_lifetime = self.region_scope_tree.temporary_scope(body.hir_id.local_id); . let block = self.mirror_block(body); . let body = self.thir.exprs.push(Expr { . ty: block_ty, . temp_lifetime, -- line 627 ---------------------------------------- -- line 761 ---------------------------------------- . ExprKind::ValueTypeAscription { source: mirrored, user_ty } . } . } . hir::ExprKind::DropTemps(ref source) => { . ExprKind::Use { source: self.mirror_expr(source) } . } . hir::ExprKind::Box(ref value) => ExprKind::Box { value: self.mirror_expr(value) }, . hir::ExprKind::Array(ref fields) => { 140 ( 0.00%) ExprKind::Array { fields: self.mirror_exprs(fields) } . } . hir::ExprKind::Tup(ref fields) => ExprKind::Tuple { fields: self.mirror_exprs(fields) }, . . hir::ExprKind::Yield(ref v, _) => ExprKind::Yield { value: self.mirror_expr(v) }, . hir::ExprKind::Err => unreachable!(), . }; . 1,003,442 ( 0.10%) Expr { temp_lifetime, ty: expr_ty, span: expr.span, kind } 236,104 ( 0.02%) } . 531 ( 0.00%) fn user_substs_applied_to_res( . &mut self, . hir_id: hir::HirId, . res: Res, . ) -> Option> { . debug!("user_substs_applied_to_res: res={:?}", res); 354 ( 0.00%) let user_provided_type = match res { . // A reference to something callable -- e.g., a fn, method, or . // a tuple-struct or tuple-variant. This has the type of a . // `Fn` but with the user-given substitutions. . Res::Def(DefKind::Fn, _) . | Res::Def(DefKind::AssocFn, _) . | Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) . | Res::Def(DefKind::Const, _) . | Res::Def(DefKind::AssocConst, _) => { 413 ( 0.00%) self.typeck_results().user_provided_types().get(hir_id).copied() . } . . // A unit struct/variant which is used as a value (e.g., . // `None`). This has the type of the enum/struct that defines . // this variant -- but with the substitutions given by the . // user. . Res::Def(DefKind::Ctor(_, CtorKind::Const), _) => { . self.user_substs_applied_to_ty_of_hir_id(hir_id) -- line 803 ---------------------------------------- -- line 805 ---------------------------------------- . . // `Self` is used in expression as a tuple struct constructor or a unit struct constructor . Res::SelfCtor(_) => self.user_substs_applied_to_ty_of_hir_id(hir_id), . . _ => bug!("user_substs_applied_to_res: unexpected res {:?} at {:?}", res, hir_id), . }; . debug!("user_substs_applied_to_res: user_provided_type={:?}", user_provided_type); . user_provided_type 354 ( 0.00%) } . 403 ( 0.00%) fn method_callee( . &mut self, . expr: &hir::Expr<'_>, . span: Span, . overloaded_callee: Option<(DefId, SubstsRef<'tcx>)>, . ) -> Expr<'tcx> { 186 ( 0.00%) let temp_lifetime = self.region_scope_tree.temporary_scope(expr.hir_id.local_id); 248 ( 0.00%) let (def_id, substs, user_ty) = match overloaded_callee { . Some((def_id, substs)) => (def_id, substs, None), . None => { . let (kind, def_id) = 279 ( 0.00%) self.typeck_results().type_dependent_def(expr.hir_id).unwrap_or_else(|| { . span_bug!(expr.span, "no type-dependent def for method callee") . }); 465 ( 0.00%) let user_ty = self.user_substs_applied_to_res(expr.hir_id, Res::Def(kind, def_id)); . debug!("method_callee: user_ty={:?}", user_ty); 465 ( 0.00%) (def_id, self.typeck_results().node_substs(expr.hir_id), user_ty) . } . }; . let ty = self.tcx().mk_fn_def(def_id, substs); 403 ( 0.00%) Expr { . temp_lifetime, . ty, . span, . kind: ExprKind::Literal { . literal: ty::Const::zero_sized(self.tcx(), ty), 186 ( 0.00%) user_ty, . const_id: None, . }, . } 248 ( 0.00%) } . 117 ( 0.00%) fn convert_arm(&mut self, arm: &'tcx hir::Arm<'tcx>) -> ArmId { 104 ( 0.00%) let arm = Arm { 39 ( 0.00%) pattern: self.pattern_from_hir(&arm.pat), . guard: arm.guard.as_ref().map(|g| match g { . hir::Guard::If(ref e) => Guard::If(self.mirror_expr(e)), . hir::Guard::IfLet(ref pat, ref e) => { . Guard::IfLet(self.pattern_from_hir(pat), self.mirror_expr(e)) . } . }), 13 ( 0.00%) body: self.mirror_expr(arm.body), 26 ( 0.00%) lint_level: LintLevel::Explicit(arm.hir_id), . scope: region::Scope { id: arm.hir_id.local_id, data: region::ScopeData::Node }, 13 ( 0.00%) span: arm.span, . }; 195 ( 0.00%) self.thir.arms.push(arm) 117 ( 0.00%) } . . fn convert_path_expr(&mut self, expr: &'tcx hir::Expr<'tcx>, res: Res) -> ExprKind<'tcx> { 819 ( 0.00%) let substs = self.typeck_results().node_substs(expr.hir_id); 819 ( 0.00%) match res { . // A regular function, constructor function or a constant. . Res::Def(DefKind::Fn, _) . | Res::Def(DefKind::AssocFn, _) . | Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) . | Res::SelfCtor(..) => { 280 ( 0.00%) let user_ty = self.user_substs_applied_to_res(expr.hir_id, res); . debug!("convert_path_expr: user_ty={:?}", user_ty); 28 ( 0.00%) ExprKind::Literal { . literal: ty::Const::zero_sized( 56 ( 0.00%) self.tcx, 84 ( 0.00%) self.typeck_results().node_type(expr.hir_id), . ), 224 ( 0.00%) user_ty, . const_id: None, . } . } . . Res::Def(DefKind::ConstParam, def_id) => { . let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); . let item_id = self.tcx.hir().get_parent_node(hir_id); . let item_def_id = self.tcx.hir().local_def_id(item_id); -- line 887 ---------------------------------------- -- line 932 ---------------------------------------- . base: None, . })), . _ => bug!("unexpected ty: {:?}", ty), . } . } . . // We encode uses of statics as a `*&STATIC` where the `&STATIC` part is . // a constant reference (or constant raw pointer for `static mut`) in MIR 56 ( 0.00%) Res::Def(DefKind::Static, id) => { 168 ( 0.00%) let ty = self.tcx.static_ptr_ty(id); 168 ( 0.00%) let temp_lifetime = self.region_scope_tree.temporary_scope(expr.hir_id.local_id); 168 ( 0.00%) let kind = if self.tcx.is_thread_local_static(id) { . ExprKind::ThreadLocalRef(id) . } else { 112 ( 0.00%) let ptr = self.tcx.create_static_alloc(id); . ExprKind::StaticRef { . literal: ty::Const::from_scalar( . self.tcx, . Scalar::from_pointer(ptr.into(), &self.tcx), . ty, . ), . def_id: id, . } . }; 84 ( 0.00%) ExprKind::Deref { 308 ( 0.00%) arg: self.thir.exprs.push(Expr { ty, temp_lifetime, span: expr.span, kind }), . } . } . 488 ( 0.00%) Res::Local(var_hir_id) => self.convert_var(var_hir_id), . . _ => span_bug!(expr.span, "res `{:?}` not yet implemented", res), . } . } . 610 ( 0.00%) fn convert_var(&mut self, var_hir_id: hir::HirId) -> ExprKind<'tcx> { . // We want upvars here not captures. . // Captures will be handled in MIR. . let is_upvar = self . .tcx . .upvars_mentioned(self.body_owner) . .map_or(false, |upvars| upvars.contains_key(&var_hir_id)); . . debug!( . "convert_var({:?}): is_upvar={}, body_owner={:?}", . var_hir_id, is_upvar, self.body_owner . ); . . if is_upvar { . ExprKind::UpvarRef { closure_def_id: self.body_owner, var_hir_id } . } else { 183 ( 0.00%) ExprKind::VarRef { id: var_hir_id } . } 488 ( 0.00%) } . . fn overloaded_operator( . &mut self, . expr: &'tcx hir::Expr<'tcx>, . args: Box<[ExprId]>, . ) -> ExprKind<'tcx> { . let fun = self.method_callee(expr, expr.span, None); . let fun = self.thir.exprs.push(fun); -- line 993 ---------------------------------------- -- line 1135 ---------------------------------------- . . trait ToBorrowKind { . fn to_borrow_kind(&self) -> BorrowKind; . } . . impl ToBorrowKind for AutoBorrowMutability { . fn to_borrow_kind(&self) -> BorrowKind { . use rustc_middle::ty::adjustment::AllowTwoPhase; 217 ( 0.00%) match *self { . AutoBorrowMutability::Mut { allow_two_phase_borrow } => BorrowKind::Mut { . allow_two_phase_borrow: match allow_two_phase_borrow { . AllowTwoPhase::Yes => true, . AllowTwoPhase::No => false, . }, . }, . AutoBorrowMutability::Not => BorrowKind::Shared, . } -- line 1151 ---------------------------------------- 441,881 ( 0.04%) -------------------------------------------------------------------------------- -- Auto-annotated source: /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_target/src/abi/mod.rs -------------------------------------------------------------------------------- Ir -- line 40 ---------------------------------------- . /// Minimum size of #[repr(C)] enums (default I32 bits) . pub c_enum_min_size: Integer, . } . . impl Default for TargetDataLayout { . /// Creates an instance of `TargetDataLayout`. . fn default() -> TargetDataLayout { . let align = |bits| Align::from_bits(bits).unwrap(); 24 ( 0.00%) TargetDataLayout { . endian: Endian::Big, . i1_align: AbiAndPrefAlign::new(align(8)), . i8_align: AbiAndPrefAlign::new(align(8)), . i16_align: AbiAndPrefAlign::new(align(16)), . i32_align: AbiAndPrefAlign::new(align(32)), . i64_align: AbiAndPrefAlign { abi: align(32), pref: align(64) }, . i128_align: AbiAndPrefAlign { abi: align(32), pref: align(64) }, . f32_align: AbiAndPrefAlign::new(align(32)), . f64_align: AbiAndPrefAlign::new(align(64)), . pointer_size: Size::from_bits(64), . pointer_align: AbiAndPrefAlign::new(align(64)), . aggregate_align: AbiAndPrefAlign { abi: align(0), pref: align(64) }, 8 ( 0.00%) vector_align: vec![ . (Size::from_bits(64), AbiAndPrefAlign::new(align(64))), . (Size::from_bits(128), AbiAndPrefAlign::new(align(128))), . ], . instruction_address_space: AddressSpace::DATA, . c_enum_min_size: Integer::I32, . } . } . } . . impl TargetDataLayout { 18 ( 0.00%) pub fn parse(target: &Target) -> Result { . // Parse an address space index from a string. . let parse_address_space = |s: &str, cause: &str| { . s.parse::().map(AddressSpace).map_err(|err| { . format!("invalid address space `{}` for `{}` in \"data-layout\": {}", s, cause, err) . }) . }; . . // Parse a bit count from a string. -- line 80 ---------------------------------------- -- line 83 ---------------------------------------- . format!("invalid {} `{}` for `{}` in \"data-layout\": {}", kind, s, cause, err) . }) . }; . . // Parse a size string. . let size = |s: &str, cause: &str| parse_bits(s, "size", cause).map(Size::from_bits); . . // Parse an alignment string. 20 ( 0.00%) let align = |s: &[&str], cause: &str| { 2 ( 0.00%) if s.is_empty() { . return Err(format!("missing alignment for `{}` in \"data-layout\"", cause)); . } 12 ( 0.00%) let align_from_bits = |bits| { . Align::from_bits(bits).map_err(|err| { . format!("invalid alignment for `{}` in \"data-layout\": {}", cause, err) . }) 16 ( 0.00%) }; 18 ( 0.00%) let abi = parse_bits(s[0], "alignment", cause)?; . let pref = s.get(1).map_or(Ok(abi), |pref| parse_bits(pref, "alignment", cause))?; 14 ( 0.00%) Ok(AbiAndPrefAlign { abi: align_from_bits(abi)?, pref: align_from_bits(pref)? }) 16 ( 0.00%) }; . . let mut dl = TargetDataLayout::default(); . let mut i128_align_src = 64; 32 ( 0.00%) for spec in target.data_layout.split('-') { . let spec_parts = spec.split(':').collect::>(); . . match &*spec_parts { 78 ( 0.00%) ["e"] => dl.endian = Endian::Little, . ["E"] => dl.endian = Endian::Big, 2 ( 0.00%) [p] if p.starts_with('P') => { . dl.instruction_address_space = parse_address_space(&p[1..], "P")? . } 44 ( 0.00%) ["a", ref a @ ..] => dl.aggregate_align = align(a, "a")?, 4 ( 0.00%) ["f32", ref a @ ..] => dl.f32_align = align(a, "f32")?, 4 ( 0.00%) ["f64", ref a @ ..] => dl.f64_align = align(a, "f64")?, 44 ( 0.00%) [p @ "p", s, ref a @ ..] | [p @ "p0", s, ref a @ ..] => { . dl.pointer_size = size(s, p)?; . dl.pointer_align = align(a, p)?; . } 64 ( 0.00%) [s, ref a @ ..] if s.starts_with('i') => { 4 ( 0.00%) let bits = match s[1..].parse::() { . Ok(bits) => bits, . Err(_) => { . size(&s[1..], "i")?; // For the user error. . continue; . } . }; 14 ( 0.00%) let a = align(a, s)?; 10 ( 0.00%) match bits { . 1 => dl.i1_align = a, . 8 => dl.i8_align = a, . 16 => dl.i16_align = a, . 32 => dl.i32_align = a, 6 ( 0.00%) 64 => dl.i64_align = a, . _ => {} . } 8 ( 0.00%) if bits >= i128_align_src && bits <= 128 { . // Default alignment for i128 is decided by taking the alignment of . // largest-sized i{64..=128}. . i128_align_src = bits; 8 ( 0.00%) dl.i128_align = a; . } . } 14 ( 0.00%) [s, ref a @ ..] if s.starts_with('v') => { . let v_size = size(&s[1..], "v")?; . let a = align(a, s)?; . if let Some(v) = dl.vector_align.iter_mut().find(|v| v.0 == v_size) { . v.1 = a; . continue; . } . // No existing entry, add a new one. . dl.vector_align.push((v_size, a)); . } . _ => {} // Ignore everything else. . } . } . . // Perform consistency checks against the Target information. 8 ( 0.00%) if dl.endian != target.endian { . return Err(format!( . "inconsistent target specification: \"data-layout\" claims \ . architecture is {}-endian, while \"target-endian\" is `{}`", . dl.endian.as_str(), . target.endian.as_str(), . )); . } . 10 ( 0.00%) if dl.pointer_size.bits() != target.pointer_width.into() { . return Err(format!( . "inconsistent target specification: \"data-layout\" claims \ . pointers are {}-bit, while \"target-pointer-width\" is `{}`", . dl.pointer_size.bits(), . target.pointer_width . )); . } . 4 ( 0.00%) dl.c_enum_min_size = Integer::from_size(Size::from_bits(target.c_enum_min_bits))?; . 34 ( 0.00%) Ok(dl) 18 ( 0.00%) } . . /// Returns exclusive upper bound on object size. . /// . /// The theoretical maximum object size is defined as the maximum positive `isize` value. . /// This ensures that the `offset` semantics remain well-defined by allowing it to correctly . /// index every address within an object along with one byte past the end, along with allowing . /// `isize` to store the difference between any two pointers into an object. . /// . /// The upper bound on 64-bit currently needs to be lower because LLVM uses a 64-bit integer . /// to represent object size in bits. It would need to be 1 << 61 to account for this, but is . /// currently conservatively bounded to 1 << 47 as that is enough to cover the current usable . /// address space on 64-bit ARMv8 and x86_64. . #[inline] . pub fn obj_size_bound(&self) -> u64 { 528,864 ( 0.05%) match self.pointer_size.bits() { . 16 => 1 << 15, . 32 => 1 << 31, . 64 => 1 << 47, . bits => panic!("obj_size_bound: unknown pointer bit size {}", bits), . } 5 ( 0.00%) } . . #[inline] . pub fn ptr_sized_integer(&self) -> Integer { 132 ( 0.00%) match self.pointer_size.bits() { . 16 => I16, . 32 => I32, . 64 => I64, . bits => panic!("ptr_sized_integer: unknown pointer bit size {}", bits), . } 4 ( 0.00%) } . . #[inline] . pub fn vector_align(&self, vec_size: Size) -> AbiAndPrefAlign { . for &(size, align) in &self.vector_align { . if size == vec_size { . return align; . } . } -- line 222 ---------------------------------------- -- line 233 ---------------------------------------- . impl HasDataLayout for TargetDataLayout { . #[inline] . fn data_layout(&self) -> &TargetDataLayout { . self . } . } . . /// Endianness of the target, which must match cfg(target-endian). 2 ( 0.00%) #[derive(Copy, Clone, PartialEq)] . pub enum Endian { . Little, . Big, . } . . impl Endian { . pub fn as_str(&self) -> &'static str { 3 ( 0.00%) match self { . Self::Little => "little", . Self::Big => "big", . } 1 ( 0.00%) } . } . . impl fmt::Debug for Endian { . fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { . f.write_str(self.as_str()) . } . } . -- line 261 ---------------------------------------- -- line 273 ---------------------------------------- . . impl ToJson for Endian { . fn to_json(&self) -> Json { . self.as_str().to_json() . } . } . . /// Size of a type in bytes. 84 ( 0.00%) #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Encodable, Decodable)] . #[derive(HashStable_Generic)] . pub struct Size { . // The top 3 bits are ALWAYS zero. 117,844 ( 0.01%) raw: u64, . } . . impl Size { . pub const ZERO: Size = Size { raw: 0 }; . . /// Rounds `bits` up to the next-higher byte boundary, if `bits` is . /// is not aligned. . pub fn from_bits(bits: impl TryInto) -> Size { -- line 293 ---------------------------------------- -- line 296 ---------------------------------------- . #[cold] . fn overflow(bits: u64) -> ! { . panic!("Size::from_bits({}) has overflowed", bits); . } . . // This is the largest value of `bits` that does not cause overflow . // during rounding, and guarantees that the resulting number of bytes . // cannot cause overflow when multiplied by 8. 12 ( 0.00%) if bits > 0xffff_ffff_ffff_fff8 { . overflow(bits); . } . . // Avoid potential overflow from `bits + 7`. 290 ( 0.00%) Size { raw: bits / 8 + ((bits % 8) + 7) / 8 } . } . . #[inline] . pub fn from_bytes(bytes: impl TryInto) -> Size { . let bytes: u64 = bytes.try_into().ok().unwrap(); . Size { raw: bytes } . } . -- line 317 ---------------------------------------- -- line 322 ---------------------------------------- . . #[inline] . pub fn bytes_usize(self) -> usize { . self.bytes().try_into().unwrap() . } . . #[inline] . pub fn bits(self) -> u64 { 381,012 ( 0.04%) self.raw << 3 . } . . #[inline] . pub fn bits_usize(self) -> usize { . self.bits().try_into().unwrap() . } . . #[inline] 6 ( 0.00%) pub fn align_to(self, align: Align) -> Size { 746 ( 0.00%) let mask = align.bytes() - 1; 723 ( 0.00%) Size::from_bytes((self.bytes() + mask) & !mask) 18 ( 0.00%) } . . #[inline] . pub fn is_aligned(self, align: Align) -> bool { 16 ( 0.00%) let mask = align.bytes() - 1; 8 ( 0.00%) self.bytes() & mask == 0 . } . . #[inline] . pub fn checked_add(self, offset: Size, cx: &C) -> Option { . let dl = cx.data_layout(); . 88,084 ( 0.01%) let bytes = self.bytes().checked_add(offset.bytes())?; . 440,381 ( 0.04%) if bytes < dl.obj_size_bound() { Some(Size::from_bytes(bytes)) } else { None } . } . . #[inline] 54 ( 0.00%) pub fn checked_mul(self, count: u64, cx: &C) -> Option { . let dl = cx.data_layout(); . 55 ( 0.00%) let bytes = self.bytes().checked_mul(count)?; 165 ( 0.00%) if bytes < dl.obj_size_bound() { Some(Size::from_bytes(bytes)) } else { None } 27 ( 0.00%) } . . /// Truncates `value` to `self` bits and then sign-extends it to 128 bits . /// (i.e., if it is negative, fill with 1's on the left). . #[inline] . pub fn sign_extend(self, value: u128) -> u128 { . let size = self.bits(); 8 ( 0.00%) if size == 0 { . // Truncated until nothing is left. . return 0; . } . // Sign-extend it. 37 ( 0.00%) let shift = 128 - size; . // Shift the unsigned value to the left, then shift back to the right as signed . // (essentially fills with sign bit on the left). 1,058 ( 0.00%) (((value << shift) as i128) >> shift) as u128 . } . . /// Truncates `value` to `self` bits. . #[inline] . pub fn truncate(self, value: u128) -> u128 { . let size = self.bits(); 117,614 ( 0.01%) if size == 0 { . // Truncated until nothing is left. . return 0; . } 117,656 ( 0.01%) let shift = 128 - size; . // Truncate (shift left to drop out leftover values, shift right to fill with zeroes). 1,467,848 ( 0.15%) (value << shift) >> shift . } . . #[inline] . pub fn signed_int_min(&self) -> i128 { 261 ( 0.00%) self.sign_extend(1_u128 << (self.bits() - 1)) as i128 . } . . #[inline] . pub fn signed_int_max(&self) -> i128 { 261 ( 0.00%) i128::MAX >> (128 - self.bits()) . } . . #[inline] 5 ( 0.00%) pub fn unsigned_int_max(&self) -> u128 { 1,184 ( 0.00%) u128::MAX >> (128 - self.bits()) 10 ( 0.00%) } . } . . // Panicking addition, subtraction and multiplication for convenience. . // Avoid during layout computation, return `LayoutError` instead. . . impl Add for Size { . type Output = Size; . #[inline] -- line 417 ---------------------------------------- -- line 439 ---------------------------------------- . size * self . } . } . . impl Mul for Size { . type Output = Size; . #[inline] . fn mul(self, count: u64) -> Size { 116,836 ( 0.01%) match self.bytes().checked_mul(count) { . Some(bytes) => Size::from_bytes(bytes), . None => panic!("Size::mul: {} * {} doesn't fit in u64", self.bytes(), count), . } . } . } . . impl AddAssign for Size { . #[inline] . fn add_assign(&mut self, other: Size) { 144 ( 0.00%) *self = *self + other; . } . } . . impl Step for Size { . #[inline] . fn steps_between(start: &Self, end: &Self) -> Option { . u64::steps_between(&start.bytes(), &end.bytes()) . } -- line 465 ---------------------------------------- -- line 494 ---------------------------------------- . Self::from_bytes(u64::backward_unchecked(start.bytes(), count)) . } . } . . /// Alignment of a type in bytes (always a power of two). . #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Encodable, Decodable)] . #[derive(HashStable_Generic)] . pub struct Align { 587 ( 0.00%) pow2: u8, . } . . impl Align { . pub const ONE: Align = Align { pow2: 0 }; . . #[inline] . pub fn from_bits(bits: u64) -> Result { . Align::from_bytes(Size::from_bits(bits).bytes()) . } . . #[inline] . pub fn from_bytes(align: u64) -> Result { . // Treat an alignment of 0 bytes like 1-byte alignment. 8 ( 0.00%) if align == 0 { . return Ok(Align::ONE); . } . . #[cold] . fn not_power_of_2(align: u64) -> String { . format!("`{}` is not a power of 2", align) . } . . #[cold] . fn too_large(align: u64) -> String { . format!("`{}` is too large", align) . } . . let mut bytes = align; . let mut pow2: u8 = 0; 56 ( 0.00%) while (bytes & 1) == 0 { 36 ( 0.00%) pow2 += 1; 24 ( 0.00%) bytes >>= 1; . } 8 ( 0.00%) if bytes != 1 { . return Err(not_power_of_2(align)); . } 8 ( 0.00%) if pow2 > 29 { . return Err(too_large(align)); . } . 10 ( 0.00%) Ok(Align { pow2 }) . } . . #[inline] . pub fn bytes(self) -> u64 { 2,399 ( 0.00%) 1 << self.pow2 . } . . #[inline] . pub fn bits(self) -> u64 { 10 ( 0.00%) self.bytes() * 8 . } . . /// Computes the best alignment possible for the given offset . /// (the largest power of two that the offset is a multiple of). . /// . /// N.B., for an offset of `0`, this happens to return `2^64`. . #[inline] . pub fn max_for_offset(offset: Size) -> Align { -- line 561 ---------------------------------------- -- line 591 ---------------------------------------- . . #[inline] . pub fn max(self, other: AbiAndPrefAlign) -> AbiAndPrefAlign { . AbiAndPrefAlign { abi: self.abi.max(other.abi), pref: self.pref.max(other.pref) } . } . } . . /// Integers, also used for enum discriminants. 54 ( 0.00%) #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, HashStable_Generic)] . pub enum Integer { . I8, . I16, . I32, . I64, . I128, . } . . impl Integer { . #[inline] . pub fn size(self) -> Size { 1,269 ( 0.00%) match self { . I8 => Size::from_bytes(1), . I16 => Size::from_bytes(2), . I32 => Size::from_bytes(4), . I64 => Size::from_bytes(8), . I128 => Size::from_bytes(16), . } . } . . pub fn align(self, cx: &C) -> AbiAndPrefAlign { . let dl = cx.data_layout(); . 150 ( 0.00%) match self { 94 ( 0.00%) I8 => dl.i8_align, . I16 => dl.i16_align, 24 ( 0.00%) I32 => dl.i32_align, 160 ( 0.00%) I64 => dl.i64_align, . I128 => dl.i128_align, . } . } . . /// Finds the smallest Integer type which can represent the signed value. . #[inline] . pub fn fit_signed(x: i128) -> Integer { . match x { 70 ( 0.00%) -0x0000_0000_0000_0080..=0x0000_0000_0000_007f => I8, . -0x0000_0000_0000_8000..=0x0000_0000_0000_7fff => I16, . -0x0000_0000_8000_0000..=0x0000_0000_7fff_ffff => I32, . -0x8000_0000_0000_0000..=0x7fff_ffff_ffff_ffff => I64, . _ => I128, . } . } . . /// Finds the smallest Integer type which can represent the unsigned value. . #[inline] . pub fn fit_unsigned(x: u128) -> Integer { . match x { 20 ( 0.00%) 0..=0x0000_0000_0000_00ff => I8, 8 ( 0.00%) 0..=0x0000_0000_0000_ffff => I16, 12 ( 0.00%) 0..=0x0000_0000_ffff_ffff => I32, . 0..=0xffff_ffff_ffff_ffff => I64, . _ => I128, . } . } . . /// Finds the smallest integer with the given alignment. 36 ( 0.00%) pub fn for_align(cx: &C, wanted: Align) -> Option { . let dl = cx.data_layout(); . 247 ( 0.00%) for candidate in [I8, I16, I32, I64, I128] { 48 ( 0.00%) if wanted == candidate.align(dl).abi && wanted.bytes() == candidate.size().bytes() { . return Some(candidate); . } . } . None 36 ( 0.00%) } . . /// Find the largest integer with the given alignment or less. . pub fn approximate_align(cx: &C, wanted: Align) -> Integer { . let dl = cx.data_layout(); . . // FIXME(eddyb) maybe include I128 in the future, when it works everywhere. . for candidate in [I64, I32, I16] { 34 ( 0.00%) if wanted >= candidate.align(dl).abi && wanted.bytes() >= candidate.size().bytes() { . return candidate; . } . } . I8 . } . . // FIXME(eddyb) consolidate this and other methods that find the appropriate . // `Integer` given some requirements. . #[inline] . fn from_size(size: Size) -> Result { 8 ( 0.00%) match size.bits() { . 8 => Ok(Integer::I8), . 16 => Ok(Integer::I16), . 32 => Ok(Integer::I32), . 64 => Ok(Integer::I64), . 128 => Ok(Integer::I128), . _ => Err(format!("rust does not support integers with {} bits", size.bits())), . } . } . } . . /// Fundamental unit of memory access and layout. 4,536 ( 0.00%) #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)] . pub enum Primitive { . /// The `bool` is the signedness of the `Integer` type. . /// . /// One would think we would not care about such details this low down, . /// but some ABIs are described in terms of C types and ISAs where the . /// integer arithmetic is done on {sign,zero}-extended registers, e.g. . /// a negative integer passed by zero-extension will appear positive in . /// the callee, and most operations on it will produce the wrong values. 282 ( 0.00%) Int(Integer, bool), . F32, . F64, . Pointer, . } . . impl Primitive { . pub fn size(self, cx: &C) -> Size { . let dl = cx.data_layout(); . 3,909 ( 0.00%) match self { . Int(i, _) => i.size(), . F32 => Size::from_bits(32), . F64 => Size::from_bits(64), 302 ( 0.00%) Pointer => dl.pointer_size, . } 5 ( 0.00%) } . . pub fn align(self, cx: &C) -> AbiAndPrefAlign { . let dl = cx.data_layout(); . 233 ( 0.00%) match self { . Int(i, _) => i.align(dl), . F32 => dl.f32_align, . F64 => dl.f64_align, 80 ( 0.00%) Pointer => dl.pointer_align, . } . } . . // FIXME(eddyb) remove, it's trivial thanks to `matches!`. . #[inline] . pub fn is_float(self) -> bool { . matches!(self, F32 | F64) . } -- line 739 ---------------------------------------- -- line 753 ---------------------------------------- . /// sequence: . /// . /// 254 (-2), 255 (-1), 0, 1, 2 . /// . /// This is intended specifically to mirror LLVM’s `!range` metadata semantics. . #[derive(Clone, Copy, PartialEq, Eq, Hash)] . #[derive(HashStable_Generic)] . pub struct WrappingRange { 369 ( 0.00%) pub start: u128, . pub end: u128, . } . . impl WrappingRange { . /// Returns `true` if `v` is contained in the range. . #[inline(always)] . pub fn contains(&self, v: u128) -> bool { 140 ( 0.00%) if self.start <= self.end { . self.start <= v && v <= self.end . } else { . self.start <= v || v <= self.end . } . } . . /// Returns `self` with replaced `start` . #[inline(always)] -- line 777 ---------------------------------------- -- line 787 ---------------------------------------- . self . } . . /// Returns `true` if `size` completely fills the range. . #[inline] . pub fn is_full_for(&self, size: Size) -> bool { . let max_value = size.unsigned_int_max(); . debug_assert!(self.start <= max_value && self.end <= max_value); 445 ( 0.00%) self.start == (self.end.wrapping_add(1) & max_value) . } . } . . impl fmt::Debug for WrappingRange { . fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { . if self.start > self.end { . write!(fmt, "(..={}) | ({}..)", self.end, self.start)?; . } else { -- line 803 ---------------------------------------- -- line 806 ---------------------------------------- . Ok(()) . } . } . . /// Information about one scalar component of a Rust type. . #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] . #[derive(HashStable_Generic)] . pub struct Scalar { 845 ( 0.00%) pub value: Primitive, . . // FIXME(eddyb) always use the shortest range, e.g., by finding . // the largest space between two consecutive valid values and . // taking everything else as the (shortest) valid range. 415 ( 0.00%) pub valid_range: WrappingRange, . } . . impl Scalar { . #[inline] . pub fn is_bool(&self) -> bool { 877 ( 0.00%) matches!( 526 ( 0.00%) self, . Scalar { value: Int(I8, false), valid_range: WrappingRange { start: 0, end: 1 } } . ) . } . . /// Returns `true` if all possible numbers are valid, i.e `valid_range` covers the whole layout . #[inline] 1 ( 0.00%) pub fn is_always_valid(&self, cx: &C) -> bool { 139 ( 0.00%) self.valid_range.is_full_for(self.value.size(cx)) 2 ( 0.00%) } . } . . /// Describes how the fields of a type are located in memory. 3,678 ( 0.00%) #[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)] . pub enum FieldsShape { . /// Scalar primitives and `!`, which never have fields. . Primitive, . . /// All fields start at no offset. The `usize` is the field count. . Union(NonZeroUsize), . . /// Array/vector-like placement, with all fields of identical types. 8 ( 0.00%) Array { stride: Size, count: u64 }, . . /// Struct-like placement, with precomputed offsets. . /// . /// Fields are guaranteed to not overlap, but note that gaps . /// before, between and after all the fields are NOT always . /// padding, and as such their contents may not be discarded. . /// For example, enum variants leave a gap at the start, . /// where the discriminant field in the enum layout goes. -- line 856 ---------------------------------------- -- line 875 ---------------------------------------- . // FIXME(camlorn) also consider small vector optimization here. . memory_index: Vec, . }, . } . . impl FieldsShape { . #[inline] . pub fn count(&self) -> usize { 335 ( 0.00%) match *self { . FieldsShape::Primitive => 0, . FieldsShape::Union(count) => count.get(), . FieldsShape::Array { count, .. } => count.try_into().unwrap(), 143 ( 0.00%) FieldsShape::Arbitrary { ref offsets, .. } => offsets.len(), . } . } . . #[inline] 58,480 ( 0.01%) pub fn offset(&self, i: usize) -> Size { 146,252 ( 0.01%) match *self { . FieldsShape::Primitive => { . unreachable!("FieldsShape::offset: `Primitive`s have no fields") . } 4 ( 0.00%) FieldsShape::Union(count) => { 2 ( 0.00%) assert!( 2 ( 0.00%) i < count.get(), . "tried to access field {} of union with {} fields", . i, . count . ); . Size::ZERO . } . FieldsShape::Array { stride, count } => { . let i = u64::try_from(i).unwrap(); 58,418 ( 0.01%) assert!(i < count); . stride * i . } 43 ( 0.00%) FieldsShape::Arbitrary { ref offsets, .. } => offsets[i], . } 58,480 ( 0.01%) } . . #[inline] . pub fn memory_index(&self, i: usize) -> usize { . match *self { . FieldsShape::Primitive => { . unreachable!("FieldsShape::memory_index: `Primitive`s have no fields") . } . FieldsShape::Union(_) | FieldsShape::Array { .. } => i, . FieldsShape::Arbitrary { ref memory_index, .. } => memory_index[i].try_into().unwrap(), . } . } . . /// Gets source indices of the fields by increasing offsets. . #[inline] . pub fn index_by_increasing_offset<'a>(&'a self) -> impl Iterator + 'a { 182 ( 0.00%) let mut inverse_small = [0u8; 64]; . let mut inverse_big = vec![]; 41 ( 0.00%) let use_small = self.count() <= inverse_small.len(); . . // We have to write this logic twice in order to keep the array small. . if let FieldsShape::Arbitrary { ref memory_index, .. } = *self { 41 ( 0.00%) if use_small { . for i in 0..self.count() { 42 ( 0.00%) inverse_small[memory_index[i] as usize] = i as u8; . } . } else { . inverse_big = vec![0; self.count()]; . for i in 0..self.count() { . inverse_big[memory_index[i] as usize] = i as u32; . } . } . } . 434 ( 0.00%) (0..self.count()).map(move |i| match *self { . FieldsShape::Primitive | FieldsShape::Union(_) | FieldsShape::Array { .. } => i, . FieldsShape::Arbitrary { .. } => { 12 ( 0.00%) if use_small { 26 ( 0.00%) inverse_small[i] as usize . } else { . inverse_big[i] as usize . } . } . }) . } . } . -- line 959 ---------------------------------------- -- line 965 ---------------------------------------- . . impl AddressSpace { . /// The default address space, corresponding to data space. . pub const DATA: Self = AddressSpace(0); . } . . /// Describes how values of the type are passed by target ABIs, . /// in terms of categories of C types there are ABI rules for. 2,360 ( 0.00%) #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable_Generic)] . pub enum Abi { . Uninhabited, . Scalar(Scalar), 15 ( 0.00%) ScalarPair(Scalar, Scalar), . Vector { . element: Scalar, . count: u64, . }, . Aggregate { . /// If true, the size is exact, otherwise it's only a lower bound. 295 ( 0.00%) sized: bool, . }, . } . . impl Abi { . /// Returns `true` if the layout corresponds to an unsized type. . #[inline] . pub fn is_unsized(&self) -> bool { 176,464 ( 0.02%) match *self { . Abi::Uninhabited | Abi::Scalar(_) | Abi::ScalarPair(..) | Abi::Vector { .. } => false, . Abi::Aggregate { sized } => !sized, . } . } . . /// Returns `true` if this is a single signed integer scalar . #[inline] . pub fn is_signed(&self) -> bool { 24 ( 0.00%) match self { 56 ( 0.00%) Abi::Scalar(scal) => match scal.value { . Primitive::Int(_, signed) => signed, . _ => false, . }, . _ => panic!("`is_signed` on non-scalar ABI {:?}", self), . } . } . . /// Returns `true` if this is an uninhabited type . #[inline] . pub fn is_uninhabited(&self) -> bool { 112 ( 0.00%) matches!(*self, Abi::Uninhabited) . } . . /// Returns `true` is this is a scalar type . #[inline] . pub fn is_scalar(&self) -> bool { . matches!(*self, Abi::Scalar(_)) . } . } . . rustc_index::newtype_index! { . pub struct VariantIdx { . derive [HashStable_Generic] . } . } . 1,496 ( 0.00%) #[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)] . pub enum Variants { . /// Single enum variants, structs/tuples, unions, and all non-ADTs. 96 ( 0.00%) Single { index: VariantIdx }, . . /// Enum-likes with more than one inhabited variant: each variant comes with . /// a *discriminant* (usually the same as the variant index but the user can . /// assign explicit discriminant values). That discriminant is encoded . /// as a *tag* on the machine. The layout of each variant is . /// a struct, and they all have space reserved for the tag. . /// For enums, the tag is the sole field of the layout. . Multiple { . tag: Scalar, 5 ( 0.00%) tag_encoding: TagEncoding, 4 ( 0.00%) tag_field: usize, 1 ( 0.00%) variants: IndexVec, . }, . } . 46 ( 0.00%) #[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)] . pub enum TagEncoding { . /// The tag directly stores the discriminant, but possibly with a smaller layout . /// (so converting the tag to the discriminant can require sign extension). . Direct, . . /// Niche (values invalid for a type) encoding the discriminant: . /// Discriminant and variant index coincide. . /// The variant `dataful_variant` contains a niche at an arbitrary -- line 1056 ---------------------------------------- -- line 1065 ---------------------------------------- . dataful_variant: VariantIdx, . niche_variants: RangeInclusive, . niche_start: u128, . }, . } . . #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable_Generic)] . pub struct Niche { 54 ( 0.00%) pub offset: Size, 54 ( 0.00%) pub scalar: Scalar, . } . . impl Niche { 36 ( 0.00%) pub fn from_scalar(cx: &C, offset: Size, scalar: Scalar) -> Option { 36 ( 0.00%) let niche = Niche { offset, scalar }; 1,236 ( 0.00%) if niche.available(cx) > 0 { Some(niche) } else { None } 42 ( 0.00%) } . . pub fn available(&self, cx: &C) -> u128 { . let Scalar { value, valid_range: v } = self.scalar; . let size = value.size(cx); 202 ( 0.00%) assert!(size.bits() <= 128); . let max_value = size.unsigned_int_max(); . . // Find out how many values are outside the valid range. . let niche = v.end.wrapping_add(1)..v.start; 84 ( 0.00%) niche.end.wrapping_sub(niche.start) & max_value . } . . pub fn reserve(&self, cx: &C, count: u128) -> Option<(u128, Scalar)> { . assert!(count > 0); . . let Scalar { value, valid_range: v } = self.scalar; . let size = value.size(cx); . assert!(size.bits() <= 128); -- line 1099 ---------------------------------------- -- line 1144 ---------------------------------------- . move_start(v) . } else { . move_end(v) . } . } . } . } . 6,496 ( 0.00%) #[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)] . pub struct Layout { . /// Says where the fields are located within the layout. . pub fields: FieldsShape, . . /// Encodes information about multi-variant layouts. . /// Even with `Multiple` variants, a layout still has its own fields! Those are then . /// shared between all variants. One of them will be the discriminant, . /// but e.g. generators can have more. . /// . /// To access all fields of this layout, both `fields` and the fields of the active variant . /// must be taken into account. 43 ( 0.00%) pub variants: Variants, . . /// The `abi` defines how this data is passed between functions, and it defines . /// value restrictions via `valid_range`. . /// . /// Note that this is entirely orthogonal to the recursive structure defined by . /// `variants` and `fields`; for example, `ManuallyDrop>` has . /// `Abi::ScalarPair`! So, even with non-`Aggregate` `abi`, `fields` and `variants` . /// have to be taken into account to find all fields of this layout. 83 ( 0.00%) pub abi: Abi, . . /// The leaf scalar with the largest number of invalid values . /// (i.e. outside of its `valid_range`), if it exists. 363 ( 0.00%) pub largest_niche: Option, . 1,345 ( 0.00%) pub align: AbiAndPrefAlign, 336 ( 0.00%) pub size: Size, . } . . impl Layout { 426 ( 0.00%) pub fn scalar(cx: &C, scalar: Scalar) -> Self { 426 ( 0.00%) let largest_niche = Niche::from_scalar(cx, Size::ZERO, scalar); . let size = scalar.value.size(cx); . let align = scalar.value.align(cx); 1,491 ( 0.00%) Layout { . variants: Variants::Single { index: VariantIdx::new(0) }, . fields: FieldsShape::Primitive, 426 ( 0.00%) abi: Abi::Scalar(scalar), 284 ( 0.00%) largest_niche, . size, . align, . } 568 ( 0.00%) } . } . . /// The layout of a type, alongside the type itself. . /// Provides various type traversal APIs (e.g., recursing into fields). . /// . /// Note that the layout is NOT guaranteed to always be identical . /// to that obtained from `layout_of(ty)`, as we need to produce . /// layouts for which Rust types do not exist, such as enum variants . /// or synthetic fields of enums (i.e., discriminants) and fat pointers. . #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable_Generic)] . pub struct TyAndLayout<'a, Ty> { 60,335 ( 0.01%) pub ty: Ty, 121,896 ( 0.01%) pub layout: &'a Layout, . } . . impl<'a, Ty> Deref for TyAndLayout<'a, Ty> { . type Target = &'a Layout; . fn deref(&self) -> &&'a Layout { . &self.layout . } . } . 15 ( 0.00%) #[derive(Copy, Clone, PartialEq, Eq, Debug)] . pub enum PointerKind { . /// Most general case, we know no restrictions to tell LLVM. . Shared, . . /// `&T` where `T` contains no `UnsafeCell`, is `noalias` and `readonly`. . Frozen, . . /// `&mut T` which is `noalias` but not `readonly`. -- line 1227 ---------------------------------------- -- line 1255 ---------------------------------------- . ) -> Option; . } . . impl<'a, Ty> TyAndLayout<'a, Ty> { . pub fn for_variant(self, cx: &C, variant_index: VariantIdx) -> Self . where . Ty: TyAbiInterface<'a, C>, . { 45 ( 0.00%) Ty::ty_and_layout_for_variant(self, cx, variant_index) . } . . pub fn field(self, cx: &C, i: usize) -> Self . where . Ty: TyAbiInterface<'a, C>, . { 117,690 ( 0.01%) Ty::ty_and_layout_field(self, cx, i) . } . . pub fn pointee_info_at(self, cx: &C, offset: Size) -> Option . where . Ty: TyAbiInterface<'a, C>, . { 142 ( 0.00%) Ty::ty_and_layout_pointee_info_at(self, cx, offset) . } . } . . impl<'a, Ty> TyAndLayout<'a, Ty> { . /// Returns `true` if the layout corresponds to an unsized type. . pub fn is_unsized(&self) -> bool { 29,708 ( 0.00%) self.abi.is_unsized() . } . . /// Returns `true` if the type is a ZST and not unsized. . pub fn is_zst(&self) -> bool { 152,626 ( 0.02%) match self.abi { . Abi::Scalar(_) | Abi::ScalarPair(..) | Abi::Vector { .. } => false, . Abi::Uninhabited => self.size.bytes() == 0, 142 ( 0.00%) Abi::Aggregate { sized } => sized && self.size.bytes() == 0, . } 56 ( 0.00%) } . . /// Determines if this type permits "raw" initialization by just transmuting some . /// memory into an instance of `T`. . /// `zero` indicates if the memory is zero-initialized, or alternatively . /// left entirely uninitialized. . /// This is conservative: in doubt, it will answer `true`. . /// . /// FIXME: Once we removed all the conservatism, we could alternatively -- line 1302 ---------------------------------------- 567,305 ( 0.06%) -------------------------------------------------------------------------------- -- Auto-annotated source: /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_resolve/src/late.rs -------------------------------------------------------------------------------- Ir -- line 141 ---------------------------------------- . /// parameters. . ConstParamTyRibKind, . } . . impl RibKind<'_> { . /// Whether this rib kind contains generic parameters, as opposed to local . /// variables. . crate fn contains_params(&self) -> bool { 13,882 ( 0.00%) match self { . NormalRibKind . | ClosureOrAsyncRibKind . | FnItemRibKind . | ConstantItemRibKind(..) . | ModuleRibKind(_) . | MacroDefinition(_) . | ConstParamTyRibKind => false, . AssocItemRibKind | ItemRibKind(_) | ForwardGenericParamBanRibKind => true, -- line 157 ---------------------------------------- -- line 174 ---------------------------------------- . #[derive(Debug)] . crate struct Rib<'a, R = Res> { . pub bindings: IdentMap, . pub kind: RibKind<'a>, . } . . impl<'a, R> Rib<'a, R> { . fn new(kind: RibKind<'a>) -> Rib<'a, R> { 511 ( 0.00%) Rib { bindings: Default::default(), kind } . } . } . . #[derive(Copy, Clone, PartialEq, Eq, Debug)] . crate enum AliasPossibility { . No, . Maybe, . } -- line 190 ---------------------------------------- -- line 212 ---------------------------------------- . match self { . PathSource::Type | PathSource::Trait(_) | PathSource::Struct => TypeNS, . PathSource::Expr(..) | PathSource::Pat | PathSource::TupleStruct(..) => ValueNS, . PathSource::TraitItem(ns) => ns, . } . } . . fn defer_to_typeck(self) -> bool { 642 ( 0.00%) match self { . PathSource::Type . | PathSource::Expr(..) . | PathSource::Pat . | PathSource::Struct . | PathSource::TupleStruct(..) => true, . PathSource::Trait(_) | PathSource::TraitItem(..) => false, . } . } -- line 228 ---------------------------------------- -- line 268 ---------------------------------------- . } . } . . fn is_call(self) -> bool { . matches!(self, PathSource::Expr(Some(&Expr { kind: ExprKind::Call(..), .. }))) . } . . crate fn is_expected(self, res: Res) -> bool { 2,026 ( 0.00%) match self { 1,322 ( 0.00%) PathSource::Type => matches!( 378 ( 0.00%) res, . Res::Def( . DefKind::Struct . | DefKind::Union . | DefKind::Enum . | DefKind::Trait . | DefKind::TraitAlias . | DefKind::TyAlias . | DefKind::AssocTy . | DefKind::TyParam . | DefKind::OpaqueTy . | DefKind::ForeignTy, . _, . ) | Res::PrimTy(..) . | Res::SelfTy(..) . ), 3 ( 0.00%) PathSource::Trait(AliasPossibility::No) => matches!(res, Res::Def(DefKind::Trait, _)), . PathSource::Trait(AliasPossibility::Maybe) => { 14 ( 0.00%) matches!(res, Res::Def(DefKind::Trait | DefKind::TraitAlias, _)) . } 519 ( 0.00%) PathSource::Expr(..) => matches!( 285 ( 0.00%) res, . Res::Def( . DefKind::Ctor(_, CtorKind::Const | CtorKind::Fn) . | DefKind::Const . | DefKind::Static . | DefKind::Fn . | DefKind::AssocFn . | DefKind::AssocConst . | DefKind::ConstParam, -- line 307 ---------------------------------------- -- line 329 ---------------------------------------- . ) | Res::SelfTy(..) . ), . PathSource::TraitItem(ns) => match res { . Res::Def(DefKind::AssocConst | DefKind::AssocFn, _) if ns == ValueNS => true, . Res::Def(DefKind::AssocTy, _) if ns == TypeNS => true, . _ => false, . }, . } 404 ( 0.00%) } . . fn error_code(self, has_unexpected_resolution: bool) -> DiagnosticId { . use rustc_errors::error_code; . match (self, has_unexpected_resolution) { . (PathSource::Trait(_), true) => error_code!(E0404), . (PathSource::Trait(_), false) => error_code!(E0405), . (PathSource::Type, true) => error_code!(E0573), . (PathSource::Type, false) => error_code!(E0412), -- line 345 ---------------------------------------- -- line 350 ---------------------------------------- . (PathSource::Pat | PathSource::TupleStruct(..), true) => error_code!(E0532), . (PathSource::Pat | PathSource::TupleStruct(..), false) => error_code!(E0531), . (PathSource::TraitItem(..), true) => error_code!(E0575), . (PathSource::TraitItem(..), false) => error_code!(E0576), . } . } . } . 2 ( 0.00%) #[derive(Default)] . struct DiagnosticMetadata<'ast> { . /// The current trait's associated items' ident, used for diagnostic suggestions. . current_trait_assoc_items: Option<&'ast [P]>, . . /// The current self type if inside an impl (used for better errors). . current_self_type: Option, . . /// The current self item if inside an ADT (used for better errors). -- line 366 ---------------------------------------- -- line 434 ---------------------------------------- . fn visit_attribute(&mut self, _: &'ast Attribute) { . // We do not want to resolve expressions that appear in attributes, . // as they do not correspond to actual code. . } . fn visit_item(&mut self, item: &'ast Item) { . let prev = replace(&mut self.diagnostic_metadata.current_item, Some(item)); . // Always report errors in items we just entered. . let old_ignore = replace(&mut self.in_func_body, false); 68 ( 0.00%) self.resolve_item(item); 34 ( 0.00%) self.in_func_body = old_ignore; 34 ( 0.00%) self.diagnostic_metadata.current_item = prev; . } 91 ( 0.00%) fn visit_arm(&mut self, arm: &'ast Arm) { . self.resolve_arm(arm); 78 ( 0.00%) } 324 ( 0.00%) fn visit_block(&mut self, block: &'ast Block) { . self.resolve_block(block); 288 ( 0.00%) } . fn visit_anon_const(&mut self, constant: &'ast AnonConst) { . // We deal with repeat expressions explicitly in `resolve_expr`. . self.resolve_anon_const(constant, IsRepeatExpr::No); . } . fn visit_expr(&mut self, expr: &'ast Expr) { 88,077 ( 0.01%) self.resolve_expr(expr, None); . } . fn visit_local(&mut self, local: &'ast Local) { . let local_spans = match local.pat.kind { . // We check for this to avoid tuple struct fields. . PatKind::Wild => None, . _ => Some(( . local.pat.span, . local.ty.as_ref().map(|ty| ty.span), . local.kind.init().map(|init| init.span), . )), . }; . let original = replace(&mut self.diagnostic_metadata.current_let_binding, local_spans); . self.resolve_local(local); . self.diagnostic_metadata.current_let_binding = original; . } 1,728 ( 0.00%) fn visit_ty(&mut self, ty: &'ast Ty) { 432 ( 0.00%) let prev = self.diagnostic_metadata.current_trait_object; 1,132 ( 0.00%) match ty.kind { 190 ( 0.00%) TyKind::Path(ref qself, ref path) => { 570 ( 0.00%) self.smart_resolve_path(ty.id, qself.as_ref(), path, PathSource::Type); . } . TyKind::ImplicitSelf => { . let self_ty = Ident::with_dummy_span(kw::SelfUpper); . let res = self 63 ( 0.00%) .resolve_ident_in_lexical_scope(self_ty, TypeNS, Some(ty.id), ty.span) 378 ( 0.00%) .map_or(Res::Err, |d| d.res()); 693 ( 0.00%) self.r.record_partial_res(ty.id, PartialRes::new(res)); . } . TyKind::TraitObject(ref bounds, ..) => { . self.diagnostic_metadata.current_trait_object = Some(&bounds[..]); . } . _ => (), . } 648 ( 0.00%) visit::walk_ty(self, ty); 432 ( 0.00%) self.diagnostic_metadata.current_trait_object = prev; 1,512 ( 0.00%) } . fn visit_poly_trait_ref(&mut self, tref: &'ast PolyTraitRef, m: &'ast TraitBoundModifier) { 6 ( 0.00%) self.smart_resolve_path( 2 ( 0.00%) tref.trait_ref.ref_id, . None, 2 ( 0.00%) &tref.trait_ref.path, 4 ( 0.00%) PathSource::Trait(AliasPossibility::Maybe), . ); . visit::walk_poly_trait_ref(self, tref, m); . } . fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) { . match foreign_item.kind { . ForeignItemKind::Fn(box Fn { ref generics, .. }) . | ForeignItemKind::TyAlias(box TyAlias { ref generics, .. }) => { . self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| { -- line 507 ---------------------------------------- -- line 513 ---------------------------------------- . visit::walk_foreign_item(this, foreign_item); . }); . } . ForeignItemKind::MacCall(..) => { . visit::walk_foreign_item(self, foreign_item); . } . } . } 576 ( 0.00%) fn visit_fn(&mut self, fn_kind: FnKind<'ast>, sp: Span, _: NodeId) { 1,040 ( 0.00%) let rib_kind = match fn_kind { . // Bail if the function is foreign, and thus cannot validly have . // a body, or if there's no body for some other reason. . FnKind::Fn(FnCtxt::Foreign, _, sig, ..) | FnKind::Fn(_, _, sig, .., None) => { . // We don't need to deal with patterns in parameters, because . // they are not possible for foreign or bodiless functions. . self.visit_fn_header(&sig.header); . visit::walk_fn_decl(self, &sig.decl); . return; . } . FnKind::Fn(FnCtxt::Free, ..) => FnItemRibKind, . FnKind::Fn(FnCtxt::Assoc(_), ..) => NormalRibKind, . FnKind::Closure(..) => ClosureOrAsyncRibKind, . }; 252 ( 0.00%) let previous_value = self.diagnostic_metadata.current_function; 72 ( 0.00%) if matches!(fn_kind, FnKind::Fn(..)) { 252 ( 0.00%) self.diagnostic_metadata.current_function = Some((fn_kind, sp)); . } . debug!("(resolving function) entering function"); 108 ( 0.00%) let declaration = fn_kind.decl(); . . // Create a value rib for the function. . self.with_rib(ValueNS, rib_kind, |this| { . // Create a label rib for the function. . this.with_label_rib(rib_kind, |this| { . // Add each argument to the rib. 72 ( 0.00%) this.resolve_params(&declaration.inputs); . . visit::walk_fn_ret_ty(this, &declaration.output); . . // Ignore errors in function bodies if this is rustdoc . // Be sure not to set this until the function signature has been resolved. . let previous_state = replace(&mut this.in_func_body, true); . // Resolve the function body, potentially inside the body of an async closure 72 ( 0.00%) match fn_kind { 180 ( 0.00%) FnKind::Fn(.., body) => walk_list!(this, visit_block, body), . FnKind::Closure(_, body) => this.visit_expr(body), . }; . . debug!("(resolving function) leaving function"); 36 ( 0.00%) this.in_func_body = previous_state; . }) . }); 216 ( 0.00%) self.diagnostic_metadata.current_function = previous_value; 288 ( 0.00%) } . 528 ( 0.00%) fn visit_generics(&mut self, generics: &'ast Generics) { . // For type parameter defaults, we have to ban access . // to following type parameters, as the InternalSubsts can only . // provide previous type parameters as they're built. We . // put all the parameters on the ban list and then remove . // them one by one as they are processed and become available. . let mut forward_ty_ban_rib = Rib::new(ForwardGenericParamBanRibKind); . let mut forward_const_ban_rib = Rib::new(ForwardGenericParamBanRibKind); . for param in generics.params.iter() { -- line 576 ---------------------------------------- -- line 593 ---------------------------------------- . // another type parameter. For ADTs, we consider it . // well-defined only after all of the ADT type parameters have . // been provided. Therefore, we do not allow use of `Self` . // anywhere in ADT type parameter defaults. . // . // (We however cannot ban `Self` for defaults on *all* generic . // lists; e.g. trait generics can usefully refer to `Self`, . // such as in the case of `trait Add`.) 66 ( 0.00%) if self.diagnostic_metadata.current_self_item.is_some() { . // (`Some` if + only if we are in ADT's generics.) . forward_ty_ban_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), Res::Err); . } . . for param in &generics.params { . match param.kind { . GenericParamKind::Lifetime => self.visit_generic_param(param), . GenericParamKind::Type { ref default } => { -- line 609 ---------------------------------------- -- line 645 ---------------------------------------- . .bindings . .remove(&Ident::with_dummy_span(param.ident.name)); . } . } . } . for p in &generics.where_clause.predicates { . self.visit_where_predicate(p); . } 528 ( 0.00%) } . . fn visit_generic_arg(&mut self, arg: &'ast GenericArg) { . debug!("visit_generic_arg({:?})", arg); . let prev = replace(&mut self.diagnostic_metadata.currently_processing_generics, true); . match arg { . GenericArg::Type(ref ty) => { . // We parse const arguments as path types as we cannot distinguish them during . // parsing. We try to resolve that ambiguity by attempting resolution the type -- line 661 ---------------------------------------- -- line 715 ---------------------------------------- . let previous_value = . replace(&mut self.diagnostic_metadata.current_where_predicate, Some(p)); . visit::walk_where_predicate(self, p); . self.diagnostic_metadata.current_where_predicate = previous_value; . } . } . . impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { 9 ( 0.00%) fn new(resolver: &'b mut Resolver<'a>) -> LateResolutionVisitor<'a, 'b, 'ast> { . // During late resolution we only track the module component of the parent scope, . // although it may be useful to track other components as well for diagnostics. 1 ( 0.00%) let graph_root = resolver.graph_root; . let parent_scope = ParentScope::module(graph_root, resolver); . let start_rib_kind = ModuleRibKind(graph_root); 30 ( 0.00%) LateResolutionVisitor { . r: resolver, . parent_scope, . ribs: PerNS { 2 ( 0.00%) value_ns: vec![Rib::new(start_rib_kind)], 2 ( 0.00%) type_ns: vec![Rib::new(start_rib_kind)], 2 ( 0.00%) macro_ns: vec![Rib::new(start_rib_kind)], . }, . label_ribs: Vec::new(), . current_trait_ref: None, . diagnostic_metadata: DiagnosticMetadata::default(), . // errors at module scope should always be reported . in_func_body: false, . } 9 ( 0.00%) } . . fn resolve_ident_in_lexical_scope( . &mut self, . ident: Ident, . ns: Namespace, . record_used_id: Option, . path_span: Span, . ) -> Option> { 1,063 ( 0.00%) self.r.resolve_ident_in_lexical_scope( . ident, . ns, 100 ( 0.00%) &self.parent_scope, . record_used_id, . path_span, . &self.ribs[ns], . ) . } . . fn resolve_path( . &mut self, . path: &[Segment], . opt_ns: Option, // `None` indicates a module path in import . record_used: bool, . path_span: Span, . crate_lint: CrateLint, . ) -> PathResult<'a> { 3,686 ( 0.00%) self.r.resolve_path_with_ribs( . path, . opt_ns, 1 ( 0.00%) &self.parent_scope, . record_used, . path_span, . crate_lint, 1 ( 0.00%) Some(&self.ribs), . ) . } . . // AST resolution . // . // We maintain a list of value ribs and type ribs. . // . // Simultaneously, we keep track of the current position in the module -- line 785 ---------------------------------------- -- line 798 ---------------------------------------- . . /// Do some `work` within a new innermost rib of the given `kind` in the given namespace (`ns`). . fn with_rib( . &mut self, . ns: Namespace, . kind: RibKind<'a>, . work: impl FnOnce(&mut Self) -> T, . ) -> T { 292 ( 0.00%) self.ribs[ns].push(Rib::new(kind)); . let ret = work(self); . self.ribs[ns].pop(); . ret . } . . fn with_scope(&mut self, id: NodeId, f: impl FnOnce(&mut Self) -> T) -> T { 8 ( 0.00%) if let Some(module) = self.r.get_module(self.r.local_def_id(id).to_def_id()) { . // Move down in the graph. . let orig_module = replace(&mut self.parent_scope.module, module); . self.with_rib(ValueNS, ModuleRibKind(module), |this| { . this.with_rib(TypeNS, ModuleRibKind(module), |this| { . let ret = f(this); 1 ( 0.00%) this.parent_scope.module = orig_module; . ret . }) . }) . } else { . f(self) . } . } . -- line 827 ---------------------------------------- -- line 908 ---------------------------------------- . let item_def_id = this.r.local_def_id(item.id).to_def_id(); . this.with_self_rib(Res::SelfTy(None, Some((item_def_id, false))), |this| { . visit::walk_item(this, item); . }); . }); . }); . } . 9 ( 0.00%) fn future_proof_import(&mut self, use_tree: &UseTree) { . let segments = &use_tree.prefix.segments; 1 ( 0.00%) if !segments.is_empty() { 2 ( 0.00%) let ident = segments[0].ident; 10 ( 0.00%) if ident.is_path_segment_keyword() || ident.span.rust_2015() { . return; . } . . let nss = match use_tree.kind { . UseTreeKind::Simple(..) if segments.len() == 1 => &[TypeNS, ValueNS][..], . _ => &[TypeNS], . }; . let report_error = |this: &Self, ns| { -- line 928 ---------------------------------------- -- line 952 ---------------------------------------- . None => {} . } . } . } else if let UseTreeKind::Nested(use_trees) = &use_tree.kind { . for (use_tree, _) in use_trees { . self.future_proof_import(use_tree); . } . } 8 ( 0.00%) } . 272 ( 0.00%) fn resolve_item(&mut self, item: &'ast Item) { . let name = item.ident.name; . debug!("(resolving item) resolving {} ({:?})", name, item.kind); . 204 ( 0.00%) match item.kind { . ItemKind::TyAlias(box TyAlias { ref generics, .. }) . | ItemKind::Fn(box Fn { ref generics, .. }) => { 4 ( 0.00%) self.compute_num_lifetime_params(item.id, generics); . self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| { 3 ( 0.00%) visit::walk_item(this, item) . }); . } . . ItemKind::Enum(_, ref generics) . | ItemKind::Struct(_, ref generics) . | ItemKind::Union(_, ref generics) => { . self.compute_num_lifetime_params(item.id, generics); . self.resolve_adt(item, generics); . } . . ItemKind::Impl(box Impl { 1 ( 0.00%) ref generics, . ref of_trait, . ref self_ty, . items: ref impl_items, . .. . }) => { 4 ( 0.00%) self.compute_num_lifetime_params(item.id, generics); 1 ( 0.00%) self.resolve_implementation(generics, of_trait, &self_ty, item.id, impl_items); . } . 1 ( 0.00%) ItemKind::Trait(box Trait { ref generics, ref bounds, ref items, .. }) => { 4 ( 0.00%) self.compute_num_lifetime_params(item.id, generics); . // Create a new rib for the trait-wide type parameters. . self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| { 2 ( 0.00%) let local_def_id = this.r.local_def_id(item.id).to_def_id(); . this.with_self_rib(Res::SelfTy(Some(local_def_id), None), |this| { 2 ( 0.00%) this.visit_generics(generics); . walk_list!(this, visit_param_bound, bounds); . 315 ( 0.00%) let walk_assoc_item = |this: &mut Self, generics, item| { . this.with_generic_param_rib(generics, AssocItemRibKind, |this| { 140 ( 0.00%) visit::walk_assoc_item(this, item, AssocCtxt::Trait) . }); 280 ( 0.00%) }; . . this.with_trait_items(items, |this| { . for item in items { 144 ( 0.00%) match &item.kind { . AssocItemKind::Const(_, ty, default) => { . this.visit_ty(ty); . // Only impose the restrictions of `ConstRibKind` for an . // actual constant expression in a provided default. . if let Some(expr) = default { . // We allow arbitrary const expressions inside of associated consts, . // even if they are potentially not const evaluatable. . // -- line 1018 ---------------------------------------- -- line 1021 ---------------------------------------- . this.with_constant_rib( . IsRepeatExpr::No, . true, . None, . |this| this.visit_expr(expr), . ); . } . } 70 ( 0.00%) AssocItemKind::Fn(box Fn { generics, .. }) => { 105 ( 0.00%) walk_assoc_item(this, generics, item); . } . AssocItemKind::TyAlias(box TyAlias { generics, .. }) => { . walk_assoc_item(this, generics, item); . } . AssocItemKind::MacCall(_) => { . panic!("unexpanded macro in resolve!") . } . }; -- line 1038 ---------------------------------------- -- line 1050 ---------------------------------------- . this.with_self_rib(Res::SelfTy(Some(local_def_id), None), |this| { . this.visit_generics(generics); . walk_list!(this, visit_param_bound, bounds); . }); . }); . } . . ItemKind::Mod(..) | ItemKind::ForeignMod(_) => { 1 ( 0.00%) self.with_scope(item.id, |this| { 3 ( 0.00%) visit::walk_item(this, item); . }); . } . 84 ( 0.00%) ItemKind::Static(ref ty, _, ref expr) | ItemKind::Const(_, ref ty, ref expr) => { . self.with_item_rib(HasGenericParams::No, |this| { 28 ( 0.00%) this.visit_ty(ty); 56 ( 0.00%) if let Some(expr) = expr { 112 ( 0.00%) let constant_item_kind = match item.kind { . ItemKind::Const(..) => ConstantItemKind::Const, . ItemKind::Static(..) => ConstantItemKind::Static, . _ => unreachable!(), . }; . // We already forbid generic params because of the above item rib, . // so it doesn't matter whether this is a trivial constant. . this.with_constant_rib( . IsRepeatExpr::No, . true, 140 ( 0.00%) Some((item.ident, constant_item_kind)), . |this| this.visit_expr(expr), . ); . } . }); . } . 1 ( 0.00%) ItemKind::Use(ref use_tree) => { 9 ( 0.00%) self.future_proof_import(use_tree); . } . . ItemKind::ExternCrate(..) | ItemKind::MacroDef(..) => { . // do nothing, these are just around to be encoded . } . . ItemKind::GlobalAsm(_) => { . visit::walk_item(self, item); . } . . ItemKind::MacCall(_) => panic!("unexpanded macro in resolve!"), . } 264 ( 0.00%) } . . fn with_generic_param_rib<'c, F>(&'c mut self, generics: &'c Generics, kind: RibKind<'a>, f: F) . where . F: FnOnce(&mut Self), . { . debug!("with_generic_param_rib"); 66 ( 0.00%) let mut function_type_rib = Rib::new(kind); . let mut function_value_rib = Rib::new(kind); . let mut seen_bindings = FxHashMap::default(); . . // We also can't shadow bindings from the parent item . if let AssocItemRibKind = kind { 35 ( 0.00%) let mut add_bindings_for_ns = |ns| { . let parent_rib = self.ribs[ns] . .iter() 245 ( 0.00%) .rfind(|r| matches!(r.kind, ItemRibKind(_))) . .expect("associated item outside of an item"); . seen_bindings . .extend(parent_rib.bindings.iter().map(|(ident, _)| (*ident, ident.span))); . }; . add_bindings_for_ns(ValueNS); . add_bindings_for_ns(TypeNS); . } . -- line 1122 ---------------------------------------- -- line 1145 ---------------------------------------- . GenericParamKind::Const { .. } => (&mut function_value_rib, DefKind::ConstParam), . _ => unreachable!(), . }; . let res = Res::Def(def_kind, self.r.local_def_id(param.id).to_def_id()); . self.r.record_partial_res(param.id, PartialRes::new(res)); . rib.bindings.insert(ident, res); . } . 618 ( 0.00%) self.ribs[ValueNS].push(function_value_rib); 528 ( 0.00%) self.ribs[TypeNS].push(function_type_rib); . . f(self); . . self.ribs[TypeNS].pop(); . self.ribs[ValueNS].pop(); . } . . fn with_label_rib(&mut self, kind: RibKind<'a>, f: impl FnOnce(&mut Self)) { 120 ( 0.00%) self.label_ribs.push(Rib::new(kind)); . f(self); . self.label_ribs.pop(); . } . . fn with_item_rib(&mut self, has_generic_params: HasGenericParams, f: impl FnOnce(&mut Self)) { . let kind = ItemRibKind(has_generic_params); . self.with_rib(ValueNS, kind, |this| this.with_rib(TypeNS, kind, f)) . } -- line 1171 ---------------------------------------- -- line 1195 ---------------------------------------- . }, . ) . }); . } . . fn with_current_self_type(&mut self, self_type: &Ty, f: impl FnOnce(&mut Self) -> T) -> T { . // Handle nested impls (inside fn bodies) . let previous_value = 1 ( 0.00%) replace(&mut self.diagnostic_metadata.current_self_type, Some(self_type.clone())); . let result = f(self); 27 ( 0.00%) self.diagnostic_metadata.current_self_type = previous_value; . result . } . . fn with_current_self_item(&mut self, self_item: &Item, f: impl FnOnce(&mut Self) -> T) -> T { . let previous_value = . replace(&mut self.diagnostic_metadata.current_self_item, Some(self_item.id)); . let result = f(self); . self.diagnostic_metadata.current_self_item = previous_value; -- line 1213 ---------------------------------------- -- line 1218 ---------------------------------------- . fn with_trait_items( . &mut self, . trait_items: &'ast [P], . f: impl FnOnce(&mut Self) -> T, . ) -> T { . let trait_assoc_items = . replace(&mut self.diagnostic_metadata.current_trait_assoc_items, Some(&trait_items)); . let result = f(self); 3 ( 0.00%) self.diagnostic_metadata.current_trait_assoc_items = trait_assoc_items; . result . } . . /// This is called to resolve a trait reference from an `impl` (i.e., `impl Trait for Foo`). 9 ( 0.00%) fn with_optional_trait_ref( . &mut self, . opt_trait_ref: Option<&TraitRef>, . f: impl FnOnce(&mut Self, Option) -> T, . ) -> T { 1 ( 0.00%) let mut new_val = None; . let mut new_id = None; 2 ( 0.00%) if let Some(trait_ref) = opt_trait_ref { . let path: Vec<_> = Segment::from_path(&trait_ref.path); 15 ( 0.00%) let res = self.smart_resolve_path_fragment( 1 ( 0.00%) trait_ref.ref_id, . None, . &path, 1 ( 0.00%) trait_ref.path.span, 1 ( 0.00%) PathSource::Trait(AliasPossibility::No), . CrateLint::SimplePath(trait_ref.ref_id), . ); . let res = res.base_res(); 1 ( 0.00%) if res != Res::Err { 13 ( 0.00%) if let PathResult::Module(ModuleOrUniformRoot::Module(module)) = self.resolve_path( . &path, . Some(TypeNS), . true, . trait_ref.path.span, 1 ( 0.00%) CrateLint::SimplePath(trait_ref.ref_id), . ) { . new_id = Some(res.def_id()); 10 ( 0.00%) new_val = Some((module, trait_ref.clone())); . } . } . } . let original_trait_ref = replace(&mut self.current_trait_ref, new_val); 7 ( 0.00%) let result = f(self, new_id); 18 ( 0.00%) self.current_trait_ref = original_trait_ref; . result 8 ( 0.00%) } . . fn with_self_rib_ns(&mut self, ns: Namespace, self_res: Res, f: impl FnOnce(&mut Self)) { . let mut self_type_rib = Rib::new(NormalRibKind); . . // Plain insert (no renaming, since types are not currently hygienic) . self_type_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), self_res); 33 ( 0.00%) self.ribs[ns].push(self_type_rib); . f(self); . self.ribs[ns].pop(); . } . . fn with_self_rib(&mut self, self_res: Res, f: impl FnOnce(&mut Self)) { . self.with_self_rib_ns(TypeNS, self_res, f) . } . -- line 1281 ---------------------------------------- -- line 1288 ---------------------------------------- . impl_items: &'ast [P], . ) { . debug!("resolve_implementation"); . // If applicable, create a rib for the type parameters. . self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| { . // Dummy self type for better errors if `Self` is used in the trait path. . this.with_self_rib(Res::SelfTy(None, None), |this| { . // Resolve the trait reference, if necessary. 10 ( 0.00%) this.with_optional_trait_ref(opt_trait_reference.as_ref(), |this, trait_id| { 2 ( 0.00%) let item_def_id = this.r.local_def_id(item_id); . . // Register the trait definitions from here. 2 ( 0.00%) if let Some(trait_id) = trait_id { 4 ( 0.00%) this.r.trait_impls.entry(trait_id).or_default().push(item_def_id); . } . . let item_def_id = item_def_id.to_def_id(); 1 ( 0.00%) this.with_self_rib(Res::SelfTy(trait_id, Some((item_def_id, false))), |this| { 1 ( 0.00%) if let Some(trait_ref) = opt_trait_reference.as_ref() { . // Resolve type arguments in the trait path. . visit::walk_trait_ref(this, trait_ref); . } . // Resolve the self type. 3 ( 0.00%) this.visit_ty(self_type); . // Resolve the generic parameters. 1 ( 0.00%) this.visit_generics(generics); . // Resolve the items within the impl. . this.with_current_self_type(self_type, |this| { . this.with_self_rib_ns(ValueNS, Res::SelfCtor(item_def_id), |this| { . debug!("resolve_implementation with_self_rib_ns(ValueNS, ...)"); 1 ( 0.00%) for item in impl_items { . use crate::ResolutionError::*; 168 ( 0.00%) match &item.kind { . AssocItemKind::Const(_default, _ty, _expr) => { . debug!("resolve_implementation AssocItemKind::Const"); . // If this is a trait impl, ensure the const . // exists in trait . this.check_trait_item( . item.id, . item.ident, . &item.kind, -- line 1328 ---------------------------------------- -- line 1344 ---------------------------------------- . visit::walk_assoc_item( . this, . item, . AssocCtxt::Impl, . ) . }, . ); . } 28 ( 0.00%) AssocItemKind::Fn(box Fn { generics, .. }) => { . debug!("resolve_implementation AssocItemKind::Fn"); . // We also need a new scope for the impl item type parameters. . this.with_generic_param_rib( . generics, . AssocItemRibKind, . |this| { . // If this is a trait impl, ensure the method . // exists in trait . this.check_trait_item( 28 ( 0.00%) item.id, 56 ( 0.00%) item.ident, . &item.kind, . ValueNS, 84 ( 0.00%) item.span, . |i, s, c| MethodNotMemberOfTrait(i, s, c), . ); . 56 ( 0.00%) visit::walk_assoc_item( . this, . item, . AssocCtxt::Impl, . ) . }, . ); . } . AssocItemKind::TyAlias(box TyAlias { -- line 1378 ---------------------------------------- -- line 1423 ---------------------------------------- . kind: &AssocItemKind, . ns: Namespace, . span: Span, . err: F, . ) where . F: FnOnce(Ident, &str, Option) -> ResolutionError<'_>, . { . // If there is a TraitRef in scope for an impl, then the method must be in the trait. 56 ( 0.00%) let Some((module, _)) = &self.current_trait_ref else { return; }; 168 ( 0.00%) ident.span.normalize_to_macros_2_0_and_adjust(module.expansion); 140 ( 0.00%) let key = self.r.new_key(ident, ns); 280 ( 0.00%) let mut binding = self.r.resolution(module, key).try_borrow().ok().and_then(|r| r.binding); . debug!(?binding); 28 ( 0.00%) if binding.is_none() { . // We could not find the trait item in the correct namespace. . // Check the other namespace to report an error. . let ns = match ns { . ValueNS => TypeNS, . TypeNS => ValueNS, . _ => ns, . }; . let key = self.r.new_key(ident, ns); -- line 1444 ---------------------------------------- -- line 1449 ---------------------------------------- . // We could not find the method: report an error. . let candidate = self.find_similarly_named_assoc_item(ident.name, kind); . let path = &self.current_trait_ref.as_ref().unwrap().1.path; . self.report_error(span, err(ident, &path_names_to_string(path), candidate)); . return; . }; . . let res = binding.res(); 56 ( 0.00%) let Res::Def(def_kind, _) = res else { bug!() }; 196 ( 0.00%) match (def_kind, kind) { . (DefKind::AssocTy, AssocItemKind::TyAlias(..)) . | (DefKind::AssocFn, AssocItemKind::Fn(..)) . | (DefKind::AssocConst, AssocItemKind::Const(..)) => { 392 ( 0.00%) self.r.record_partial_res(id, PartialRes::new(res)); . return; . } . _ => {} . } . . // The method kind does not correspond to what appeared in the trait, report. . let path = &self.current_trait_ref.as_ref().unwrap().1.path; . let (code, kind) = match kind { -- line 1470 ---------------------------------------- -- line 1480 ---------------------------------------- . kind, . code, . trait_path: path_names_to_string(path), . trait_item_span: binding.span, . }, . ); . } . 324 ( 0.00%) fn resolve_params(&mut self, params: &'ast [Param]) { 180 ( 0.00%) let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())]; 216 ( 0.00%) for Param { pat, ty, .. } in params { . self.resolve_pattern(pat, PatternSource::FnParam, &mut bindings); 148 ( 0.00%) self.visit_ty(ty); . debug!("(resolving function / closure) recorded parameter"); . } 288 ( 0.00%) } . . fn resolve_local(&mut self, local: &'ast Local) { . debug!("resolving local ({:?})", local); . // Resolve the type. . walk_list!(self, visit_ty, &local.ty); . . // Resolve the initializer. . if let Some((init, els)) = local.kind.init_else_opt() { -- line 1503 ---------------------------------------- -- line 1615 ---------------------------------------- . } . . // 5) Finally bubble up all the binding maps. . maps . } . . /// Check the consistency of the outermost or-patterns. . fn check_consistent_bindings_top(&mut self, pat: &'ast Pat) { 350 ( 0.00%) pat.walk(&mut |pat| match pat.kind { . PatKind::Or(ref ps) => { . self.check_consistent_bindings(ps); . false . } . _ => true, . }) . } . . fn resolve_arm(&mut self, arm: &'ast Arm) { . self.with_rib(ValueNS, NormalRibKind, |this| { . this.resolve_pattern_top(&arm.pat, PatternSource::Match); 13 ( 0.00%) walk_list!(this, visit_expr, &arm.guard); . this.visit_expr(&arm.body); . }); . } . . /// Arising from `source`, resolve a top level pattern. . fn resolve_pattern_top(&mut self, pat: &'ast Pat, pat_src: PatternSource) { 52 ( 0.00%) let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())]; . self.resolve_pattern(pat, pat_src, &mut bindings); . } . . fn resolve_pattern( . &mut self, . pat: &'ast Pat, . pat_src: PatternSource, . bindings: &mut SmallVec<[(PatBoundCtx, FxHashSet); 1]>, . ) { . // We walk the pattern before declaring the pattern's inner bindings, . // so that we avoid resolving a literal expression to a binding defined . // by the pattern. 150 ( 0.00%) visit::walk_pat(self, pat); . self.resolve_pattern_inner(pat, pat_src, bindings); . // This has to happen *after* we determine which pat_idents are variants: . self.check_consistent_bindings_top(pat); . } . . /// Resolve bindings in a pattern. This is a helper to `resolve_pattern`. . /// . /// ### `bindings` -- line 1663 ---------------------------------------- -- line 1679 ---------------------------------------- . /// See the implementation and `fresh_binding` for more details. . fn resolve_pattern_inner( . &mut self, . pat: &Pat, . pat_src: PatternSource, . bindings: &mut SmallVec<[(PatBoundCtx, FxHashSet); 1]>, . ) { . // Visit all direct subpatterns of this pattern. 400 ( 0.00%) pat.walk(&mut |pat| { . debug!("resolve_pattern pat={:?} node={:?}", pat, pat.kind); 237 ( 0.00%) match pat.kind { 148 ( 0.00%) PatKind::Ident(bmode, ident, ref sub) => { . // First try to resolve the identifier as some existing entity, . // then fall back to a fresh binding. . let has_sub = sub.is_some(); 407 ( 0.00%) let res = self . .try_resolve_as_non_binding(pat_src, pat, bmode, ident, has_sub) 407 ( 0.00%) .unwrap_or_else(|| self.fresh_binding(ident, pat.id, pat_src, bindings)); 259 ( 0.00%) self.r.record_partial_res(pat.id, PartialRes::new(res)); 111 ( 0.00%) self.r.record_pat_span(pat.id, pat.span); . } . PatKind::TupleStruct(ref qself, ref path, ref sub_patterns) => { . self.smart_resolve_path( . pat.id, . qself.as_ref(), . path, . PathSource::TupleStruct( . pat.span, -- line 1706 ---------------------------------------- -- line 1740 ---------------------------------------- . return false; . } . _ => {} . } . true . }); . } . 444 ( 0.00%) fn fresh_binding( . &mut self, . ident: Ident, . pat_id: NodeId, . pat_src: PatternSource, . bindings: &mut SmallVec<[(PatBoundCtx, FxHashSet); 1]>, . ) -> Res { . // Add the binding to the local ribs, if it doesn't already exist in the bindings map. . // (We must not add it if it's in the bindings map because that breaks the assumptions . // later passes make about or-patterns.) 185 ( 0.00%) let ident = ident.normalize_to_macro_rules(); . . let mut bound_iter = bindings.iter().filter(|(_, set)| set.contains(&ident)); . // Already bound in a product pattern? e.g. `(a, a)` which is not allowed. . let already_bound_and = bound_iter.clone().any(|(ctx, _)| *ctx == PatBoundCtx::Product); . // Already bound in an or-pattern? e.g. `V1(a) | V2(a)`. . // This is *required* for consistency which is checked later. . let already_bound_or = bound_iter.any(|(ctx, _)| *ctx == PatBoundCtx::Or); . 37 ( 0.00%) if already_bound_and { . // Overlap in a product pattern somewhere; report an error. . use ResolutionError::*; . let error = match pat_src { . // `fn f(a: u8, a: u8)`: . PatternSource::FnParam => IdentifierBoundMoreThanOnceInParameterList, . // `Variant(a, a)`: . _ => IdentifierBoundMoreThanOnceInSamePattern, . }; . self.report_error(ident.span, error(ident.name)); . } . . // Record as bound if it's valid: . let ident_valid = ident.name != kw::Empty; 37 ( 0.00%) if ident_valid { 74 ( 0.00%) bindings.last_mut().unwrap().1.insert(ident); . } . 37 ( 0.00%) if already_bound_or { . // `Variant1(a) | Variant2(a)`, ok . // Reuse definition from the first `a`. . self.innermost_rib_bindings(ValueNS)[&ident] . } else { . let res = Res::Local(pat_id); . if ident_valid { . // A completely fresh binding add to the set if it's valid. 74 ( 0.00%) self.innermost_rib_bindings(ValueNS).insert(ident, res); . } 296 ( 0.00%) res . } 333 ( 0.00%) } . . fn innermost_rib_bindings(&mut self, ns: Namespace) -> &mut IdentMap { . &mut self.ribs[ns].last_mut().unwrap().bindings . } . 481 ( 0.00%) fn try_resolve_as_non_binding( . &mut self, . pat_src: PatternSource, . pat: &Pat, . bm: BindingMode, . ident: Ident, . has_sub: bool, . ) -> Option { . // An immutable (no `mut`) by-value (no `ref`) binding pattern without . // a sub pattern (no `@ $pat`) is syntactically ambiguous as it could . // also be interpreted as a path to e.g. a constant, variant, etc. 74 ( 0.00%) let is_syntactic_ambiguity = !has_sub && bm == BindingMode::ByValue(Mutability::Not); . . let ls_binding = self.resolve_ident_in_lexical_scope(ident, ValueNS, None, pat.span)?; . let (res, binding) = match ls_binding { . LexicalScopeBinding::Item(binding) . if is_syntactic_ambiguity && binding.is_ambiguity() => . { . // For ambiguous bindings we don't know all their definitions and cannot check . // whether they can be shadowed by fresh bindings or not, so force an error. -- line 1822 ---------------------------------------- -- line 1882 ---------------------------------------- . None . } . _ => span_bug!( . ident.span, . "unexpected resolution for an identifier in pattern: {:?}", . res, . ), . } 333 ( 0.00%) } . . // High-level and context dependent path resolution routine. . // Resolves the path and records the resolution into definition map. . // If resolution fails tries several techniques to find likely . // resolution candidates, suggest imports or other help, and report . // errors in user friendly way. 2,568 ( 0.00%) fn smart_resolve_path( . &mut self, . id: NodeId, . qself: Option<&QSelf>, . path: &Path, . source: PathSource<'ast>, . ) { 3,210 ( 0.00%) self.smart_resolve_path_fragment( . id, . qself, . &Segment::from_path(path), 214 ( 0.00%) path.span, 856 ( 0.00%) source, . CrateLint::SimplePath(id), . ); . } . 3,010 ( 0.00%) fn smart_resolve_path_fragment( . &mut self, . id: NodeId, . qself: Option<&QSelf>, . path: &[Segment], . span: Span, . source: PathSource<'ast>, . crate_lint: CrateLint, . ) -> PartialRes { . tracing::debug!( . "smart_resolve_path_fragment(id={:?}, qself={:?}, path={:?})", . id, . qself, . path . ); 1,720 ( 0.00%) let ns = source.namespace(); . 1,290 ( 0.00%) let report_errors = |this: &mut Self, res: Option| { . if this.should_report_errs() { . let (err, candidates) = this.smart_resolve_report_errors(path, span, source, res); . . let def_id = this.parent_scope.module.nearest_parent_mod(); . let instead = res.is_some(); . let suggestion = . if res.is_none() { this.report_missing_type_error(path) } else { None }; . // get_from_node_id -- line 1939 ---------------------------------------- -- line 2014 ---------------------------------------- . err.cancel(); . } . . // We don't return `Some(parent_err)` here, because the error will . // be already printed as part of the `use` injections . None . }; . 4,730 ( 0.00%) let partial_res = match self.resolve_qpath_anywhere( . id, . qself, . path, . ns, . span, . source.defer_to_typeck(), . crate_lint, . ) { 1,290 ( 0.00%) Ok(Some(partial_res)) if partial_res.unresolved_segments() == 0 => { 1,505 ( 0.00%) if source.is_expected(partial_res.base_res()) || partial_res.base_res() == Res::Err . { 1,290 ( 0.00%) partial_res . } else { . report_errors(self, Some(partial_res.base_res())) . } . } . . Ok(Some(partial_res)) if source.defer_to_typeck() => { . // Not fully resolved associated item `T::A::B` or `::A::B` . // or `::A::B`. If `B` should be resolved in value namespace then -- line 2042 ---------------------------------------- -- line 2073 ---------------------------------------- . } . . PartialRes::new(Res::Err) . } . . _ => report_errors(self, None), . }; . 430 ( 0.00%) if !matches!(source, PathSource::TraitItem(..)) { . // Avoid recording definition of `A::B` in `::B::C`. 860 ( 0.00%) self.r.record_partial_res(id, partial_res); . } . . partial_res 1,720 ( 0.00%) } . . fn self_type_is_available(&mut self, span: Span) -> bool { . let binding = self.resolve_ident_in_lexical_scope( . Ident::with_dummy_span(kw::SelfUpper), . TypeNS, . None, . span, . ); -- line 2095 ---------------------------------------- -- line 2113 ---------------------------------------- . . #[inline] . /// If we're actually rustdoc then avoid giving a name resolution error for `cfg()` items. . fn should_report_errs(&self) -> bool { . !(self.r.session.opts.actually_rustdoc && self.in_func_body) . } . . // Resolve in alternative namespaces if resolution in the primary namespace fails. 2,795 ( 0.00%) fn resolve_qpath_anywhere( . &mut self, . id: NodeId, . qself: Option<&QSelf>, . path: &[Segment], . primary_ns: Namespace, . span: Span, . defer_to_typeck: bool, . crate_lint: CrateLint, . ) -> Result, Spanned>> { . let mut fin_res = None; . 1,505 ( 0.00%) for (i, &ns) in [primary_ns, TypeNS, ValueNS].iter().enumerate() { 430 ( 0.00%) if i == 0 || ns != primary_ns { 860 ( 0.00%) match self.resolve_qpath(id, qself, path, ns, span, crate_lint)? { . Some(partial_res) 1,290 ( 0.00%) if partial_res.unresolved_segments() == 0 || defer_to_typeck => . { 2,580 ( 0.00%) return Ok(Some(partial_res)); . } . partial_res => { . if fin_res.is_none() { . fin_res = partial_res; . } . } . } . } -- line 2147 ---------------------------------------- -- line 2155 ---------------------------------------- . if let Ok((_, res)) = . self.r.resolve_macro_path(&path, None, &self.parent_scope, false, false) . { . return Ok(Some(PartialRes::new(res))); . } . } . . Ok(fin_res) 1,720 ( 0.00%) } . . /// Handles paths that may refer to associated items. . fn resolve_qpath( . &mut self, . id: NodeId, . qself: Option<&QSelf>, . path: &[Segment], . ns: Namespace, -- line 2171 ---------------------------------------- -- line 2172 ---------------------------------------- . span: Span, . crate_lint: CrateLint, . ) -> Result, Spanned>> { . debug!( . "resolve_qpath(id={:?}, qself={:?}, path={:?}, ns={:?}, span={:?})", . id, qself, path, ns, span, . ); . 215 ( 0.00%) if let Some(qself) = qself { . if qself.position == 0 { . // This is a case like `::B`, where there is no . // trait to resolve. In that case, we leave the `B` . // segment to be resolved by type-check. . return Ok(Some(PartialRes::with_unresolved_segments( . Res::Def(DefKind::Mod, DefId::local(CRATE_DEF_INDEX)), . path.len(), . ))); -- line 2188 ---------------------------------------- -- line 2216 ---------------------------------------- . // have to be resolved by type-check, since that requires doing . // trait resolution. . return Ok(Some(PartialRes::with_unresolved_segments( . partial_res.base_res(), . partial_res.unresolved_segments() + path.len() - qself.position - 1, . ))); . } . 1,296 ( 0.00%) let result = match self.resolve_path(&path, Some(ns), true, span, crate_lint) { 2,756 ( 0.00%) PathResult::NonModule(path_res) => path_res, 12 ( 0.00%) PathResult::Module(ModuleOrUniformRoot::Module(module)) if !module.is_normal() => { . PartialRes::new(module.res().unwrap()) . } . // In `a(::assoc_item)*` `a` cannot be a module. If `a` does resolve to a module we . // don't report an error right away, but try to fallback to a primitive type. . // So, we are still able to successfully resolve something like . // . // use std::u8; // bring module u8 in scope . // fn f() -> u8 { // OK, resolves to primitive u8, not to std::u8 -- line 2234 ---------------------------------------- -- line 2248 ---------------------------------------- . PathResult::Module(ModuleOrUniformRoot::Module(module)) => { . PartialRes::new(module.res().unwrap()) . } . PathResult::Failed { is_error_from_last_segment: false, span, label, suggestion } => { . return Err(respan(span, ResolutionError::FailedToResolve { label, suggestion })); . } . PathResult::Module(..) | PathResult::Failed { .. } => return Ok(None), . PathResult::Indeterminate => bug!("indeterminate path result in resolve_qpath"), 1,075 ( 0.00%) }; . 355 ( 0.00%) if path.len() > 1 . && result.base_res() != Res::Err 28 ( 0.00%) && path[0].ident.name != kw::PathRoot . && path[0].ident.name != kw::DollarCrate . { . let unqualified_result = { 140 ( 0.00%) match self.resolve_path( 140 ( 0.00%) &[*path.last().unwrap()], . Some(ns), . false, . span, . CrateLint::No, . ) { . PathResult::NonModule(path_res) => path_res.base_res(), . PathResult::Module(ModuleOrUniformRoot::Module(module)) => { . module.res().unwrap() . } 112 ( 0.00%) _ => return Ok(Some(result)), . } . }; . if result.base_res() == unqualified_result { . let lint = lint::builtin::UNUSED_QUALIFICATIONS; . self.r.lint_buffer.buffer_lint(lint, id, span, "unnecessary qualification") . } . } . 748 ( 0.00%) Ok(Some(result)) . } . . fn with_resolved_label(&mut self, label: Option