-------------------------------------------------------------------------------- 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 language_tags --edition=2018 src/lib.rs --error-format=json --json=diagnostic-rendered-ansi,artifacts,future-incompat --crate-type lib --emit=dep-info,metadata -C embed-bitcode=no -C debuginfo=2 -C metadata=aaee50e6aad6f6d4 -C extra-filename=-aaee50e6aad6f6d4 --out-dir /usr/home/liquid/tmp/.tmp6B3QFv/target/debug/deps -L dependency=/usr/home/liquid/tmp/.tmp6B3QFv/target/debug/deps -Adeprecated -Aunknown-lints -Zincremental-verify-ich Data file: results/cgout-w-profiling-language-tags-0.3.2-Check-Full Events recorded: Ir Events shown: Ir Event sort order: Ir Thresholds: 0.1 Include dirs: User annotated: Auto-annotation: on -------------------------------------------------------------------------------- Ir -------------------------------------------------------------------------------- 3,937,161,001 (100.0%) PROGRAM TOTALS -------------------------------------------------------------------------------- Ir file:function -------------------------------------------------------------------------------- 120,808,669 ( 3.07%) ./malloc/malloc.c:_int_malloc 102,788,097 ( 2.61%) ./malloc/malloc.c:_int_free 81,576,303 ( 2.07%) ./string/../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S:__memcpy_avx_unaligned_erms 66,340,086 ( 1.68%) ./malloc/malloc.c:malloc 40,189,611 ( 1.02%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_index/src/bit_set.rs:>::union::> 28,636,536 ( 0.73%) ./malloc/malloc.c:free 23,985,114 ( 0.61%) ./malloc/malloc.c:malloc_consolidate 19,814,826 ( 0.50%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_index/src/bit_set.rs:>::union::> 18,127,768 ( 0.46%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_const_eval/src/interpret/step.rs:>::run 16,671,744 ( 0.42%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_const_eval/src/interpret/operand.rs:>::try_read_immediate 15,443,647 ( 0.39%) /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/hashbrown-0.12.0/src/raw/mod.rs:>>::from_key_hashed_nocheck:: 14,864,912 ( 0.38%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_const_eval/src/interpret/operand.rs:>::eval_operand 14,775,779 ( 0.38%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs:rustc_mir_dataflow::drop_flag_effects::on_all_children_bits::is_terminal_path 14,507,357 ( 0.37%) ./malloc/malloc.c:unlink_chunk.constprop.0 13,956,497 ( 0.35%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_parse/src/lexer/mod.rs:::next_token 13,598,008 ( 0.35%) /usr/home/liquid/rust/worktree-benchmarking/library/core/src/result.rs:>::run 12,222,637 ( 0.31%) /usr/home/liquid/rust/worktree-benchmarking/library/core/src/num/uint_macros.rs:::short_write_process_buffer:: 12,083,445 ( 0.31%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_parse/src/parser/mod.rs:::check 11,958,560 ( 0.30%) /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::> 11,446,155 ( 0.29%) /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/hashbrown-0.12.0/src/raw/mod.rs:>>::get:: 10,731,429 ( 0.27%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_const_eval/src/interpret/place.rs:>::force_allocation_maybe_sized 10,342,405 ( 0.26%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_parse/src/lexer/tokentrees.rs:::parse_token_tree 10,305,124 ( 0.26%) ./elf/dl-lookup.c:_dl_lookup_symbol_x 10,274,957 ( 0.26%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_span/src/caching_source_map_view.rs:::span_data_to_lines_and_cols 10,065,758 ( 0.26%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_const_eval/src/interpret/place.rs:>::copy_op_no_validate 9,997,020 ( 0.25%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_borrowck/src/lib.rs:::access_place 9,919,577 ( 0.25%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_const_eval/src/interpret/place.rs:>::eval_place 9,915,777 ( 0.25%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_ast_pretty/src/pp/ring.rs:>::pop_first 9,181,611 ( 0.23%) /usr/home/liquid/rust/worktree-benchmarking/library/alloc/src/collections/vec_deque/mod.rs:>::push_back 8,653,265 ( 0.22%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_ast_pretty/src/pp.rs:::advance_left 8,648,877 ( 0.22%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_lexer/src/lib.rs:::advance_token 8,294,335 ( 0.21%) /usr/home/liquid/rust/worktree-benchmarking/library/std/src/sys/unix/alloc.rs:__rdl_alloc 8,225,479 ( 0.21%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_ast/src/token.rs:::clone 8,199,036 ( 0.21%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_data_structures/src/sip128.rs:::short_write_process_buffer:: 8,198,208 ( 0.21%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_middle/src/hir/map/mod.rs:::attrs 8,044,114 ( 0.20%) /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/hashbrown-0.12.0/src/raw/mod.rs:, (), core::hash::BuildHasherDefault>>::from_hash::>::{closure#0}> 7,951,900 ( 0.20%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_span/src/lib.rs:>::hash_stable 7,877,075 ( 0.20%) /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/hashbrown-0.12.0/src/raw/mod.rs:>::reserve_rehash::>::{closure#0}> 7,721,981 ( 0.20%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_parse/src/parser/mod.rs:::next 7,610,013 ( 0.19%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_const_eval/src/interpret/operand.rs:>::access_local 7,587,544 ( 0.19%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_parse/src/parser/mod.rs:::bump 7,459,902 ( 0.19%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_middle/src/middle/region.rs:::temporary_scope 7,437,264 ( 0.19%) /usr/home/liquid/rust/worktree-benchmarking/library/core/src/iter/adapters/zip.rs:>::union::> 7,391,140 ( 0.19%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_resolve/src/lib.rs:::traits_in_scope 7,112,401 ( 0.18%) /usr/home/liquid/rust/worktree-benchmarking/library/core/src/option.rs:::advance_left 7,012,179 ( 0.18%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_mir_build/src/thir/cx/expr.rs:::mirror_expr_inner 6,881,574 ( 0.17%) /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/hashbrown-0.12.0/src/raw/mod.rs:, (), core::hash::BuildHasherDefault>>::from_hash::, rustc_middle::ty::context::Interned>::{closure#0}> 6,839,026 ( 0.17%) /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/hashbrown-0.12.0/src/raw/mod.rs:::node_type_opt 6,686,366 ( 0.17%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_ast/src/token.rs:::eq 6,612,273 ( 0.17%) /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/smallvec-1.7.0/src/lib.rs:>::try_reserve 6,604,702 ( 0.17%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_index/src/bit_set.rs:>::union::> 6,557,840 ( 0.17%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_metadata/src/rmeta/encoder.rs:>::encode 6,345,043 ( 0.16%) /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/hashbrown-0.12.0/src/raw/mod.rs:>>::insert 6,332,250 ( 0.16%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_middle/src/ty/context.rs:::maybe_lint_level_root_bounded 6,279,499 ( 0.16%) ./malloc/malloc.c:calloc 6,259,238 ( 0.16%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_privacy/src/lib.rs: as rustc_middle::ty::fold::TypeVisitor>::visit_ty 6,155,727 ( 0.16%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_middle/src/mir/terminator.rs:::successors 6,152,350 ( 0.16%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_middle/src/mir/traversal.rs:::traverse_successor 6,147,725 ( 0.16%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs:rustc_mir_dataflow::drop_flag_effects::drop_flag_effects_for_location::<::statement_effect>::{closure#0}> 6,066,780 ( 0.15%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_middle/src/hir/map/mod.rs:::find_parent_node 5,934,431 ( 0.15%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_resolve/src/lib.rs:::resolutions 5,851,917 ( 0.15%) /usr/home/liquid/rust/worktree-benchmarking/library/core/src/slice/mod.rs:::lookup_source_file_idx 5,734,827 ( 0.15%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_mir_build/src/thir/cx/expr.rs:::make_mirror_unadjusted 5,686,959 ( 0.14%) /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/hashbrown-0.12.0/src/map.rs:>>::from_key_hashed_nocheck:: 5,641,100 ( 0.14%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs:rustc_mir_dataflow::drop_flag_effects::drop_flag_effects_for_location::<::statement_effect>::{closure#0}> 5,533,678 ( 0.14%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_data_structures/src/sip128.rs:>::hash_stable 5,493,460 ( 0.14%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_middle/src/mir/interpret/allocation.rs:::set_range_inbounds 5,363,415 ( 0.14%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_middle/src/ty/layout.rs: as rustc_middle::ty::layout::LayoutOf>::layout_of 5,341,377 ( 0.14%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_const_eval/src/interpret/operand.rs:>::eval_place_to_op 5,283,846 ( 0.13%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_middle/src/middle/region.rs:>>::get:: 5,201,883 ( 0.13%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_ast/src/tokenstream.rs:::next_with_spacing 5,165,949 ( 0.13%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_infer/src/infer/mod.rs:::shallow_resolve_ty 5,135,536 ( 0.13%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_middle/src/ty/subst.rs:::fold_ty 5,131,615 ( 0.13%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_typeck/src/check/regionck.rs:::visit_expr 5,084,794 ( 0.13%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_const_eval/src/interpret/eval_context.rs:>::subst_from_frame_and_normalize_erasing_regions::<&rustc_middle::ty::TyS> 5,007,392 ( 0.13%) ./malloc/malloc.c:realloc 4,873,399 ( 0.12%) /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/hashbrown-0.12.0/src/raw/mod.rs:, rustc_query_system::dep_graph::graph::DepNodeIndex), core::hash::BuildHasherDefault>>::from_key_hashed_nocheck:: 4,865,376 ( 0.12%) /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 4,854,658 ( 0.12%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_lint/src/levels.rs:::push 4,835,679 ( 0.12%) ./elf/dl-lookup.c:do_lookup_x 4,829,550 ( 0.12%) /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/hashbrown-0.12.0/src/raw/mod.rs:>>::from_key_hashed_nocheck:: 4,779,943 ( 0.12%) /usr/home/liquid/rust/worktree-benchmarking/library/core/src/slice/iter/macros.rs:::traits_in_scope 4,768,220 ( 0.12%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_typeck/src/check/writeback.rs:::visit_node_id 4,732,284 ( 0.12%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_const_eval/src/interpret/eval_context.rs:>::eval_place 4,654,816 ( 0.12%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_const_eval/src/interpret/place.rs:>::write_immediate_no_validate 4,636,309 ( 0.12%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_const_eval/src/interpret/place.rs:>::place_field 4,611,492 ( 0.12%) /usr/home/liquid/rust/worktree-benchmarking/library/core/src/cell.rs:::attrs 4,582,167 ( 0.12%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_infer/src/infer/undo_log.rs:::rollback_to 4,564,049 ( 0.12%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_mir_build/src/build/expr/as_operand.rs:::as_operand 4,547,752 ( 0.12%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_const_eval/src/interpret/operand.rs:>::const_val_to_op 4,523,275 ( 0.11%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_middle/src/ty/layout.rs:<&rustc_middle::ty::TyS as rustc_target::abi::TyAbiInterface>>::ty_and_layout_field 4,522,973 ( 0.11%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_parse/src/parser/expr.rs:::parse_assoc_expr_with 4,507,942 ( 0.11%) /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/hashbrown-0.12.0/src/raw/mod.rs:>::insert::>::{closure#0}> 4,503,492 ( 0.11%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_const_eval/src/interpret/memory.rs:>::copy_repeatedly 4,498,775 ( 0.11%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_typeck/src/check/coercion.rs:::coerce 4,439,417 ( 0.11%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_parse/src/lexer/tokentrees.rs:::push 4,432,494 ( 0.11%) /usr/home/liquid/rust/worktree-benchmarking/library/alloc/src/vec/into_iter.rs:> as core::ops::drop::Drop>::drop 4,403,160 ( 0.11%) /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/smallvec-1.7.0/src/lib.rs: as core::iter::traits::collect::Extend>::extend::>> 4,403,160 ( 0.11%) /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/smallvec-1.7.0/src/lib.rs: as core::iter::traits::collect::Extend>::extend::>> 4,372,097 ( 0.11%) /usr/home/liquid/rust/worktree-benchmarking/library/core/src/ptr/mod.rs:>::truncate 4,369,750 ( 0.11%) /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 4,360,953 ( 0.11%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_typeck/src/check/expr.rs:::check_expr_with_expectation_and_args 4,338,784 ( 0.11%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_middle/src/ty/context.rs:::lang_items 4,256,098 ( 0.11%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_const_eval/src/interpret/place.rs:>::try_read_immediate 4,249,869 ( 0.11%) /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} 4,141,271 ( 0.11%) ./elf/../sysdeps/x86_64/dl-machine.h:_dl_relocate_object 4,137,753 ( 0.11%) /usr/home/liquid/rust/worktree-benchmarking/library/alloc/src/collections/vec_deque/mod.rs:::advance_left 4,122,884 ( 0.10%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_ast_pretty/src/pp.rs:::scan_string 4,071,839 ( 0.10%) /usr/home/liquid/rust/worktree-benchmarking/library/core/src/../../stdarch/crates/core_arch/src/x86/sse2.rs:>>::from_key_hashed_nocheck:: 4,055,155 ( 0.10%) /usr/home/liquid/rust/worktree-benchmarking/library/core/src/slice/index.rs:>::run 4,046,229 ( 0.10%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_middle/src/ty/layout.rs:<&rustc_middle::ty::TyS as rustc_target::abi::TyAbiInterface<_>>::ty_and_layout_field::field_ty_or_layout::> 4,021,002 ( 0.10%) /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/hashbrown-0.12.0/src/raw/mod.rs:>::reserve_rehash::>::{closure#0}> 4,002,453 ( 0.10%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_const_eval/src/interpret/memory.rs:>::get_size_and_align 4,000,388 ( 0.10%) /usr/home/liquid/rust/worktree-benchmarking/library/alloc/src/vec/mod.rs:>::run 3,999,989 ( 0.10%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_ast/src/token.rs:::ident 3,956,093 ( 0.10%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_serialize/src/leb128.rs:>::encode 3,946,416 ( 0.10%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_borrowck/src/type_check/mod.rs:::typeck_mir 3,943,167 ( 0.10%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_mir_dataflow/src/impls/mod.rs:::apply_effects_in_block:: -------------------------------------------------------------------------------- -- Auto-annotated source: /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_mir_dataflow/src/impls/mod.rs -------------------------------------------------------------------------------- Ir -- line 65 ---------------------------------------- . /// places that would require a dynamic drop-flag at that statement. . pub struct MaybeInitializedPlaces<'a, 'tcx> { . tcx: TyCtxt<'tcx>, . body: &'a Body<'tcx>, . mdpe: &'a MoveDataParamEnv<'tcx>, . } . . impl<'a, 'tcx> MaybeInitializedPlaces<'a, 'tcx> { 416 ( 0.00%) pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>) -> Self { 1,248 ( 0.00%) MaybeInitializedPlaces { tcx, body, mdpe } 416 ( 0.00%) } . } . . impl<'a, 'tcx> HasMoveData<'tcx> for MaybeInitializedPlaces<'a, 'tcx> { . fn move_data(&self) -> &MoveData<'tcx> { 780 ( 0.00%) &self.mdpe.move_data . } . } . . /// `MaybeUninitializedPlaces` tracks all places that might be . /// uninitialized upon reaching a particular point in the control flow . /// for a function. . /// . /// For example, in code like the following, we have corresponding -- line 88 ---------------------------------------- -- line 120 ---------------------------------------- . tcx: TyCtxt<'tcx>, . body: &'a Body<'tcx>, . mdpe: &'a MoveDataParamEnv<'tcx>, . . mark_inactive_variants_as_uninit: bool, . } . . impl<'a, 'tcx> MaybeUninitializedPlaces<'a, 'tcx> { 208 ( 0.00%) pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>) -> Self { 832 ( 0.00%) MaybeUninitializedPlaces { tcx, body, mdpe, mark_inactive_variants_as_uninit: false } 208 ( 0.00%) } . . /// Causes inactive enum variants to be marked as "maybe uninitialized" after a switch on an . /// enum discriminant. . /// . /// This is correct in a vacuum but is not the default because it causes problems in the borrow . /// checker, where this information gets propagated along `FakeEdge`s. 50 ( 0.00%) pub fn mark_inactive_variants_as_uninit(mut self) -> Self { 50 ( 0.00%) self.mark_inactive_variants_as_uninit = true; 600 ( 0.00%) self 50 ( 0.00%) } . } . . impl<'a, 'tcx> HasMoveData<'tcx> for MaybeUninitializedPlaces<'a, 'tcx> { . fn move_data(&self) -> &MoveData<'tcx> { 41,130 ( 0.00%) &self.mdpe.move_data 40,500 ( 0.00%) } . } . . /// `DefinitelyInitializedPlaces` tracks all places that are definitely . /// initialized upon reaching a particular point in the control flow . /// for a function. . /// . /// For example, in code like the following, we have corresponding . /// dataflow information shown in the right-hand comments. -- line 154 ---------------------------------------- -- line 189 ---------------------------------------- . impl<'a, 'tcx> DefinitelyInitializedPlaces<'a, 'tcx> { . pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>) -> Self { . DefinitelyInitializedPlaces { tcx, body, mdpe } . } . } . . impl<'a, 'tcx> HasMoveData<'tcx> for DefinitelyInitializedPlaces<'a, 'tcx> { . fn move_data(&self) -> &MoveData<'tcx> { 209,375 ( 0.01%) &self.mdpe.move_data 209,375 ( 0.01%) } . } . . /// `EverInitializedPlaces` tracks all places that might have ever been . /// initialized upon reaching a particular point in the control flow . /// for a function, without an intervening `StorageDead`. . /// . /// This dataflow is used to determine if an immutable local variable may . /// be assigned to. -- line 206 ---------------------------------------- -- line 237 ---------------------------------------- . impl<'a, 'tcx> EverInitializedPlaces<'a, 'tcx> { . pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>) -> Self { . EverInitializedPlaces { tcx, body, mdpe } . } . } . . impl<'a, 'tcx> HasMoveData<'tcx> for EverInitializedPlaces<'a, 'tcx> { . fn move_data(&self) -> &MoveData<'tcx> { 480 ( 0.00%) &self.mdpe.move_data . } . } . . impl<'a, 'tcx> MaybeInitializedPlaces<'a, 'tcx> { . fn update_bits( . trans: &mut impl GenKill, . path: MovePathIndex, . state: DropFlagState, -- line 253 ---------------------------------------- -- line 284 ---------------------------------------- . } . } . } . . impl<'tcx> AnalysisDomain<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { . type Domain = BitSet; . const NAME: &'static str = "maybe_init"; . 3,900 ( 0.00%) fn bottom_value(&self, _: &mir::Body<'tcx>) -> Self::Domain { . // bottom = uninitialized . BitSet::new_empty(self.move_data().move_paths.len()) 5,460 ( 0.00%) } . 258 ( 0.00%) fn initialize_start_block(&self, _: &mir::Body<'tcx>, state: &mut Self::Domain) { 1,290 ( 0.00%) drop_flag_effects_for_function_entry(self.tcx, self.body, self.mdpe, |path, s| { . assert!(s == DropFlagState::Present); 173 ( 0.00%) state.insert(path); . }); . } . } . . impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { . type Idx = MovePathIndex; . . fn statement_effect( . &self, . trans: &mut impl GenKill, . statement: &mir::Statement<'tcx>, . location: Location, . ) { 1,358,836 ( 0.03%) drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| { 162,095 ( 0.00%) Self::update_bits(trans, path, s) . }); . 487,878 ( 0.01%) if !self.tcx.sess.opts.debugging_opts.precise_enum_drop_elaboration { . return; . } . . // Mark all places as "maybe init" if they are mutably borrowed. See #90752. . for_each_mut_borrow(statement, location, |place| { 875 ( 0.00%) let LookupResult::Exact(mpi) = self.move_data().rev_lookup.find(place.as_ref()) else { return }; 511 ( 0.00%) on_all_children_bits(self.tcx, self.body, self.move_data(), mpi, |child| { 30,366 ( 0.00%) trans.gen(child); . }) . }) . } . . fn terminator_effect( . &self, . trans: &mut impl GenKill, . terminator: &mir::Terminator<'tcx>, . location: Location, . ) { 324,957 ( 0.01%) drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| { . Self::update_bits(trans, path, s) . }); . 94,089 ( 0.00%) if !self.tcx.sess.opts.debugging_opts.precise_enum_drop_elaboration { . return; . } . . for_each_mut_borrow(terminator, location, |place| { . let LookupResult::Exact(mpi) = self.move_data().rev_lookup.find(place.as_ref()) else { return }; . on_all_children_bits(self.tcx, self.body, self.move_data(), mpi, |child| { . trans.gen(child); . }) -- line 349 ---------------------------------------- -- line 351 ---------------------------------------- . } . . fn call_return_effect( . &self, . trans: &mut impl GenKill, . _block: mir::BasicBlock, . return_places: CallReturnPlaces<'_, 'tcx>, . ) { 52,255 ( 0.00%) return_places.for_each(|place| { . // when a call returns successfully, that means we need to set . // the bits for that dest_place to 1 (initialized). . on_lookup_result_bits( 60,586 ( 0.00%) self.tcx, 30,293 ( 0.00%) self.body, 121,172 ( 0.00%) self.move_data(), 121,172 ( 0.00%) self.move_data().rev_lookup.find(place.as_ref()), . |mpi| { . trans.gen(mpi); . }, . ); . }); . } . . fn switch_int_edge_effects>( . &self, . block: mir::BasicBlock, . discr: &mir::Operand<'tcx>, . edge_effects: &mut impl SwitchIntEdgeEffects, . ) { 992 ( 0.00%) if !self.tcx.sess.opts.debugging_opts.precise_enum_drop_elaboration { . return; . } . 496 ( 0.00%) let enum_ = discr.place().and_then(|discr| { 976 ( 0.00%) switch_on_enum_discriminant(self.tcx, &self.body, &self.body[block], discr) . }); . 882 ( 0.00%) let (enum_place, enum_def) = match enum_ { 150 ( 0.00%) Some(x) => x, . None => return, . }; . . let mut discriminants = enum_def.discriminants(self.tcx); 525 ( 0.00%) edge_effects.apply(|trans, edge| { . let value = match edge.value { . Some(x) => x, . None => return, . }; . . // MIR building adds discriminants to the `values` array in the same order as they . // are yielded by `AdtDef::discriminants`. We rely on this to match each . // discriminant in `values` to its corresponding variant in linear time. . let (variant, _) = discriminants 1,076 ( 0.00%) .find(|&(_, discr)| discr.val == value) . .expect("Order of `AdtDef::discriminants` differed from `SwitchInt::values`"); . . // Kill all move paths that correspond to variants we know to be inactive along this . // particular outgoing edge of a `SwitchInt`. 994 ( 0.00%) drop_flag_effects::on_all_inactive_variants( 142 ( 0.00%) self.tcx, 142 ( 0.00%) self.body, 426 ( 0.00%) self.move_data(), 284 ( 0.00%) enum_place, . variant, . |mpi| trans.kill(mpi), . ); . }); . } . } . . impl<'tcx> AnalysisDomain<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { . type Domain = BitSet; . . const NAME: &'static str = "maybe_uninit"; . 3,150 ( 0.00%) fn bottom_value(&self, _: &mir::Body<'tcx>) -> Self::Domain { . // bottom = initialized (start_block_effect counters this at outset) . BitSet::new_empty(self.move_data().move_paths.len()) 4,410 ( 0.00%) } . . // sets on_entry bits for Arg places 1,040 ( 0.00%) fn initialize_start_block(&self, _: &mir::Body<'tcx>, state: &mut Self::Domain) { . // set all bits to 1 (uninit) before gathering counterevidence . state.insert_all(); . 1,664 ( 0.00%) drop_flag_effects_for_function_entry(self.tcx, self.body, self.mdpe, |path, s| { . assert!(s == DropFlagState::Present); 170 ( 0.00%) state.remove(path); . }); . } . } . . impl<'tcx> GenKillAnalysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { . type Idx = MovePathIndex; . . fn statement_effect( . &self, . trans: &mut impl GenKill, . _statement: &mir::Statement<'tcx>, . location: Location, . ) { 1,115,879 ( 0.03%) drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| { 166,643 ( 0.00%) Self::update_bits(trans, path, s) . }); . . // Unlike in `MaybeInitializedPlaces` above, we don't need to change the state when a . // mutable borrow occurs. Places cannot become uninitialized through a mutable reference. . } . . fn terminator_effect( . &self, . trans: &mut impl GenKill, . _terminator: &mir::Terminator<'tcx>, . location: Location, . ) { 123,976 ( 0.00%) drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| { . Self::update_bits(trans, path, s) . }); . } . . fn call_return_effect( . &self, . trans: &mut impl GenKill, . _block: mir::BasicBlock, . return_places: CallReturnPlaces<'_, 'tcx>, . ) { 51,645 ( 0.00%) return_places.for_each(|place| { . // when a call returns successfully, that means we need to set . // the bits for that dest_place to 0 (initialized). . on_lookup_result_bits( 40,500 ( 0.00%) self.tcx, 20,250 ( 0.00%) self.body, 81,000 ( 0.00%) self.move_data(), 81,000 ( 0.00%) self.move_data().rev_lookup.find(place.as_ref()), . |mpi| { 20,250 ( 0.00%) trans.kill(mpi); . }, . ); . }); . } . . fn switch_int_edge_effects>( . &self, . block: mir::BasicBlock, . discr: &mir::Operand<'tcx>, . edge_effects: &mut impl SwitchIntEdgeEffects, . ) { 716 ( 0.00%) if !self.tcx.sess.opts.debugging_opts.precise_enum_drop_elaboration { . return; . } . 358 ( 0.00%) if !self.mark_inactive_variants_as_uninit { . return; . } . . let enum_ = discr.place().and_then(|discr| { . switch_on_enum_discriminant(self.tcx, &self.body, &self.body[block], discr) . }); . . let (enum_place, enum_def) = match enum_ { -- line 510 ---------------------------------------- -- line 609 ---------------------------------------- . } . } . . impl<'tcx> AnalysisDomain<'tcx> for EverInitializedPlaces<'_, 'tcx> { . type Domain = BitSet; . . const NAME: &'static str = "ever_init"; . 2,400 ( 0.00%) fn bottom_value(&self, _: &mir::Body<'tcx>) -> Self::Domain { . // bottom = no initialized variables by default . BitSet::new_empty(self.move_data().inits.len()) 3,360 ( 0.00%) } . 158 ( 0.00%) fn initialize_start_block(&self, body: &mir::Body<'tcx>, state: &mut Self::Domain) { 158 ( 0.00%) for arg_init in 0..body.arg_count { . state.insert(InitIndex::new(arg_init)); . } 316 ( 0.00%) } . } . . impl<'tcx> GenKillAnalysis<'tcx> for EverInitializedPlaces<'_, 'tcx> { . type Idx = InitIndex; . 45,638 ( 0.00%) #[instrument(skip(self, trans), level = "debug")] . fn statement_effect( . &self, . trans: &mut impl GenKill, . stmt: &mir::Statement<'tcx>, . location: Location, . ) { 115,244 ( 0.00%) let move_data = self.move_data(); . let init_path_map = &move_data.init_path_map; . let init_loc_map = &move_data.init_loc_map; . let rev_lookup = &move_data.rev_lookup; . . debug!("initializes move_indexes {:?}", &init_loc_map[location]); . trans.gen_all(init_loc_map[location].iter().copied()); . 275,522 ( 0.01%) if let mir::StatementKind::StorageDead(local) = stmt.kind { . // End inits for StorageDead, so that an immutable variable can . // be reinitialized on the next iteration of the loop. 45,034 ( 0.00%) let move_path_index = rev_lookup.find_local(local); . debug!("clears the ever initialized status of {:?}", init_path_map[move_path_index]); . trans.kill_all(init_path_map[move_path_index].iter().copied()); . } . } . 10,134 ( 0.00%) #[instrument(skip(self, trans, _terminator), level = "debug")] . fn terminator_effect( . &self, . trans: &mut impl GenKill, . _terminator: &mir::Terminator<'tcx>, . location: Location, . ) { 45,456 ( 0.00%) let (body, move_data) = (self.body, self.move_data()); . let term = body[location.block].terminator(); . let init_loc_map = &move_data.init_loc_map; . debug!(?term); . debug!("initializes move_indexes {:?}", init_loc_map[location]); . trans.gen_all( . init_loc_map[location] . .iter() . .filter(|init_index| { 41,316 ( 0.00%) move_data.inits[**init_index].kind != InitKind::NonPanicPathOnly . }) . .copied(), . ); . } . . fn call_return_effect( . &self, . trans: &mut impl GenKill, . block: mir::BasicBlock, . _return_places: CallReturnPlaces<'_, 'tcx>, . ) { 10,451 ( 0.00%) let move_data = self.move_data(); . let init_loc_map = &move_data.init_loc_map; . 10,451 ( 0.00%) let call_loc = self.body.terminator_loc(block); . for init_index in &init_loc_map[call_loc] { 10,451 ( 0.00%) trans.gen(*init_index); . } . } . } . . /// Inspect a `SwitchInt`-terminated basic block to see if the condition of that `SwitchInt` is . /// an enum discriminant. . /// . /// We expect such blocks to have a call to `discriminant` as their last statement like so: -- line 697 ---------------------------------------- -- line 699 ---------------------------------------- . /// ```text . /// ... . /// _42 = discriminant(_1) . /// SwitchInt(_42, ..) . /// ``` . /// . /// If the basic block matches this pattern, this function returns the place corresponding to the . /// enum (`_1` in the example above) as well as the `AdtDef` of that enum. 1,952 ( 0.00%) fn switch_on_enum_discriminant<'mir, 'tcx>( . tcx: TyCtxt<'tcx>, . body: &'mir mir::Body<'tcx>, . block: &'mir mir::BasicBlockData<'tcx>, . switch_on: mir::Place<'tcx>, . ) -> Option<(mir::Place<'tcx>, &'tcx ty::AdtDef)> { 1,189 ( 0.00%) match block.statements.last().map(|stmt| &stmt.kind) { . Some(mir::StatementKind::Assign(box (lhs, mir::Rvalue::Discriminant(discriminated)))) 225 ( 0.00%) if *lhs == switch_on => . { 300 ( 0.00%) match &discriminated.ty(body, tcx).ty.kind() { 525 ( 0.00%) ty::Adt(def, _) => Some((*discriminated, def)), . . // `Rvalue::Discriminant` is also used to get the active yield point for a . // generator, but we do not need edge-specific effects in that case. This may . // change in the future. . ty::Generator(..) => None, . . t => bug!("`discriminant` called on unexpected type {:?}", t), . } . } . . _ => None, . } 2,196 ( 0.00%) } . . struct OnMutBorrow(F); . . impl Visitor<'_> for OnMutBorrow . where . F: FnMut(&mir::Place<'_>), . { . fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'_>, location: Location) { . // FIXME: Does `&raw const foo` allow mutation? See #90413. 175,235 ( 0.00%) match rvalue { 250 ( 0.00%) mir::Rvalue::Ref(_, mir::BorrowKind::Mut { .. }, place) . | mir::Rvalue::AddressOf(_, place) => (self.0)(place), . . _ => {} . } . . self.super_rvalue(rvalue, location) . } . } -- line 750 ---------------------------------------- -- line 754 ---------------------------------------- . /// This DOES NOT call `f` for a shared borrow of a type with interior mutability. That's okay for . /// initializedness, because we cannot move from an `UnsafeCell` (outside of `core::cell`), but . /// other analyses will likely need to check for `!Freeze`. . fn for_each_mut_borrow<'tcx>( . mir: &impl MirVisitable<'tcx>, . location: Location, . f: impl FnMut(&mir::Place<'_>), . ) { 388,184 ( 0.01%) let mut vis = OnMutBorrow(f); . 1,295,160 ( 0.03%) mir.apply(location, &mut vis); . } 524,384 ( 0.01%) -------------------------------------------------------------------------------- -- Auto-annotated source: /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs -------------------------------------------------------------------------------- Ir -- line 48 ---------------------------------------- . // . // FIXME: we have to do something for moving slice patterns. . fn place_contents_drop_state_cannot_differ<'tcx>( . tcx: TyCtxt<'tcx>, . body: &Body<'tcx>, . place: mir::Place<'tcx>, . ) -> bool { . let ty = place.ty(body, tcx).ty; 2,637,190 ( 0.07%) match ty.kind() { . ty::Array(..) => { . debug!( . "place_contents_drop_state_cannot_differ place: {:?} ty: {:?} => false", . place, ty . ); . false . } . ty::Slice(..) | ty::Ref(..) | ty::RawPtr(..) => { . debug!( . "place_contents_drop_state_cannot_differ place: {:?} ty: {:?} refd => true", . place, ty . ); . true . } 1,805,013 ( 0.05%) ty::Adt(def, _) if (def.has_dtor(tcx) && !def.is_box()) || def.is_union() => { . debug!( . "place_contents_drop_state_cannot_differ place: {:?} ty: {:?} Drop => true", . place, ty . ); . true . } . _ => false, . } -- line 79 ---------------------------------------- -- line 83 ---------------------------------------- . tcx: TyCtxt<'tcx>, . body: &Body<'tcx>, . move_data: &MoveData<'tcx>, . lookup_result: LookupResult, . each_child: F, . ) where . F: FnMut(MovePathIndex), . { 121,616 ( 0.00%) match lookup_result { . LookupResult::Parent(..) => { . // access to untracked value - do not touch children . } . LookupResult::Exact(e) => on_all_children_bits(tcx, body, move_data, e, each_child), . } . } . . pub fn on_all_children_bits<'tcx, F>( -- line 99 ---------------------------------------- -- line 100 ---------------------------------------- . tcx: TyCtxt<'tcx>, . body: &Body<'tcx>, . move_data: &MoveData<'tcx>, . move_path_index: MovePathIndex, . mut each_child: F, . ) where . F: FnMut(MovePathIndex), . { 3,536,160 ( 0.09%) fn is_terminal_path<'tcx>( . tcx: TyCtxt<'tcx>, . body: &Body<'tcx>, . move_data: &MoveData<'tcx>, . path: MovePathIndex, . ) -> bool { 884,040 ( 0.02%) place_contents_drop_state_cannot_differ(tcx, body, move_data.move_paths[path].place) 3,536,160 ( 0.09%) } . 4,003,614 ( 0.10%) fn on_all_children_bits<'tcx, F>( . tcx: TyCtxt<'tcx>, . body: &Body<'tcx>, . move_data: &MoveData<'tcx>, . move_path_index: MovePathIndex, . each_child: &mut F, . ) where . F: FnMut(MovePathIndex), . { 81,505 ( 0.00%) each_child(move_path_index); . 3,094,140 ( 0.08%) if is_terminal_path(tcx, body, move_data, move_path_index) { . return; . } . 434,491 ( 0.01%) let mut next_child_index = move_data.move_paths[move_path_index].first_child; 869,305 ( 0.02%) while let Some(child_index) = next_child_index { 642 ( 0.00%) on_all_children_bits(tcx, body, move_data, child_index, each_child); 107 ( 0.00%) next_child_index = move_data.move_paths[child_index].next_sibling; . } 3,411,514 ( 0.09%) } 2,685,816 ( 0.07%) on_all_children_bits(tcx, body, move_data, move_path_index, &mut each_child); . } . . pub fn on_all_drop_children_bits<'tcx, F>( . tcx: TyCtxt<'tcx>, . body: &Body<'tcx>, . ctxt: &MoveDataParamEnv<'tcx>, . path: MovePathIndex, . mut each_child: F, -- line 146 ---------------------------------------- -- line 156 ---------------------------------------- . if erased_ty.needs_drop(tcx, ctxt.param_env) { . each_child(child); . } else { . debug!("on_all_drop_children_bits - skipping") . } . }) . } . 5,726 ( 0.00%) pub fn drop_flag_effects_for_function_entry<'tcx, F>( . tcx: TyCtxt<'tcx>, . body: &Body<'tcx>, . ctxt: &MoveDataParamEnv<'tcx>, . mut callback: F, . ) where . F: FnMut(MovePathIndex, DropFlagState), . { . let move_data = &ctxt.move_data; 516 ( 0.00%) for arg in body.args_iter() { 688 ( 0.00%) let place = mir::Place::from(arg); 1,032 ( 0.00%) let lookup_result = move_data.rev_lookup.find(place.as_ref()); . on_lookup_result_bits(tcx, body, move_data, lookup_result, |mpi| { 346 ( 0.00%) callback(mpi, DropFlagState::Present) . }); . } 4,128 ( 0.00%) } . 4,732,092 ( 0.12%) pub fn drop_flag_effects_for_location<'tcx, F>( . tcx: TyCtxt<'tcx>, . body: &Body<'tcx>, . ctxt: &MoveDataParamEnv<'tcx>, . loc: Location, . mut callback: F, . ) where . F: FnMut(MovePathIndex, DropFlagState), . { . let move_data = &ctxt.move_data; . debug!("drop_flag_effects_for_location({:?})", loc); . . // first, move out of the RHS 207,201 ( 0.01%) for mi in &move_data.loc_map[loc] { 1,157,016 ( 0.03%) let path = mi.move_path_index(move_data); . debug!("moving out of path {:?}", move_data.move_paths[path]); . 299,632 ( 0.01%) on_all_children_bits(tcx, body, move_data, path, |mpi| callback(mpi, DropFlagState::Absent)) . } . . debug!("drop_flag_effects: assignment for location({:?})", loc); . 81,505 ( 0.00%) for_location_inits(tcx, body, move_data, loc, |mpi| callback(mpi, DropFlagState::Present)); 3,653,768 ( 0.09%) } . . pub fn for_location_inits<'tcx, F>( . tcx: TyCtxt<'tcx>, . body: &Body<'tcx>, . move_data: &MoveData<'tcx>, . loc: Location, . mut callback: F, . ) where . F: FnMut(MovePathIndex), . { 207,201 ( 0.01%) for ii in &move_data.init_loc_map[loc] { 608,384 ( 0.02%) let init = move_data.inits[*ii]; 445,578 ( 0.01%) match init.kind { . InitKind::Deep => { . let path = init.path; . . on_all_children_bits(tcx, body, move_data, path, &mut callback) . } . InitKind::Shallow => { . let mpi = init.path; . callback(mpi); -- line 226 ---------------------------------------- -- line 230 ---------------------------------------- . } . } . . /// Calls `handle_inactive_variant` for each descendant move path of `enum_place` that contains a . /// `Downcast` to a variant besides the `active_variant`. . /// . /// NOTE: If there are no move paths corresponding to an inactive variant, . /// `handle_inactive_variant` will not be called for that variant. 1,704 ( 0.00%) pub(crate) fn on_all_inactive_variants<'tcx>( . tcx: TyCtxt<'tcx>, . body: &mir::Body<'tcx>, . move_data: &MoveData<'tcx>, . enum_place: mir::Place<'tcx>, . active_variant: VariantIdx, . mut handle_inactive_variant: impl FnMut(MovePathIndex), . ) { 710 ( 0.00%) let enum_mpi = match move_data.rev_lookup.find(enum_place.as_ref()) { . LookupResult::Exact(mpi) => mpi, . LookupResult::Parent(_) => return, . }; . . let enum_path = &move_data.move_paths[enum_mpi]; 219 ( 0.00%) for (variant_mpi, variant_path) in enum_path.children(&move_data.move_paths) { . // Because of the way we build the `MoveData` tree, each child should have exactly one more . // projection than `enum_place`. This additional projection must be a downcast since the . // base is an enum. . let (downcast, base_proj) = variant_path.place.projection.split_last().unwrap(); . assert_eq!(enum_place.projection.len(), base_proj.len()); . . let variant_idx = match *downcast { . mir::ProjectionElem::Downcast(_, idx) => idx, -- line 260 ---------------------------------------- -- line 262 ---------------------------------------- . }; . . if variant_idx != active_variant { . on_all_children_bits(tcx, body, move_data, variant_mpi, |mpi| { . handle_inactive_variant(mpi) . }); . } . } 1,136 ( 0.00%) } 3,218,808 ( 0.08%) -------------------------------------------------------------------------------- -- 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. 1,071,223 ( 0.03%) #[derive(Debug, Clone, PartialEq, Encodable, Decodable, HashStable_Generic)] . pub enum TokenTree { . /// A single token. 387,372 ( 0.01%) Token(Token), . /// A delimited sequence of token trees. 43,320 ( 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 { 79 ( 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 { 172,724 ( 0.00%) TokenTree::Token(Token::new(kind, span)) . } . . /// Returns the opening delimiter as a token tree. 21,606 ( 0.00%) pub fn open_tt(span: DelimSpan, delim: DelimToken) -> TokenTree { 64,818 ( 0.00%) TokenTree::token(token::OpenDelim(delim), span.open) 21,606 ( 0.00%) } . . /// Returns the closing delimiter as a token tree. 21,575 ( 0.00%) pub fn close_tt(span: DelimSpan, delim: DelimToken) -> TokenTree { 64,725 ( 0.00%) TokenTree::token(token::CloseDelim(delim), span.close) 21,575 ( 0.00%) } . 768 ( 0.00%) pub fn uninterpolate(self) -> TokenTree { 512 ( 0.00%) match self { 2,304 ( 0.00%) TokenTree::Token(token) => TokenTree::Token(token.uninterpolate().into_owned()), . tt => tt, . } 1,024 ( 0.00%) } . } . . impl HashStable for TokenStream . where . CTX: crate::HashStableContext, . { 423 ( 0.00%) fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { 1,142 ( 0.00%) for sub_tt in self.trees() { . sub_tt.hash_stable(hcx, hasher); . } 376 ( 0.00%) } . } . . pub trait CreateTokenStream: sync::Send + sync::Sync { . fn create_token_stream(&self) -> AttrAnnotatedTokenStream; . } . . impl CreateTokenStream for AttrAnnotatedTokenStream { . fn create_token_stream(&self) -> AttrAnnotatedTokenStream { -- line 131 ---------------------------------------- -- 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 { 43,090 ( 0.00%) pub fn new(tokens: Vec<(AttrAnnotatedTokenTree, Spacing)>) -> AttrAnnotatedTokenStream { . AttrAnnotatedTokenStream(Lrc::new(tokens)) 43,090 ( 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); . 121,737 ( 0.00%) #[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 { 120 ( 0.00%) TokenStream::new(vec![(tree, Spacing::Alone)]) . } . } . . impl From for TreeAndSpacing { . fn from(tree: TokenTree) -> TreeAndSpacing { 64,902 ( 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 { 21,545 ( 0.00%) self.0.is_empty() 21,545 ( 0.00%) } . . pub fn len(&self) -> usize { 162,197 ( 0.00%) 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 { 147 ( 0.00%) self.clone().into_trees() 294 ( 0.00%) } . 21,647 ( 0.00%) pub fn into_trees(self) -> Cursor { . Cursor::new(self) 43,294 ( 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; . 1,080 ( 0.00%) fn next(&mut self) -> Option { 4,692 ( 0.00%) self.next_with_spacing().map(|(tree, _)| tree) 1,440 ( 0.00%) } . } . . impl Cursor { . fn new(stream: TokenStream) -> Self { . Cursor { stream, index: 0 } . } . 809,185 ( 0.02%) pub fn next_with_spacing(&mut self) -> Option { 486,591 ( 0.01%) if self.index < self.stream.len() { 236,958 ( 0.01%) self.index += 1; 827,876 ( 0.02%) Some(self.stream.0[self.index - 1].clone()) . } else { 87,138 ( 0.00%) None . } 971,022 ( 0.02%) } . . 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; . } . 167,999 ( 0.00%) pub fn look_ahead(&self, n: usize) -> Option<&TokenTree> { 335,998 ( 0.01%) self.stream.0[self.index..].get(n).map(|(tree, _)| tree) 335,998 ( 0.01%) } . } . 46,061 ( 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 } . } . 43,086 ( 0.00%) pub fn from_pair(open: Span, close: Span) -> Self { . DelimSpan { open, close } 21,543 ( 0.00%) } . . pub fn dummy() -> Self { . Self::from_single(DUMMY_SP) 183 ( 0.00%) } . 64 ( 0.00%) pub fn entire(self) -> Span { . self.open.with_hi(self.close.hi()) 48 ( 0.00%) } . } 2,219 ( 0.00%) -------------------------------------------------------------------------------- -- Auto-annotated source: /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_middle/src/ty/subst.rs -------------------------------------------------------------------------------- Ir -- line 22 ---------------------------------------- . . /// An entity in the Rust type system, which can be one of . /// several kinds (types, lifetimes, and consts). . /// To reduce memory usage, a `GenericArg` is an interned pointer, . /// with the lowest 2 bits being reserved for a tag to . /// indicate the type (`Ty`, `Region`, or `Const`) it points to. . #[derive(Copy, Clone, PartialEq, Eq, Hash)] . pub struct GenericArg<'tcx> { 257,891 ( 0.01%) ptr: NonZeroUsize, 648,128 ( 0.02%) marker: PhantomData<(Ty<'tcx>, ty::Region<'tcx>, &'tcx ty::Const<'tcx>)>, . } . . const TAG_MASK: usize = 0b11; . const TYPE_TAG: usize = 0b00; . const REGION_TAG: usize = 0b01; . const CONST_TAG: usize = 0b10; . 46,280 ( 0.00%) #[derive(Debug, TyEncodable, TyDecodable, PartialEq, Eq, PartialOrd, Ord, HashStable)] . pub enum GenericArgKind<'tcx> { . Lifetime(ty::Region<'tcx>), . Type(Ty<'tcx>), . Const(&'tcx ty::Const<'tcx>), . } . . impl<'tcx> GenericArgKind<'tcx> { 12,305 ( 0.00%) fn pack(self) -> GenericArg<'tcx> { 12,305 ( 0.00%) let (tag, ptr) = match self { . GenericArgKind::Lifetime(lt) => { . // Ensure we can use the tag bits. . assert_eq!(mem::align_of_val(lt) & TAG_MASK, 0); . (REGION_TAG, lt as *const _ as usize) . } . GenericArgKind::Type(ty) => { . // Ensure we can use the tag bits. . assert_eq!(mem::align_of_val(ty) & TAG_MASK, 0); -- line 56 ---------------------------------------- -- line 58 ---------------------------------------- . } . GenericArgKind::Const(ct) => { . // Ensure we can use the tag bits. . assert_eq!(mem::align_of_val(ct) & TAG_MASK, 0); . (CONST_TAG, ct as *const _ as usize) . } . }; . 55,364 ( 0.00%) GenericArg { ptr: unsafe { NonZeroUsize::new_unchecked(ptr | tag) }, marker: PhantomData } 12,305 ( 0.00%) } . } . . impl<'tcx> fmt::Debug for GenericArg<'tcx> { . fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { . match self.unpack() { . GenericArgKind::Lifetime(lt) => lt.fmt(f), . GenericArgKind::Type(ty) => ty.fmt(f), . GenericArgKind::Const(ct) => ct.fmt(f), -- line 75 ---------------------------------------- -- line 85 ---------------------------------------- . . impl<'tcx> PartialOrd for GenericArg<'tcx> { . fn partial_cmp(&self, other: &GenericArg<'_>) -> Option { . Some(self.cmp(&other)) . } . } . . impl<'tcx> From> for GenericArg<'tcx> { 24,013 ( 0.00%) fn from(r: ty::Region<'tcx>) -> GenericArg<'tcx> { . GenericArgKind::Lifetime(r).pack() 24,013 ( 0.00%) } . } . . impl<'tcx> From> for GenericArg<'tcx> { 270,977 ( 0.01%) fn from(ty: Ty<'tcx>) -> GenericArg<'tcx> { . GenericArgKind::Type(ty).pack() 270,977 ( 0.01%) } . } . . impl<'tcx> From<&'tcx ty::Const<'tcx>> for GenericArg<'tcx> { 300 ( 0.00%) fn from(c: &'tcx ty::Const<'tcx>) -> GenericArg<'tcx> { . GenericArgKind::Const(c).pack() 300 ( 0.00%) } . } . . impl<'tcx> GenericArg<'tcx> { . #[inline] . pub fn unpack(self) -> GenericArgKind<'tcx> { . let ptr = self.ptr.get(); . unsafe { 3,399,244 ( 0.09%) match ptr & TAG_MASK { 21,022 ( 0.00%) REGION_TAG => GenericArgKind::Lifetime(&*((ptr & !TAG_MASK) as *const _)), 777,441 ( 0.02%) TYPE_TAG => GenericArgKind::Type(&*((ptr & !TAG_MASK) as *const _)), 10,699 ( 0.00%) CONST_TAG => GenericArgKind::Const(&*((ptr & !TAG_MASK) as *const _)), . _ => intrinsics::unreachable(), . } . } . } . . /// Unpack the `GenericArg` as a type when it is known certainly to be a type. . /// This is true in cases where `Substs` is used in places where the kinds are known . /// to be limited (e.g. in tuples, where the only parameters are type parameters). . pub fn expect_ty(self) -> Ty<'tcx> { . match self.unpack() { . GenericArgKind::Type(ty) => ty, . _ => bug!("expected a type, but found another kind"), . } 30,844 ( 0.00%) } . . /// Unpack the `GenericArg` as a const when it is known certainly to be a const. . pub fn expect_const(self) -> &'tcx ty::Const<'tcx> { . match self.unpack() { . GenericArgKind::Const(c) => c, . _ => bug!("expected a const, but found another kind"), . } . } -- line 140 ---------------------------------------- -- line 170 ---------------------------------------- . GenericArgKind::Type(ty) => ty.visit_with(visitor), . GenericArgKind::Const(ct) => ct.visit_with(visitor), . } . } . } . . impl<'tcx, E: TyEncoder<'tcx>> Encodable for GenericArg<'tcx> { . fn encode(&self, e: &mut E) -> Result<(), E::Error> { 906 ( 0.00%) self.unpack().encode(e) . } . } . . impl<'tcx, D: TyDecoder<'tcx>> Decodable for GenericArg<'tcx> { 61,525 ( 0.00%) fn decode(d: &mut D) -> GenericArg<'tcx> { 61,525 ( 0.00%) GenericArgKind::decode(d).pack() . } . } . . /// A substitution mapping generic parameters to new values. . pub type InternalSubsts<'tcx> = List>; . . pub type SubstsRef<'tcx> = &'tcx InternalSubsts<'tcx>; . . impl<'a, 'tcx> InternalSubsts<'tcx> { . /// Interpret these substitutions as the substitutions of a closure type. . /// Closure substitutions have a particular structure controlled by the . /// compiler that encodes information like the signature and closure kind; . /// see `ty::ClosureSubsts` struct for more comments. 643 ( 0.00%) pub fn as_closure(&'a self) -> ClosureSubsts<'a> { . ClosureSubsts { substs: self } 643 ( 0.00%) } . . /// Interpret these substitutions as the substitutions of a generator type. . /// Generator substitutions have a particular structure controlled by the . /// compiler that encodes information like the signature and generator kind; . /// see `ty::GeneratorSubsts` struct for more comments. . pub fn as_generator(&'tcx self) -> GeneratorSubsts<'tcx> { . GeneratorSubsts { substs: self } . } -- line 208 ---------------------------------------- -- line 211 ---------------------------------------- . /// Inline const substitutions have a particular structure controlled by the . /// compiler that encodes information like the inferred type; . /// see `ty::InlineConstSubsts` struct for more comments. . pub fn as_inline_const(&'tcx self) -> InlineConstSubsts<'tcx> { . InlineConstSubsts { substs: self } . } . . /// Creates an `InternalSubsts` that maps each generic parameter to itself. 5,070 ( 0.00%) pub fn identity_for_item(tcx: TyCtxt<'tcx>, def_id: DefId) -> SubstsRef<'tcx> { 524 ( 0.00%) Self::for_item(tcx, def_id, |param, _| tcx.mk_param_from_def(param)) 4,563 ( 0.00%) } . . /// Creates an `InternalSubsts` for generic parameter definitions, . /// by calling closures to obtain each kind. . /// The closures get to observe the `InternalSubsts` as they're . /// being built, which can be used to correctly . /// substitute defaults of generic parameters. 144,047 ( 0.00%) pub fn for_item(tcx: TyCtxt<'tcx>, def_id: DefId, mut mk_kind: F) -> SubstsRef<'tcx> . where . F: FnMut(&ty::GenericParamDef, &[GenericArg<'tcx>]) -> GenericArg<'tcx>, . { . let defs = tcx.generics_of(def_id); . let count = defs.count(); . let mut substs = SmallVec::with_capacity(count); 49,948 ( 0.00%) Self::fill_item(&mut substs, tcx, defs, &mut mk_kind); 32,124 ( 0.00%) tcx.intern_substs(&substs) 144,558 ( 0.00%) } . . pub fn extend_to(&self, tcx: TyCtxt<'tcx>, def_id: DefId, mut mk_kind: F) -> SubstsRef<'tcx> . where . F: FnMut(&ty::GenericParamDef, &[GenericArg<'tcx>]) -> GenericArg<'tcx>, . { . Self::for_item(tcx, def_id, |param, substs| { . self.get(param.index as usize).cloned().unwrap_or_else(|| mk_kind(param, substs)) . }) . } . 171,895 ( 0.00%) pub fn fill_item( . substs: &mut SmallVec<[GenericArg<'tcx>; 8]>, . tcx: TyCtxt<'tcx>, . defs: &ty::Generics, . mk_kind: &mut F, . ) where . F: FnMut(&ty::GenericParamDef, &[GenericArg<'tcx>]) -> GenericArg<'tcx>, . { 79,367 ( 0.00%) if let Some(def_id) = defs.parent { . let parent_defs = tcx.generics_of(def_id); 2,938 ( 0.00%) Self::fill_item(substs, tcx, parent_defs, mk_kind); . } . Self::fill_single(substs, defs, mk_kind) 137,320 ( 0.00%) } . 72 ( 0.00%) pub fn fill_single( . substs: &mut SmallVec<[GenericArg<'tcx>; 8]>, . defs: &ty::Generics, . mk_kind: &mut F, . ) where . F: FnMut(&ty::GenericParamDef, &[GenericArg<'tcx>]) -> GenericArg<'tcx>, . { . substs.reserve(defs.params.len()); . for param in &defs.params { . let kind = mk_kind(param, substs); 52,962 ( 0.00%) assert_eq!(param.index as usize, substs.len()); . substs.push(kind); . } 72 ( 0.00%) } . . #[inline] . pub fn types(&'a self) -> impl DoubleEndedIterator> + 'a { . self.iter() . .filter_map(|k| if let GenericArgKind::Type(ty) = k.unpack() { Some(ty) } else { None }) . } . . #[inline] -- line 284 ---------------------------------------- -- line 302 ---------------------------------------- . self.iter().filter_map(|k| match k.unpack() { . GenericArgKind::Lifetime(_) => None, . generic => Some(generic), . }) . } . . #[inline] . pub fn type_at(&self, i: usize) -> Ty<'tcx> { 154,515 ( 0.00%) if let GenericArgKind::Type(ty) = self[i].unpack() { . ty . } else { . bug!("expected type for param #{} in {:?}", i, self); . } . } . . #[inline] . pub fn region_at(&self, i: usize) -> ty::Region<'tcx> { -- line 318 ---------------------------------------- -- line 350 ---------------------------------------- . /// impl X for U { fn f() {} } . /// ``` . /// . /// * If `self` is `[Self, S, T]`: the identity substs of `f` in the trait. . /// * If `source_ancestor` is the def_id of the trait. . /// * If `target_substs` is `[U]`, the substs for the impl. . /// * Then we will return `[U, T]`, the subst for `f` in the impl that . /// are needed for it to match the trait. 2,667 ( 0.00%) pub fn rebase_onto( . &self, . tcx: TyCtxt<'tcx>, . source_ancestor: DefId, . target_substs: SubstsRef<'tcx>, . ) -> SubstsRef<'tcx> { . let defs = tcx.generics_of(source_ancestor); 762 ( 0.00%) tcx.mk_substs(target_substs.iter().chain(self.iter().skip(defs.params.len()))) 3,048 ( 0.00%) } . . pub fn truncate_to(&self, tcx: TyCtxt<'tcx>, generics: &ty::Generics) -> SubstsRef<'tcx> { . tcx.mk_substs(self.iter().take(generics.count())) . } . } . . impl<'tcx> TypeFoldable<'tcx> for SubstsRef<'tcx> { 5,257 ( 0.00%) fn try_super_fold_with>( . self, . folder: &mut F, . ) -> Result { . // This code is hot enough that it's worth specializing for the most . // common length lists, to avoid the overhead of `SmallVec` creation. . // The match arms are in order of frequency. The 1, 2, and 0 cases are . // typically hit in 90--99.99% of cases. When folding doesn't change . // the substs, it's faster to reuse the existing substs rather than . // calling `intern_substs`. 615,134 ( 0.02%) match self.len() { . 1 => { 42,997 ( 0.00%) let param0 = self[0].try_fold_with(folder)?; 150,895 ( 0.00%) if param0 == self[0] { Ok(self) } else { Ok(folder.tcx().intern_substs(&[param0])) } . } . 2 => { 80,469 ( 0.00%) let param0 = self[0].try_fold_with(folder)?; 223,529 ( 0.01%) let param1 = self[1].try_fold_with(folder)?; 269,242 ( 0.01%) if param0 == self[0] && param1 == self[1] { . Ok(self) . } else { 347,140 ( 0.01%) Ok(folder.tcx().intern_substs(&[param0, param1])) . } . } . 0 => Ok(self), . _ => { . let params: SmallVec<[_; 8]> = 4,448 ( 0.00%) self.iter().map(|k| k.try_fold_with(folder)).collect::>()?; 412 ( 0.00%) if params[..] == self[..] { . Ok(self) . } else { 1,014 ( 0.00%) Ok(folder.tcx().intern_substs(¶ms)) . } . } . } 10,688 ( 0.00%) } . . fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { 44,421 ( 0.00%) self.iter().try_for_each(|t| t.visit_with(visitor)) . } . } . . /////////////////////////////////////////////////////////////////////////// . // Public trait `Subst` . // . // Just call `foo.subst(tcx, substs)` to perform a substitution across . // `foo`. Or use `foo.subst_spanned(tcx, substs, Some(span))` when -- line 420 ---------------------------------------- -- line 435 ---------------------------------------- . . impl<'tcx, T: TypeFoldable<'tcx>> Subst<'tcx> for T { . fn subst_spanned( . self, . tcx: TyCtxt<'tcx>, . substs: &[GenericArg<'tcx>], . span: Option, . ) -> T { 2,581,315 ( 0.07%) let mut folder = SubstFolder { tcx, substs, span, binders_passed: 0 }; . self.fold_with(&mut folder) . } . } . . /////////////////////////////////////////////////////////////////////////// . // The actual substitution engine itself is a type folder. . . struct SubstFolder<'a, 'tcx> { -- line 451 ---------------------------------------- -- line 456 ---------------------------------------- . span: Option, . . /// Number of region binders we have passed through while doing the substitution . binders_passed: u32, . } . . impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> { . fn tcx<'b>(&'b self) -> TyCtxt<'tcx> { 18,413 ( 0.00%) self.tcx . } . . fn fold_binder>( . &mut self, . t: ty::Binder<'tcx, T>, . ) -> ty::Binder<'tcx, T> { 146,496 ( 0.00%) self.binders_passed += 1; 5,531 ( 0.00%) let t = t.super_fold_with(self); 146,496 ( 0.00%) self.binders_passed -= 1; . t . } . 47,748 ( 0.00%) fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { . // Note: This routine only handles regions that are bound on . // type declarations and other outer declarations, not those . // bound in *fn types*. Region substitution of the bound . // regions that appear in a function signature is done using . // the specialized routine `ty::replace_late_regions()`. 15,916 ( 0.00%) match *r { 13,414 ( 0.00%) ty::ReEarlyBound(data) => { 13,414 ( 0.00%) let rk = self.substs.get(data.index as usize).map(|k| k.unpack()); . match rk { 6,707 ( 0.00%) Some(GenericArgKind::Lifetime(lt)) => self.shift_region_through_binders(lt), . _ => { . let span = self.span.unwrap_or(DUMMY_SP); . let msg = format!( . "Region parameter out of range \ . when substituting in region {} (index={})", . data.name, data.index . ); . span_bug!(span, "{}", msg); . } . } . } . _ => r, . } 55,706 ( 0.00%) } . 1,586,634 ( 0.04%) fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { 528,878 ( 0.01%) if !t.needs_subst() { . return t; . } . 57,776 ( 0.00%) match *t.kind() { 95,540 ( 0.00%) ty::Param(p) => self.ty_for_param(p, t), 58,680 ( 0.00%) _ => t.super_fold_with(self), . } 2,595,490 ( 0.07%) } . 497,119 ( 0.01%) fn fold_const(&mut self, c: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { 143,564 ( 0.00%) if let ty::ConstKind::Param(p) = c.val { . self.const_for_param(p, c) . } else { 636,399 ( 0.02%) c.super_fold_with(self) . } 2,448 ( 0.00%) } . . #[inline] . fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> { . c.super_fold_with(self) . } . } . . impl<'a, 'tcx> SubstFolder<'a, 'tcx> { . fn ty_for_param(&self, p: ty::ParamTy, source_ty: Ty<'tcx>) -> Ty<'tcx> { . // Look up the type in the substitutions. It really should be in there. 38,216 ( 0.00%) let opt_ty = self.substs.get(p.index as usize).map(|k| k.unpack()); . let ty = match opt_ty { . Some(GenericArgKind::Type(ty)) => ty, . Some(kind) => { . let span = self.span.unwrap_or(DUMMY_SP); . span_bug!( . span, . "expected type for `{:?}` ({:?}/{}) but found {:?} \ . when substituting, substs={:?}", -- line 539 ---------------------------------------- -- line 562 ---------------------------------------- . } . . fn const_for_param( . &self, . p: ParamConst, . source_ct: &'tcx ty::Const<'tcx>, . ) -> &'tcx ty::Const<'tcx> { . // Look up the const in the substitutions. It really should be in there. 612 ( 0.00%) let opt_ct = self.substs.get(p.index as usize).map(|k| k.unpack()); . let ct = match opt_ct { . Some(GenericArgKind::Const(ct)) => ct, . Some(kind) => { . let span = self.span.unwrap_or(DUMMY_SP); . span_bug!( . span, . "expected const for `{:?}` ({:?}/{}) but found {:?} \ . when substituting substs={:?}", -- line 578 ---------------------------------------- -- line 645 ---------------------------------------- . fn shift_vars_through_binders>(&self, val: T) -> T { . debug!( . "shift_vars(val={:?}, binders_passed={:?}, has_escaping_bound_vars={:?})", . val, . self.binders_passed, . val.has_escaping_bound_vars() . ); . 69,920 ( 0.00%) if self.binders_passed == 0 || !val.has_escaping_bound_vars() { . return val; . } . . let result = ty::fold::shift_vars(self.tcx(), val, self.binders_passed); . debug!("shift_vars: shifted result = {:?}", result); . . result . } . . fn shift_region_through_binders(&self, region: ty::Region<'tcx>) -> ty::Region<'tcx> { 16,207 ( 0.00%) if self.binders_passed == 0 || !region.has_escaping_bound_vars() { . return region; . } . ty::fold::shift_region(self.tcx, region, self.binders_passed) . } . } . . /// Stores the user-given substs to reach some fully qualified path . /// (e.g., `::Item` or `::Item`). . #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] 1,022 ( 0.00%) #[derive(HashStable, TypeFoldable, Lift)] . pub struct UserSubsts<'tcx> { . /// The substitutions for the item as given by the user. . pub substs: SubstsRef<'tcx>, . . /// The self type, in the case of a `::Item` path (when applied . /// to an inherent impl). See `UserSelfTy` below. 270 ( 0.00%) pub user_self_ty: Option>, . } . . /// Specifies the user-given self type. In the case of a path that . /// refers to a member in an inherent impl, this self type is . /// sometimes needed to constrain the type parameters on the impl. For . /// example, in this code: . /// . /// ``` -- line 689 ---------------------------------------- -- line 696 ---------------------------------------- . /// self type `Foo`. Then we can instantiate the parameters of . /// the impl (with the substs from `UserSubsts`) and apply those to . /// the self type, giving `Foo`. Finally, we unify that with . /// the self type here, which contains `?A` to be `&'static u32` . #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] . #[derive(HashStable, TypeFoldable, Lift)] . pub struct UserSelfTy<'tcx> { . pub impl_def_id: DefId, 90 ( 0.00%) pub self_ty: Ty<'tcx>, . } 859,416 ( 0.02%) -------------------------------------------------------------------------------- -- Auto-annotated source: /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_ast/src/token.rs -------------------------------------------------------------------------------- Ir -- line 12 ---------------------------------------- . use rustc_data_structures::sync::Lrc; . use rustc_macros::HashStable_Generic; . use rustc_span::symbol::{kw, sym}; . use rustc_span::symbol::{Ident, Symbol}; . use rustc_span::{self, edition::Edition, Span, DUMMY_SP}; . use std::borrow::Cow; . use std::{fmt, mem}; . 9,856 ( 0.00%) #[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)] . pub enum CommentKind { . Line, . Block, . } . 97 ( 0.00%) #[derive(Clone, PartialEq, Encodable, Decodable, Hash, Debug, Copy)] . #[derive(HashStable_Generic)] . pub enum BinOpToken { . Plus, . Minus, . Star, . Slash, . Percent, . Caret, . And, . Or, . Shl, . Shr, . } . . /// A delimiter token. 106,369 ( 0.00%) #[derive(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Debug, Copy)] . #[derive(HashStable_Generic)] . pub enum DelimToken { . /// A round parenthesis (i.e., `(` or `)`). . Paren, . /// A square bracket (i.e., `[` or `]`). . Bracket, . /// A curly brace (i.e., `{` or `}`). . Brace, . /// An empty delimiter. . NoDelim, . } . 886 ( 0.00%) #[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)] . pub enum LitKind { . Bool, // AST only, must never appear in a `Token` . Byte, . Char, . Integer, . Float, . Str, . StrRaw(u16), // raw string delimited by `n` hash symbols . ByteStr, . ByteStrRaw(u16), // raw byte string delimited by `n` hash symbols . Err, . } . . /// A literal token. 66,217 ( 0.00%) #[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)] . pub struct Lit { . pub kind: LitKind, . pub symbol: Symbol, . pub suffix: Option, . } . . impl fmt::Display for Lit { 153,575 ( 0.00%) fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 276,435 ( 0.01%) let Lit { kind, symbol, suffix } = *self; . match kind { . Byte => write!(f, "b'{}'", symbol)?, 90,315 ( 0.00%) Char => write!(f, "'{}'", symbol)?, 1,731 ( 0.00%) Str => write!(f, "\"{}\"", symbol)?, . StrRaw(n) => write!( . f, . "r{delim}\"{string}\"{delim}", . delim = "#".repeat(n as usize), . string = symbol . )?, . ByteStr => write!(f, "b\"{}\"", symbol)?, . ByteStrRaw(n) => write!( . f, . "br{delim}\"{string}\"{delim}", . delim = "#".repeat(n as usize), . string = symbol . )?, 99 ( 0.00%) Integer | Float | Bool | Err => write!(f, "{}", symbol)?, . } . 61,430 ( 0.00%) if let Some(suffix) = suffix { . write!(f, "{}", suffix)?; . } . . Ok(()) 153,575 ( 0.00%) } . } . . impl LitKind { . /// An English article for the literal token kind. . pub fn article(self) -> &'static str { . match self { . Integer | Err => "an", . _ => "a", -- line 113 ---------------------------------------- -- line 130 ---------------------------------------- . crate fn may_have_suffix(self) -> bool { . matches!(self, Integer | Float | Err) . } . } . . impl Lit { . pub fn new(kind: LitKind, symbol: Symbol, suffix: Option) -> Lit { . Lit { kind, symbol, suffix } 215,338 ( 0.01%) } . } . 160 ( 0.00%) pub fn ident_can_begin_expr(name: Symbol, span: Span, is_raw: bool) -> bool { 280 ( 0.00%) let ident_token = Token::new(Ident(name, is_raw), span); . 94 ( 0.00%) !ident_token.is_reserved_ident() . || ident_token.is_path_segment_keyword() . || [ . kw::Async, . kw::Do, . kw::Box, . kw::Break, . kw::Const, . kw::Continue, -- line 152 ---------------------------------------- -- line 161 ---------------------------------------- . kw::True, . kw::Try, . kw::Unsafe, . kw::While, . kw::Yield, . kw::Static, . ] . .contains(&name) 200 ( 0.00%) } . . fn ident_can_begin_type(name: Symbol, span: Span, is_raw: bool) -> bool { 174 ( 0.00%) let ident_token = Token::new(Ident(name, is_raw), span); . 70 ( 0.00%) !ident_token.is_reserved_ident() . || ident_token.is_path_segment_keyword() . || [kw::Underscore, kw::For, kw::Impl, kw::Fn, kw::Unsafe, kw::Extern, kw::Typeof, kw::Dyn] . .contains(&name) . } . 14,612,613 ( 0.37%) #[derive(Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)] . pub enum TokenKind { . /* Expression-operator symbols. */ . Eq, . Lt, . Le, . EqEq, . Ne, . Ge, . Gt, . AndAnd, . OrOr, . Not, . Tilde, 65,730 ( 0.00%) BinOp(BinOpToken), 12 ( 0.00%) BinOpEq(BinOpToken), . . /* Structural symbols */ . At, . Dot, . DotDot, . DotDotDot, . DotDotEq, . Comma, -- line 203 ---------------------------------------- -- line 208 ---------------------------------------- . LArrow, . FatArrow, . Pound, . Dollar, . Question, . /// Used by proc macros for representing lifetimes, not generated by lexer right now. . SingleQuote, . /// An opening delimiter (e.g., `{`). 191,598 ( 0.00%) OpenDelim(DelimToken), . /// A closing delimiter (e.g., `}`). 283,830 ( 0.01%) CloseDelim(DelimToken), . . /* Literals */ 94,379 ( 0.00%) Literal(Lit), . . /// Identifier token. . /// Do not forget about `NtIdent` when you want to match on identifiers. . /// It's recommended to use `Token::(ident,uninterpolate,uninterpolated_span)` to . /// treat regular and interpolated identifiers in the same way. 23,390 ( 0.00%) Ident(Symbol, /* is_raw */ bool), . /// Lifetime identifier token. . /// Do not forget about `NtLifetime` when you want to match on lifetime identifiers. . /// It's recommended to use `Token::(lifetime,uninterpolate,uninterpolated_span)` to . /// treat regular and interpolated lifetime identifiers in the same way. 156 ( 0.00%) Lifetime(Symbol), . . Interpolated(Lrc), . . /// A doc comment token. . /// `Symbol` is the doc comment's data excluding its "quotes" (`///`, `/**`, etc) . /// similarly to symbols in string literal tokens. 801 ( 0.00%) DocComment(CommentKind, ast::AttrStyle, Symbol), . . Eof, . } . . // `TokenKind` 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!(TokenKind, 16); . 418,046 ( 0.01%) #[derive(Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)] . pub struct Token { 3,608 ( 0.00%) pub kind: TokenKind, . pub span: Span, . } . . impl TokenKind { . pub fn lit(kind: LitKind, symbol: Symbol, suffix: Option) -> TokenKind { . Literal(Lit::new(kind, symbol, suffix)) . } . . // An approximation to proc-macro-style single-character operators used by rustc parser. . // If the operator token can be broken into two tokens, the first of which is single-character, . // then this function performs that operation, otherwise it returns `None`. 10,777 ( 0.00%) pub fn break_two_token_op(&self) -> Option<(TokenKind, TokenKind)> { 43,117 ( 0.00%) Some(match *self { . Le => (Lt, Eq), . EqEq => (Eq, Eq), . Ne => (Not, Eq), . Ge => (Gt, Eq), . AndAnd => (BinOp(And), BinOp(And)), . OrOr => (BinOp(Or), BinOp(Or)), . BinOp(Shl) => (Lt, Lt), . BinOp(Shr) => (Gt, Gt), -- line 271 ---------------------------------------- -- line 280 ---------------------------------------- . BinOpEq(Shl) => (Lt, Le), . BinOpEq(Shr) => (Gt, Ge), . DotDot => (Dot, Dot), . DotDotDot => (Dot, DotDot), . ModSep => (Colon, Colon), . RArrow => (BinOp(Minus), Gt), . LArrow => (Lt, BinOp(Minus)), . FatArrow => (Eq, Gt), 10,776 ( 0.00%) _ => return None, . }) 10,777 ( 0.00%) } . . /// Returns tokens that are likely to be typed accidentally instead of the current token. . /// Enables better error recovery when the wrong token is found. . pub fn similar_tokens(&self) -> Option> { . match *self { . Comma => Some(vec![Dot, Lt, Semi]), . Semi => Some(vec![Colon, Comma]), . FatArrow => Some(vec![Eq, RArrow]), . _ => None, . } . } . . pub fn should_end_const_arg(&self) -> bool { 166 ( 0.00%) matches!(self, Gt | Ge | BinOp(Shr) | BinOpEq(Shr)) 40 ( 0.00%) } . } . . impl Token { 170,266 ( 0.00%) pub fn new(kind: TokenKind, span: Span) -> Self { 511,941 ( 0.01%) Token { kind, span } 170,266 ( 0.00%) } . . /// Some token that will be thrown away later. 289 ( 0.00%) pub fn dummy() -> Self { . Token::new(TokenKind::Question, DUMMY_SP) 289 ( 0.00%) } . . /// Recovers a `Token` from an `Ident`. This creates a raw identifier if necessary. . pub fn from_ast_ident(ident: Ident) -> Self { 608 ( 0.00%) Token::new(Ident(ident.name, ident.is_raw_guess()), ident.span) . } . . /// Return this token by value and leave a dummy token in its place. 106,107 ( 0.00%) pub fn take(&mut self) -> Self { . mem::replace(self, Token::dummy()) 106,107 ( 0.00%) } . . /// For interpolated tokens, returns a span of the fragment to which the interpolated . /// token refers. For all other tokens this is just a regular span. . /// It is particularly important to use this for identifiers and lifetimes . /// for which spans affect name resolution and edition checks. . /// Note that keywords are also identifiers, so they should use this . /// if they keep spans or perform edition checks. . pub fn uninterpolated_span(&self) -> Span { 650 ( 0.00%) match &self.kind { . Interpolated(nt) => nt.span(), 325 ( 0.00%) _ => self.span, . } 325 ( 0.00%) } . . pub fn is_op(&self) -> bool { 318,321 ( 0.01%) !matches!( 106,107 ( 0.00%) self.kind, . OpenDelim(..) . | CloseDelim(..) . | Literal(..) . | DocComment(..) . | Ident(..) . | Lifetime(..) . | Interpolated(..) . | Eof . ) 106,107 ( 0.00%) } . . pub fn is_like_plus(&self) -> bool { 2,289 ( 0.00%) matches!(self.kind, BinOp(Plus) | BinOpEq(Plus)) 457 ( 0.00%) } . . /// Returns `true` if the token can appear at the start of an expression. 46 ( 0.00%) pub fn can_begin_expr(&self) -> bool { 230 ( 0.00%) match self.uninterpolate().kind { 360 ( 0.00%) Ident(name, is_raw) => 120 ( 0.00%) ident_can_begin_expr(name, self.span, is_raw), // value name or keyword . OpenDelim(..) | // tuple, array or block . Literal(..) | // literal . Not | // operator not . BinOp(Minus) | // unary minus . BinOp(Star) | // dereference . BinOp(Or) | OrOr | // closure . BinOp(And) | // reference . AndAnd | // double reference -- line 371 ---------------------------------------- -- line 376 ---------------------------------------- . Lifetime(..) | // labeled loop . Pound => true, // expression attributes . Interpolated(ref nt) => matches!(**nt, NtLiteral(..) | . NtExpr(..) | . NtBlock(..) | . NtPath(..)), . _ => false, . } 92 ( 0.00%) } . . /// Returns `true` if the token can appear at the start of a type. 232 ( 0.00%) pub fn can_begin_type(&self) -> bool { 481 ( 0.00%) match self.uninterpolate().kind { 261 ( 0.00%) Ident(name, is_raw) => 29 ( 0.00%) ident_can_begin_type(name, self.span, is_raw), // type name or keyword . OpenDelim(Paren) | // tuple . OpenDelim(Bracket) | // array . Not | // never . BinOp(Star) | // raw pointer . BinOp(And) | // reference . AndAnd | // double reference . Question | // maybe bound in trait object . Lifetime(..) | // lifetime bound in trait object . Lt | BinOp(Shl) | // associated path . ModSep => true, // global path . Interpolated(ref nt) => matches!(**nt, NtTy(..) | NtPath(..)), . _ => false, . } 348 ( 0.00%) } . . /// Returns `true` if the token can appear at the start of a const param. . pub fn can_begin_const_arg(&self) -> bool { 255 ( 0.00%) match self.kind { . OpenDelim(Brace) => true, . Interpolated(ref nt) => matches!(**nt, NtExpr(..) | NtBlock(..) | NtLiteral(..)), 51 ( 0.00%) _ => self.can_begin_literal_maybe_minus(), . } . } . . /// Returns `true` if the token can appear at the start of a generic bound. . pub fn can_begin_bound(&self) -> bool { . self.is_path_start() . || self.is_lifetime() . || self.is_keyword(kw::For) -- line 419 ---------------------------------------- -- line 427 ---------------------------------------- . } . . /// Returns `true` if the token is any literal, a minus (which can prefix a literal, . /// for example a '-42', or one of the boolean idents). . /// . /// In other words, would this token be a valid start of `parse_literal_maybe_minus`? . /// . /// Keep this in sync with and `Lit::from_token`, excluding unary negation. 51 ( 0.00%) pub fn can_begin_literal_maybe_minus(&self) -> bool { 460 ( 0.00%) match self.uninterpolate().kind { . Literal(..) | BinOp(Minus) => true, 116 ( 0.00%) Ident(name, false) if name.is_bool_lit() => true, . Interpolated(ref nt) => match &**nt { . NtLiteral(_) => true, . NtExpr(e) => match &e.kind { . ast::ExprKind::Lit(_) => true, . ast::ExprKind::Unary(ast::UnOp::Neg, e) => { . matches!(&e.kind, ast::ExprKind::Lit(_)) . } . _ => false, . }, . _ => false, . }, . _ => false, . } 102 ( 0.00%) } . . // A convenience function for matching on identifiers during parsing. . // Turns interpolated identifier (`$i: ident`) or lifetime (`$l: lifetime`) token . // into the regular identifier or lifetime token it refers to, . // otherwise returns the original token. 52,872 ( 0.00%) pub fn uninterpolate(&self) -> Cow<'_, Token> { 774,892 ( 0.02%) match &self.kind { . Interpolated(nt) => match **nt { . NtIdent(ident, is_raw) => { . Cow::Owned(Token::new(Ident(ident.name, is_raw), ident.span)) . } . NtLifetime(ident) => Cow::Owned(Token::new(Lifetime(ident.name), ident.span)), . _ => Cow::Borrowed(self), . }, . _ => Cow::Borrowed(self), . } 52,872 ( 0.00%) } . . /// Returns an identifier if this token is an identifier. 199,941 ( 0.01%) pub fn ident(&self) -> Option<(Ident, /* is_raw */ bool)> { . let token = self.uninterpolate(); 547,596 ( 0.01%) match token.kind { 1,185,285 ( 0.03%) Ident(name, is_raw) => Some((Ident::new(name, token.span), is_raw)), . _ => None, . } 1,312,751 ( 0.03%) } . . /// Returns a lifetime identifier if this token is a lifetime. 193 ( 0.00%) pub fn lifetime(&self) -> Option { . let token = self.uninterpolate(); 940 ( 0.00%) match token.kind { 560 ( 0.00%) Lifetime(name) => Some(Ident::new(name, token.span)), . _ => None, . } 1,351 ( 0.00%) } . . /// Returns `true` if the token is an identifier. . pub fn is_ident(&self) -> bool { . self.ident().is_some() 10,464 ( 0.00%) } . . /// Returns `true` if the token is a lifetime. 277 ( 0.00%) pub fn is_lifetime(&self) -> bool { . self.lifetime().is_some() 554 ( 0.00%) } . . /// Returns `true` if the token is an identifier whose name is the given . /// string slice. 10,559 ( 0.00%) pub fn is_ident_named(&self, name: Symbol) -> bool { . self.ident().map_or(false, |(ident, _)| ident.name == name) 21,118 ( 0.00%) } . . /// Returns `true` if the token is an interpolated path. . fn is_path(&self) -> bool { 44,560 ( 0.00%) if let Interpolated(ref nt) = self.kind { . if let NtPath(..) = **nt { . return true; . } . } . false . } . . /// Would `maybe_whole_expr` in `parser.rs` return `Ok(..)`? -- line 515 ---------------------------------------- -- line 522 ---------------------------------------- . } . } . . false . } . . // Is the token an interpolated block (`$b:block`)? . pub fn is_whole_block(&self) -> bool { 30 ( 0.00%) if let Interpolated(ref nt) = self.kind { . if let NtBlock(..) = **nt { . return true; . } . } . false 15 ( 0.00%) } . . /// Returns `true` if the token is either the `mut` or `const` keyword. . pub fn is_mutability(&self) -> bool { . self.is_keyword(kw::Mut) || self.is_keyword(kw::Const) . } . 282 ( 0.00%) pub fn is_qpath_start(&self) -> bool { 22,562 ( 0.00%) self == &Lt || self == &BinOp(Shl) . } . 44,560 ( 0.00%) pub fn is_path_start(&self) -> bool { 66,802 ( 0.00%) self == &ModSep . || self.is_qpath_start() . || self.is_path() . || self.is_path_segment_keyword() 11,005 ( 0.00%) || self.is_ident() && !self.is_reserved_ident() 55,700 ( 0.00%) } . . /// Returns `true` if the token is a given keyword, `kw`. 24,554 ( 0.00%) pub fn is_keyword(&self, kw: Symbol) -> bool { . self.is_non_raw_ident_where(|id| id.name == kw) 49,108 ( 0.00%) } . 189 ( 0.00%) pub fn is_path_segment_keyword(&self) -> bool { . self.is_non_raw_ident_where(Ident::is_path_segment_keyword) . } . . // Returns true for reserved identifiers used internally for elided lifetimes, . // unnamed method parameters, crate root module, error recovery etc. 81 ( 0.00%) pub fn is_special_ident(&self) -> bool { . self.is_non_raw_ident_where(Ident::is_special) . } . . /// Returns `true` if the token is a keyword used in the language. 81 ( 0.00%) pub fn is_used_keyword(&self) -> bool { . self.is_non_raw_ident_where(Ident::is_used_keyword) . } . . /// Returns `true` if the token is a keyword reserved for possible future use. 81 ( 0.00%) pub fn is_unused_keyword(&self) -> bool { . self.is_non_raw_ident_where(Ident::is_unused_keyword) . } . . /// Returns `true` if the token is either a special identifier or a keyword. . pub fn is_reserved_ident(&self) -> bool { . self.is_non_raw_ident_where(Ident::is_reserved) . } . . /// Returns `true` if the token is the identifier `true` or `false`. 197 ( 0.00%) pub fn is_bool_lit(&self) -> bool { 394 ( 0.00%) self.is_non_raw_ident_where(|id| id.name.is_bool_lit()) . } . . pub fn is_numeric_lit(&self) -> bool { . matches!( . self.kind, . Literal(Lit { kind: LitKind::Integer, .. }) | Literal(Lit { kind: LitKind::Float, .. }) . ) . } . . /// Returns `true` if the token is a non-raw identifier for which `pred` holds. 12 ( 0.00%) pub fn is_non_raw_ident_where(&self, pred: impl FnOnce(Ident) -> bool) -> bool { 924,753 ( 0.02%) match self.ident() { 10,986 ( 0.00%) Some((id, false)) => pred(id), . _ => false, . } 15 ( 0.00%) } . 413,360 ( 0.01%) pub fn glue(&self, joint: &Token) -> Option { 206,680 ( 0.01%) let kind = match self.kind { 236 ( 0.00%) Eq => match joint.kind { . Eq => EqEq, . Gt => FatArrow, . _ => return None, . }, 68 ( 0.00%) Lt => match joint.kind { . Eq => Le, . Lt => BinOp(Shl), . Le => BinOpEq(Shl), . BinOp(Minus) => LArrow, . _ => return None, . }, 41 ( 0.00%) Gt => match joint.kind { . Eq => Ge, . Gt => BinOp(Shr), . Ge => BinOpEq(Shr), . _ => return None, . }, 2 ( 0.00%) Not => match joint.kind { . Eq => Ne, . _ => return None, . }, 817 ( 0.00%) BinOp(op) => match joint.kind { . Eq => BinOpEq(op), 25 ( 0.00%) BinOp(And) if op == And => AndAnd, 12 ( 0.00%) BinOp(Or) if op == Or => OrOr, 56 ( 0.00%) Gt if op == Minus => RArrow, . _ => return None, . }, 60 ( 0.00%) Dot => match joint.kind { . Dot => DotDot, . DotDot => DotDotDot, . _ => return None, . }, . DotDot => match joint.kind { . Dot => DotDotDot, . Eq => DotDotEq, . _ => return None, . }, 20,064 ( 0.00%) Colon => match joint.kind { . Colon => ModSep, . _ => return None, . }, . SingleQuote => match joint.kind { . Ident(name, false) => Lifetime(Symbol::intern(&format!("'{}", name))), . _ => return None, . }, . . Le | EqEq | Ne | Ge | AndAnd | OrOr | Tilde | BinOpEq(..) | At | DotDotDot . | DotDotEq | Comma | Semi | ModSep | RArrow | LArrow | FatArrow | Pound | Dollar . | Question | OpenDelim(..) | CloseDelim(..) | Literal(..) | Ident(..) . | Lifetime(..) | Interpolated(..) | DocComment(..) | Eof => return None, . }; . 132,860 ( 0.00%) Some(Token::new(kind, self.span.to(joint.span))) 372,024 ( 0.01%) } . } . . impl PartialEq for Token { . fn eq(&self, rhs: &TokenKind) -> bool { 803,282 ( 0.02%) self.kind == *rhs . } . } . . #[derive(Clone, Encodable, Decodable)] . /// For interpolation during macro expansion. . pub enum Nonterminal { . NtItem(P), . NtBlock(P), -- line 675 ---------------------------------------- -- line 711 ---------------------------------------- . Path, . Vis, . TT, . } . . impl NonterminalKind { . /// The `edition` closure is used to get the edition for the given symbol. Doing . /// `span.edition()` is expensive, so we do it lazily. 52 ( 0.00%) pub fn from_symbol( . symbol: Symbol, . edition: impl FnOnce() -> Edition, . ) -> Option { 108 ( 0.00%) Some(match symbol { . sym::item => NonterminalKind::Item, . sym::block => NonterminalKind::Block, . sym::stmt => NonterminalKind::Stmt, . sym::pat => match edition() { . Edition::Edition2015 | Edition::Edition2018 => { . NonterminalKind::PatParam { inferred: true } . } . Edition::Edition2021 => NonterminalKind::PatWithOr, -- line 731 ---------------------------------------- -- line 737 ---------------------------------------- . sym::lifetime => NonterminalKind::Lifetime, . sym::literal => NonterminalKind::Literal, . sym::meta => NonterminalKind::Meta, . sym::path => NonterminalKind::Path, . sym::vis => NonterminalKind::Vis, . sym::tt => NonterminalKind::TT, . _ => return None, . }) 52 ( 0.00%) } . fn symbol(self) -> Symbol { . match self { . NonterminalKind::Item => sym::item, . NonterminalKind::Block => sym::block, . NonterminalKind::Stmt => sym::stmt, . NonterminalKind::PatParam { inferred: false } => sym::pat_param, . NonterminalKind::PatParam { inferred: true } | NonterminalKind::PatWithOr => sym::pat, . NonterminalKind::Expr => sym::expr, -- line 753 ---------------------------------------- 5,103,318 ( 0.13%) -------------------------------------------------------------------------------- -- Auto-annotated source: /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_mir_build/src/build/expr/as_operand.rs -------------------------------------------------------------------------------- Ir -- line 15 ---------------------------------------- . /// please do *not* return it from functions to avoid bad . /// miscompiles. . crate fn as_local_operand( . &mut self, . block: BasicBlock, . expr: &Expr<'tcx>, . ) -> BlockAnd> { . let local_scope = self.local_scope(); 83,496 ( 0.00%) self.as_operand(block, Some(local_scope), expr, None) . } . . /// Returns an operand suitable for use until the end of the current scope expression and . /// suitable also to be passed as function arguments. . /// . /// The operand returned from this function will *not be valid* after an ExprKind::Scope is . /// passed, so please do *not* return it from functions to avoid bad miscompiles. Returns an . /// operand suitable for use as a call argument. This is almost always equivalent to -- line 31 ---------------------------------------- -- line 72 ---------------------------------------- . /// . /// See #68034 for more details. . crate fn as_local_call_operand( . &mut self, . block: BasicBlock, . expr: &Expr<'tcx>, . ) -> BlockAnd> { . let local_scope = self.local_scope(); 52,715 ( 0.00%) self.as_call_operand(block, Some(local_scope), expr) . } . . /// Compile `expr` into a value that can be used as an operand. . /// If `expr` is a place like `x`, this will introduce a . /// temporary `tmp = x`, so that we capture the value of `x` at . /// this time. . /// . /// If we end up needing to create a temporary, then we will use -- line 88 ---------------------------------------- -- line 89 ---------------------------------------- . /// `local_info` as its `LocalInfo`, unless `as_temporary` . /// has already assigned it a non-`None` `LocalInfo`. . /// Normally, you should use `None` for `local_info` . /// . /// The operand is known to be live until the end of `scope`. . /// . /// Like `as_local_call_operand`, except that the argument will . /// not be valid once `scope` ends. 1,150,010 ( 0.03%) crate fn as_operand( . &mut self, . mut block: BasicBlock, . scope: Option, . expr: &Expr<'tcx>, . local_info: Option>>, . ) -> BlockAnd> { . debug!("as_operand(block={:?}, expr={:?} local_info={:?})", block, expr, local_info); . let this = self; . 709,122 ( 0.02%) if let ExprKind::Scope { region_scope, lint_level, value } = expr.kind { 104,034 ( 0.00%) let source_info = this.source_info(expr.span); . let region_scope = (region_scope, source_info); . return this.in_scope(region_scope, lint_level, |this| { 676,221 ( 0.02%) this.as_operand(block, scope, &this.thir[value], local_info) . }); . } . . let category = Category::of(&expr.kind).unwrap(); . debug!("as_operand: category={:?} for={:?}", category, expr.kind); . match category { . Category::Constant => { 123,759 ( 0.00%) let constant = this.as_constant(expr); . block.and(Operand::Constant(Box::new(constant))) . } . Category::Place | Category::Rvalue(..) => { . let operand = unpack!(block = this.as_temp(block, scope, expr, Mutability::Mut)); 43,462 ( 0.00%) if this.local_decls[operand].local_info.is_none() { 43,462 ( 0.00%) this.local_decls[operand].local_info = local_info; . } 21,731 ( 0.00%) block.and(Operand::Move(Place::from(operand))) . } . } 1,056,740 ( 0.03%) } . 273,949 ( 0.01%) crate fn as_call_operand( . &mut self, . mut block: BasicBlock, . scope: Option, . expr: &Expr<'tcx>, . ) -> BlockAnd> { . debug!("as_call_operand(block={:?}, expr={:?})", block, expr); . let this = self; . 136,929 ( 0.00%) if let ExprKind::Scope { region_scope, lint_level, value } = expr.kind { 21,060 ( 0.00%) let source_info = this.source_info(expr.span); . let region_scope = (region_scope, source_info); . return this.in_scope(region_scope, lint_level, |this| { 115,830 ( 0.00%) this.as_call_operand(block, scope, &this.thir[value]) . }); . } . 10,543 ( 0.00%) let tcx = this.tcx; . 42,172 ( 0.00%) if tcx.features().unsized_fn_params { . let ty = expr.ty; . let span = expr.span; . let param_env = this.param_env; . . if !ty.is_sized(tcx.at(span), param_env) { . // !sized means !copy, so this is an unsized move . assert!(!ty.is_copy_modulo_regions(tcx.at(span), param_env)); . -- line 159 ---------------------------------------- -- line 171 ---------------------------------------- . projection: tcx.intern_place_elems(&[PlaceElem::Deref]), . }; . . return block.and(Operand::Move(place)); . } . } . } . 94,887 ( 0.00%) this.as_operand(block, scope, expr, None) 168,584 ( 0.00%) } . } 709,244 ( 0.02%) -------------------------------------------------------------------------------- -- Auto-annotated source: /usr/home/liquid/rust/worktree-benchmarking/library/core/src/../../stdarch/crates/core_arch/src/x86/sse2.rs -------------------------------------------------------------------------------- Ir -- line 94 ---------------------------------------- . /// Adds packed 32-bit integers in `a` and `b`. . /// . /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_add_epi32) . #[inline] . #[target_feature(enable = "sse2")] . #[cfg_attr(test, assert_instr(paddd))] . #[stable(feature = "simd_x86", since = "1.27.0")] . pub unsafe fn _mm_add_epi32(a: __m128i, b: __m128i) -> __m128i { 17 ( 0.00%) transmute(simd_add(a.as_i32x4(), b.as_i32x4())) . } . . /// Adds packed 64-bit integers in `a` and `b`. . /// . /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_add_epi64) . #[inline] . #[target_feature(enable = "sse2")] . #[cfg_attr(test, assert_instr(paddq))] -- line 110 ---------------------------------------- -- line 790 ---------------------------------------- . /// Compares packed 8-bit integers in `a` and `b` for equality. . /// . /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpeq_epi8) . #[inline] . #[target_feature(enable = "sse2")] . #[cfg_attr(test, assert_instr(pcmpeqb))] . #[stable(feature = "simd_x86", since = "1.27.0")] . pub unsafe fn _mm_cmpeq_epi8(a: __m128i, b: __m128i) -> __m128i { 583,555 ( 0.01%) transmute::(simd_eq(a.as_i8x16(), b.as_i8x16())) . } . . /// Compares packed 16-bit integers in `a` and `b` for equality. . /// . /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpeq_epi16) . #[inline] . #[target_feature(enable = "sse2")] . #[cfg_attr(test, assert_instr(pcmpeqw))] -- line 806 ---------------------------------------- -- line 856 ---------------------------------------- . /// Compares packed 8-bit integers in `a` and `b` for less-than. . /// . /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmplt_epi8) . #[inline] . #[target_feature(enable = "sse2")] . #[cfg_attr(test, assert_instr(pcmpgtb))] . #[stable(feature = "simd_x86", since = "1.27.0")] . pub unsafe fn _mm_cmplt_epi8(a: __m128i, b: __m128i) -> __m128i { 59,648 ( 0.00%) transmute::(simd_lt(a.as_i8x16(), b.as_i8x16())) . } . . /// Compares packed 16-bit integers in `a` and `b` for less-than. . /// . /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmplt_epi16) . #[inline] . #[target_feature(enable = "sse2")] . #[cfg_attr(test, assert_instr(pcmpgtw))] -- line 872 ---------------------------------------- -- line 1174 ---------------------------------------- . /// `mem_addr` must be aligned on a 16-byte boundary. . /// . /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_load_si128) . #[inline] . #[target_feature(enable = "sse2")] . #[cfg_attr(test, assert_instr(movaps))] . #[stable(feature = "simd_x86", since = "1.27.0")] . pub unsafe fn _mm_load_si128(mem_addr: *const __m128i) -> __m128i { 247,313 ( 0.01%) *mem_addr . } . . /// Loads 128-bits of integer data from memory into a new vector. . /// . /// `mem_addr` does not need to be aligned on any particular boundary. . /// . /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loadu_si128) . #[inline] -- line 1190 ---------------------------------------- -- line 1237 ---------------------------------------- . /// `mem_addr` does not need to be aligned on any particular boundary. . /// . /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_storeu_si128) . #[inline] . #[target_feature(enable = "sse2")] . #[cfg_attr(test, assert_instr(movups))] // FIXME movdqu expected . #[stable(feature = "simd_x86", since = "1.27.0")] . pub unsafe fn _mm_storeu_si128(mem_addr: *mut __m128i, a: __m128i) { 16 ( 0.00%) storeudq(mem_addr as *mut i8, a); . } . . /// Stores the lower 64-bit integer `a` to a memory location. . /// . /// `mem_addr` does not need to be aligned on any particular boundary. . /// . /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_storel_epi64) . #[inline] -- line 1253 ---------------------------------------- -- line 1373 ---------------------------------------- . /// Returns a mask of the most significant bit of each element in `a`. . /// . /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_movemask_epi8) . #[inline] . #[target_feature(enable = "sse2")] . #[cfg_attr(test, assert_instr(pmovmskb))] . #[stable(feature = "simd_x86", since = "1.27.0")] . pub unsafe fn _mm_movemask_epi8(a: __m128i) -> i32 { 35,885,109 ( 0.91%) pmovmskb(a.as_i8x16()) . } . . /// Shuffles 32-bit integers in `a` using the control in `IMM8`. . /// . /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_shuffle_epi32) . #[inline] . #[target_feature(enable = "sse2")] . #[cfg_attr(test, assert_instr(pshufd, IMM8 = 9))] -- line 1389 ---------------------------------------- -------------------------------------------------------------------------------- -- Auto-annotated source: /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_ast_pretty/src/pp.rs -------------------------------------------------------------------------------- Ir -- line 166 ---------------------------------------- . String(Cow<'static, str>), . Break(BreakToken), . Begin(BeginToken), . End, . } . . impl Token { . pub fn is_hardbreak_tok(&self) -> bool { 61,338 ( 0.00%) matches!(self, Token::Break(BreakToken { offset: 0, blank_space: SIZE_INFINITY })) . } . } . . #[derive(Copy, Clone)] . enum PrintFrame { . Fits, . Broken { offset: isize, breaks: Breaks }, . } -- line 182 ---------------------------------------- -- line 213 ---------------------------------------- . . #[derive(Clone)] . struct BufEntry { . token: Token, . size: isize, . } . . impl Printer { 188 ( 0.00%) pub fn new() -> Self { . let linewidth = 78; 3,304 ( 0.00%) Printer { . out: String::new(), . margin: linewidth as isize, . space: linewidth as isize, . buf: RingBuffer::new(), . left_total: 0, . right_total: 0, . scan_stack: VecDeque::new(), . print_stack: Vec::new(), . pending_indentation: 0, . last_printed: None, . } 235 ( 0.00%) } . . pub fn last_token(&self) -> Option<&Token> { . self.last_token_still_buffered().or_else(|| self.last_printed.as_ref()) . } . . pub fn last_token_still_buffered(&self) -> Option<&Token> { . self.buf.last().map(|last| &last.token) . } . . /// Be very careful with this! . pub fn replace_last_token_still_buffered(&mut self, token: Token) { . self.buf.last_mut().unwrap().token = token; . } . . fn scan_eof(&mut self) { 146 ( 0.00%) if !self.scan_stack.is_empty() { 102 ( 0.00%) self.check_stack(0); 102 ( 0.00%) self.advance_left(); . } . } . . fn scan_begin(&mut self, token: BeginToken) { 101,968 ( 0.00%) if self.scan_stack.is_empty() { 102 ( 0.00%) self.left_total = 1; . self.right_total = 1; . self.buf.clear(); . } 407,872 ( 0.01%) let right = self.buf.push(BufEntry { token: Token::Begin(token), size: -self.right_total }); . self.scan_stack.push_back(right); . } . . fn scan_end(&mut self) { 101,968 ( 0.00%) if self.scan_stack.is_empty() { . self.print_end(); . } else { . let right = self.buf.push(BufEntry { token: Token::End, size: -1 }); . self.scan_stack.push_back(right); . } . } . . fn scan_break(&mut self, token: BreakToken) { 30,673 ( 0.00%) if self.scan_stack.is_empty() { 2 ( 0.00%) self.left_total = 1; . self.right_total = 1; . self.buf.clear(); . } else { 61,344 ( 0.00%) self.check_stack(0); . } 122,692 ( 0.00%) let right = self.buf.push(BufEntry { token: Token::Break(token), size: -self.right_total }); . self.scan_stack.push_back(right); 92,019 ( 0.00%) self.right_total += token.blank_space; . } . 1,194,633 ( 0.03%) fn scan_string(&mut self, string: Cow<'static, str>) { 132,737 ( 0.00%) if self.scan_stack.is_empty() { . self.print_string(&string); . } else { . let len = string.len() as isize; 132,642 ( 0.00%) self.buf.push(BufEntry { token: Token::String(string), size: len }); 397,926 ( 0.01%) self.right_total += len; . self.check_stream(); . } 1,061,136 ( 0.03%) } . . fn check_stream(&mut self) { 585,008 ( 0.01%) while self.right_total - self.left_total > self.space { 32,667 ( 0.00%) if *self.scan_stack.front().unwrap() == self.buf.index_of_first() { . self.scan_stack.pop_front().unwrap(); 5,673 ( 0.00%) self.buf.first_mut().unwrap().size = SIZE_INFINITY; . } 21,778 ( 0.00%) self.advance_left(); 10,889 ( 0.00%) if self.buf.is_empty() { . break; . } . } . } . 553,231 ( 0.01%) fn advance_left(&mut self) { 756,278 ( 0.02%) while self.buf.first().unwrap().size >= 0 { 1,101,753 ( 0.03%) let left = self.buf.pop_first().unwrap(); . . match &left.token { . Token::String(string) => { 397,926 ( 0.01%) self.left_total += string.len() as isize; . self.print_string(string); . } . Token::Break(token) => { 92,019 ( 0.00%) self.left_total += token.blank_space; . self.print_break(*token, left.size); . } 921 ( 0.00%) Token::Begin(token) => self.print_begin(*token, left.size), . Token::End => self.print_end(), . } . 2,938,008 ( 0.07%) self.last_printed = Some(left.token); . 367,251 ( 0.01%) if self.buf.is_empty() { . break; . } . } 87,520 ( 0.00%) } . 276,507 ( 0.01%) fn check_stack(&mut self, mut depth: usize) { 484,763 ( 0.01%) while let Some(&index) = self.scan_stack.back() { . let mut entry = &mut self.buf[index]; 973,785 ( 0.02%) match entry.token { . Token::Begin(_) => { 224,940 ( 0.01%) if depth == 0 { . break; . } . self.scan_stack.pop_back().unwrap(); 304,983 ( 0.01%) entry.size += self.right_total; 101,661 ( 0.00%) depth -= 1; . } . Token::End => { . // paper says + not =, but that makes no sense. . self.scan_stack.pop_back().unwrap(); 101,965 ( 0.00%) entry.size = 1; 203,930 ( 0.01%) depth += 1; . } . _ => { . self.scan_stack.pop_back().unwrap(); 75,930 ( 0.00%) entry.size += self.right_total; 65,261 ( 0.00%) if depth == 0 { . break; . } . } . } . } 245,784 ( 0.01%) } . . fn get_top(&self) -> PrintFrame { 92,019 ( 0.00%) *self . .print_stack . .last() . .unwrap_or(&PrintFrame::Broken { offset: 0, breaks: Breaks::Inconsistent }) . } . . fn print_begin(&mut self, token: BeginToken, size: isize) { 305,904 ( 0.01%) if size > self.space { 1,535 ( 0.00%) let col = self.margin - self.space + token.offset; . self.print_stack.push(PrintFrame::Broken { offset: col, breaks: token.breaks }); . } else { . self.print_stack.push(PrintFrame::Fits); . } . } . . fn print_end(&mut self) { . self.print_stack.pop().unwrap(); . } . . fn print_break(&mut self, token: BreakToken, size: isize) { . let break_offset = 100,326 ( 0.00%) match self.get_top() { . PrintFrame::Fits => None, . PrintFrame::Broken { offset, breaks: Breaks::Consistent } => Some(offset), . PrintFrame::Broken { offset, breaks: Breaks::Inconsistent } => { . if size > self.space { Some(offset) } else { None } . } . }; . if let Some(offset) = break_offset { . self.out.push('\n'); 16,089 ( 0.00%) self.pending_indentation = offset + token.offset; 21,452 ( 0.00%) self.space = self.margin - (offset + token.offset); . } else { 75,930 ( 0.00%) self.pending_indentation += token.blank_space; 101,240 ( 0.00%) self.space -= token.blank_space; . } . } . . fn print_string(&mut self, string: &str) { . // Write the pending indent. A more concise way of doing this would be: . // . // write!(self.out, "{: >n$}", "", n = self.pending_indentation as usize)?; . // . // But that is significantly slower. This code is sufficiently hot, and indents can get . // sufficiently large, that the difference is significant on some workloads. 132,737 ( 0.00%) self.out.reserve(self.pending_indentation as usize); 8 ( 0.00%) self.out.extend(iter::repeat(' ').take(self.pending_indentation as usize)); 132,737 ( 0.00%) self.pending_indentation = 0; . . self.out.push_str(string); 663,590 ( 0.02%) self.space -= string.len() as isize; . } . . // Convenience functions to talk to the printer. . . /// "raw box" 165,880 ( 0.00%) pub fn rbox(&mut self, indent: usize, breaks: Breaks) { . self.scan_begin(BeginToken { offset: indent as isize, breaks }) 124,410 ( 0.00%) } . . /// Inconsistent breaking box 487,398 ( 0.01%) pub fn ibox(&mut self, indent: usize) { . self.rbox(indent, Breaks::Inconsistent) 406,165 ( 0.01%) } . . /// Consistent breaking box . pub fn cbox(&mut self, indent: usize) { . self.rbox(indent, Breaks::Consistent) . } . 245,384 ( 0.01%) pub fn break_offset(&mut self, n: usize, off: isize) { . self.scan_break(BreakToken { offset: off, blank_space: n as isize }) 184,038 ( 0.00%) } . 407,872 ( 0.01%) pub fn end(&mut self) { . self.scan_end() 407,872 ( 0.01%) } . 730 ( 0.00%) pub fn eof(mut self) -> String { . self.scan_eof(); 584 ( 0.00%) self.out 730 ( 0.00%) } . . pub fn word>>(&mut self, wrd: S) { . let string = wrd.into(); 947,332 ( 0.02%) self.scan_string(string) . } . . fn spaces(&mut self, n: usize) { 122,692 ( 0.00%) self.break_offset(n, 0) . } . . crate fn zerobreak(&mut self) { . self.spaces(0) . } . . pub fn space(&mut self) { . self.spaces(1) . } . . pub fn hardbreak(&mut self) { . self.spaces(SIZE_INFINITY as usize) . } . . pub fn is_beginning_of_line(&self) -> bool { 61,338 ( 0.00%) match self.last_token() { . Some(last_token) => last_token.is_hardbreak_tok(), . None => true, . } . } . . pub fn hardbreak_tok_offset(off: isize) -> Token { . Token::Break(BreakToken { offset: off, blank_space: SIZE_INFINITY }) . } -- line 481 ---------------------------------------- 2,081,165 ( 0.05%) -------------------------------------------------------------------------------- -- Auto-annotated source: /usr/home/liquid/rust/worktree-benchmarking/library/core/src/ptr/mod.rs -------------------------------------------------------------------------------- Ir -- line 180 ---------------------------------------- . /// assert_eq!(v, &[0.into()]); . /// . /// // Ensure that the last item was dropped. . /// assert!(weak.upgrade().is_none()); . /// ``` . #[stable(feature = "drop_in_place", since = "1.8.0")] . #[lang = "drop_in_place"] . #[allow(unconditional_recursion)] 42,283,433 ( 1.07%) pub unsafe fn drop_in_place(to_drop: *mut T) { . // Code here does not matter - this is replaced by the . // real drop glue by the compiler. . . // SAFETY: see comment above . unsafe { drop_in_place(to_drop) } . } . . /// Creates a null raw pointer. -- line 196 ---------------------------------------- -- line 366 ---------------------------------------- . let mut tmp = MaybeUninit::::uninit(); . . // Perform the swap . // SAFETY: the caller must guarantee that `x` and `y` are . // valid for writes and properly aligned. `tmp` cannot be . // overlapping either `x` or `y` because `tmp` was just allocated . // on the stack as a separate allocated object. . unsafe { 8 ( 0.00%) copy_nonoverlapping(x, tmp.as_mut_ptr(), 1); 8 ( 0.00%) copy(y, x, 1); // `x` and `y` may overlap . copy_nonoverlapping(tmp.as_ptr(), y, 1); . } . } . . /// Swaps `count * size_of::()` bytes between the two regions of memory . /// beginning at `x` and `y`. The two regions must *not* overlap. . /// . /// # Safety -- line 383 ---------------------------------------- -- line 448 ---------------------------------------- . return; . } . } . . // Direct swapping, for the cases not going through the block optimization. . // SAFETY: the caller must guarantee that `x` and `y` are valid . // for writes, properly aligned, and non-overlapping. . unsafe { 14 ( 0.00%) let z = read(x); . copy_nonoverlapping(y, x, 1); . write(y, z); . } . } . . #[inline] . #[rustc_const_unstable(feature = "const_swap", issue = "83163")] . const unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) { -- line 464 ---------------------------------------- -- line 693 ---------------------------------------- . let mut tmp = MaybeUninit::::uninit(); . // SAFETY: the caller must guarantee that `src` is valid for reads. . // `src` cannot overlap `tmp` because `tmp` was just allocated on . // the stack as a separate allocated object. . // . // Also, since we just wrote a valid value into `tmp`, it is guaranteed . // to be properly initialized. . unsafe { 859,227 ( 0.02%) copy_nonoverlapping(src, tmp.as_mut_ptr(), 1); 6,213,720 ( 0.16%) tmp.assume_init() . } . } . . /// Reads the value from `src` without moving it. This leaves the . /// memory in `src` unchanged. . /// . /// Unlike [`read`], `read_unaligned` works with unaligned pointers. . /// -- line 710 ---------------------------------------- -- line 884 ---------------------------------------- . #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")] . fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize); . } . . // SAFETY: the caller must guarantee that `dst` is valid for writes. . // `dst` cannot overlap `src` because the caller has mutable access . // to `dst` while `src` is owned by this function. . unsafe { 47,474,028 ( 1.21%) copy_nonoverlapping(&src as *const T, dst, 1); . intrinsics::forget(src); . } . } . . /// Overwrites a memory location with the given value without reading or . /// dropping the old value. . /// . /// Unlike [`write()`], the pointer may be unaligned. -- line 900 ---------------------------------------- -- line 1206 ---------------------------------------- . if stride == 1 { . // `stride == 1` case can be computed more simply through `-p (mod a)`, but doing so . // inhibits LLVM's ability to select instructions like `lea`. Instead we compute . // . // round_up_to_next_alignment(p, a) - p . // . // which distributes operations around the load-bearing, but pessimizing `and` sufficiently . // for LLVM to be able to utilize the various optimizations it knows about. 1,287 ( 0.00%) return wrapping_sub( 3,600 ( 0.00%) wrapping_add(p as usize, a_minus_one) & wrapping_sub(0, a), . p as usize, . ); . } . . let pmoda = p as usize & a_minus_one; . if pmoda == 0 { . // Already aligned. Yay! . return 0; -- line 1223 ---------------------------------------- -- line 1348 ---------------------------------------- . /// assert!(std::ptr::eq( . /// &wrapper as &dyn Trait as *const dyn Trait as *const u8, . /// &wrapper.member as &dyn Trait as *const dyn Trait as *const u8, . /// )); . /// ``` . #[stable(feature = "ptr_eq", since = "1.17.0")] . #[inline] . pub fn eq(a: *const T, b: *const T) -> bool { 1,804,499 ( 0.05%) a == b . } . . /// Hash a raw pointer. . /// . /// This can be used to hash a `&T` reference (which coerces to `*const T` implicitly) . /// by its address rather than the value it points to . /// (which is what the `Hash for &T` implementation does). . /// -- line 1364 ---------------------------------------- 7,054,608 ( 0.18%) -------------------------------------------------------------------------------- -- Auto-annotated source: /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_middle/src/ty/layout.rs -------------------------------------------------------------------------------- Ir -- line 23 ---------------------------------------- . use std::iter; . use std::num::NonZeroUsize; . use std::ops::Bound; . . use rand::{seq::SliceRandom, SeedableRng}; . use rand_xoshiro::Xoshiro128StarStar; . . pub fn provide(providers: &mut ty::query::Providers) { 6 ( 0.00%) *providers = . ty::query::Providers { layout_of, fn_abi_of_fn_ptr, fn_abi_of_instance, ..*providers }; . } . . pub trait IntegerExt { . fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>, signed: bool) -> Ty<'tcx>; . fn from_attr(cx: &C, ity: attr::IntType) -> Integer; . fn from_int_ty(cx: &C, ity: ty::IntTy) -> Integer; . fn from_uint_ty(cx: &C, uty: ty::UintTy) -> Integer; -- line 39 ---------------------------------------- -- line 59 ---------------------------------------- . (I16, true) => tcx.types.i16, . (I32, true) => tcx.types.i32, . (I64, true) => tcx.types.i64, . (I128, true) => tcx.types.i128, . } . } . . /// Gets the Integer type from an attr::IntType. 12 ( 0.00%) fn from_attr(cx: &C, ity: attr::IntType) -> Integer { . let dl = cx.data_layout(); . 30 ( 0.00%) match ity { . attr::SignedInt(ast::IntTy::I8) | attr::UnsignedInt(ast::UintTy::U8) => I8, . attr::SignedInt(ast::IntTy::I16) | attr::UnsignedInt(ast::UintTy::U16) => I16, . attr::SignedInt(ast::IntTy::I32) | attr::UnsignedInt(ast::UintTy::U32) => I32, . attr::SignedInt(ast::IntTy::I64) | attr::UnsignedInt(ast::UintTy::U64) => I64, . attr::SignedInt(ast::IntTy::I128) | attr::UnsignedInt(ast::UintTy::U128) => I128, . attr::SignedInt(ast::IntTy::Isize) | attr::UnsignedInt(ast::UintTy::Usize) => { 6 ( 0.00%) dl.ptr_sized_integer() . } . } 12 ( 0.00%) } . . fn from_int_ty(cx: &C, ity: ty::IntTy) -> Integer { 10 ( 0.00%) match ity { . ty::IntTy::I8 => I8, . ty::IntTy::I16 => I16, . ty::IntTy::I32 => I32, . ty::IntTy::I64 => I64, . ty::IntTy::I128 => I128, 431 ( 0.00%) ty::IntTy::Isize => cx.data_layout().ptr_sized_integer(), . } . } . fn from_uint_ty(cx: &C, ity: ty::UintTy) -> Integer { . match ity { . ty::UintTy::U8 => I8, . ty::UintTy::U16 => I16, . ty::UintTy::U32 => I32, . ty::UintTy::U64 => I64, . ty::UintTy::U128 => I128, 2 ( 0.00%) ty::UintTy::Usize => cx.data_layout().ptr_sized_integer(), . } . } . . /// Finds the appropriate Integer type and signedness for the given . /// signed discriminant range and `#[repr]` attribute. . /// N.B.: `u128` values above `i128::MAX` will be treated as signed, but . /// that shouldn't affect anything, other than maybe debuginfo. 9 ( 0.00%) fn repr_discr<'tcx>( . tcx: TyCtxt<'tcx>, . ty: Ty<'tcx>, . repr: &ReprOptions, . min: i128, . max: i128, . ) -> (Integer, bool) { . // Theoretically, negative values could be larger in unsigned representation . // than the unsigned representation of the signed minimum. However, if there . // are any negative values, the only valid unsigned representation is u128 . // which can fit all i128 values, so the result remains unaffected. . let unsigned_fit = Integer::fit_unsigned(cmp::max(min as u128, max as u128)); . let signed_fit = cmp::max(Integer::fit_signed(min), Integer::fit_signed(max)); . 9 ( 0.00%) if let Some(ity) = repr.int { . let discr = Integer::from_attr(&tcx, ity); . let fit = if ity.is_signed() { signed_fit } else { unsigned_fit }; . if discr < fit { . bug!( . "Integer::repr_discr: `#[repr]` hint too small for \ . discriminant range of enum `{}", . ty . ) . } . return (discr, ity.is_signed()); . } . 6 ( 0.00%) let at_least = if repr.c() { . // This is usually I32, however it can be different on some platforms, . // notably hexagon and arm-none/thumb-none . tcx.data_layout().c_enum_min_size . } else { . // repr(Rust) enums try to be as small as possible . I8 . }; . . // If there are no negative values, we can use the unsigned fit. 27 ( 0.00%) if min >= 0 { . (cmp::max(unsigned_fit, at_least), false) . } else { . (cmp::max(signed_fit, at_least), true) . } 18 ( 0.00%) } . } . . pub trait PrimitiveExt { . fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx>; . fn to_int_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx>; . } . . impl PrimitiveExt for Primitive { -- line 157 ---------------------------------------- -- line 215 ---------------------------------------- . "unable to determine layout for `{}` because `{}` cannot be normalized", . t, . e.get_type_for_failure() . ), . } . } . } . 992 ( 0.00%) #[instrument(skip(tcx, query), level = "debug")] . fn layout_of<'tcx>( . tcx: TyCtxt<'tcx>, . query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>, . ) -> Result, LayoutError<'tcx>> { . ty::tls::with_related_context(tcx, move |icx| { 62 ( 0.00%) let (param_env, ty) = query.into_parts(); . debug!(?ty); . 248 ( 0.00%) if !tcx.recursion_limit().value_within_limit(icx.layout_depth) { . tcx.sess.fatal(&format!("overflow representing the type `{}`", ty)); . } . . // Update the ImplicitCtxt to increase the layout_depth 558 ( 0.00%) let icx = ty::tls::ImplicitCtxt { layout_depth: icx.layout_depth + 1, ..icx.clone() }; . . ty::tls::enter_context(&icx, |_| { 186 ( 0.00%) let param_env = param_env.with_reveal_all_normalized(tcx); . let unnormalized_ty = ty; . . // FIXME: We might want to have two different versions of `layout_of`: . // One that can be called after typecheck has completed and can use . // `normalize_erasing_regions` here and another one that can be called . // before typecheck has completed and uses `try_normalize_erasing_regions`. . let ty = match tcx.try_normalize_erasing_regions(param_env, ty) { . Ok(t) => t, . Err(normalization_error) => { . return Err(LayoutError::NormalizationFailure(ty, normalization_error)); . } . }; . 62 ( 0.00%) if ty != unnormalized_ty { . // Ensure this layout is also cached for the normalized type. . return tcx.layout_of(param_env.and(ty)); . } . 240 ( 0.00%) let cx = LayoutCx { tcx, param_env }; . 180 ( 0.00%) let layout = cx.layout_of_uncached(ty)?; . let layout = TyAndLayout { ty, layout }; . . cx.record_layout_for_printing(layout); . . // Type-level uninhabitedness should always imply ABI uninhabitedness. 60 ( 0.00%) if tcx.conservative_is_privately_uninhabited(param_env.and(ty)) { . assert!(layout.abi.is_uninhabited()); . } . 180 ( 0.00%) Ok(layout) . }) . }) . } . . pub struct LayoutCx<'tcx, C> { . pub tcx: C, . pub param_env: ty::ParamEnv<'tcx>, . } -- line 279 ---------------------------------------- -- line 291 ---------------------------------------- . // Invert a bijective mapping, i.e. `invert(map)[y] = x` if `map[x] = y`. . // This is used to go between `memory_index` (source field order to memory order) . // and `inverse_memory_index` (memory order to source field order). . // See also `FieldsShape::Arbitrary::memory_index` for more details. . // FIXME(eddyb) build a better abstraction for permutations, if possible. . fn invert_mapping(map: &[u32]) -> Vec { . let mut inverse = vec![0; map.len()]; . for i in 0..map.len() { 128 ( 0.00%) inverse[map[i] as usize] = i as u32; . } . inverse . } . . impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { 36 ( 0.00%) fn scalar_pair(&self, a: Scalar, b: Scalar) -> Layout { . let dl = self.data_layout(); 28 ( 0.00%) let b_align = b.value.align(dl); 32 ( 0.00%) let align = a.value.align(dl).max(b_align).max(dl.aggregate_align); . let b_offset = a.value.size(dl).align_to(b_align.abi); . let size = (b_offset + b.value.size(dl)).align_to(align.abi); . . // HACK(nox): We iter on `b` and then `a` because `max_by_key` . // returns the last maximum. 48 ( 0.00%) let largest_niche = Niche::from_scalar(dl, b_offset, b) . .into_iter() 40 ( 0.00%) .chain(Niche::from_scalar(dl, Size::ZERO, a)) . .max_by_key(|niche| niche.available(dl)); . 76 ( 0.00%) Layout { . variants: Variants::Single { index: VariantIdx::new(0) }, . fields: FieldsShape::Arbitrary { 8 ( 0.00%) offsets: vec![Size::ZERO, b_offset], 8 ( 0.00%) memory_index: vec![0, 1], . }, 52 ( 0.00%) abi: Abi::ScalarPair(a, b), 40 ( 0.00%) largest_niche, . align, . size, . } 32 ( 0.00%) } . 552 ( 0.00%) fn univariant_uninterned( . &self, . ty: Ty<'tcx>, . fields: &[TyAndLayout<'_>], . repr: &ReprOptions, . kind: StructKind, . ) -> Result> { . let dl = self.data_layout(); 184 ( 0.00%) let pack = repr.pack; 46 ( 0.00%) if pack.is_some() && repr.align.is_some() { . self.tcx.sess.delay_span_bug(DUMMY_SP, "struct cannot be packed and aligned"); . return Err(LayoutError::Unknown(ty)); . } . 184 ( 0.00%) let mut align = if pack.is_some() { dl.i8_align } else { dl.aggregate_align }; . . let mut inverse_memory_index: Vec = (0..fields.len() as u32).collect(); . . let optimize = !repr.inhibit_struct_field_reordering_opt(); 46 ( 0.00%) if optimize { . let end = 322 ( 0.00%) if let StructKind::MaybeUnsized = kind { fields.len() - 1 } else { fields.len() }; . let optimizing = &mut inverse_memory_index[..end]; 46 ( 0.00%) let field_align = |f: &TyAndLayout<'_>| { . if let Some(pack) = pack { f.align.abi.min(pack) } else { f.align.abi } . }; . . // If `-Z randomize-layout` was enabled for the type definition we can shuffle . // the field ordering to try and catch some code making assumptions about layouts . // we don't guarantee . if repr.can_randomize_type_layout() { . // `ReprOptions.layout_seed` is a deterministic seed that we can use to -- line 363 ---------------------------------------- -- line 364 ---------------------------------------- . // randomize field ordering with . let mut rng = Xoshiro128StarStar::seed_from_u64(repr.field_shuffle_seed); . . // Shuffle the ordering of the fields . optimizing.shuffle(&mut rng); . . // Otherwise we just leave things alone and actually optimize the type's fields . } else { 92 ( 0.00%) match kind { . StructKind::AlwaysSized | StructKind::MaybeUnsized => { 105 ( 0.00%) optimizing.sort_by_key(|&x| { . // Place ZSTs first to avoid "interesting offsets", . // especially with only one or two non-ZST fields. . let f = &fields[x as usize]; . (!f.is_zst(), cmp::Reverse(field_align(f))) . }); . } . . StructKind::Prefixed(..) => { . // Sort in ascending alignment so that the layout stays optimal . // regardless of the prefix 125 ( 0.00%) optimizing.sort_by_key(|&x| field_align(&fields[x as usize])); . } . } . . // FIXME(Kixiron): We can always shuffle fields within a given alignment class . // regardless of the status of `-Z randomize-layout` . } . } . -- line 393 ---------------------------------------- -- line 399 ---------------------------------------- . // produce `memory_index` (see `invert_mapping`). . . let mut sized = true; . let mut offsets = vec![Size::ZERO; fields.len()]; . let mut offset = Size::ZERO; . let mut largest_niche = None; . let mut largest_niche_available = 0; . 138 ( 0.00%) if let StructKind::Prefixed(prefix_size, prefix_align) = kind { . let prefix_align = 175 ( 0.00%) if let Some(pack) = pack { prefix_align.min(pack) } else { prefix_align }; . align = align.max(AbiAndPrefAlign::new(prefix_align)); . offset = prefix_size.align_to(prefix_align); . } . 32 ( 0.00%) for &i in &inverse_memory_index { 412 ( 0.00%) let field = fields[i as usize]; 64 ( 0.00%) if !sized { . self.tcx.sess.delay_span_bug( . DUMMY_SP, . &format!( . "univariant: field #{} of `{}` comes after unsized field", . offsets.len(), . ty . ), . ); . } . 160 ( 0.00%) if field.is_unsized() { . sized = false; . } . . // Invariant: offset < dl.obj_size_bound() <= 1<<61 64 ( 0.00%) let field_align = if let Some(pack) = pack { . field.align.min(AbiAndPrefAlign::new(pack)) . } else { 96 ( 0.00%) field.align . }; . offset = offset.align_to(field_align.abi); . align = align.max(field_align); . . debug!("univariant offset: {:?} field: {:#?}", offset, field); 64 ( 0.00%) offsets[i as usize] = offset; . 32 ( 0.00%) if !repr.hide_niche() { 200 ( 0.00%) if let Some(mut niche) = field.largest_niche { . let available = niche.available(dl); 32 ( 0.00%) if available > largest_niche_available { . largest_niche_available = available; . niche.offset += offset; 96 ( 0.00%) largest_niche = Some(niche); . } . } . } . 32 ( 0.00%) offset = offset.checked_add(field.size, dl).ok_or(LayoutError::SizeOverflow(ty))?; . } . 112 ( 0.00%) if let Some(repr_align) = repr.align { . align = align.max(AbiAndPrefAlign::new(repr_align)); . } . . debug!("univariant min_size: {:?}", offset); . let min_size = offset; . . // As stated above, inverse_memory_index holds field indices by increasing offset. . // This makes it an already-sorted view of the offsets vec. . // To invert it, consider: . // If field 5 has offset 0, offsets[0] is 5, and memory_index[5] should be 0. . // Field 5 would be the first element, so memory_index is i: . // Note: if we didn't optimize, it's already right. . . let memory_index = 92 ( 0.00%) if optimize { invert_mapping(&inverse_memory_index) } else { inverse_memory_index }; . . let size = min_size.align_to(align.abi); 92 ( 0.00%) let mut abi = Abi::Aggregate { sized }; . . // Unpack newtype ABIs and find scalar pairs. 184 ( 0.00%) if sized && size.bytes() > 0 { . // All other fields must be ZSTs. . let mut non_zst_fields = fields.iter().enumerate().filter(|&(_, f)| !f.is_zst()); . 24 ( 0.00%) match (non_zst_fields.next(), non_zst_fields.next(), non_zst_fields.next()) { . // We have exactly one non-ZST field. . (Some((i, field)), None, None) => { . // Field fills the struct and it has a scalar or scalar pair ABI. 44 ( 0.00%) if offsets[i].bytes() == 0 && align.abi == field.align.abi && size == field.size . { 36 ( 0.00%) match field.abi { . // For plain scalars, or vectors of them, we can't unpack . // newtypes for `#[repr(C)]`, as that affects C ABIs. . Abi::Scalar(_) | Abi::Vector { .. } if optimize => { . abi = field.abi; . } . // But scalar pairs are Rust-specific and get . // treated as aggregates by C ABIs anyway. . Abi::ScalarPair(..) => { -- line 496 ---------------------------------------- -- line 528 ---------------------------------------- . abi = pair.abi; . } . } . . _ => {} . } . } . 32 ( 0.00%) if fields.iter().any(|f| f.abi.is_uninhabited()) { . abi = Abi::Uninhabited; . } . 1,472 ( 0.00%) Ok(Layout { . variants: Variants::Single { index: VariantIdx::new(0) }, 460 ( 0.00%) fields: FieldsShape::Arbitrary { offsets, memory_index }, . abi, 506 ( 0.00%) largest_niche, . align, . size, . }) 460 ( 0.00%) } . 600 ( 0.00%) fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<'tcx>> { 120 ( 0.00%) let tcx = self.tcx; 60 ( 0.00%) let param_env = self.param_env; . let dl = self.data_layout(); 68 ( 0.00%) let scalar_unit = |value: Primitive| { 1 ( 0.00%) let size = value.size(dl); 30 ( 0.00%) assert!(size.bits() <= 128); 41 ( 0.00%) Scalar { value, valid_range: WrappingRange { start: 0, end: size.unsigned_int_max() } } 8 ( 0.00%) }; . let scalar = |value: Primitive| tcx.intern_layout(Layout::scalar(self, scalar_unit(value))); . . let univariant = |fields: &[TyAndLayout<'_>], repr: &ReprOptions, kind| { 315 ( 0.00%) Ok(tcx.intern_layout(self.univariant_uninterned(ty, fields, repr, kind)?)) . }; . debug_assert!(!ty.has_infer_types_or_consts()); . 466 ( 0.00%) Ok(match *ty.kind() { . // Basic scalars. . ty::Bool => tcx.intern_layout(Layout::scalar( . self, 12 ( 0.00%) Scalar { value: Int(I8, false), valid_range: WrappingRange { start: 0, end: 1 } }, . )), . ty::Char => tcx.intern_layout(Layout::scalar( . self, 12 ( 0.00%) Scalar { . value: Int(I32, false), . valid_range: WrappingRange { start: 0, end: 0x10FFFF }, . }, . )), 15 ( 0.00%) ty::Int(ity) => scalar(Int(Integer::from_int_ty(dl, ity), true)), 20 ( 0.00%) ty::Uint(ity) => scalar(Int(Integer::from_uint_ty(dl, ity), false)), . ty::Float(fty) => scalar(match fty { . ty::FloatTy::F32 => F32, . ty::FloatTy::F64 => F64, . }), . ty::FnPtr(_) => { . let mut ptr = scalar_unit(Pointer); . ptr.valid_range = ptr.valid_range.with_start(1); . tcx.intern_layout(Layout::scalar(self, ptr)) -- line 588 ---------------------------------------- -- line 594 ---------------------------------------- . fields: FieldsShape::Primitive, . abi: Abi::Uninhabited, . largest_niche: None, . align: dl.i8_align, . size: Size::ZERO, . }), . . // Potentially-wide pointers. 4 ( 0.00%) ty::Ref(_, pointee, _) | ty::RawPtr(ty::TypeAndMut { ty: pointee, .. }) => { . let mut data_ptr = scalar_unit(Pointer); . if !ty.is_unsafe_ptr() { . data_ptr.valid_range = data_ptr.valid_range.with_start(1); . } . . let pointee = tcx.normalize_erasing_regions(param_env, pointee); 32 ( 0.00%) if pointee.is_sized(tcx.at(DUMMY_SP), param_env) { 17 ( 0.00%) return Ok(tcx.intern_layout(Layout::scalar(self, data_ptr))); . } . 12 ( 0.00%) let unsized_part = tcx.struct_tail_erasing_lifetimes(pointee, param_env); 12 ( 0.00%) let metadata = match unsized_part.kind() { . ty::Foreign(..) => { . return Ok(tcx.intern_layout(Layout::scalar(self, data_ptr))); . } 16 ( 0.00%) ty::Slice(_) | ty::Str => scalar_unit(Int(dl.ptr_sized_integer(), false)), . ty::Dynamic(..) => { 2 ( 0.00%) let mut vtable = scalar_unit(Pointer); 2 ( 0.00%) vtable.valid_range = vtable.valid_range.with_start(1); 8 ( 0.00%) vtable . } . _ => return Err(LayoutError::Unknown(unsized_part)), . }; . . // Effectively a (ptr, meta) tuple. 63 ( 0.00%) tcx.intern_layout(self.scalar_pair(data_ptr, metadata)) . } . . // Arrays and slices. 60 ( 0.00%) ty::Array(element, mut count) => { 20 ( 0.00%) if count.has_projections() { . count = tcx.normalize_erasing_regions(param_env, count); . if count.has_projections() { . return Err(LayoutError::Unknown(ty)); . } . } . 80 ( 0.00%) let count = count.try_eval_usize(tcx, param_env).ok_or(LayoutError::Unknown(ty))?; 100 ( 0.00%) let element = self.layout_of(element)?; . let size = 100 ( 0.00%) element.size.checked_mul(count, dl).ok_or(LayoutError::SizeOverflow(ty))?; . . let abi = 154 ( 0.00%) if count != 0 && tcx.conservative_is_privately_uninhabited(param_env.and(ty)) { . Abi::Uninhabited . } else { . Abi::Aggregate { sized: true } . }; . 209 ( 0.00%) let largest_niche = if count != 0 { element.largest_niche } else { None }; . 440 ( 0.00%) tcx.intern_layout(Layout { . variants: Variants::Single { index: VariantIdx::new(0) }, 20 ( 0.00%) fields: FieldsShape::Array { stride: element.size, count }, . abi, . largest_niche, 20 ( 0.00%) align: element.align, . size, . }) . } . ty::Slice(element) => { . let element = self.layout_of(element)?; . tcx.intern_layout(Layout { . variants: Variants::Single { index: VariantIdx::new(0) }, . fields: FieldsShape::Array { stride: element.size, count: 0 }, . abi: Abi::Aggregate { sized: false }, . largest_niche: None, . align: element.align, . size: Size::ZERO, . }) . } 6 ( 0.00%) ty::Str => tcx.intern_layout(Layout { . variants: Variants::Single { index: VariantIdx::new(0) }, . fields: FieldsShape::Array { stride: Size::from_bytes(1), count: 0 }, . abi: Abi::Aggregate { sized: false }, . largest_niche: None, 1 ( 0.00%) align: dl.i8_align, . size: Size::ZERO, . }), . . // Odd unit types. 6 ( 0.00%) ty::FnDef(..) => univariant(&[], &ReprOptions::default(), StructKind::AlwaysSized)?, . ty::Dynamic(..) | ty::Foreign(..) => { . let mut unit = self.univariant_uninterned( . ty, . &[], . &ReprOptions::default(), . StructKind::AlwaysSized, . )?; . match unit.abi { -- line 692 ---------------------------------------- -- line 702 ---------------------------------------- . let tys = substs.as_closure().upvar_tys(); . univariant( . &tys.map(|ty| self.layout_of(ty)).collect::, _>>()?, . &ReprOptions::default(), . StructKind::AlwaysSized, . )? . } . 12 ( 0.00%) ty::Tuple(tys) => { . let kind = 36 ( 0.00%) if tys.len() == 0 { StructKind::AlwaysSized } else { StructKind::MaybeUnsized }; . 12 ( 0.00%) univariant( 24 ( 0.00%) &tys.iter() . .map(|k| self.layout_of(k.expect_ty())) . .collect::, _>>()?, 24 ( 0.00%) &ReprOptions::default(), . kind, . )? . } . . // SIMD vector types. 18 ( 0.00%) ty::Adt(def, substs) if def.repr.simd() => { . if !def.is_struct() { . // Should have yielded E0517 by now. . tcx.sess.delay_span_bug( . DUMMY_SP, . "#[repr(simd)] was applied to an ADT that is not a struct", . ); . return Err(LayoutError::Unknown(ty)); . } -- line 732 ---------------------------------------- -- line 833 ---------------------------------------- . abi: Abi::Vector { element: e_abi, count: e_len }, . largest_niche: e_ly.largest_niche, . size, . align, . }) . } . . // ADTs. 18 ( 0.00%) ty::Adt(def, substs) => { . // Cache the field layouts. 18 ( 0.00%) let variants = def . .variants . .iter() . .map(|v| { . v.fields . .iter() 64 ( 0.00%) .map(|field| self.layout_of(field.ty(tcx, substs))) . .collect::, _>>() . }) . .collect::, _>>()?; . 9 ( 0.00%) if def.is_union() { . if def.repr.pack.is_some() && def.repr.align.is_some() { . self.tcx.sess.delay_span_bug( . tcx.def_span(def.did), . "union cannot be packed and aligned", . ); . return Err(LayoutError::Unknown(ty)); . } . -- line 862 ---------------------------------------- -- line 921 ---------------------------------------- . } . . // A variant is absent if it's uninhabited and only has ZST fields. . // Present uninhabited variants only require space for their fields, . // but *not* an encoding of the discriminant (e.g., a tag value). . // See issue #49298 for more details on the need to leave space . // for non-ZST uninhabited data (mostly partial initialization). . let absent = |fields: &[TyAndLayout<'_>]| { 8 ( 0.00%) let uninhabited = fields.iter().any(|f| f.abi.is_uninhabited()); . let is_zst = fields.iter().all(|f| f.is_zst()); 25 ( 0.00%) uninhabited && is_zst 25 ( 0.00%) }; . let (present_first, present_second) = { . let mut present_variants = variants . .iter_enumerated() 48 ( 0.00%) .filter_map(|(i, v)| if absent(v) { None } else { Some(i) }); . (present_variants.next(), present_variants.next()) . }; 18 ( 0.00%) let present_first = match present_first { . Some(present_first) => present_first, . // Uninhabited because it has no variants, or only absent ones. . None if def.is_enum() => { . return Ok(tcx.layout_of(param_env.and(tcx.types.never))?.layout); . } . // If it's a struct, still compute a layout so that we can still compute the . // field offsets. . None => VariantIdx::new(0), . }; . 9 ( 0.00%) let is_struct = !def.is_enum() || . // Only one variant is present. 3 ( 0.00%) (present_second.is_none() && . // Representation optimizations are allowed. . !def.repr.inhibit_enum_layout_opt()); . if is_struct { . // Struct, or univariant enum equivalent to a struct. . // (Typechecking will reject discriminant-sizing attrs.) . . let v = present_first; 6 ( 0.00%) let kind = if def.is_enum() || variants[v].is_empty() { . StructKind::AlwaysSized . } else { 18 ( 0.00%) let param_env = tcx.param_env(def.did); 6 ( 0.00%) let last_field = def.variants[v].fields.last().unwrap(); . let always_sized = 36 ( 0.00%) tcx.type_of(last_field.did).is_sized(tcx.at(DUMMY_SP), param_env); 12 ( 0.00%) if !always_sized { . StructKind::MaybeUnsized . } else { . StructKind::AlwaysSized . } . }; . 78 ( 0.00%) let mut st = self.univariant_uninterned(ty, &variants[v], &def.repr, kind)?; 30 ( 0.00%) st.variants = Variants::Single { index: v }; 42 ( 0.00%) let (start, end) = self.tcx.layout_scalar_valid_range(def.did); 24 ( 0.00%) match st.abi { . Abi::Scalar(ref mut scalar) | Abi::ScalarPair(ref mut scalar, _) => { . // the asserts ensure that we are not using the . // `#[rustc_layout_scalar_valid_range(n)]` . // attribute to widen the range of anything as that would probably . // result in UB somewhere . // FIXME(eddyb) the asserts are probably not needed, . // as larger validity ranges would result in missed . // optimizations, *not* wrongly assuming the inner -- line 985 ---------------------------------------- -- line 1013 ---------------------------------------- . st.largest_niche = Some(niche); . } . } . None => st.largest_niche = Some(niche), . } . } . } . _ => assert!( 18 ( 0.00%) start == Bound::Unbounded && end == Bound::Unbounded, . "nonscalar layout for layout_scalar_valid_range type {:?}: {:#?}", . def, . st, . ), . } . 54 ( 0.00%) return Ok(tcx.intern_layout(st)); . } . . // At this point, we have handled all unions and . // structs. (We have also handled univariant enums . // that allow representation optimization.) . assert!(def.is_enum()); . . // The current code for niche-filling relies on variant indices . // instead of actual discriminants, so dataful enums with . // explicit discriminants (RFC #2363) would misbehave. . let no_explicit_discriminants = def . .variants . .iter_enumerated() . .all(|(i, v)| v.discr == ty::VariantDiscr::Relative(i.as_u32())); . 6 ( 0.00%) let mut niche_filling_layout = None; . . // Niche-filling enum optimization. 6 ( 0.00%) if !def.repr.inhibit_enum_layout_opt() && no_explicit_discriminants { . let mut dataful_variant = None; . let mut niche_variants = VariantIdx::MAX..=VariantIdx::new(0); . . // Find one non-ZST variant. 159 ( 0.00%) 'variants: for (v, fields) in variants.iter_enumerated() { 75 ( 0.00%) if absent(fields) { . continue 'variants; . } 50 ( 0.00%) for f in fields { . if !f.is_zst() { . if dataful_variant.is_none() { . dataful_variant = Some(v); . continue 'variants; . } else { . dataful_variant = None; . break 'variants; . } . } . } 92 ( 0.00%) niche_variants = *niche_variants.start().min(&v)..=v; . } . 6 ( 0.00%) if niche_variants.start() > niche_variants.end() { . dataful_variant = None; . } . . if let Some(i) = dataful_variant { . let count = (niche_variants.end().as_u32() . - niche_variants.start().as_u32() . + 1) as u128; . -- line 1078 ---------------------------------------- -- line 1151 ---------------------------------------- . largest_niche, . size, . align, . }); . } . } . } . 15 ( 0.00%) let (mut min, mut max) = (i128::MAX, i128::MIN); 25 ( 0.00%) let discr_type = def.repr.discr_type(); 9 ( 0.00%) let bits = Integer::from_attr(self, discr_type).size().bits(); 58 ( 0.00%) for (i, discr) in def.discriminants(tcx) { 2 ( 0.00%) if variants[i].iter().any(|f| f.abi.is_uninhabited()) { . continue; . } . let mut x = discr.val as i128; 25 ( 0.00%) if discr_type.is_signed() { . // sign extend the raw representation to be an i128 475 ( 0.00%) x = (x << (128 - bits)) >> (128 - bits); . } 100 ( 0.00%) if x < min { 12 ( 0.00%) min = x; . } 100 ( 0.00%) if x > max { 75 ( 0.00%) max = x; . } . } . // We might have no inhabited variants, so pretend there's at least one. 3 ( 0.00%) if (min, max) == (i128::MAX, i128::MIN) { . min = 0; . max = 0; . } 15 ( 0.00%) assert!(min <= max, "discriminant range is {}...{}", min, max); 27 ( 0.00%) let (min_ity, signed) = Integer::repr_discr(tcx, ty, &def.repr, min, max); . 6 ( 0.00%) let mut align = dl.aggregate_align; 3 ( 0.00%) let mut size = Size::ZERO; . . // We're interested in the smallest alignment, so start large. 6 ( 0.00%) let mut start_align = Align::from_bytes(256).unwrap(); 15 ( 0.00%) assert_eq!(Integer::for_align(dl, start_align), None); . . // repr(C) on an enum tells us to make a (tag, union) layout, . // so we need to grow the prefix alignment to be at least . // the alignment of the union. (This value is used both for . // determining the alignment of the overall enum, and the . // determining the alignment of the payload after the tag.) 39 ( 0.00%) let mut prefix_align = min_ity.align(dl).abi; 3 ( 0.00%) if def.repr.c() { . for fields in &variants { . for field in fields { . prefix_align = prefix_align.max(field.align.abi); . } . } . } . . // Create the set of structs that represent each variant. 6 ( 0.00%) let mut layout_variants = variants . .iter_enumerated() . .map(|(i, field_layouts)| { 475 ( 0.00%) let mut st = self.univariant_uninterned( 25 ( 0.00%) ty, . &field_layouts, 50 ( 0.00%) &def.repr, 100 ( 0.00%) StructKind::Prefixed(min_ity.size(), prefix_align), . )?; 75 ( 0.00%) st.variants = Variants::Single { index: i }; . // Find the first field we can't move later . // to make room for a larger discriminant. . for field in 329 ( 0.00%) st.fields.index_by_increasing_offset().map(|j| field_layouts[j]) . { . if !field.is_zst() || field.align.abi.bytes() != 1 { 4 ( 0.00%) start_align = start_align.min(field.align.abi); . break; . } . } 100 ( 0.00%) size = cmp::max(size, st.size); 75 ( 0.00%) align = align.max(st.align); 150 ( 0.00%) Ok(st) . }) . .collect::, _>>()?; . . // Align the maximum variant size to the largest alignment. 15 ( 0.00%) size = size.align_to(align.abi); . 12 ( 0.00%) if size.bytes() >= dl.obj_size_bound() { . return Err(LayoutError::SizeOverflow(ty)); . } . 12 ( 0.00%) let typeck_ity = Integer::from_attr(dl, def.repr.discr_type()); 9 ( 0.00%) if typeck_ity < min_ity { . // It is a bug if Layout decided on a greater discriminant size than typeck for . // some reason at this point (based on values discriminant can take on). Mostly . // because this discriminant will be loaded, and then stored into variable of . // type calculated by typeck. Consider such case (a bug): typeck decided on . // byte-sized discriminant, but layout thinks we need a 16-bit to store all . // discriminant values. That would be a bug, because then, in codegen, in order . // to store this 16-bit discriminant into 8-bit sized temporary some of the . // space necessary to represent would have to be discarded (or layout is wrong -- line 1250 ---------------------------------------- -- line 1263 ---------------------------------------- . // as the alignment of the first field of each variant. . // We increase the size of the discriminant to avoid LLVM copying . // padding when it doesn't need to. This normally causes unaligned . // load/stores and excessive memcpy/memset operations. By using a . // bigger integer size, LLVM can be sure about its contents and . // won't be so conservative. . . // Use the initial field alignment 9 ( 0.00%) let mut ity = if def.repr.c() || def.repr.int.is_some() { . min_ity . } else { 9 ( 0.00%) Integer::for_align(dl, start_align).unwrap_or(min_ity) . }; . . // If the alignment is not larger than the chosen discriminant size, . // don't use the alignment as the final size. 3 ( 0.00%) if ity <= min_ity { . ity = min_ity; . } else { . // Patch up the variants' first few fields. . let old_ity_size = min_ity.size(); . let new_ity_size = ity.size(); . for variant in &mut layout_variants { . match variant.fields { . FieldsShape::Arbitrary { ref mut offsets, .. } => { -- line 1287 ---------------------------------------- -- line 1296 ---------------------------------------- . variant.size = new_ity_size; . } . } . _ => bug!(), . } . } . } . 3 ( 0.00%) let tag_mask = ity.size().unsigned_int_max(); . let tag = Scalar { . value: Int(ity, signed), . valid_range: WrappingRange { 15 ( 0.00%) start: (min as u128 & tag_mask), 12 ( 0.00%) end: (max as u128 & tag_mask), . }, . }; . let mut abi = Abi::Aggregate { sized: true }; 18 ( 0.00%) if tag.value.size(dl) == size { . abi = Abi::Scalar(tag); . } else { . // Try to use a ScalarPair for all tagged enums. . let mut common_prim = None; . for (field_layouts, layout_variant) in iter::zip(&variants, &layout_variants) { 14 ( 0.00%) let offsets = match layout_variant.fields { . FieldsShape::Arbitrary { ref offsets, .. } => offsets, . _ => bug!(), . }; . let mut fields = . iter::zip(field_layouts, offsets).filter(|p| !p.0.is_zst()); 70 ( 0.00%) let (field, offset) = match (fields.next(), fields.next()) { . (None, None) => continue, . (Some(pair), None) => pair, . _ => { . common_prim = None; . break; . } . }; 6 ( 0.00%) let prim = match field.abi { 4 ( 0.00%) Abi::Scalar(scalar) => scalar.value, . _ => { . common_prim = None; . break; . } . }; 4 ( 0.00%) if let Some(pair) = common_prim { . // This is pretty conservative. We could go fancier . // by conflating things like i32 and u32, or even . // realising that (u8, u8) could just cohabit with . // u16 or even u32. 9 ( 0.00%) if pair != (prim, offset) { . common_prim = None; . break; . } . } else { . common_prim = Some((prim, offset)); . } . } 2 ( 0.00%) if let Some((prim, offset)) = common_prim { 17 ( 0.00%) let pair = self.scalar_pair(tag, scalar_unit(prim)); 2 ( 0.00%) let pair_offsets = match pair.fields { 2 ( 0.00%) FieldsShape::Arbitrary { ref offsets, ref memory_index } => { 1 ( 0.00%) assert_eq!(memory_index, &[0, 1]); . offsets . } . _ => bug!(), . }; 6 ( 0.00%) if pair_offsets[0] == Size::ZERO 2 ( 0.00%) && pair_offsets[1] == *offset 1 ( 0.00%) && align == pair.align 1 ( 0.00%) && size == pair.size . { . // We can use `ScalarPair` only when it matches our . // already computed layout (including `#[repr(C)]`). 27 ( 0.00%) abi = pair.abi; . } 1 ( 0.00%) } . } . . if layout_variants.iter().all(|v| v.abi.is_uninhabited()) { . abi = Abi::Uninhabited; . } . 48 ( 0.00%) let largest_niche = Niche::from_scalar(dl, Size::ZERO, tag); . . let tagged_layout = Layout { . variants: Variants::Multiple { . tag, . tag_encoding: TagEncoding::Direct, . tag_field: 0, . variants: layout_variants, . }, . fields: FieldsShape::Arbitrary { 15 ( 0.00%) offsets: vec![Size::ZERO], 12 ( 0.00%) memory_index: vec![0], . }, . largest_niche, . abi, 6 ( 0.00%) align, 3 ( 0.00%) size, . }; . 9 ( 0.00%) let best_layout = match (tagged_layout, niche_filling_layout) { . (tagged_layout, Some(niche_filling_layout)) => { . // Pick the smaller layout; otherwise, . // pick the layout with the larger niche; otherwise, . // pick tagged as it has simpler codegen. . cmp::min_by_key(tagged_layout, niche_filling_layout, |layout| { . let niche_size = layout.largest_niche.map_or(0, |n| n.available(dl)); . (layout.size, cmp::Reverse(niche_size)) . }) . } 183 ( 0.00%) (tagged_layout, None) => tagged_layout, . }; . 27 ( 0.00%) tcx.intern_layout(best_layout) 18 ( 0.00%) } . . // Types with no meaningful known layout. . ty::Projection(_) | ty::Opaque(..) => { . // NOTE(eddyb) `layout_of` query should've normalized these away, . // if that was possible, so there's no reason to try again here. . return Err(LayoutError::Unknown(ty)); . } . -- line 1419 ---------------------------------------- -- line 1420 ---------------------------------------- . ty::Placeholder(..) | ty::GeneratorWitness(..) | ty::Infer(_) => { . bug!("Layout::compute: unexpected type `{}`", ty) . } . . ty::Bound(..) | ty::Param(_) | ty::Error(_) => { . return Err(LayoutError::Unknown(ty)); . } . }) 480 ( 0.00%) } . } . . /// Overlap eligibility and variant assignment for each GeneratorSavedLocal. . #[derive(Clone, Debug, PartialEq)] . enum SavedLocalEligibility { . Unassigned, . Assigned(VariantIdx), . // FIXME: Use newtype_index so we aren't wasting bytes -- line 1436 ---------------------------------------- -- line 1755 ---------------------------------------- . } . . /// This is invoked by the `layout_of` query to record the final . /// layout of each type. . #[inline(always)] . fn record_layout_for_printing(&self, layout: TyAndLayout<'tcx>) { . // If we are running with `-Zprint-type-sizes`, maybe record layouts . // for dumping later. 300 ( 0.00%) if self.tcx.sess.opts.debugging_opts.print_type_sizes { . self.record_layout_for_printing_outlined(layout) . } . } . . fn record_layout_for_printing_outlined(&self, layout: TyAndLayout<'tcx>) { . // Ignore layouts that are done with non-empty environments or . // non-monomorphic layouts, as the user only wants to see the stuff . // resulting from the final codegen session. -- line 1771 ---------------------------------------- -- line 2041 ---------------------------------------- . . pub trait HasParamEnv<'tcx> { . fn param_env(&self) -> ty::ParamEnv<'tcx>; . } . . impl<'tcx> HasDataLayout for TyCtxt<'tcx> { . #[inline] . fn data_layout(&self) -> &TargetDataLayout { 586,558 ( 0.01%) &self.data_layout . } . } . . impl<'tcx> HasTargetSpec for TyCtxt<'tcx> { . fn target_spec(&self) -> &Target { . &self.sess.target . } . } -- line 2057 ---------------------------------------- -- line 2080 ---------------------------------------- . #[inline] . fn tcx(&self) -> TyCtxt<'tcx> { . **self . } . } . . impl<'tcx, C> HasParamEnv<'tcx> for LayoutCx<'tcx, C> { . fn param_env(&self) -> ty::ParamEnv<'tcx> { 35 ( 0.00%) self.param_env . } . } . . impl<'tcx, T: HasDataLayout> HasDataLayout for LayoutCx<'tcx, T> { . fn data_layout(&self) -> &TargetDataLayout { . self.tcx.data_layout() . } . } -- line 2096 ---------------------------------------- -- line 2098 ---------------------------------------- . impl<'tcx, T: HasTargetSpec> HasTargetSpec for LayoutCx<'tcx, T> { . fn target_spec(&self) -> &Target { . self.tcx.target_spec() . } . } . . impl<'tcx, T: HasTyCtxt<'tcx>> HasTyCtxt<'tcx> for LayoutCx<'tcx, T> { . fn tcx(&self) -> TyCtxt<'tcx> { 35 ( 0.00%) self.tcx.tcx() . } . } . . pub trait MaybeResult { . type Error; . . fn from(x: Result) -> Self; . fn to_result(self) -> Result; -- line 2114 ---------------------------------------- -- line 2124 ---------------------------------------- . Ok(self) . } . } . . impl MaybeResult for Result { . type Error = E; . . fn from(x: Result) -> Self { 847,445 ( 0.02%) x . } . fn to_result(self) -> Result { . self . } . } . . pub type TyAndLayout<'tcx> = rustc_target::abi::TyAndLayout<'tcx, Ty<'tcx>>; . -- line 2140 ---------------------------------------- -- line 2167 ---------------------------------------- . ) -> >>::Error; . } . . /// Blanket extension trait for contexts that can compute layouts of types. . pub trait LayoutOf<'tcx>: LayoutOfHelpers<'tcx> { . /// Computes the layout of a type. Note that this implicitly . /// executes in "reveal all" mode, and will normalize the input type. . #[inline] 2,258,581 ( 0.06%) fn layout_of(&self, ty: Ty<'tcx>) -> Self::LayoutOfResult { . self.spanned_layout_of(ty, DUMMY_SP) 2,258,552 ( 0.06%) } . . /// Computes the layout of a type, at `span`. Note that this implicitly . /// executes in "reveal all" mode, and will normalize the input type. . // FIXME(eddyb) avoid passing information like this, and instead add more . // `TyCtxt::at`-like APIs to be able to do e.g. `cx.at(span).layout_of(ty)`. . #[inline] . fn spanned_layout_of(&self, ty: Ty<'tcx>, span: Span) -> Self::LayoutOfResult { . let span = if !span.is_dummy() { span } else { self.layout_tcx_at_span() }; -- line 2185 ---------------------------------------- -- line 2268 ---------------------------------------- . Variants::Multiple { ref variants, .. } => &variants[variant_index], . }; . . assert_eq!(layout.variants, Variants::Single { index: variant_index }); . . TyAndLayout { ty: this.ty, layout } . } . 2,339,625 ( 0.06%) fn ty_and_layout_field(this: TyAndLayout<'tcx>, cx: &C, i: usize) -> TyAndLayout<'tcx> { . enum TyMaybeWithLayout<'tcx> { . Ty(Ty<'tcx>), . TyAndLayout(TyAndLayout<'tcx>), . } . 1,871,700 ( 0.05%) fn field_ty_or_layout<'tcx>( . this: TyAndLayout<'tcx>, . cx: &(impl HasTyCtxt<'tcx> + HasParamEnv<'tcx>), . i: usize, . ) -> TyMaybeWithLayout<'tcx> { . let tcx = cx.tcx(); . let tag_layout = |tag: Scalar| -> TyAndLayout<'tcx> { . let layout = Layout::scalar(cx, tag); . TyAndLayout { layout: tcx.intern_layout(layout), ty: tag.value.to_ty(tcx) } . }; . 467,925 ( 0.01%) match *this.ty.kind() { . ty::Bool . | ty::Char . | ty::Int(_) . | ty::Uint(_) . | ty::Float(_) . | ty::FnPtr(_) . | ty::Never . | ty::FnDef(..) -- line 2301 ---------------------------------------- -- line 2350 ---------------------------------------- . */ . } . _ => bug!("TyAndLayout::field({:?}): not applicable", this), . } . } . . // Arrays and slices. . ty::Array(element, _) | ty::Slice(element) => TyMaybeWithLayout::Ty(element), 2,308 ( 0.00%) ty::Str => TyMaybeWithLayout::Ty(tcx.types.u8), . . // Tuples, generators and closures. . ty::Closure(_, ref substs) => field_ty_or_layout( . TyAndLayout { ty: substs.as_closure().tupled_upvars_ty(), ..this }, . cx, . i, . ), . -- line 2366 ---------------------------------------- -- line 2377 ---------------------------------------- . Variants::Multiple { tag, tag_field, .. } => { . if i == tag_field { . return TyMaybeWithLayout::TyAndLayout(tag_layout(tag)); . } . TyMaybeWithLayout::Ty(substs.as_generator().prefix_tys().nth(i).unwrap()) . } . }, . 21,000 ( 0.00%) ty::Tuple(tys) => TyMaybeWithLayout::Ty(tys[i].expect_ty()), . . // ADTs. 29,763 ( 0.00%) ty::Adt(def, substs) => { 59,526 ( 0.00%) match this.variants { 29,763 ( 0.00%) Variants::Single { index } => { 119,052 ( 0.00%) TyMaybeWithLayout::Ty(def.variants[index].fields[i].ty(tcx, substs)) . } . . // Discriminant field for enums (where applicable). . Variants::Multiple { tag, .. } => { . assert_eq!(i, 0); . return TyMaybeWithLayout::TyAndLayout(tag_layout(tag)); . } . } -- line 2399 ---------------------------------------- -- line 2402 ---------------------------------------- . ty::Projection(_) . | ty::Bound(..) . | ty::Placeholder(..) . | ty::Opaque(..) . | ty::Param(_) . | ty::Infer(_) . | ty::Error(_) => bug!("TyAndLayout::field: unexpected type `{}`", this.ty), . } 1,403,775 ( 0.04%) } . 623,900 ( 0.02%) match field_ty_or_layout(this, cx, i) { 311,950 ( 0.01%) TyMaybeWithLayout::Ty(field_ty) => { . cx.tcx().layout_of(cx.param_env().and(field_ty)).unwrap_or_else(|e| { . bug!( . "failed to get layout for `{}`: {},\n\ . despite it being a field (#{}) of an existing layout: {:#?}", . field_ty, . e, . i, . this . ) . }) . } . TyMaybeWithLayout::TyAndLayout(field_layout) => field_layout, . } 1,247,800 ( 0.03%) } . . fn ty_and_layout_pointee_info_at( . this: TyAndLayout<'tcx>, . cx: &C, . offset: Size, . ) -> Option { . let tcx = cx.tcx(); . let param_env = cx.param_env(); -- line 2435 ---------------------------------------- -- line 2573 ---------------------------------------- . } . . impl<'tcx> ty::Instance<'tcx> { . // NOTE(eddyb) this is private to avoid using it from outside of . // `fn_abi_of_instance` - any other uses are either too high-level . // for `Instance` (e.g. typeck would use `Ty::fn_sig` instead), . // or should go through `FnAbi` instead, to avoid losing any . // adjustments `fn_abi_of_instance` might be performing. 33 ( 0.00%) fn fn_sig_for_fn_abi( . &self, . tcx: TyCtxt<'tcx>, . param_env: ty::ParamEnv<'tcx>, . ) -> ty::PolyFnSig<'tcx> { 18 ( 0.00%) let ty = self.ty(tcx, param_env); 9 ( 0.00%) match *ty.kind() { . ty::FnDef(..) => { . // HACK(davidtwco,eddyb): This is a workaround for polymorphization considering . // parameters unused if they show up in the signature, but not in the `mir::Body` . // (i.e. due to being inside a projection that got normalized, see . // `src/test/ui/polymorphization/normalized_sig_types.rs`), and codegen not keeping . // track of a polymorphization `ParamEnv` to allow normalizing later. 6 ( 0.00%) let mut sig = match *ty.kind() { 21 ( 0.00%) ty::FnDef(def_id, substs) => tcx . .normalize_erasing_regions(tcx.param_env(def_id), tcx.fn_sig(def_id)) . .subst(tcx, substs), . _ => unreachable!(), . }; . 6 ( 0.00%) if let ty::InstanceDef::VtableShim(..) = self.def { . // Modify `fn(self, ...)` to `fn(self: *mut Self, ...)`. . sig = sig.map_bound(|mut sig| { . let mut inputs_and_output = sig.inputs_and_output.to_vec(); . inputs_and_output[0] = tcx.mk_mut_ptr(inputs_and_output[0]); . sig.inputs_and_output = tcx.intern_type_list(&inputs_and_output); . sig . }); . } 24 ( 0.00%) sig . } . ty::Closure(def_id, substs) => { . let sig = substs.as_closure().sig(); . . let bound_vars = tcx.mk_bound_variable_kinds( . sig.bound_vars() . .iter() . .chain(iter::once(ty::BoundVariableKind::Region(ty::BrEnv))), -- line 2618 ---------------------------------------- -- line 2669 ---------------------------------------- . hir::Unsafety::Normal, . rustc_target::spec::abi::Abi::Rust, . ), . bound_vars, . ) . } . _ => bug!("unexpected type {:?} in Instance::fn_sig", ty), . } 27 ( 0.00%) } . } . . /// Calculates whether a function's ABI can unwind or not. . /// . /// This takes two primary parameters: . /// . /// * `codegen_fn_attr_flags` - these are flags calculated as part of the . /// codegen attrs for a defined function. For function pointers this set of -- line 2685 ---------------------------------------- -- line 2725 ---------------------------------------- . /// might (from a foreign exception or similar). . #[inline] . pub fn fn_can_unwind<'tcx>( . tcx: TyCtxt<'tcx>, . codegen_fn_attr_flags: CodegenFnAttrFlags, . abi: SpecAbi, . ) -> bool { . // Special attribute for functions which can't unwind. 6 ( 0.00%) if codegen_fn_attr_flags.contains(CodegenFnAttrFlags::NEVER_UNWIND) { . return false; . } . . // Otherwise if this isn't special then unwinding is generally determined by . // the ABI of the itself. ABIs like `C` have variants which also . // specifically allow unwinding (`C-unwind`), but not all platform-specific . // ABIs have such an option. Otherwise the only other thing here is Rust . // itself, and those ABIs are determined by the panic strategy configured -- line 2741 ---------------------------------------- -- line 2767 ---------------------------------------- . // to `panic=abort`). . // . // Eventually the check against `c_unwind` here will ideally get removed and . // this'll be a little cleaner as it'll be a straightforward check of the . // ABI. . // . // [rfc]: https://github.com/rust-lang/rfcs/blob/master/text/2945-c-unwind-abi.md . use SpecAbi::*; 12 ( 0.00%) match abi { . C { unwind } | Stdcall { unwind } | System { unwind } | Thiscall { unwind } => { . unwind . || (!tcx.features().c_unwind && tcx.sess.panic_strategy() == PanicStrategy::Unwind) . } . Cdecl . | Fastcall . | Vectorcall . | Aapcs -- line 2783 ---------------------------------------- -- line 2797 ---------------------------------------- . | Unadjusted => false, . Rust | RustCall => tcx.sess.panic_strategy() == PanicStrategy::Unwind, . } . } . . #[inline] . pub fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: SpecAbi) -> Conv { . use rustc_target::spec::abi::Abi::*; 30 ( 0.00%) match tcx.sess.target.adjust_abi(abi) { . RustIntrinsic | PlatformIntrinsic | Rust | RustCall => Conv::Rust, . . // It's the ABI's job to select this, not ours. . System { .. } => bug!("system abi should be selected elsewhere"), . EfiApi => bug!("eficall abi should be selected elsewhere"), . . Stdcall { .. } => Conv::X86Stdcall, . Fastcall => Conv::X86Fastcall, -- line 2813 ---------------------------------------- -- line 2915 ---------------------------------------- . } . . /// Compute a `FnAbi` suitable for declaring/defining an `fn` instance, and for . /// direct calls to an `fn`. . /// . /// NB: that includes virtual calls, which are represented by "direct calls" . /// to an `InstanceDef::Virtual` instance (of `::fn`). . #[inline] 158,736 ( 0.00%) fn fn_abi_of_instance( . &self, . instance: ty::Instance<'tcx>, . extra_args: &'tcx ty::List>, . ) -> Self::FnAbiOfResult { . // FIXME(eddyb) get a better `span` here. . let span = self.layout_tcx_at_span(); . let tcx = self.tcx().at(span); . . MaybeResult::from( 99,210 ( 0.00%) tcx.fn_abi_of_instance(self.param_env().and((instance, extra_args))).map_err(|err| { . // HACK(eddyb) at least for definitions of/calls to `Instance`s, . // we can get some kind of span even if one wasn't provided. . // However, we don't do this early in order to avoid calling . // `def_span` unconditionally (which may have a perf penalty). . let span = if !span.is_dummy() { span } else { tcx.def_span(instance.def_id()) }; . self.handle_fn_abi_err(err, span, FnAbiRequest::OfInstance { instance, extra_args }) . }), . ) 158,736 ( 0.00%) } . } . . impl<'tcx, C: FnAbiOfHelpers<'tcx>> FnAbiOf<'tcx> for C {} . . fn fn_abi_of_fn_ptr<'tcx>( . tcx: TyCtxt<'tcx>, . query: ty::ParamEnvAnd<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List>)>, . ) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, FnAbiError<'tcx>> { -- line 2950 ---------------------------------------- -- line 2954 ---------------------------------------- . sig, . extra_args, . None, . CodegenFnAttrFlags::empty(), . false, . ) . } . 27 ( 0.00%) fn fn_abi_of_instance<'tcx>( . tcx: TyCtxt<'tcx>, . query: ty::ParamEnvAnd<'tcx, (ty::Instance<'tcx>, &'tcx ty::List>)>, . ) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, FnAbiError<'tcx>> { 24 ( 0.00%) let (param_env, (instance, extra_args)) = query.into_parts(); . 12 ( 0.00%) let sig = instance.fn_sig_for_fn_abi(tcx, param_env); . 15 ( 0.00%) let caller_location = if instance.def.requires_caller_location(tcx) { . Some(tcx.caller_location_ty()) . } else { . None . }; . 3 ( 0.00%) let attrs = tcx.codegen_fn_attrs(instance.def_id()).flags; . 24 ( 0.00%) LayoutCx { tcx, param_env }.fn_abi_new_uncached( 12 ( 0.00%) sig, . extra_args, . caller_location, . attrs, 15 ( 0.00%) matches!(instance.def, ty::InstanceDef::Virtual(..)), . ) 27 ( 0.00%) } . . impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { . // FIXME(eddyb) perhaps group the signature/type-containing (or all of them?) . // arguments of this method, into a separate `struct`. 39 ( 0.00%) fn fn_abi_new_uncached( . &self, . sig: ty::PolyFnSig<'tcx>, . extra_args: &[Ty<'tcx>], . caller_location: Option>, . codegen_fn_attr_flags: CodegenFnAttrFlags, . // FIXME(eddyb) replace this with something typed, like an `enum`. . force_thin_self_ptr: bool, . ) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, FnAbiError<'tcx>> { . debug!("fn_abi_new_uncached({:?}, {:?})", sig, extra_args); . 45 ( 0.00%) let sig = self.tcx.normalize_erasing_late_bound_regions(self.param_env, sig); . . let conv = conv_from_spec_abi(self.tcx(), sig.abi); . . let mut inputs = sig.inputs(); . let extra_args = if sig.abi == RustCall { . assert!(!sig.c_variadic && extra_args.is_empty()); . . if let Some(input) = sig.inputs().last() { -- line 3009 ---------------------------------------- -- line 3018 ---------------------------------------- . } . } else { . bug!( . "argument to function with \"rust-call\" ABI \ . is not a tuple" . ); . } . } else { 12 ( 0.00%) assert!(sig.c_variadic || extra_args.is_empty()); . extra_args.to_vec() . }; . 3 ( 0.00%) let target = &self.tcx.sess.target; 9 ( 0.00%) let target_env_gnu_like = matches!(&target.env[..], "gnu" | "musl" | "uclibc"); 9 ( 0.00%) let win_x64_gnu = target.os == "windows" && target.arch == "x86_64" && target.env == "gnu"; . let linux_s390x_gnu_like = 12 ( 0.00%) target.os == "linux" && target.arch == "s390x" && target_env_gnu_like; . let linux_sparc64_gnu_like = 12 ( 0.00%) target.os == "linux" && target.arch == "sparc64" && target_env_gnu_like; . let linux_powerpc_gnu_like = 18 ( 0.00%) target.os == "linux" && target.arch == "powerpc" && target_env_gnu_like; . use SpecAbi::*; 12 ( 0.00%) let rust_abi = matches!(sig.abi, RustIntrinsic | PlatformIntrinsic | Rust | RustCall); . . // Handle safe Rust thin and fat pointers. 3 ( 0.00%) let adjust_for_rust_scalar = |attrs: &mut ArgAttributes, . scalar: Scalar, . layout: TyAndLayout<'tcx>, . offset: Size, . is_return: bool| { . // Booleans are always an i1 that needs to be zero-extended. . if scalar.is_bool() { . attrs.ext(ArgExtension::Zext); . return; -- line 3051 ---------------------------------------- -- line 3100 ---------------------------------------- . . if kind == PointerKind::UniqueBorrowed && !is_return { . attrs.set(ArgAttribute::NoAliasMutRef); . } . } . } . }; . 45 ( 0.00%) let arg_of = |ty: Ty<'tcx>, arg_idx: Option| -> Result<_, FnAbiError<'tcx>> { 9 ( 0.00%) let is_return = arg_idx.is_none(); . 15 ( 0.00%) let layout = self.layout_of(ty)?; 9 ( 0.00%) let layout = if force_thin_self_ptr && arg_idx == Some(0) { . // Don't pass the vtable, it's not an argument of the virtual fn. . // Instead, pass just the data pointer, but give it the type `*const/mut dyn Trait` . // or `&/&mut dyn Trait` because this is special-cased elsewhere in codegen . make_thin_self_ptr(self, layout) . } else { . layout . }; . 36 ( 0.00%) let mut arg = ArgAbi::new(self, layout, |layout, scalar, offset| { . let mut attrs = ArgAttributes::new(); . adjust_for_rust_scalar(&mut attrs, scalar, *layout, offset, is_return); . attrs . }); . 6 ( 0.00%) if arg.layout.is_zst() { . // For some forsaken reason, x86_64-pc-windows-gnu . // doesn't ignore zero-sized struct arguments. . // The same is true for {s390x,sparc64,powerpc}-unknown-linux-{gnu,musl,uclibc}. . if is_return . || rust_abi . || (!win_x64_gnu . && !linux_s390x_gnu_like . && !linux_sparc64_gnu_like . && !linux_powerpc_gnu_like) . { . arg.mode = PassMode::Ignore; . } . } . 129 ( 0.00%) Ok(arg) . }; . 123 ( 0.00%) let mut fn_abi = FnAbi { . ret: arg_of(sig.output(), None)?, 6 ( 0.00%) args: inputs . .iter() . .cloned() . .chain(extra_args) . .chain(caller_location) . .enumerate() 3 ( 0.00%) .map(|(i, ty)| arg_of(ty, Some(i))) . .collect::>()?, . c_variadic: sig.c_variadic, . fixed_count: inputs.len(), . conv, . can_unwind: fn_can_unwind(self.tcx(), codegen_fn_attr_flags, sig.abi), . }; . self.fn_abi_adjust_for_abi(&mut fn_abi, sig.abi)?; . debug!("fn_abi_new_uncached = {:?}", fn_abi); 12 ( 0.00%) Ok(self.tcx.arena.alloc(fn_abi)) 24 ( 0.00%) } . . fn fn_abi_adjust_for_abi( . &self, . fn_abi: &mut FnAbi<'tcx, Ty<'tcx>>, . abi: SpecAbi, . ) -> Result<(), FnAbiError<'tcx>> { . if abi == SpecAbi::Unadjusted { . return Ok(()); . } . . if abi == SpecAbi::Rust . || abi == SpecAbi::RustCall . || abi == SpecAbi::RustIntrinsic . || abi == SpecAbi::PlatformIntrinsic . { 36 ( 0.00%) let fixup = |arg: &mut ArgAbi<'tcx, Ty<'tcx>>| { 6 ( 0.00%) if arg.is_ignore() { . return; . } . 36 ( 0.00%) match arg.layout.abi { . Abi::Aggregate { .. } => {} . . // This is a fun case! The gist of what this is doing is . // that we want callers and callees to always agree on the . // ABI of how they pass SIMD arguments. If we were to *not* . // make these arguments indirect then they'd be immediates . // in LLVM, which means that they'd used whatever the . // appropriate ABI is for the callee and the caller. That -- line 3192 ---------------------------------------- -- line 3211 ---------------------------------------- . return; . } . . _ => return, . } . . // Pass and return structures up to 2 pointers in size by value, matching `ScalarPair`. . // LLVM will usually pass these in 2 registers, which is more efficient than by-ref. 6 ( 0.00%) let max_by_val_size = Pointer.size(self) * 2; . let size = arg.layout.size; . 24 ( 0.00%) if arg.layout.is_unsized() || size > max_by_val_size { . arg.make_indirect(); . } else { . // We want to pass small aggregates as immediates, but using . // a LLVM aggregate type for this leads to bad optimizations, . // so we pick an appropriately sized integer type instead. . arg.cast_to(Reg { kind: RegKind::Integer, size }); . } 30 ( 0.00%) }; 3 ( 0.00%) fixup(&mut fn_abi.ret); . for arg in &mut fn_abi.args { 18 ( 0.00%) fixup(arg); . } . } else { . fn_abi.adjust_for_foreign_abi(self, abi)?; . } . . Ok(()) . } . } -- line 3241 ---------------------------------------- 43,900 ( 0.00%) -------------------------------------------------------------------------------- -- Auto-annotated source: /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_infer/src/infer/undo_log.rs -------------------------------------------------------------------------------- Ir -- line 28 ---------------------------------------- . PushRegionObligation, . } . . macro_rules! impl_from { . ($($ctor: ident ($ty: ty),)*) => { . $( . impl<'tcx> From<$ty> for UndoLog<'tcx> { . fn from(x: $ty) -> Self { 514 ( 0.00%) UndoLog::$ctor(x.into()) . } . } . )* . } . } . . // Upcast from a single kind of "undoable action" to the general enum . impl_from! { -- line 44 ---------------------------------------- -- line 57 ---------------------------------------- . ConstUnificationTable(sv::UndoLog>>), . . RegionUnificationTable(sv::UndoLog>>), . ProjectionCache(traits::UndoLog<'tcx>), . } . . /// The Rollback trait defines how to rollback a particular action. . impl<'tcx> Rollback> for InferCtxtInner<'tcx> { 463,173 ( 0.01%) fn reverse(&mut self, undo: UndoLog<'tcx>) { 771,955 ( 0.02%) match undo { 1,355,130 ( 0.03%) UndoLog::TypeVariables(undo) => self.type_variable_storage.reverse(undo), 404 ( 0.00%) UndoLog::ConstUnificationTable(undo) => self.const_unification_storage.reverse(undo), 734 ( 0.00%) UndoLog::IntUnificationTable(undo) => self.int_unification_storage.reverse(undo), . UndoLog::FloatUnificationTable(undo) => self.float_unification_storage.reverse(undo), . UndoLog::RegionConstraintCollector(undo) => { 68,180 ( 0.00%) self.region_constraint_storage.as_mut().unwrap().reverse(undo) . } . UndoLog::RegionUnificationTable(undo) => { 17,002 ( 0.00%) self.region_constraint_storage.as_mut().unwrap().unification_table.reverse(undo) . } . UndoLog::ProjectionCache(undo) => self.projection_cache.reverse(undo), . UndoLog::PushRegionObligation => { . self.region_obligations.pop(); . } . } 617,564 ( 0.02%) } . } . . /// The combined undo log for all the various unification tables. For each change to the storage . /// for any kind of inference variable, we record an UndoLog entry in the vector here. . pub(crate) struct InferCtxtUndoLogs<'tcx> { . logs: Vec>, . num_open_snapshots: usize, . } . . impl Default for InferCtxtUndoLogs<'_> { . fn default() -> Self { 6,930 ( 0.00%) Self { logs: Default::default(), num_open_snapshots: Default::default() } . } . } . . /// The UndoLogs trait defines how we undo a particular kind of action (of type T). We can undo any . /// action that is convertable into an UndoLog (per the From impls above). . impl<'tcx, T> UndoLogs for InferCtxtUndoLogs<'tcx> . where . UndoLog<'tcx>: From, -- line 102 ---------------------------------------- -- line 103 ---------------------------------------- . { . #[inline] . fn num_open_snapshots(&self) -> usize { . self.num_open_snapshots . } . . #[inline] . fn push(&mut self, undo: T) { 50,726 ( 0.00%) if self.in_snapshot() { 4,112 ( 0.00%) self.logs.push(undo.into()) . } . } . . fn clear(&mut self) { . self.logs.clear(); . self.num_open_snapshots = 0; . } . -- line 120 ---------------------------------------- -- line 125 ---------------------------------------- . { . if self.in_snapshot() { . self.logs.extend(undos.into_iter().map(UndoLog::from)) . } . } . } . . impl<'tcx> InferCtxtInner<'tcx> { 436,524 ( 0.01%) pub fn rollback_to(&mut self, snapshot: Snapshot<'tcx>) { . debug!("rollback_to({})", snapshot.undo_len); . self.undo_log.assert_open_snapshot(&snapshot); . 608,681 ( 0.02%) while self.undo_log.logs.len() > snapshot.undo_len { . let undo = self.undo_log.logs.pop().unwrap(); 1,852,692 ( 0.05%) self.reverse(undo); . } . 171,105 ( 0.00%) if self.undo_log.num_open_snapshots == 1 { . // The root snapshot. It's safe to clear the undo log because . // there's no snapshot further out that we might need to roll back . // to. 67,470 ( 0.00%) assert!(snapshot.undo_len == 0); . self.undo_log.logs.clear(); . } . 251,997 ( 0.01%) self.undo_log.num_open_snapshots -= 1; 509,278 ( 0.01%) } . . pub fn commit(&mut self, snapshot: Snapshot<'tcx>) { . debug!("commit({})", snapshot.undo_len); . 561,804 ( 0.01%) if self.undo_log.num_open_snapshots == 1 { . // The root snapshot. It's safe to clear the undo log because . // there's no snapshot further out that we might need to roll back . // to. 116,862 ( 0.00%) assert!(snapshot.undo_len == 0); . self.undo_log.logs.clear(); . } . 620,235 ( 0.02%) self.undo_log.num_open_snapshots -= 1; . } . } . . impl<'tcx> InferCtxtUndoLogs<'tcx> { . pub fn start_snapshot(&mut self) -> Snapshot<'tcx> { 1,040,088 ( 0.03%) self.num_open_snapshots += 1; . Snapshot { undo_len: self.logs.len(), _marker: PhantomData } . } . . pub(crate) fn region_constraints_in_snapshot( . &self, . s: &Snapshot<'tcx>, . ) -> impl Iterator> + Clone { 4,530 ( 0.00%) self.logs[s.undo_len..].iter().filter_map(|log| match log { . UndoLog::RegionConstraintCollector(log) => Some(log), . _ => None, . }) . } . . pub(crate) fn region_constraints( . &self, . ) -> impl Iterator> + Clone { -- line 186 ---------------------------------------- -- line 187 ---------------------------------------- . self.logs.iter().filter_map(|log| match log { . UndoLog::RegionConstraintCollector(log) => Some(log), . _ => None, . }) . } . . fn assert_open_snapshot(&self, snapshot: &Snapshot<'tcx>) { . // Failures here may indicate a failure to follow a stack discipline. 218,262 ( 0.01%) assert!(self.logs.len() >= snapshot.undo_len); 218,262 ( 0.01%) assert!(self.num_open_snapshots > 0); . } . } . . impl<'tcx> std::ops::Index for InferCtxtUndoLogs<'tcx> { . type Output = UndoLog<'tcx>; . . fn index(&self, key: usize) -> &Self::Output { . &self.logs[key] -- line 204 ---------------------------------------- 267,137 ( 0.01%) -------------------------------------------------------------------------------- -- Auto-annotated source: /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_parse/src/lexer/mod.rs -------------------------------------------------------------------------------- Ir -- line 26 ---------------------------------------- . pub struct UnmatchedBrace { . pub expected_delim: token::DelimToken, . pub found_delim: Option, . pub found_span: Span, . pub unclosed_span: Option, . pub candidate_span: Option, . } . 28 ( 0.00%) crate fn parse_token_trees<'a>( . sess: &'a ParseSess, . src: &'a str, . start_pos: BytePos, . override_span: Option, . ) -> (PResult<'a, TokenStream>, Vec) { . StringReader { sess, start_pos, pos: start_pos, end_src_index: src.len(), src, override_span } . .into_token_trees() 18 ( 0.00%) } . . struct StringReader<'a> { . sess: &'a ParseSess, . /// Initial position, read-only. . start_pos: BytePos, . /// The absolute offset within the source_map of the current character. . pos: BytePos, . /// Stop reading src at this index. -- line 50 ---------------------------------------- -- line 51 ---------------------------------------- . end_src_index: usize, . /// Source text to tokenize. . src: &'a str, . override_span: Option, . } . . impl<'a> StringReader<'a> { . fn mk_sp(&self, lo: BytePos, hi: BytePos) -> Span { 171,263 ( 0.00%) self.override_span.unwrap_or_else(|| Span::with_root_ctxt(lo, hi)) . } . . /// Returns the next token, and info about preceding whitespace, if any. 1,044,365 ( 0.03%) fn next_token(&mut self) -> (Spacing, Token) { . let mut spacing = Spacing::Joint; . . // Skip `#!` at the start of the file 298,390 ( 0.01%) let start_src_index = self.src_index(self.pos); 447,585 ( 0.01%) let text: &str = &self.src[start_src_index..self.end_src_index]; . let is_beginning_of_file = self.pos == self.start_pos; 149,195 ( 0.00%) if is_beginning_of_file { 8 ( 0.00%) if let Some(shebang_len) = rustc_lexer::strip_shebang(text) { . self.pos = self.pos + BytePos::from_usize(shebang_len); . spacing = Spacing::Alone; . } . } . . // Skip trivial (whitespace & comments) tokens . loop { 218,177 ( 0.01%) let start_src_index = self.src_index(self.pos); 551,058 ( 0.01%) let text: &str = &self.src[start_src_index..self.end_src_index]; . 183,686 ( 0.00%) if text.is_empty() { . let span = self.mk_sp(self.pos, self.pos); 10 ( 0.00%) return (spacing, Token::new(token::Eof, span)); . } . 551,052 ( 0.01%) let token = rustc_lexer::first_token(text); . 367,368 ( 0.01%) let start = self.pos; 183,684 ( 0.00%) self.pos = self.pos + BytePos::from_usize(token.len); . . debug!("next_token: {:?}({:?})", token.kind, self.str_from(start)); . 1,470,540 ( 0.04%) match self.cook_lexer_token(token.kind, start) { 1,193,544 ( 0.03%) Some(kind) => { . let span = self.mk_sp(start, self.pos); 895,158 ( 0.02%) return (spacing, Token::new(kind, span)); . } . None => spacing = Spacing::Alone, . } . } 1,342,755 ( 0.03%) } . . /// Report a fatal lexical error with a given span. . fn fatal_span(&self, sp: Span, m: &str) -> FatalError { . self.sess.span_diagnostic.span_fatal(sp, m) . } . . /// Report a lexical error with a given span. . fn err_span(&self, sp: Span, m: &str) { -- line 110 ---------------------------------------- -- line 130 ---------------------------------------- . ) -> DiagnosticBuilder<'a> { . self.sess . .span_diagnostic . .struct_span_fatal(self.mk_sp(from_pos, to_pos), &format!("{}: {}", m, escaped_char(c))) . } . . /// Detect usages of Unicode codepoints changing the direction of the text on screen and loudly . /// complain about it. 294 ( 0.00%) fn lint_unicode_text_flow(&self, start: BytePos) { . // Opening delimiter of the length 2 is not included into the comment text. . let content_start = start + BytePos(2); . let content = self.str_from(content_start); . if contains_text_flow_control_chars(content) { . let span = self.mk_sp(start, self.pos); . self.sess.buffer_lint_with_diagnostic( . &TEXT_DIRECTION_CODEPOINT_IN_COMMENT, . span, . ast::CRATE_NODE_ID, . "unicode codepoint changing visible direction of text present in comment", . BuiltinLintDiagnostics::UnicodeTextFlow(span, content.to_string()), . ); . } 336 ( 0.00%) } . . /// Turns simple `rustc_lexer::TokenKind` enum into a rich . /// `rustc_ast::TokenKind`. This turns strings into interned . /// symbols and runs additional validation. . fn cook_lexer_token(&self, token: rustc_lexer::TokenKind, start: BytePos) -> Option { 918,420 ( 0.02%) Some(match token { 309 ( 0.00%) rustc_lexer::TokenKind::LineComment { doc_style } => { . // Skip non-doc comments 1,419 ( 0.00%) let doc_style = if let Some(doc_style) = doc_style { . doc_style . } else { . self.lint_unicode_text_flow(start); . return None; . }; . . // Opening delimiter of the length 3 is not included into the symbol. . let content_start = start + BytePos(3); . let content = self.str_from(content_start); 1,335 ( 0.00%) self.cook_doc_comment(content_start, content, CommentKind::Line, doc_style) . } . rustc_lexer::TokenKind::BlockComment { doc_style, terminated } => { . if !terminated { . let msg = match doc_style { . Some(_) => "unterminated block doc-comment", . None => "unterminated block comment", . }; . let last_bpos = self.pos; -- line 179 ---------------------------------------- -- line 198 ---------------------------------------- . let content_end = self.pos - BytePos(if terminated { 2 } else { 0 }); . let content = self.str_from_to(content_start, content_end); . self.cook_doc_comment(content_start, content, CommentKind::Block, doc_style) . } . rustc_lexer::TokenKind::Whitespace => return None, . rustc_lexer::TokenKind::Ident . | rustc_lexer::TokenKind::RawIdent . | rustc_lexer::TokenKind::UnknownPrefix => { 88,264 ( 0.00%) let is_raw_ident = token == rustc_lexer::TokenKind::RawIdent; 110,330 ( 0.00%) let is_unknown_prefix = token == rustc_lexer::TokenKind::UnknownPrefix; . let mut ident_start = start; 44,132 ( 0.00%) if is_raw_ident { . ident_start = ident_start + BytePos(2); . } 66,198 ( 0.00%) if is_unknown_prefix { . self.report_unknown_prefix(start); . } 110,330 ( 0.00%) let sym = nfc_normalize(self.str_from(ident_start)); . let span = self.mk_sp(start, self.pos); 88,264 ( 0.00%) self.sess.symbol_gallery.insert(sym, span); 44,132 ( 0.00%) if is_raw_ident { . if !sym.can_be_raw() { . self.err_span(span, &format!("`{}` cannot be a raw identifier", sym)); . } . self.sess.raw_identifier_spans.borrow_mut().push(span); . } 154,462 ( 0.00%) token::Ident(sym, is_raw_ident) . } . rustc_lexer::TokenKind::InvalidIdent . // Do not recover an identifier with emoji if the codepoint is a confusable . // with a recoverable substitution token, like `âž–`. . if UNICODE_ARRAY . .iter() . .find(|&&(c, _, _)| { . let sym = self.str_from(start); -- line 232 ---------------------------------------- -- line 234 ---------------------------------------- . }) . .is_none() => . { . let sym = nfc_normalize(self.str_from(start)); . let span = self.mk_sp(start, self.pos); . self.sess.bad_unicode_identifiers.borrow_mut().entry(sym).or_default().push(span); . token::Ident(sym, false) . } 493,696 ( 0.01%) rustc_lexer::TokenKind::Literal { kind, suffix_start } => { . let suffix_start = start + BytePos(suffix_start as u32); . let (kind, symbol) = self.cook_lexer_literal(start, suffix_start, kind); 92,568 ( 0.00%) let suffix = if suffix_start < self.pos { . let string = self.str_from(suffix_start); . if string == "_" { . self.sess . .span_diagnostic . .struct_span_warn( . self.mk_sp(suffix_start, self.pos), . "underscore literal suffix is not allowed", . ) -- line 253 ---------------------------------------- -- line 264 ---------------------------------------- . .emit(); . None . } else { . Some(Symbol::intern(string)) . } . } else { . None . }; 246,848 ( 0.01%) token::Literal(token::Lit { kind, symbol, suffix }) . } 76 ( 0.00%) rustc_lexer::TokenKind::Lifetime { starts_with_number } => { . // Include the leading `'` in the real identifier, for macro . // expansion purposes. See #12512 for the gory details of why . // this is necessary. . let lifetime_name = self.str_from(start); 38 ( 0.00%) if starts_with_number { . self.err_span_(start, self.pos, "lifetimes cannot start with a number"); . } 114 ( 0.00%) let ident = Symbol::intern(lifetime_name); 152 ( 0.00%) token::Lifetime(ident) . } . rustc_lexer::TokenKind::Semi => token::Semi, . rustc_lexer::TokenKind::Comma => token::Comma, . rustc_lexer::TokenKind::Dot => token::Dot, . rustc_lexer::TokenKind::OpenParen => token::OpenDelim(token::Paren), . rustc_lexer::TokenKind::CloseParen => token::CloseDelim(token::Paren), . rustc_lexer::TokenKind::OpenBrace => token::OpenDelim(token::Brace), . rustc_lexer::TokenKind::CloseBrace => token::CloseDelim(token::Brace), -- line 291 ---------------------------------------- -- line 324 ---------------------------------------- . err.help("source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used"); . } . err.emit(); . token? . } . }) . } . 3,204 ( 0.00%) fn cook_doc_comment( . &self, . content_start: BytePos, . content: &str, . comment_kind: CommentKind, . doc_style: DocStyle, . ) -> TokenKind { 267 ( 0.00%) if content.contains('\r') { . for (idx, _) in content.char_indices().filter(|&(_, c)| c == '\r') { . self.err_span_( . content_start + BytePos(idx as u32), . content_start + BytePos(idx as u32 + 1), . match comment_kind { . CommentKind::Line => "bare CR not allowed in doc-comment", . CommentKind::Block => "bare CR not allowed in block doc-comment", . }, -- line 347 ---------------------------------------- -- line 349 ---------------------------------------- . } . } . . let attr_style = match doc_style { . DocStyle::Outer => AttrStyle::Outer, . DocStyle::Inner => AttrStyle::Inner, . }; . 801 ( 0.00%) token::DocComment(comment_kind, attr_style, Symbol::intern(content)) 4,005 ( 0.00%) } . . fn cook_lexer_literal( . &self, . start: BytePos, . suffix_start: BytePos, . kind: rustc_lexer::LiteralKind, . ) -> (token::LitKind, Symbol) { . // prefix means `"` or `br"` or `r###"`, ... . let (lit_kind, mode, prefix_len, postfix_len) = match kind { 30,138 ( 0.00%) rustc_lexer::LiteralKind::Char { terminated } => { 30,138 ( 0.00%) if !terminated { . self.sess.span_diagnostic.span_fatal_with_code( . self.mk_sp(start, suffix_start), . "unterminated character literal", . error_code!(E0762), . ) . } . (token::Char, Mode::Char, 1, 1) // ' ' . } 5 ( 0.00%) rustc_lexer::LiteralKind::Byte { terminated } => { 5 ( 0.00%) if !terminated { . self.sess.span_diagnostic.span_fatal_with_code( . self.mk_sp(start + BytePos(1), suffix_start), . "unterminated byte constant", . error_code!(E0763), . ) . } . (token::Byte, Mode::Byte, 2, 1) // b' ' . } 616 ( 0.00%) rustc_lexer::LiteralKind::Str { terminated } => { 616 ( 0.00%) if !terminated { . self.sess.span_diagnostic.span_fatal_with_code( . self.mk_sp(start, suffix_start), . "unterminated double quote string", . error_code!(E0765), . ) . } . (token::Str, Mode::Str, 1, 1) // " " . } -- line 397 ---------------------------------------- -- line 410 ---------------------------------------- . let n = u32::from(n_hashes); . (token::StrRaw(n_hashes), Mode::RawStr, 2 + n, 1 + n) // r##" "## . } . rustc_lexer::LiteralKind::RawByteStr { n_hashes, err } => { . self.report_raw_str_error(start, err); . let n = u32::from(n_hashes); . (token::ByteStrRaw(n_hashes), Mode::RawByteStr, 3 + n, 1 + n) // br##" "## . } 194 ( 0.00%) rustc_lexer::LiteralKind::Int { base, empty_int } => { 97 ( 0.00%) return if empty_int { . self.sess . .span_diagnostic . .struct_span_err_with_code( . self.mk_sp(start, suffix_start), . "no valid digits found for number", . error_code!(E0768), . ) . .emit(); . (token::Integer, sym::integer(0)) . } else { . self.validate_int_literal(base, start, suffix_start); 291 ( 0.00%) (token::Integer, self.symbol_from_to(start, suffix_start)) . }; . } . rustc_lexer::LiteralKind::Float { base, empty_exponent } => { . if empty_exponent { . self.err_span_(start, self.pos, "expected at least one digit in exponent"); . } . . match base { -- line 439 ---------------------------------------- -- line 452 ---------------------------------------- . } . . let id = self.symbol_from_to(start, suffix_start); . return (token::Float, id); . } . }; . let content_start = start + BytePos(prefix_len); . let content_end = suffix_start - BytePos(postfix_len); 92,277 ( 0.00%) let id = self.symbol_from_to(content_start, content_end); . self.validate_literal_escape(mode, content_start, content_end, prefix_len, postfix_len); . (lit_kind, id) . } . . #[inline] . fn src_index(&self, pos: BytePos) -> usize { . (pos - self.start_pos).to_usize() . } . . /// Slice of the source text from `start` up to but excluding `self.pos`, . /// meaning the slice does not include the character `self.ch`. . fn str_from(&self, start: BytePos) -> &str { 135,073 ( 0.00%) self.str_from_to(start, self.pos) . } . . /// As symbol_from, with an explicit endpoint. . fn symbol_from_to(&self, start: BytePos, end: BytePos) -> Symbol { . debug!("taking an ident from {:?} to {:?}", start, end); 369,787 ( 0.01%) Symbol::intern(self.str_from_to(start, end)) . } . . /// Slice of the source text spanning from `start` up to but excluding `end`. 84,028 ( 0.00%) fn str_from_to(&self, start: BytePos, end: BytePos) -> &str { . &self.src[self.src_index(start)..self.src_index(end)] 336,112 ( 0.01%) } . . fn report_raw_str_error(&self, start: BytePos, opt_err: Option) { . match opt_err { . Some(RawStrError::InvalidStarter { bad_char }) => { . self.report_non_started_raw_string(start, bad_char) . } . Some(RawStrError::NoTerminator { expected, found, possible_terminator_offset }) => self . .report_unterminated_raw_string(start, expected, possible_terminator_offset, found), -- line 493 ---------------------------------------- -- line 609 ---------------------------------------- . fn validate_literal_escape( . &self, . mode: Mode, . content_start: BytePos, . content_end: BytePos, . prefix_len: u32, . postfix_len: u32, . ) { 184,554 ( 0.00%) let lit_content = self.str_from_to(content_start, content_end); 948,866 ( 0.02%) unescape::unescape_literal(lit_content, mode, &mut |range, result| { . // Here we only check for errors. The actual unescaping is done later. 68,042 ( 0.00%) if let Err(err) = result { . let span_with_quotes = self . .mk_sp(content_start - BytePos(prefix_len), content_end + BytePos(postfix_len)); . let (start, end) = (range.start as u32, range.end as u32); . let lo = content_start + BytePos(start); . let hi = lo + BytePos(end - start); . let span = self.mk_sp(lo, hi); . emit_unescape_error( . &self.sess.span_diagnostic, -- line 628 ---------------------------------------- -- line 629 ---------------------------------------- . lit_content, . span_with_quotes, . span, . mode, . range, . err, . ); . } 306,189 ( 0.01%) }); . } . . fn validate_int_literal(&self, base: Base, content_start: BytePos, content_end: BytePos) { 388 ( 0.00%) let base = match base { . Base::Binary => 2, . Base::Octal => 8, . _ => return, . }; . let s = self.str_from_to(content_start + BytePos(2), content_end); . for (idx, c) in s.char_indices() { . let idx = idx as u32; . if c != '_' && c.to_digit(base).is_none() { -- line 649 ---------------------------------------- -- line 650 ---------------------------------------- . let lo = content_start + BytePos(2 + idx); . let hi = content_start + BytePos(2 + idx + c.len_utf8() as u32); . self.err_span_(lo, hi, &format!("invalid digit for a base {} literal", base)); . } . } . } . } . 198,594 ( 0.01%) pub fn nfc_normalize(string: &str) -> Symbol { . use unicode_normalization::{is_nfc_quick, IsNormalized, UnicodeNormalization}; 44,132 ( 0.00%) match is_nfc_quick(string.chars()) { 220,660 ( 0.01%) IsNormalized::Yes => Symbol::intern(string), . _ => { . let normalized_str: String = string.chars().nfc().collect(); . Symbol::intern(&normalized_str) . } . } . } 907,733 ( 0.02%) -------------------------------------------------------------------------------- -- Auto-annotated source: /usr/home/liquid/rust/worktree-benchmarking/library/alloc/src/collections/vec_deque/mod.rs -------------------------------------------------------------------------------- Ir -- line 126 ---------------------------------------- . self.extend(remainder.iter().cloned()); . } . } . } . } . . #[stable(feature = "rust1", since = "1.0.0")] . unsafe impl<#[may_dangle] T, A: Allocator> Drop for VecDeque { 2,282 ( 0.00%) fn drop(&mut self) { . /// Runs the destructor for all items in the slice when it gets dropped (normally or . /// during unwinding). . struct Dropper<'a, T>(&'a mut [T]); . . impl<'a, T> Drop for Dropper<'a, T> { . fn drop(&mut self) { . unsafe { . ptr::drop_in_place(self.0); -- line 142 ---------------------------------------- -- line 146 ---------------------------------------- . . let (front, back) = self.as_mut_slices(); . unsafe { . let _back_dropper = Dropper(back); . // use drop for [T] . ptr::drop_in_place(front); . } . // RawVec handles deallocation 2,608 ( 0.00%) } . } . . #[stable(feature = "rust1", since = "1.0.0")] . impl Default for VecDeque { . /// Creates an empty `VecDeque`. . #[inline] . fn default() -> VecDeque { . VecDeque::new() . } . } . . impl VecDeque { . /// Marginally more convenient . #[inline] . fn ptr(&self) -> *mut T { 735,402 ( 0.02%) self.buf.ptr() . } . . /// Marginally more convenient . #[inline] . fn cap(&self) -> usize { . if mem::size_of::() == 0 { . // For zero sized types, we are always at maximum capacity . MAXIMUM_ZST_CAPACITY . } else { 782,676 ( 0.02%) self.buf.capacity() . } . } . . /// Turn ptr into a slice . #[inline] . unsafe fn buffer_as_slice(&self) -> &[T] { . unsafe { slice::from_raw_parts(self.ptr(), self.cap()) } . } -- line 188 ---------------------------------------- -- line 191 ---------------------------------------- . #[inline] . unsafe fn buffer_as_mut_slice(&mut self) -> &mut [T] { . unsafe { slice::from_raw_parts_mut(self.ptr(), self.cap()) } . } . . /// Moves an element out of the buffer . #[inline] . unsafe fn buffer_read(&mut self, off: usize) -> T { 248,749 ( 0.01%) unsafe { ptr::read(self.ptr().add(off)) } . } . . /// Writes an element into the buffer, moving it. . #[inline] . unsafe fn buffer_write(&mut self, off: usize, value: T) { . unsafe { . ptr::write(self.ptr().add(off), value); . } . } . . /// Returns `true` if the buffer is at full capacity. . #[inline] . fn is_full(&self) -> bool { 2,064,249 ( 0.05%) self.cap() - self.len() == 1 . } . . /// Returns the index in the underlying buffer for a given logical element . /// index. . #[inline] . fn wrap_index(&self, idx: usize) -> usize { . wrap_index(idx, self.cap()) . } -- line 221 ---------------------------------------- -- line 452 ---------------------------------------- . // [o o . o o o o o ] . // T H . // B [. . . o o o o o o o . . . . . . ] . // H T . // [o o o o o . o o ] . // H T . // C [o o o o o . . . . . . . . . o o ] . 312 ( 0.00%) if self.tail <= self.head { . // A . // Nop 10 ( 0.00%) } else if self.head < old_capacity - self.tail { . // B . unsafe { . self.copy_nonoverlapping(old_capacity, 0, self.head); . } 4 ( 0.00%) self.head += old_capacity; . debug_assert!(self.head > self.tail); . } else { . // C 2 ( 0.00%) let new_tail = new_capacity - (old_capacity - self.tail); . unsafe { . self.copy_nonoverlapping(new_tail, self.tail, old_capacity - self.tail); . } 1 ( 0.00%) self.tail = new_tail; . debug_assert!(self.head < self.tail); . } . debug_assert!(self.head < self.cap()); . debug_assert!(self.tail < self.cap()); . debug_assert!(self.cap().count_ones() == 1); . } . } . -- line 484 ---------------------------------------- -- line 507 ---------------------------------------- . /// use std::collections::VecDeque; . /// . /// let vector: VecDeque = VecDeque::with_capacity(10); . /// ``` . #[inline] . #[stable(feature = "rust1", since = "1.0.0")] . #[must_use] . pub fn with_capacity(capacity: usize) -> VecDeque { 1,358 ( 0.00%) Self::with_capacity_in(capacity, Global) . } . } . . impl VecDeque { . /// Creates an empty `VecDeque`. . /// . /// # Examples . /// -- line 523 ---------------------------------------- -- line 524 ---------------------------------------- . /// ``` . /// use std::collections::VecDeque; . /// . /// let vector: VecDeque = VecDeque::new(); . /// ``` . #[inline] . #[unstable(feature = "allocator_api", issue = "32838")] . pub fn new_in(alloc: A) -> VecDeque { 360 ( 0.00%) VecDeque::with_capacity_in(INITIAL_CAPACITY, alloc) . } . . /// Creates an empty `VecDeque` with space for at least `capacity` elements. . /// . /// # Examples . /// . /// ``` . /// use std::collections::VecDeque; . /// . /// let vector: VecDeque = VecDeque::with_capacity(10); . /// ``` . #[unstable(feature = "allocator_api", issue = "32838")] 3,436 ( 0.00%) pub fn with_capacity_in(capacity: usize, alloc: A) -> VecDeque { 2,018 ( 0.00%) assert!(capacity < 1_usize << usize::BITS - 1, "capacity overflow"); . // +1 since the ringbuffer always leaves one space empty . let cap = cmp::max(capacity + 1, MINIMUM_CAPACITY + 1).next_power_of_two(); . 4,952 ( 0.00%) VecDeque { tail: 0, head: 0, buf: RawVec::with_capacity_in(cap, alloc) } 5,154 ( 0.00%) } . . /// Provides a reference to the element at the given index. . /// . /// Element at index 0 is the front of the queue. . /// . /// # Examples . /// . /// ``` -- line 559 ---------------------------------------- -- line 562 ---------------------------------------- . /// let mut buf = VecDeque::new(); . /// buf.push_back(3); . /// buf.push_back(4); . /// buf.push_back(5); . /// assert_eq!(buf.get(1), Some(&4)); . /// ``` . #[stable(feature = "rust1", since = "1.0.0")] . pub fn get(&self, index: usize) -> Option<&T> { 2,547,750 ( 0.06%) if index < self.len() { . let idx = self.wrap_add(self.tail, index); . unsafe { Some(&*self.ptr().add(idx)) } . } else { . None . } . } . . /// Provides a mutable reference to the element at the given index. -- line 578 ---------------------------------------- -- line 591 ---------------------------------------- . /// if let Some(elem) = buf.get_mut(1) { . /// *elem = 7; . /// } . /// . /// assert_eq!(buf[1], 7); . /// ``` . #[stable(feature = "rust1", since = "1.0.0")] . pub fn get_mut(&mut self, index: usize) -> Option<&mut T> { 1,461,162 ( 0.04%) if index < self.len() { . let idx = self.wrap_add(self.tail, index); . unsafe { Some(&mut *self.ptr().add(idx)) } . } else { . None . } . } . . /// Swaps elements at indices `i` and `j`. -- line 607 ---------------------------------------- -- line 924 ---------------------------------------- . /// buf.push_back(5); . /// buf.push_back(10); . /// buf.push_back(15); . /// assert_eq!(buf, [5, 10, 15]); . /// buf.truncate(1); . /// assert_eq!(buf, [5]); . /// ``` . #[stable(feature = "deque_extras", since = "1.16.0")] 416 ( 0.00%) pub fn truncate(&mut self, len: usize) { . /// Runs the destructor for all items in the slice when it gets dropped (normally or . /// during unwinding). . struct Dropper<'a, T>(&'a mut [T]); . . impl<'a, T> Drop for Dropper<'a, T> { . fn drop(&mut self) { . unsafe { . ptr::drop_in_place(self.0); -- line 940 ---------------------------------------- -- line 945 ---------------------------------------- . // Safe because: . // . // * Any slice passed to `drop_in_place` is valid; the second case has . // `len <= front.len()` and returning on `len > self.len()` ensures . // `begin <= back.len()` in the first case . // * The head of the VecDeque is moved before calling `drop_in_place`, . // so no value is dropped twice if `drop_in_place` panics . unsafe { 104 ( 0.00%) if len > self.len() { . return; . } . let num_dropped = self.len() - len; . let (front, back) = self.as_mut_slices(); 104 ( 0.00%) if len > front.len() { . let begin = len - front.len(); . let drop_back = back.get_unchecked_mut(begin..) as *mut _; . self.head = self.wrap_sub(self.head, num_dropped); . ptr::drop_in_place(drop_back); . } else { . let drop_back = back as *mut _; . let drop_front = front.get_unchecked_mut(len..) as *mut _; 52 ( 0.00%) self.head = self.wrap_sub(self.head, num_dropped); . . // Make sure the second half is dropped even when a destructor . // in the first one panics. . let _back_dropper = Dropper(&mut *drop_back); . ptr::drop_in_place(drop_front); . } . } 416 ( 0.00%) } . . /// Returns a reference to the underlying allocator. . #[unstable(feature = "allocator_api", issue = "32838")] . #[inline] . pub fn allocator(&self) -> &A { . self.buf.allocator() . } . -- line 982 ---------------------------------------- -- line 1085 ---------------------------------------- . /// vector.as_mut_slices().0[0] = 42; . /// vector.as_mut_slices().1[0] = 24; . /// assert_eq!(vector.as_slices(), (&[42, 10][..], &[24, 1][..])); . /// ``` . #[inline] . #[stable(feature = "deque_extras_15", since = "1.5.0")] . pub fn as_mut_slices(&mut self) -> (&mut [T], &mut [T]) { . unsafe { 1,484 ( 0.00%) let head = self.head; 1,484 ( 0.00%) let tail = self.tail; 1,814 ( 0.00%) let buf = self.buffer_as_mut_slice(); . RingSlices::ring_slices(buf, head, tail) . } . } . . /// Returns the number of elements in the `VecDeque`. . /// . /// # Examples . /// -- line 1103 ---------------------------------------- -- line 1106 ---------------------------------------- . /// . /// let mut v = VecDeque::new(); . /// assert_eq!(v.len(), 0); . /// v.push_back(1); . /// assert_eq!(v.len(), 1); . /// ``` . #[stable(feature = "rust1", since = "1.0.0")] . pub fn len(&self) -> usize { 1,196,317 ( 0.03%) count(self.tail, self.head, self.cap()) . } . . /// Returns `true` if the `VecDeque` is empty. . /// . /// # Examples . /// . /// ``` . /// use std::collections::VecDeque; -- line 1122 ---------------------------------------- -- line 1123 ---------------------------------------- . /// . /// let mut v = VecDeque::new(); . /// assert!(v.is_empty()); . /// v.push_front(1); . /// assert!(!v.is_empty()); . /// ``` . #[stable(feature = "rust1", since = "1.0.0")] . pub fn is_empty(&self) -> bool { 2,559,654 ( 0.07%) self.tail == self.head . } . . fn range_tail_head(&self, range: R) -> (usize, usize) . where . R: RangeBounds, . { . let Range { start, end } = slice::range(range, ..self.len()); . let tail = self.wrap_add(self.tail, start); -- line 1139 ---------------------------------------- -- line 1307 ---------------------------------------- . /// let mut v = VecDeque::new(); . /// v.push_back(1); . /// v.clear(); . /// assert!(v.is_empty()); . /// ``` . #[stable(feature = "rust1", since = "1.0.0")] . #[inline] . pub fn clear(&mut self) { 105 ( 0.00%) self.truncate(0); . } . . /// Returns `true` if the `VecDeque` contains an element equal to the . /// given value. . /// . /// # Examples . /// . /// ``` -- line 1323 ---------------------------------------- -- line 1396 ---------------------------------------- . /// assert_eq!(d.back(), None); . /// . /// d.push_back(1); . /// d.push_back(2); . /// assert_eq!(d.back(), Some(&2)); . /// ``` . #[stable(feature = "rust1", since = "1.0.0")] . pub fn back(&self) -> Option<&T> { 30,723 ( 0.00%) self.get(self.len().wrapping_sub(1)) . } . . /// Provides a mutable reference to the back element, or `None` if the . /// `VecDeque` is empty. . /// . /// # Examples . /// . /// ``` -- line 1412 ---------------------------------------- -- line 1441 ---------------------------------------- . /// d.push_back(2); . /// . /// assert_eq!(d.pop_front(), Some(1)); . /// assert_eq!(d.pop_front(), Some(2)); . /// assert_eq!(d.pop_front(), None); . /// ``` . #[stable(feature = "rust1", since = "1.0.0")] . pub fn pop_front(&mut self) -> Option { 547,834 ( 0.01%) if self.is_empty() { . None . } else { . let tail = self.tail; 912,965 ( 0.02%) self.tail = self.wrap_add(self.tail, 1); 86,239 ( 0.00%) unsafe { Some(self.buffer_read(tail)) } . } . } . . /// Removes the last element from the `VecDeque` and returns it, or `None` if . /// it is empty. . /// . /// # Examples . /// -- line 1462 ---------------------------------------- -- line 1466 ---------------------------------------- . /// let mut buf = VecDeque::new(); . /// assert_eq!(buf.pop_back(), None); . /// buf.push_back(1); . /// buf.push_back(3); . /// assert_eq!(buf.pop_back(), Some(3)); . /// ``` . #[stable(feature = "rust1", since = "1.0.0")] . pub fn pop_back(&mut self) -> Option { 228,936 ( 0.01%) if self.is_empty() { . None . } else { 355,907 ( 0.01%) self.head = self.wrap_sub(self.head, 1); . let head = self.head; . unsafe { Some(self.buffer_read(head)) } . } . } . . /// Prepends an element to the `VecDeque`. . /// . /// # Examples -- line 1485 ---------------------------------------- -- line 1513 ---------------------------------------- . /// use std::collections::VecDeque; . /// . /// let mut buf = VecDeque::new(); . /// buf.push_back(1); . /// buf.push_back(3); . /// assert_eq!(3, *buf.back().unwrap()); . /// ``` . #[stable(feature = "rust1", since = "1.0.0")] 1,469,004 ( 0.04%) pub fn push_back(&mut self, value: T) { 2,064,249 ( 0.05%) if self.is_full() { 134 ( 0.00%) self.grow(); . } . 78 ( 0.00%) let head = self.head; 688,161 ( 0.02%) self.head = self.wrap_add(self.head, 1); 320,832 ( 0.01%) unsafe { self.buffer_write(head, value) } 1,469,004 ( 0.04%) } . . #[inline] . fn is_contiguous(&self) -> bool { . // FIXME: Should we consider `head == 0` to mean . // that `self` is contiguous? . self.tail <= self.head . } . -- line 1537 ---------------------------------------- -- line 2209 ---------------------------------------- . self.truncate(idx); . } . } . . // Double the buffer size. This method is inline(never), so we expect it to only . // be called in cold paths. . // This may panic or abort . #[inline(never)] 468 ( 0.00%) fn grow(&mut self) { . // Extend or possibly remove this assertion when valid use-cases for growing the . // buffer without it being full emerge . debug_assert!(self.is_full()); . let old_cap = self.cap(); 234 ( 0.00%) self.buf.reserve_exact(old_cap, old_cap); 390 ( 0.00%) assert!(self.cap() == old_cap * 2); . unsafe { . self.handle_capacity_increase(old_cap); . } . debug_assert!(!self.is_full()); 468 ( 0.00%) } . . /// Modifies the `VecDeque` in-place so that `len()` is equal to `new_len`, . /// either by removing excess elements from the back or by appending . /// elements generated by calling `generator` to the back. . /// . /// # Examples . /// . /// ``` -- line 2236 ---------------------------------------- -- line 2751 ---------------------------------------- . } . } . . /// Returns the index in the underlying buffer for a given logical element index. . #[inline] . fn wrap_index(index: usize, size: usize) -> usize { . // size is always a power of 2 . debug_assert!(size.is_power_of_two()); 3,660,223 ( 0.09%) index & (size - 1) . } . . /// Calculate the number of elements left to be read in the buffer . #[inline] . fn count(tail: usize, head: usize, size: usize) -> usize { . // size is always a power of 2 5,516,360 ( 0.14%) (head.wrapping_sub(tail)) & (size - 1) . } . . #[stable(feature = "rust1", since = "1.0.0")] . impl PartialEq for VecDeque { . fn eq(&self, other: &Self) -> bool { . if self.len() != other.len() { . return false; . } -- line 2774 ---------------------------------------- -- line 2902 ---------------------------------------- . . fn into_iter(self) -> IterMut<'a, T> { . self.iter_mut() . } . } . . #[stable(feature = "rust1", since = "1.0.0")] . impl Extend for VecDeque { 112 ( 0.00%) fn extend>(&mut self, iter: I) { . // This function should be the moral equivalent of: . // . // for item in iter.into_iter() { . // self.push_back(item); . // } . let mut iter = iter.into_iter(); . while let Some(element) = iter.next() { 283 ( 0.00%) if self.len() == self.capacity() { . let (lower, _) = iter.size_hint(); . self.reserve(lower.saturating_add(1)); . } . . let head = self.head; 63 ( 0.00%) self.head = self.wrap_add(self.head, 1); . unsafe { 8 ( 0.00%) self.buffer_write(head, element); . } . } 128 ( 0.00%) } . . #[inline] . fn extend_one(&mut self, elem: T) { . self.push_back(elem); . } . . #[inline] . fn extend_reserve(&mut self, additional: usize) { -- line 2937 ---------------------------------------- 644,906 ( 0.02%) -------------------------------------------------------------------------------- -- Auto-annotated source: /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_typeck/src/check/expr.rs -------------------------------------------------------------------------------- Ir -- line 56 ---------------------------------------- . } . . pub fn check_expr_has_type_or_error( . &self, . expr: &'tcx hir::Expr<'tcx>, . expected: Ty<'tcx>, . extend_err: impl Fn(&mut DiagnosticBuilder<'_>), . ) -> Ty<'tcx> { 143 ( 0.00%) self.check_expr_meets_expectation_or_error(expr, ExpectHasType(expected), extend_err) . } . . fn check_expr_meets_expectation_or_error( . &self, . expr: &'tcx hir::Expr<'tcx>, . expected: Expectation<'tcx>, . extend_err: impl Fn(&mut DiagnosticBuilder<'_>), . ) -> Ty<'tcx> { . let expected_ty = expected.to_option(&self).unwrap_or(self.tcx.types.bool); . let mut ty = self.check_expr_with_expectation(expr, expected); . . // While we don't allow *arbitrary* coercions here, we *do* allow . // coercions from ! to `expected`. 176 ( 0.00%) if ty.is_never() { 4 ( 0.00%) assert!( 12 ( 0.00%) !self.typeck_results.borrow().adjustments().contains_key(expr.hir_id), . "expression with never type wound up being adjusted" . ); 10 ( 0.00%) let adj_ty = self.next_ty_var(TypeVariableOrigin { . kind: TypeVariableOriginKind::AdjustmentType, 2 ( 0.00%) span: expr.span, . }); 6 ( 0.00%) self.apply_adjustments( . expr, 4 ( 0.00%) vec![Adjustment { kind: Adjust::NeverToAny, target: adj_ty }], . ); . ty = adj_ty; . } . 1,413 ( 0.00%) if let Some(mut err) = self.demand_suptype_diag(expr.span, expected_ty, ty) { . let expr = expr.peel_drop_temps(); . self.suggest_deref_ref_or_into(&mut err, expr, expected_ty, ty, None); . extend_err(&mut err); . err.emit(); . } . ty . } . 19,656 ( 0.00%) pub(super) fn check_expr_coercable_to_type( . &self, . expr: &'tcx hir::Expr<'tcx>, . expected: Ty<'tcx>, . expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>, . ) -> Ty<'tcx> { . let ty = self.check_expr_with_hint(expr, expected); . // checks don't need two phase . self.demand_coerce(expr, ty, expected, expected_ty_expr, AllowTwoPhase::No) 15,288 ( 0.00%) } . . pub(super) fn check_expr_with_hint( . &self, . expr: &'tcx hir::Expr<'tcx>, . expected: Ty<'tcx>, . ) -> Ty<'tcx> { 142 ( 0.00%) self.check_expr_with_expectation(expr, ExpectHasType(expected)) . } . . fn check_expr_with_expectation_and_needs( . &self, . expr: &'tcx hir::Expr<'tcx>, . expected: Expectation<'tcx>, . needs: Needs, . ) -> Ty<'tcx> { . let ty = self.check_expr_with_expectation(expr, expected); . . // If the expression is used in a place whether mutable place is required . // e.g. LHS of assignment, perform the conversion. 176 ( 0.00%) if let Needs::MutPlace = needs { 99 ( 0.00%) self.convert_place_derefs_to_mutable(expr); . } . . ty . } . . pub(super) fn check_expr(&self, expr: &'tcx hir::Expr<'tcx>) -> Ty<'tcx> { . self.check_expr_with_expectation(expr, NoExpectation) . } -- line 141 ---------------------------------------- -- line 159 ---------------------------------------- . /// that there are actually multiple representations for `Error`, so avoid . /// that when err needs to be handled differently. . #[instrument(skip(self, expr), level = "debug")] . pub(super) fn check_expr_with_expectation( . &self, . expr: &'tcx hir::Expr<'tcx>, . expected: Expectation<'tcx>, . ) -> Ty<'tcx> { 352,465 ( 0.01%) self.check_expr_with_expectation_and_args(expr, expected, &[]) . } . . /// Same as `check_expr_with_expectation`, but allows us to pass in the arguments of a . /// `ExprKind::Call` when evaluating its callee when it is an `ExprKind::Path`. 833,209 ( 0.02%) pub(super) fn check_expr_with_expectation_and_args( . &self, . expr: &'tcx hir::Expr<'tcx>, . expected: Expectation<'tcx>, . args: &'tcx [hir::Expr<'tcx>], . ) -> Ty<'tcx> { 256,372 ( 0.01%) if self.tcx().sess.verbose() { . // make this code only run with -Zverbose because it is probably slow . if let Ok(lint_str) = self.tcx.sess.source_map().span_to_snippet(expr.span) { . if !lint_str.contains('\n') { . debug!("expr text: {}", lint_str); . } else { . let mut lines = lint_str.lines(); . if let Some(line0) = lines.next() { . let remaining_lines = lines.count(); -- line 186 ---------------------------------------- -- line 189 ---------------------------------------- . } . } . } . } . . // True if `expr` is a `Try::from_ok(())` that is a result of desugaring a try block . // without the final expr (e.g. `try { return; }`). We don't want to generate an . // unreachable_code lint for it since warnings for autogenerated code are confusing. 128,186 ( 0.00%) let is_try_block_generated_unit_expr = match expr.kind { 50,595 ( 0.00%) ExprKind::Call(_, args) if expr.span.is_desugaring(DesugaringKind::TryBlock) => { . args.len() == 1 && args[0].span.is_desugaring(DesugaringKind::TryBlock) . } . . _ => false, . }; . . // Warn for expressions after diverging siblings. . if !is_try_block_generated_unit_expr { 448,651 ( 0.01%) self.warn_if_unreachable(expr.hir_id, expr.span, "expression"); . } . . // Hide the outer diverging and has_errors flags. . let old_diverges = self.diverges.replace(Diverges::Maybe); . let old_has_errors = self.has_errors.replace(false); . 149,880 ( 0.00%) let ty = ensure_sufficient_stack(|| match &expr.kind { . hir::ExprKind::Path( . qpath @ hir::QPath::Resolved(..) | qpath @ hir::QPath::TypeRelative(..), 64,986 ( 0.00%) ) => self.check_expr_path(qpath, expr, args), 266,310 ( 0.01%) _ => self.check_expr_kind(expr, expected), . }); . . // Warn for non-block expressions with diverging children. 256,372 ( 0.01%) match expr.kind { . ExprKind::Block(..) . | ExprKind::If(..) . | ExprKind::Let(..) . | ExprKind::Loop(..) . | ExprKind::Match(..) => {} . // If `expr` is a result of desugaring the try block and is an ok-wrapped . // diverging expression (e.g. it arose from desugaring of `try { return }`), . // we skip issuing a warning because it is autogenerated code. 50,595 ( 0.00%) ExprKind::Call(..) if expr.span.is_desugaring(DesugaringKind::TryBlock) => {} 50,595 ( 0.00%) ExprKind::Call(callee, _) => self.warn_if_unreachable(expr.hir_id, callee.span, "call"), 212 ( 0.00%) ExprKind::MethodCall(segment, ..) => { 636 ( 0.00%) self.warn_if_unreachable(expr.hir_id, segment.ident.span, "call") . } 319,884 ( 0.01%) _ => self.warn_if_unreachable(expr.hir_id, expr.span, "expression"), . } . . // Any expression that produces a value of type `!` must have diverged 64,093 ( 0.00%) if ty.is_never() { 69 ( 0.00%) self.diverges.set(self.diverges.get() | Diverges::always(expr.span)); . } . . // Record the type, which applies it effects. . // We need to do this after the warning above, so that . // we don't warn for the diverging expression itself. 320,465 ( 0.01%) self.write_ty(expr.hir_id, ty); . . // Combine the diverging and has_error flags. . self.diverges.set(self.diverges.get() | old_diverges); 64,093 ( 0.00%) self.has_errors.set(self.has_errors.get() | old_has_errors); . . debug!("type of {} is...", self.tcx.hir().node_to_string(expr.hir_id)); . debug!("... {:?}, expected is {:?}", ty, expected); . . ty 576,837 ( 0.01%) } . 1,028,647 ( 0.03%) #[instrument(skip(self, expr), level = "debug")] . fn check_expr_kind( . &self, . expr: &'tcx hir::Expr<'tcx>, . expected: Expectation<'tcx>, . ) -> Ty<'tcx> { . trace!("expr={:#?}", expr); . 53,262 ( 0.00%) let tcx = self.tcx; 319,604 ( 0.01%) match expr.kind { . ExprKind::Box(subexpr) => self.check_expr_box(subexpr, expected), . ExprKind::Lit(ref lit) => self.check_lit(&lit, expected), 2,072 ( 0.00%) ExprKind::Binary(op, lhs, rhs) => self.check_binop(expr, op, lhs, rhs), 87 ( 0.00%) ExprKind::Assign(lhs, rhs, ref span) => { . self.check_expr_assign(expr, expected, lhs, rhs, span) . } 56 ( 0.00%) ExprKind::AssignOp(op, lhs, rhs) => self.check_binop_assign(expr, op, lhs, rhs), 465 ( 0.00%) ExprKind::Unary(unop, oprnd) => self.check_expr_unary(unop, oprnd, expected, expr), 990 ( 0.00%) ExprKind::AddrOf(kind, mutbl, oprnd) => { . self.check_expr_addr_of(kind, mutbl, oprnd, expected, expr) . } 32 ( 0.00%) ExprKind::Path(QPath::LangItem(lang_item, _, hir_id)) => { . self.check_lang_item_path(lang_item, expr, hir_id) . } . ExprKind::Path(ref qpath) => self.check_expr_path(qpath, expr, &[]), . ExprKind::InlineAsm(asm) => self.check_expr_asm(asm), . ExprKind::Break(destination, ref expr_opt) => { 28 ( 0.00%) self.check_expr_break(destination, expr_opt.as_deref(), expr) . } . ExprKind::Continue(destination) => { . if destination.target_id.is_ok() { . tcx.types.never . } else { . // There was an error; make type-check fail. . tcx.ty_error() . } . } . ExprKind::Ret(ref expr_opt) => self.check_expr_return(expr_opt.as_deref(), expr), 25 ( 0.00%) ExprKind::Let(let_expr) => self.check_expr_let(let_expr), 14 ( 0.00%) ExprKind::Loop(body, _, source, _) => { . self.check_expr_loop(body, source, expected, expr) . } 189 ( 0.00%) ExprKind::Match(discrim, arms, match_src) => { 441 ( 0.00%) self.check_match(expr, &discrim, arms, expected, match_src) . } 57 ( 0.00%) ExprKind::Closure(capture, decl, body_id, _, gen) => { 228 ( 0.00%) self.check_expr_closure(expr, capture, &decl, body_id, gen, expected) . } 2,904 ( 0.00%) ExprKind::Block(body, _) => self.check_block_with_expected(&body, expected), 80,952 ( 0.00%) ExprKind::Call(callee, args) => self.check_call(expr, &callee, args, expected), 212 ( 0.00%) ExprKind::MethodCall(segment, args, _) => { . self.check_method_call(expr, segment, args, expected) . } 36 ( 0.00%) ExprKind::Cast(e, t) => self.check_expr_cast(e, t, expr), . ExprKind::Type(e, t) => { . let ty = self.to_ty_saving_user_provided_ty(&t); . self.check_expr_eq_type(&e, ty); . ty . } 445 ( 0.00%) ExprKind::If(cond, then_expr, opt_else_expr) => { 89 ( 0.00%) self.check_then_else(cond, then_expr, opt_else_expr, expr.span, expected) . } 69 ( 0.00%) ExprKind::DropTemps(e) => self.check_expr_with_expectation(e, expected), 19,876 ( 0.00%) ExprKind::Array(args) => self.check_expr_array(args, expected, expr), . ExprKind::ConstBlock(ref anon_const) => { . self.check_expr_const_block(anon_const, expected, expr) . } 10 ( 0.00%) ExprKind::Repeat(element, ref count) => { . self.check_expr_repeat(element, count, expected, expr) . } 2,679 ( 0.00%) ExprKind::Tup(elts) => self.check_expr_tuple(elts, expected, expr), 145 ( 0.00%) ExprKind::Struct(qpath, fields, ref base_expr) => { . self.check_expr_struct(expr, expected, qpath, fields, base_expr) . } 910 ( 0.00%) ExprKind::Field(base, field) => self.check_field(expr, &base, field), 111 ( 0.00%) ExprKind::Index(base, idx) => self.check_expr_index(base, idx, expr), . ExprKind::Yield(value, ref src) => self.check_expr_yield(value, expr, src), . hir::ExprKind::Err => tcx.ty_error(), . } . } . . fn check_expr_box(&self, expr: &'tcx hir::Expr<'tcx>, expected: Expectation<'tcx>) -> Ty<'tcx> { . let expected_inner = expected.to_option(self).map_or(NoExpectation, |ty| match ty.kind() { . ty::Adt(def, _) if def.is_box() => Expectation::rvalue_hint(self, ty.boxed_ty()), -- line 342 ---------------------------------------- -- line 350 ---------------------------------------- . fn check_expr_unary( . &self, . unop: hir::UnOp, . oprnd: &'tcx hir::Expr<'tcx>, . expected: Expectation<'tcx>, . expr: &'tcx hir::Expr<'tcx>, . ) -> Ty<'tcx> { . let tcx = self.tcx; 155 ( 0.00%) let expected_inner = match unop { . hir::UnOp::Not | hir::UnOp::Neg => expected, . hir::UnOp::Deref => NoExpectation, . }; 310 ( 0.00%) let mut oprnd_t = self.check_expr_with_expectation(&oprnd, expected_inner); . 155 ( 0.00%) if !oprnd_t.references_error() { 1,085 ( 0.00%) oprnd_t = self.structurally_resolved_type(expr.span, oprnd_t); 342 ( 0.00%) match unop { . hir::UnOp::Deref => { . if let Some(ty) = self.lookup_derefing(expr, oprnd, oprnd_t) { . oprnd_t = ty; . } else { . let mut err = type_error_struct!( . tcx.sess, . expr.span, . oprnd_t, -- line 374 ---------------------------------------- -- line 382 ---------------------------------------- . { . tcx.sess.parse_sess.expr_parentheses_needed(&mut err, *sp); . } . err.emit(); . oprnd_t = tcx.ty_error(); . } . } . hir::UnOp::Not => { 64 ( 0.00%) let result = self.check_user_unop(expr, oprnd_t, unop); . // If it's builtin, we can reuse the type, this helps inference. 96 ( 0.00%) if !(oprnd_t.is_integral() || *oprnd_t.kind() == ty::Bool) { . oprnd_t = result; . } . } . hir::UnOp::Neg => { . let result = self.check_user_unop(expr, oprnd_t, unop); . // If it's builtin, we can reuse the type, this helps inference. . if !oprnd_t.is_numeric() { . oprnd_t = result; -- line 400 ---------------------------------------- -- line 409 ---------------------------------------- . &self, . kind: hir::BorrowKind, . mutbl: hir::Mutability, . oprnd: &'tcx hir::Expr<'tcx>, . expected: Expectation<'tcx>, . expr: &'tcx hir::Expr<'tcx>, . ) -> Ty<'tcx> { . let hint = expected.only_has_type(self).map_or(NoExpectation, |ty| { 455 ( 0.00%) match ty.kind() { . ty::Ref(_, ty, _) | ty::RawPtr(ty::TypeAndMut { ty, .. }) => { 352 ( 0.00%) if oprnd.is_syntactic_place_expr() { . // Places may legitimately have unsized types. . // For example, dereferences of a fat pointer and . // the last field of a struct can be unsized. . ExpectHasType(ty) . } else { 138 ( 0.00%) Expectation::rvalue_hint(self, ty) . } . } . _ => NoExpectation, . } 273 ( 0.00%) }); . let ty = . self.check_expr_with_expectation_and_needs(&oprnd, hint, Needs::maybe_mut_place(mutbl)); . . let tm = ty::TypeAndMut { ty, mutbl }; 110 ( 0.00%) match kind { 110 ( 0.00%) _ if tm.ty.references_error() => self.tcx.ty_error(), . hir::BorrowKind::Raw => { . self.check_named_place_expr(oprnd); . self.tcx.mk_ptr(tm) . } . hir::BorrowKind::Ref => { . // Note: at this point, we cannot say what the best lifetime . // is to use for resulting pointer. We want to use the . // shortest lifetime possible so as to avoid spurious borrowck -- line 444 ---------------------------------------- -- line 448 ---------------------------------------- . // type inference is complete. . // . // Therefore, here we simply generate a region variable. The . // region inferencer will then select a suitable value. . // Finally, borrowck will infer the value of the region again, . // this time with enough precision to check that the value . // whose address was taken can actually be made to live as long . // as it needs to live. 550 ( 0.00%) let region = self.next_region_var(infer::AddrOfRegion(expr.span)); 110 ( 0.00%) self.tcx.mk_ref(region, tm) . } . } . } . . /// Does this expression refer to a place that either: . /// * Is based on a local or static. . /// * Contains a dereference . /// Note that the adjustments for the children of `expr` should already -- line 465 ---------------------------------------- -- line 489 ---------------------------------------- . } . . fn check_lang_item_path( . &self, . lang_item: hir::LangItem, . expr: &'tcx hir::Expr<'tcx>, . hir_id: Option, . ) -> Ty<'tcx> { 192 ( 0.00%) self.resolve_lang_item_path(lang_item, expr.span, expr.hir_id, hir_id).1 . } . 119,141 ( 0.00%) pub(crate) fn check_expr_path( . &self, . qpath: &'tcx hir::QPath<'tcx>, . expr: &'tcx hir::Expr<'tcx>, . args: &'tcx [hir::Expr<'tcx>], . ) -> Ty<'tcx> { 10,831 ( 0.00%) let tcx = self.tcx; 119,141 ( 0.00%) let (res, opt_ty, segs) = 108,310 ( 0.00%) self.resolve_ty_and_res_fully_qualified_call(qpath, expr.hir_id, expr.span); 63,710 ( 0.00%) let ty = match res { . Res::Err => { . self.set_tainted_by_errors(); . tcx.ty_error() . } . Res::Def(DefKind::Ctor(_, CtorKind::Fictive), _) => { . report_unexpected_variant_res(tcx, res, expr.span); . tcx.ty_error() . } 194,958 ( 0.00%) _ => self.instantiate_value_path(segs, opt_ty, res, expr.span, expr.hir_id).0, . }; . 32,493 ( 0.00%) if let ty::FnDef(..) = ty.kind() { 30,309 ( 0.00%) let fn_sig = ty.fn_sig(tcx); 40,412 ( 0.00%) if !tcx.features().unsized_fn_params { . // We want to remove some Sized bounds from std functions, . // but don't want to expose the removal to stable Rust. . // i.e., we don't want to allow . // . // ```rust . // drop as fn(str); . // ``` . // . // to work in stable even if the Sized bound on `drop` is relaxed. . for i in 0..fn_sig.inputs().skip_binder().len() { . // We just want to check sizedness, so instead of introducing . // placeholder lifetimes with probing, we just replace higher lifetimes . // with fresh vars. 10,180 ( 0.00%) let span = args.get(i).map(|a| a.span).unwrap_or(expr.span); . let input = self . .replace_bound_vars_with_fresh_vars( . span, . infer::LateBoundRegionConversionTime::FnCall, . fn_sig.input(i), . ) . .0; 40,720 ( 0.00%) self.require_type_is_sized_deferred( . input, . span, 30,540 ( 0.00%) traits::SizedArgumentType(None), . ); . } . } . // Here we want to prevent struct constructors from returning unsized types. . // There were two cases this happened: fn pointer coercion in stable . // and usual function call in presence of unsized_locals. . // Also, as we just want to check sizedness, instead of introducing . // placeholder lifetimes with probing, we just replace higher lifetimes -- line 556 ---------------------------------------- -- line 557 ---------------------------------------- . // with fresh vars. . let output = self . .replace_bound_vars_with_fresh_vars( . expr.span, . infer::LateBoundRegionConversionTime::FnCall, . fn_sig.output(), . ) . .0; 60,618 ( 0.00%) self.require_type_is_sized_deferred(output, expr.span, traits::SizedReturnType); . } . . // We always require that the type provided as the value for . // a type parameter outlives the moment of instantiation. 43,324 ( 0.00%) let substs = self.typeck_results.borrow().node_substs(expr.hir_id); . self.add_wf_bounds(substs, expr); . . ty 86,648 ( 0.00%) } . . fn check_expr_break( . &self, . destination: hir::Destination, . expr_opt: Option<&'tcx hir::Expr<'tcx>>, . expr: &'tcx hir::Expr<'tcx>, . ) -> Ty<'tcx> { 7 ( 0.00%) let tcx = self.tcx; 42 ( 0.00%) if let Ok(target_id) = destination.target_id { . let (e_ty, cause); 21 ( 0.00%) if let Some(e) = expr_opt { . // If this is a break with a value, we need to type-check . // the expression. Get an expected type from the loop context. . let opt_coerce_to = { . // We should release `enclosing_breakables` before the `check_expr_with_hint` . // below, so can't move this block of code to the enclosing scope and share . // `ctxt` with the second `encloding_breakables` borrow below. . let mut enclosing_breakables = self.enclosing_breakables.borrow_mut(); . match enclosing_breakables.opt_find_breakable(target_id) { -- line 593 ---------------------------------------- -- line 609 ---------------------------------------- . . // Recurse without `enclosing_breakables` borrowed. . e_ty = self.check_expr_with_hint(e, coerce_to); . cause = self.misc(e.span); . } else { . // Otherwise, this is a break *without* a value. That's . // always legal, and is equivalent to `break ()`. . e_ty = tcx.mk_unit(); 21 ( 0.00%) cause = self.misc(expr.span); . } . . // Now that we have type-checked `expr_opt`, borrow . // the `enclosing_loops` field and let's coerce the . // type of `expr_opt` into what is expected. . let mut enclosing_breakables = self.enclosing_breakables.borrow_mut(); 35 ( 0.00%) let ctxt = match enclosing_breakables.opt_find_breakable(target_id) { . Some(ctxt) => ctxt, . None => { . // Avoid ICE when `break` is inside a closure (#65383). . return tcx.ty_error_with_message( . expr.span, . "break was outside loop, but no error was emitted", . ); . } . }; . 14 ( 0.00%) if let Some(ref mut coerce) = ctxt.coerce { . if let Some(ref e) = expr_opt { . coerce.coerce(self, &cause, e, e_ty); . } else { . assert!(e_ty.is_unit()); . let ty = coerce.expected_ty(); . coerce.coerce_forced_unit( . self, . &cause, -- line 643 ---------------------------------------- -- line 664 ---------------------------------------- . } else { . // If `ctxt.coerce` is `None`, we can just ignore . // the type of the expression. This is because . // either this was a break *without* a value, in . // which case it is always a legal type (`()`), or . // else an error would have been flagged by the . // `loops` pass for using break with an expression . // where you are not supposed to. 7 ( 0.00%) assert!(expr_opt.is_none() || self.tcx.sess.has_errors()); . } . . // If we encountered a `break`, then (no surprise) it may be possible to break from the . // loop... unless the value being returned from the loop diverges itself, e.g. . // `break return 5` or `break loop {}`. 42 ( 0.00%) ctxt.may_break |= !self.diverges.get().is_always(); . . // the type of a `break` is always `!`, since it diverges . tcx.types.never . } else { . // Otherwise, we failed to find the enclosing loop; . // this can only happen if the `break` was not . // inside a loop at all, which is caught by the . // loop-checking pass. -- line 686 ---------------------------------------- -- line 708 ---------------------------------------- . } . } . . fn check_expr_return( . &self, . expr_opt: Option<&'tcx hir::Expr<'tcx>>, . expr: &'tcx hir::Expr<'tcx>, . ) -> Ty<'tcx> { 31 ( 0.00%) if self.ret_coercion.is_none() { . let mut err = ReturnStmtOutsideOfFnBody { . span: expr.span, . encl_body_span: None, . encl_fn_span: None, . }; . . let encl_item_id = self.tcx.hir().get_parent_item(expr.hir_id); . -- line 724 ---------------------------------------- -- line 756 ---------------------------------------- . . self.tcx.sess.emit_err(err); . . if let Some(e) = expr_opt { . // We still have to type-check `e` (issue #86188), but calling . // `check_return_expr` only works inside fn bodies. . self.check_expr(e); . } 62 ( 0.00%) } else if let Some(e) = expr_opt { 31 ( 0.00%) if self.ret_coercion_span.get().is_none() { 30 ( 0.00%) self.ret_coercion_span.set(Some(e.span)); . } 124 ( 0.00%) self.check_return_expr(e, true); . } else { . let mut coercion = self.ret_coercion.as_ref().unwrap().borrow_mut(); . if self.ret_coercion_span.get().is_none() { . self.ret_coercion_span.set(Some(expr.span)); . } . let cause = self.cause(expr.span, ObligationCauseCode::ReturnNoExpression); . if let Some((fn_decl, _)) = self.get_fn_decl(expr.hir_id) { . coercion.coerce_forced_unit( -- line 776 ---------------------------------------- -- line 786 ---------------------------------------- . } . }, . true, . ); . } else { . coercion.coerce_forced_unit(self, &cause, &mut |_| (), true); . } . } 93 ( 0.00%) self.tcx.types.never . } . . /// `explicit_return` is `true` if we're checkng an explicit `return expr`, . /// and `false` if we're checking a trailing expression. 1,136 ( 0.00%) pub(super) fn check_return_expr( . &self, . return_expr: &'tcx hir::Expr<'tcx>, . explicit_return: bool, . ) { . let ret_coercion = self.ret_coercion.as_ref().unwrap_or_else(|| { . span_bug!(return_expr.span, "check_return_expr called outside fn body") . }); . . let ret_ty = ret_coercion.borrow().expected_ty(); . let return_expr_ty = self.check_expr_with_hint(return_expr, ret_ty); 142 ( 0.00%) let mut span = return_expr.span; . // Use the span of the trailing expression for our cause, . // not the span of the entire function 284 ( 0.00%) if !explicit_return { 316 ( 0.00%) if let ExprKind::Block(body, _) = return_expr.kind { 282 ( 0.00%) if let Some(last_expr) = body.expr { 94 ( 0.00%) span = last_expr.span; . } . } . } . ret_coercion.borrow_mut().coerce( . self, 284 ( 0.00%) &self.cause(span, ObligationCauseCode::ReturnValue(return_expr.hir_id)), . return_expr, . return_expr_ty, . ); 1,136 ( 0.00%) } . 363 ( 0.00%) pub(crate) fn check_lhs_assignable( . &self, . lhs: &'tcx hir::Expr<'tcx>, . err_code: &'static str, . op_span: Span, . ) { 132 ( 0.00%) if lhs.is_syntactic_place_expr() { . return; . } . . // FIXME: Make this use SessionDiagnostic once error codes can be dynamically set. . let mut err = self.tcx.sess.struct_span_err_with_code( . op_span, . "invalid left-hand side of assignment", . DiagnosticId::Error(err_code.into()), -- line 842 ---------------------------------------- -- line 880 ---------------------------------------- . | hir::Node::Crate(_) => break, . _ => { . parent = self.tcx.hir().get_parent_node(parent); . } . } . } . . err.emit(); 264 ( 0.00%) } . . // A generic function for checking the 'then' and 'else' clauses in an 'if' . // or 'if-else' expression. . fn check_then_else( . &self, . cond_expr: &'tcx hir::Expr<'tcx>, . then_expr: &'tcx hir::Expr<'tcx>, . opt_else_expr: Option<&'tcx hir::Expr<'tcx>>, . sp: Span, . orig_expected: Expectation<'tcx>, . ) -> Ty<'tcx> { . let cond_ty = self.check_expr_has_type_or_error(cond_expr, self.tcx.types.bool, |_| {}); . 445 ( 0.00%) self.warn_if_unreachable( 178 ( 0.00%) cond_expr.hir_id, 89 ( 0.00%) then_expr.span, . "block in `if` or `while` expression", . ); . 178 ( 0.00%) let cond_diverges = self.diverges.get(); . self.diverges.set(Diverges::Maybe); . . let expected = orig_expected.adjust_for_branches(self); . let then_ty = self.check_expr_with_expectation(then_expr, expected); . let then_diverges = self.diverges.get(); . self.diverges.set(Diverges::Maybe); . . // We've already taken the expected type's preferences -- line 916 ---------------------------------------- -- line 919 ---------------------------------------- . // `expected` if it represents a *hard* constraint . // (`only_has_type`); otherwise, we just go with a . // fresh type variable. . let coerce_to_ty = expected.coercion_target_type(self, sp); . let mut coerce: DynamicCoerceMany<'_> = CoerceMany::new(coerce_to_ty); . . coerce.coerce(self, &self.misc(sp), then_expr, then_ty); . 178 ( 0.00%) if let Some(else_expr) = opt_else_expr { 88 ( 0.00%) let else_ty = if sp.desugaring_kind() == Some(DesugaringKind::LetElse) { . // todo introduce `check_expr_with_expectation(.., Expectation::LetElse)` . // for errors that point to the offending expression rather than the entire block. . // We could use `check_expr_eq_type(.., tcx.types.never)`, but then there is no . // way to detect that the expected type originated from let-else and provide . // a customized error. . let else_ty = self.check_expr(else_expr); . let cause = self.cause(else_expr.span, ObligationCauseCode::LetElse); . -- line 936 ---------------------------------------- -- line 943 ---------------------------------------- . else_ty . } . } else { . self.check_expr_with_expectation(else_expr, expected) . }; . let else_diverges = self.diverges.get(); . . let opt_suggest_box_span = 352 ( 0.00%) self.opt_suggest_box_span(else_expr.span, else_ty, orig_expected); . let if_cause = . self.if_cause(sp, then_expr, else_expr, then_ty, else_ty, opt_suggest_box_span); . . coerce.coerce(self, &if_cause, else_expr, else_ty); . . // We won't diverge unless both branches do (or the condition does). 748 ( 0.00%) self.diverges.set(cond_diverges | then_diverges & else_diverges); . } else { . self.if_fallback_coercion(sp, then_expr, &mut coerce); . . // If the condition is false we can't diverge. . self.diverges.set(cond_diverges); . } . 1,157 ( 0.00%) let result_ty = coerce.complete(self); 89 ( 0.00%) if cond_ty.references_error() { self.tcx.ty_error() } else { result_ty } . } . . /// Type check assignment expression `expr` of form `lhs = rhs`. . /// The expected type is `()` and is passed to the function for the purposes of diagnostics. . fn check_expr_assign( . &self, . expr: &'tcx hir::Expr<'tcx>, . expected: Expectation<'tcx>, . lhs: &'tcx hir::Expr<'tcx>, . rhs: &'tcx hir::Expr<'tcx>, . span: &Span, . ) -> Ty<'tcx> { 29 ( 0.00%) let expected_ty = expected.coercion_target_type(self, expr.span); 58 ( 0.00%) if expected_ty == self.tcx.types.bool { . // The expected type is `bool` but this will result in `()` so we can reasonably . // say that the user intended to write `lhs == rhs` instead of `lhs = rhs`. . // The likely cause of this is `if foo = bar { .. }`. . let actual_ty = self.tcx.mk_unit(); . let mut err = self.demand_suptype_diag(expr.span, expected_ty, actual_ty).unwrap(); . let lhs_ty = self.check_expr(&lhs); . let rhs_ty = self.check_expr(&rhs); . let (applicability, eq) = if self.can_coerce(rhs_ty, lhs_ty) { -- line 989 ---------------------------------------- -- line 1019 ---------------------------------------- . if lhs_ty.references_error() || rhs_ty.references_error() { . err.delay_as_bug() . } else { . err.emit(); . } . return self.tcx.ty_error(); . } . 174 ( 0.00%) self.check_lhs_assignable(lhs, "E0070", *span); . . let lhs_ty = self.check_expr_with_needs(&lhs, Needs::MutPlace); 174 ( 0.00%) let rhs_ty = self.check_expr_coercable_to_type(&rhs, lhs_ty, Some(lhs)); . 174 ( 0.00%) self.require_type_is_sized(lhs_ty, lhs.span, traits::AssignmentLhsSized); . 58 ( 0.00%) if lhs_ty.references_error() || rhs_ty.references_error() { . self.tcx.ty_error() . } else { . self.tcx.mk_unit() . } . } . . fn check_expr_let(&self, let_expr: &'tcx hir::Let<'tcx>) -> Ty<'tcx> { . // for let statements, this is done in check_stmt 25 ( 0.00%) let init = let_expr.init; 175 ( 0.00%) self.warn_if_unreachable(init.hir_id, init.span, "block in `let` expression"); . // otherwise check exactly as a let statement 50 ( 0.00%) self.check_decl(let_expr.into()); . // but return a bool, for this is a boolean expression 75 ( 0.00%) self.tcx.types.bool . } . . fn check_expr_loop( . &self, . body: &'tcx hir::Block<'tcx>, . source: hir::LoopSource, . expected: Expectation<'tcx>, . expr: &'tcx hir::Expr<'tcx>, . ) -> Ty<'tcx> { 14 ( 0.00%) let coerce = match source { . // you can only use break with a value from a normal `loop { }` . hir::LoopSource::Loop => { . let coerce_to = expected.coercion_target_type(self, body.span); . Some(CoerceMany::new(coerce_to)) . } . . hir::LoopSource::While | hir::LoopSource::ForLoop => None, . }; . . let ctxt = BreakableCtxt { . coerce, . may_break: false, // Will get updated if/when we find a `break`. . }; . 119 ( 0.00%) let (ctxt, ()) = self.with_breakable_ctxt(expr.hir_id, ctxt, || { 21 ( 0.00%) self.check_block_no_value(&body); . }); . 14 ( 0.00%) if ctxt.may_break { . // No way to know whether it's diverging because . // of a `break` or an outer `break` or `return`. . self.diverges.set(Diverges::Maybe); . } . . // If we permit break with a value, then result type is . // the LUB of the breaks (possibly ! if none); else, it . // is nil. This makes sense because infinite loops -- line 1085 ---------------------------------------- -- line 1095 ---------------------------------------- . /// Checks a method call. . fn check_method_call( . &self, . expr: &'tcx hir::Expr<'tcx>, . segment: &hir::PathSegment<'_>, . args: &'tcx [hir::Expr<'tcx>], . expected: Expectation<'tcx>, . ) -> Ty<'tcx> { 424 ( 0.00%) let rcvr = &args[0]; . let rcvr_t = self.check_expr(&rcvr); . // no need to check for bot/err -- callee does that 848 ( 0.00%) let rcvr_t = self.structurally_resolved_type(args[0].span, rcvr_t); 212 ( 0.00%) let span = segment.ident.span; . 3,392 ( 0.00%) let method = match self.lookup_method(rcvr_t, segment, span, expr, rcvr, args) { 424 ( 0.00%) Ok(method) => { . // We could add a "consider `foo::`" suggestion here, but I wasn't able to . // trigger this codepath causing `structuraly_resolved_type` to emit an error. . 2,332 ( 0.00%) self.write_method_call(expr.hir_id, method); 1,060 ( 0.00%) Ok(method) . } . Err(error) => { . if segment.ident.name != kw::Empty { . if let Some(mut err) = self.report_method_error( . span, . rcvr_t, . segment.ident, . SelfSource::MethodCall(&args[0]), -- line 1123 ---------------------------------------- -- line 1127 ---------------------------------------- . err.emit(); . } . } . Err(()) . } . }; . . // Call the generic checker. 2,968 ( 0.00%) self.check_method_argument_types( . span, . expr, 1,272 ( 0.00%) method, . &args[1..], . DontTupleArguments, . expected, . ) . } . . fn check_expr_cast( . &self, . e: &'tcx hir::Expr<'tcx>, . t: &'tcx hir::Ty<'tcx>, . expr: &'tcx hir::Expr<'tcx>, . ) -> Ty<'tcx> { . // Find the type of `e`. Supply hints based on the type we are casting to, . // if appropriate. 48 ( 0.00%) let t_cast = self.to_ty_saving_user_provided_ty(t); . let t_cast = self.resolve_vars_if_possible(t_cast); . let t_expr = self.check_expr_with_expectation(e, ExpectCastableToType(t_cast)); . let t_expr = self.resolve_vars_if_possible(t_expr); . . // Eagerly check for some obvious errors. 24 ( 0.00%) if t_expr.references_error() || t_cast.references_error() { . self.tcx.ty_error() . } else { . // Defer other checks until we're done type checking. . let mut deferred_cast_checks = self.deferred_cast_checks.borrow_mut(); 36 ( 0.00%) match cast::CastCheck::new(self, e, t_expr, t_cast, t.span, expr.span) { . Ok(cast_check) => { . debug!( . "check_expr_cast: deferring cast from {:?} to {:?}: {:?}", . t_cast, t_expr, cast_check, . ); . deferred_cast_checks.push(cast_check); . t_cast . } -- line 1172 ---------------------------------------- -- line 1176 ---------------------------------------- . } . . fn check_expr_array( . &self, . args: &'tcx [hir::Expr<'tcx>], . expected: Expectation<'tcx>, . expr: &'tcx hir::Expr<'tcx>, . ) -> Ty<'tcx> { 9,938 ( 0.00%) let element_ty = if !args.is_empty() { 29,811 ( 0.00%) let coerce_to = expected . .to_option(self) 29,811 ( 0.00%) .and_then(|uty| match *uty.kind() { . ty::Array(ty, _) | ty::Slice(ty) => Some(ty), . _ => None, . }) . .unwrap_or_else(|| { . self.next_ty_var(TypeVariableOrigin { . kind: TypeVariableOriginKind::TypeInference, . span: expr.span, . }) . }); . let mut coerce = CoerceMany::with_coercion_sites(coerce_to, args); 9,937 ( 0.00%) assert_eq!(self.diverges.get(), Diverges::Maybe); . for e in args { . let e_ty = self.check_expr_with_hint(e, coerce_to); 39,738 ( 0.00%) let cause = self.misc(e.span); 238,428 ( 0.01%) coerce.coerce(self, &cause, e, e_ty); . } 119,244 ( 0.00%) coerce.complete(self) . } else { 4 ( 0.00%) self.next_ty_var(TypeVariableOrigin { . kind: TypeVariableOriginKind::TypeInference, 1 ( 0.00%) span: expr.span, . }) . }; 59,633 ( 0.00%) self.tcx.mk_array(element_ty, args.len() as u64) . } . . fn check_expr_const_block( . &self, . anon_const: &'tcx hir::AnonConst, . expected: Expectation<'tcx>, . _expr: &'tcx hir::Expr<'tcx>, . ) -> Ty<'tcx> { -- line 1219 ---------------------------------------- -- line 1232 ---------------------------------------- . fn check_expr_repeat( . &self, . element: &'tcx hir::Expr<'tcx>, . count: &'tcx hir::ArrayLen, . expected: Expectation<'tcx>, . _expr: &'tcx hir::Expr<'tcx>, . ) -> Ty<'tcx> { . let tcx = self.tcx; 25 ( 0.00%) let count = self.array_length_to_const(count); . 10 ( 0.00%) let uty = match expected { 20 ( 0.00%) ExpectHasType(uty) => match *uty.kind() { . ty::Array(ty, _) | ty::Slice(ty) => Some(ty), . _ => None, . }, . _ => None, . }; . . let (element_ty, t) = match uty { . Some(uty) => { 12 ( 0.00%) self.check_expr_coercable_to_type(&element, uty, None); . (uty, uty) . } . None => { 15 ( 0.00%) let ty = self.next_ty_var(TypeVariableOrigin { . kind: TypeVariableOriginKind::MiscVariable, 3 ( 0.00%) span: element.span, . }); . let element_ty = self.check_expr_has_type_or_error(&element, ty, |_| {}); . (element_ty, ty) . } . }; . 5 ( 0.00%) if element_ty.references_error() { . return tcx.ty_error(); . } . . tcx.mk_ty(ty::Array(t, count)) . } . . fn check_expr_tuple( . &self, . elts: &'tcx [hir::Expr<'tcx>], . expected: Expectation<'tcx>, . expr: &'tcx hir::Expr<'tcx>, . ) -> Ty<'tcx> { 1,786 ( 0.00%) let flds = expected.only_has_type(self).and_then(|ty| { 891 ( 0.00%) let ty = self.resolve_vars_with_obligations(ty); 1,782 ( 0.00%) match ty.kind() { 883 ( 0.00%) ty::Tuple(flds) => Some(&flds[..]), . _ => None, . } . }); . 6,197 ( 0.00%) let elt_ts_iter = elts.iter().enumerate().map(|(i, e)| match flds { 3,508 ( 0.00%) Some(fs) if i < fs.len() => { 6,139 ( 0.00%) let ety = fs[i].expect_ty(); 11,401 ( 0.00%) self.check_expr_coercable_to_type(&e, ety, None); . ety . } 10 ( 0.00%) _ => self.check_expr_with_expectation(&e, NoExpectation), . }); 1,786 ( 0.00%) let tuple = self.tcx.mk_tup(elt_ts_iter); 893 ( 0.00%) if tuple.references_error() { . self.tcx.ty_error() . } else { 6,251 ( 0.00%) self.require_type_is_sized(tuple, expr.span, traits::TupleInitializerSized); . tuple . } . } . . fn check_expr_struct( . &self, . expr: &hir::Expr<'_>, . expected: Expectation<'tcx>, . qpath: &QPath<'_>, . fields: &'tcx [hir::ExprField<'tcx>], . base_expr: &'tcx Option<&'tcx hir::Expr<'tcx>>, . ) -> Ty<'tcx> { . // Find the relevant variant 290 ( 0.00%) let (variant, adt_ty) = if let Some(variant_ty) = self.check_struct_path(qpath, expr.hir_id) . { . variant_ty . } else { . self.check_struct_fields_on_error(fields, base_expr); . return self.tcx.ty_error(); . }; . . // Prohibit struct expressions when non-exhaustive flag is set. . let adt = adt_ty.ty_adt_def().expect("`check_struct_path` returned non-ADT type"); 65 ( 0.00%) if !adt.did.is_local() && variant.is_field_list_non_exhaustive() { . self.tcx . .sess . .emit_err(StructExprNonExhaustive { span: expr.span, what: adt.variant_descr() }); . } . 406 ( 0.00%) self.check_expr_struct_fields( . adt_ty, . expected, . expr.hir_id, 87 ( 0.00%) qpath.span(), . variant, . fields, . base_expr, 58 ( 0.00%) expr.span, . ); . 203 ( 0.00%) self.require_type_is_sized(adt_ty, expr.span, traits::StructInitializerSized); . adt_ty . } . 406 ( 0.00%) fn check_expr_struct_fields( . &self, . adt_ty: Ty<'tcx>, . expected: Expectation<'tcx>, . expr_id: hir::HirId, . span: Span, . variant: &'tcx ty::VariantDef, . ast_fields: &'tcx [hir::ExprField<'tcx>], . base_expr: &'tcx Option<&'tcx hir::Expr<'tcx>>, . expr_span: Span, . ) { 58 ( 0.00%) let tcx = self.tcx; . . let adt_ty_hint = self 58 ( 0.00%) .expected_inputs_for_expected_output(span, expected, adt_ty, &[adt_ty]) . .get(0) . .cloned() . .unwrap_or(adt_ty); . // re-link the regions that EIfEO can erase. . self.demand_eqtype(span, adt_ty_hint, adt_ty); . 58 ( 0.00%) let (substs, adt_kind, kind_name) = match adt_ty.kind() { 58 ( 0.00%) ty::Adt(adt, substs) => (substs, adt.adt_kind(), adt.variant_descr()), . _ => span_bug!(span, "non-ADT passed to check_expr_struct_fields"), . }; . . let mut remaining_fields = variant . .fields . .iter() . .enumerate() 378 ( 0.00%) .map(|(i, field)| (field.ident(tcx).normalize_to_macros_2_0(), (i, field))) . .collect::>(); . . let mut seen_fields = FxHashMap::default(); . . let mut error_happened = false; . . // Type-check each field. . for field in ast_fields { 968 ( 0.00%) let ident = tcx.adjust_ident(field.ident, variant.def_id); 189 ( 0.00%) let field_type = if let Some((i, v_field)) = remaining_fields.remove(&ident) { 189 ( 0.00%) seen_fields.insert(ident, field.span); . self.write_field_index(field.hir_id, i); . . // We don't look at stability attributes on . // struct-like enums (yet...), but it's definitely not . // a bug to have constructed one. 63 ( 0.00%) if adt_kind != AdtKind::Enum { 531 ( 0.00%) tcx.check_stability(v_field.did, Some(expr_id), field.span, None); . } . 189 ( 0.00%) self.field_ty(field.span, v_field, substs) . } else { . error_happened = true; . if let Some(prev_span) = seen_fields.get(&ident) { . tcx.sess.emit_err(FieldMultiplySpecifiedInInitializer { . span: field.ident.span, . prev_span: *prev_span, . ident, . }); -- line 1402 ---------------------------------------- -- line 1406 ---------------------------------------- . ); . } . . tcx.ty_error() . }; . . // Make sure to give a type to the field even if there's . // an error, so we can continue type-checking. 315 ( 0.00%) self.check_expr_coercable_to_type(&field.expr, field_type, None); . } . . // Make sure the programmer specified correct number of fields. . if kind_name == "union" { . if ast_fields.len() != 1 { . struct_span_err!( . tcx.sess, . span, -- line 1422 ---------------------------------------- -- line 1425 ---------------------------------------- . ) . .emit(); . } . } . . // If check_expr_struct_fields hit an error, do not attempt to populate . // the fields with the base_expr. This could cause us to hit errors later . // when certain fields are assumed to exist that in fact do not. 58 ( 0.00%) if error_happened { . return; . } . 87 ( 0.00%) if let Some(base_expr) = base_expr { . // FIXME: We are currently creating two branches here in order to maintain . // consistency. But they should be merged as much as possible. . let fru_tys = if self.tcx.features().type_changing_struct_update { . let base_ty = self.check_expr(base_expr); . match adt_ty.kind() { . ty::Adt(adt, substs) if adt.is_struct() => { . match base_ty.kind() { . ty::Adt(base_adt, base_subs) if adt == base_adt => { -- line 1445 ---------------------------------------- -- line 1528 ---------------------------------------- . return self . .tcx . .sess . .emit_err(FunctionalRecordUpdateOnNonStruct { span: base_expr.span }); . } . } . }; . self.typeck_results.borrow_mut().fru_field_types_mut().insert(expr_id, fru_tys); 29 ( 0.00%) } else if kind_name != "union" && !remaining_fields.is_empty() { . let inaccessible_remaining_fields = remaining_fields.iter().any(|(_, (_, field))| { . !field.vis.is_accessible_from(tcx.parent_module(expr_id).to_def_id(), tcx) . }); . . if inaccessible_remaining_fields { . self.report_inaccessible_fields(adt_ty, span); . } else { . self.report_missing_fields(adt_ty, span, remaining_fields); . } . } 290 ( 0.00%) } . . fn check_struct_fields_on_error( . &self, . fields: &'tcx [hir::ExprField<'tcx>], . base_expr: &'tcx Option<&'tcx hir::Expr<'tcx>>, . ) { . for field in fields { . self.check_expr(&field.expr); -- line 1555 ---------------------------------------- -- line 1805 ---------------------------------------- . names.iter().take(limit).map(|n| format!("`{}`", n)).collect::>().join(", "); . if names.len() > limit { . display = format!("{} ... and {} others", display, names.len() - limit); . } . display . } . . // Check field access expressions 840 ( 0.00%) fn check_field( . &self, . expr: &'tcx hir::Expr<'tcx>, . base: &'tcx hir::Expr<'tcx>, . field: Ident, . ) -> Ty<'tcx> { . debug!("check_field(expr: {:?}, base: {:?}, field: {:?})", expr, base, field); . let expr_t = self.check_expr(base); 350 ( 0.00%) let expr_t = self.structurally_resolved_type(base.span, expr_t); 140 ( 0.00%) let mut private_candidate = None; 70 ( 0.00%) let mut autoderef = self.autoderef(expr.span, expr_t); 548 ( 0.00%) while let Some((base_t, _)) = autoderef.next() { . debug!("base_t: {:?}", base_t); 553 ( 0.00%) match base_t.kind() { 198 ( 0.00%) ty::Adt(base_def, substs) if !base_def.is_enum() => { . debug!("struct named {:?}", base_t); 528 ( 0.00%) let (ident, def_scope) = 792 ( 0.00%) self.tcx.adjust_ident_and_get_scope(field, base_def.did, self.body_id); 132 ( 0.00%) let fields = &base_def.non_enum_variant().fields; . if let Some(index) = fields . .iter() 1,946 ( 0.00%) .position(|f| f.ident(self.tcx).normalize_to_macros_2_0() == ident) . { . let field = &fields[index]; 198 ( 0.00%) let field_ty = self.field_ty(expr.span, field, substs); . // Save the index of all fields regardless of their visibility in case . // of error recovery. . self.write_field_index(expr.hir_id, index); . let adjustments = self.adjust_steps(&autoderef); 66 ( 0.00%) if field.vis.is_accessible_from(def_scope, self.tcx) { 660 ( 0.00%) self.apply_adjustments(base, adjustments); 1,188 ( 0.00%) self.register_predicates(autoderef.into_obligations()); . 924 ( 0.00%) self.tcx.check_stability(field.did, Some(expr.hir_id), expr.span, None); . return field_ty; . } . private_candidate = Some((adjustments, base_def.did, field_ty)); . } . } . ty::Tuple(tys) => { 8 ( 0.00%) let fstr = field.as_str(); 12 ( 0.00%) if let Ok(index) = fstr.parse::() { 8 ( 0.00%) if fstr == index.to_string() { 12 ( 0.00%) if let Some(field_ty) = tys.get(index) { . let adjustments = self.adjust_steps(&autoderef); 36 ( 0.00%) self.apply_adjustments(base, adjustments); 72 ( 0.00%) self.register_predicates(autoderef.into_obligations()); . . self.write_field_index(expr.hir_id, index); 16 ( 0.00%) return field_ty.expect_ty(); . } . } . } . } . _ => {} . } . } . self.structurally_resolved_type(autoderef.span(), autoderef.final_ty(false)); -- line 1870 ---------------------------------------- -- line 1890 ---------------------------------------- . E0610, . "`{}` is a primitive type and therefore doesn't have fields", . expr_t . ) . .emit(); . } . . self.tcx().ty_error() 770 ( 0.00%) } . . fn suggest_await_on_field_access( . &self, . err: &mut DiagnosticBuilder<'_>, . field_ident: Ident, . base: &'tcx hir::Expr<'tcx>, . ty: Ty<'tcx>, . ) { -- line 1906 ---------------------------------------- -- line 2301 ---------------------------------------- . &self, . base: &'tcx hir::Expr<'tcx>, . idx: &'tcx hir::Expr<'tcx>, . expr: &'tcx hir::Expr<'tcx>, . ) -> Ty<'tcx> { . let base_t = self.check_expr(&base); . let idx_t = self.check_expr(&idx); . 37 ( 0.00%) if base_t.references_error() { . base_t 37 ( 0.00%) } else if idx_t.references_error() { . idx_t . } else { 222 ( 0.00%) let base_t = self.structurally_resolved_type(base.span, base_t); 74 ( 0.00%) match self.lookup_indexing(expr, base, base_t, idx, idx_t) { . Some((index_ty, element_ty)) => { . // two-phase not needed because index_ty is never mutable . self.demand_coerce(idx, idx_t, index_ty, None, AllowTwoPhase::No); . element_ty . } . None => { . let mut err = type_error_struct!( . self.tcx.sess, -- line 2323 ---------------------------------------- 674,344 ( 0.02%) -------------------------------------------------------------------------------- -- Auto-annotated source: /usr/home/liquid/rust/worktree-benchmarking/library/alloc/src/vec/into_iter.rs -------------------------------------------------------------------------------- Ir -- line 51 ---------------------------------------- . /// let vec = vec!['a', 'b', 'c']; . /// let mut into_iter = vec.into_iter(); . /// assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']); . /// let _ = into_iter.next().unwrap(); . /// assert_eq!(into_iter.as_slice(), &['b', 'c']); . /// ``` . #[stable(feature = "vec_into_iter_as_slice", since = "1.15.0")] . pub fn as_slice(&self) -> &[T] { 3,682 ( 0.00%) unsafe { slice::from_raw_parts(self.ptr, self.len()) } . } . . /// Returns the remaining items of this iterator as a mutable slice. . /// . /// # Examples . /// . /// ``` . /// let vec = vec!['a', 'b', 'c']; -- line 67 ---------------------------------------- -- line 80 ---------------------------------------- . /// Returns a reference to the underlying allocator. . #[unstable(feature = "allocator_api", issue = "32838")] . #[inline] . pub fn allocator(&self) -> &A { . &self.alloc . } . . fn as_raw_mut_slice(&mut self) -> *mut [T] { 1,101,088 ( 0.03%) ptr::slice_from_raw_parts_mut(self.ptr as *mut T, self.len()) . } . . /// Drops remaining elements and relinquishes the backing allocation. . /// . /// This is roughly equivalent to the following, but more efficient . /// . /// ``` . /// # let mut into_iter = Vec::::with_capacity(10).into_iter(); -- line 96 ---------------------------------------- -- line 99 ---------------------------------------- . /// ``` . #[cfg(not(no_global_oom_handling))] . pub(super) fn forget_allocation_drop_remaining(&mut self) { . let remaining = self.as_raw_mut_slice(); . . // overwrite the individual fields instead of creating a new . // struct and then overwriting &mut self. . // this creates less assembly 441 ( 0.00%) self.cap = 0; 882 ( 0.00%) self.buf = unsafe { NonNull::new_unchecked(RawVec::NEW.ptr()) }; 636 ( 0.00%) self.ptr = self.buf.as_ptr(); 599 ( 0.00%) self.end = self.buf.as_ptr(); . . unsafe { . ptr::drop_in_place(remaining); . } . } . } . . #[stable(feature = "vec_intoiter_as_ref", since = "1.46.0")] -- line 118 ---------------------------------------- -- line 128 ---------------------------------------- . unsafe impl Sync for IntoIter {} . . #[stable(feature = "rust1", since = "1.0.0")] . impl Iterator for IntoIter { . type Item = T; . . #[inline] . fn next(&mut self) -> Option { 1,908,608 ( 0.05%) if self.ptr as *const _ == self.end { 65,285 ( 0.00%) None 72 ( 0.00%) } else if mem::size_of::() == 0 { . // purposefully don't use 'ptr.offset' because for . // vectors with 0-size elements this would return the . // same pointer. . self.ptr = unsafe { arith_offset(self.ptr as *const i8, 1) as *mut T }; . . // Make up a value of this ZST. . Some(unsafe { mem::zeroed() }) . } else { . let old = self.ptr; 173,586 ( 0.00%) self.ptr = unsafe { self.ptr.offset(1) }; . 231,393 ( 0.01%) Some(unsafe { ptr::read(old) }) . } . } . . #[inline] . fn size_hint(&self) -> (usize, Option) { . let exact = if mem::size_of::() == 0 { . (self.end as usize).wrapping_sub(self.ptr as usize) . } else { . unsafe { self.end.offset_from(self.ptr) as usize } . }; 3 ( 0.00%) (exact, Some(exact)) . } . . #[inline] . fn advance_by(&mut self, n: usize) -> Result<(), usize> { . let step_size = self.len().min(n); . let to_drop = ptr::slice_from_raw_parts_mut(self.ptr as *mut T, step_size); . if mem::size_of::() == 0 { . // SAFETY: due to unchecked casts of unsigned amounts to signed offsets the wraparound -- line 169 ---------------------------------------- -- line 181 ---------------------------------------- . if step_size < n { . return Err(step_size); . } . Ok(()) . } . . #[inline] . fn count(self) -> usize { 2 ( 0.00%) self.len() . } . . #[doc(hidden)] . unsafe fn __iterator_get_unchecked(&mut self, i: usize) -> Self::Item . where . Self: TrustedRandomAccessNoCoerce, . { . // SAFETY: the caller must guarantee that `i` is in bounds of the -- line 197 ---------------------------------------- -- line 207 ---------------------------------------- . } . } . } . . #[stable(feature = "rust1", since = "1.0.0")] . impl DoubleEndedIterator for IntoIter { . #[inline] . fn next_back(&mut self) -> Option { 36,466 ( 0.00%) if self.end == self.ptr { . None . } else if mem::size_of::() == 0 { . // See above for why 'ptr.offset' isn't used . self.end = unsafe { arith_offset(self.end as *const i8, -1) as *mut T }; . . // Make up a value of this ZST. . Some(unsafe { mem::zeroed() }) . } else { 982 ( 0.00%) self.end = unsafe { self.end.offset(-1) }; . 239 ( 0.00%) Some(unsafe { ptr::read(self.end) }) . } . } . . #[inline] . fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { . let step_size = self.len().min(n); . if mem::size_of::() == 0 { . // SAFETY: same as for advance_by() -- line 234 ---------------------------------------- -- line 295 ---------------------------------------- . #[cfg(test)] . fn clone(&self) -> Self { . crate::slice::to_vec(self.as_slice(), self.alloc.clone()).into_iter() . } . } . . #[stable(feature = "rust1", since = "1.0.0")] . unsafe impl<#[may_dangle] T, A: Allocator> Drop for IntoIter { 3,568,677 ( 0.09%) fn drop(&mut self) { . struct DropGuard<'a, T, A: Allocator>(&'a mut IntoIter); . . impl Drop for DropGuard<'_, T, A> { . fn drop(&mut self) { . unsafe { . // `IntoIter::alloc` is not used anymore after this . let alloc = ptr::read(&self.0.alloc); . // RawVec handles deallocation 643,400 ( 0.02%) let _ = RawVec::from_raw_parts_in(self.0.buf.as_ptr(), self.0.cap, alloc); . } . } . } . . let guard = DropGuard(self); . // destroy the remaining elements . unsafe { 51 ( 0.00%) ptr::drop_in_place(guard.0.as_raw_mut_slice()); . } . // now `guard` will be dropped and do the rest 3,304,058 ( 0.08%) } . } . . #[unstable(issue = "none", feature = "inplace_iteration")] . #[doc(hidden)] . unsafe impl InPlaceIterable for IntoIter {} . . #[unstable(issue = "none", feature = "inplace_iteration")] . #[doc(hidden)] -- line 331 ---------------------------------------- 534,091 ( 0.01%) -------------------------------------------------------------------------------- -- Auto-annotated source: /usr/home/liquid/rust/worktree-benchmarking/library/core/src/cell.rs -------------------------------------------------------------------------------- Ir -- line 346 ---------------------------------------- . /// . /// let c = Cell::new(5); . /// . /// c.set(10); . /// ``` . #[inline] . #[stable(feature = "rust1", since = "1.0.0")] . pub fn set(&self, val: T) { 653 ( 0.00%) let old = self.replace(val); 640 ( 0.00%) drop(old); . } . . /// Swaps the values of two `Cell`s. . /// Difference with `std::mem::swap` is that this function doesn't require `&mut` reference. . /// . /// # Examples . /// . /// ``` -- line 363 ---------------------------------------- -- line 434 ---------------------------------------- . /// . /// let five = c.get(); . /// ``` . #[inline] . #[stable(feature = "rust1", since = "1.0.0")] . pub fn get(&self) -> T { . // SAFETY: This can cause data races if called from a separate thread, . // but `Cell` is `!Sync` so this won't happen. 537,825 ( 0.01%) unsafe { *self.value.get() } . } . . /// Updates the contained value using a function and returns the new value. . /// . /// # Examples . /// . /// ``` . /// #![feature(cell_update)] -- line 450 ---------------------------------------- -- line 689 ---------------------------------------- . . #[inline(always)] . fn is_writing(x: BorrowFlag) -> bool { . x < UNUSED . } . . #[inline(always)] . fn is_reading(x: BorrowFlag) -> bool { 1,352,260 ( 0.03%) x > UNUSED . } . . impl RefCell { . /// Creates a new `RefCell` containing `value`. . /// . /// # Examples . /// . /// ``` -- line 705 ---------------------------------------- -- line 706 ---------------------------------------- . /// use std::cell::RefCell; . /// . /// let c = RefCell::new(5); . /// ``` . #[stable(feature = "rust1", since = "1.0.0")] . #[rustc_const_stable(feature = "const_refcell_new", since = "1.24.0")] . #[inline] . pub const fn new(value: T) -> RefCell { 17,621 ( 0.00%) RefCell { 16,325 ( 0.00%) value: UnsafeCell::new(value), . borrow: Cell::new(UNUSED), . #[cfg(feature = "debug_refcell")] . borrowed_at: Cell::new(None), . } . } . . /// Consumes the `RefCell`, returning the wrapped value. . /// -- line 723 ---------------------------------------- -- line 731 ---------------------------------------- . /// let five = c.into_inner(); . /// ``` . #[stable(feature = "rust1", since = "1.0.0")] . #[rustc_const_unstable(feature = "const_cell_into_inner", issue = "78729")] . #[inline] . pub const fn into_inner(self) -> T { . // Since this function takes `self` (the `RefCell`) by value, the . // compiler statically verifies that it is not currently borrowed. 892 ( 0.00%) self.value.into_inner() . } . . /// Replaces the wrapped value with a new one, returning the old value, . /// without deinitializing either one. . /// . /// This function corresponds to [`std::mem::replace`](../mem/fn.replace.html). . /// . /// # Panics -- line 747 ---------------------------------------- -- line 845 ---------------------------------------- . /// let c = RefCell::new(5); . /// . /// let m = c.borrow_mut(); . /// let b = c.borrow(); // this causes a panic . /// ``` . #[stable(feature = "rust1", since = "1.0.0")] . #[inline] . #[track_caller] 21,178 ( 0.00%) pub fn borrow(&self) -> Ref<'_, T> { . self.try_borrow().expect("already mutably borrowed") 63,534 ( 0.00%) } . . /// Immutably borrows the wrapped value, returning an error if the value is currently mutably . /// borrowed. . /// . /// The borrow lasts until the returned `Ref` exits scope. Multiple immutable borrows can be . /// taken out at the same time. . /// . /// This is the non-panicking variant of [`borrow`](#method.borrow). -- line 863 ---------------------------------------- -- line 937 ---------------------------------------- . /// let c = RefCell::new(5); . /// let m = c.borrow(); . /// . /// let b = c.borrow_mut(); // this causes a panic . /// ``` . #[stable(feature = "rust1", since = "1.0.0")] . #[inline] . #[track_caller] 48,687 ( 0.00%) pub fn borrow_mut(&self) -> RefMut<'_, T> { . self.try_borrow_mut().expect("already borrowed") 146,061 ( 0.00%) } . . /// Mutably borrows the wrapped value, returning an error if the value is currently borrowed. . /// . /// The borrow lasts until the returned `RefMut` or all `RefMut`s derived . /// from it exit scope. The value cannot be borrowed while this borrow is . /// active. . /// . /// This is the non-panicking variant of [`borrow_mut`](#method.borrow_mut). -- line 955 ---------------------------------------- -- line 975 ---------------------------------------- . match BorrowRefMut::new(&self.borrow) { . Some(b) => { . #[cfg(feature = "debug_refcell")] . { . self.borrowed_at.set(Some(crate::panic::Location::caller())); . } . . // SAFETY: `BorrowRef` guarantees unique access. 22 ( 0.00%) Ok(RefMut { value: unsafe { &mut *self.value.get() }, borrow: b }) . } . None => Err(BorrowMutError { . // If a borrow occurred, then we must already have an outstanding borrow, . // so `borrowed_at` will be `Some` . #[cfg(feature = "debug_refcell")] . location: self.borrowed_at.get().unwrap(), . }), . } -- line 991 ---------------------------------------- -- line 1254 ---------------------------------------- . . struct BorrowRef<'b> { . borrow: &'b Cell, . } . . impl<'b> BorrowRef<'b> { . #[inline] . fn new(borrow: &'b Cell) -> Option> { 1,479,911 ( 0.04%) let b = borrow.get().wrapping_add(1); 987,232 ( 0.03%) if !is_reading(b) { . // Incrementing borrow can result in a non-reading value (<= 0) in these cases: . // 1. It was < 0, i.e. there are writing borrows, so we can't allow a read borrow . // due to Rust's reference aliasing rules . // 2. It was isize::MAX (the max amount of reading borrows) and it overflowed . // into isize::MIN (the max amount of writing borrows) so we can't allow . // an additional read borrow because isize can't represent so many read borrows . // (this can only happen if you mem::forget more than a small constant amount of . // `Ref`s, which is not good practice) -- line 1271 ---------------------------------------- -- line 1279 ---------------------------------------- . Some(BorrowRef { borrow }) . } . } . } . . impl Drop for BorrowRef<'_> { . #[inline] . fn drop(&mut self) { 657,471 ( 0.02%) let borrow = self.borrow.get(); . debug_assert!(is_reading(borrow)); 1,274,597 ( 0.03%) self.borrow.set(borrow - 1); . } . } . . impl Clone for BorrowRef<'_> { . #[inline] . fn clone(&self) -> Self { . // Since this Ref exists, we know the borrow flag . // is a reading borrow. -- line 1297 ---------------------------------------- -- line 1645 ---------------------------------------- . . struct BorrowRefMut<'b> { . borrow: &'b Cell, . } . . impl Drop for BorrowRefMut<'_> { . #[inline] . fn drop(&mut self) { 5,777,309 ( 0.15%) let borrow = self.borrow.get(); . debug_assert!(is_writing(borrow)); 11,145,850 ( 0.28%) self.borrow.set(borrow + 1); . } . } . . impl<'b> BorrowRefMut<'b> { . #[inline] . fn new(borrow: &'b Cell) -> Option> { . // NOTE: Unlike BorrowRefMut::clone, new is called to create the initial . // mutable reference, and so there must currently be no existing . // references. Thus, while clone increments the mutable refcount, here . // we explicitly only allow going from UNUSED to UNUSED - 1. 11,825,978 ( 0.30%) match borrow.get() { . UNUSED => { . borrow.set(UNUSED - 1); . Some(BorrowRefMut { borrow }) . } . _ => None, . } . } . -- line 1674 ---------------------------------------- -- line 1711 ---------------------------------------- . self.value . } . } . . #[stable(feature = "rust1", since = "1.0.0")] . impl DerefMut for RefMut<'_, T> { . #[inline] . fn deref_mut(&mut self) -> &mut T { 218 ( 0.00%) self.value . } . } . . #[unstable(feature = "coerce_unsized", issue = "27732")] . impl<'b, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized> for RefMut<'b, T> {} . . #[stable(feature = "std_guard_impls", since = "1.20.0")] . impl fmt::Display for RefMut<'_, T> { -- line 1727 ---------------------------------------- -- line 1909 ---------------------------------------- . /// ``` . #[inline(always)] . #[stable(feature = "rust1", since = "1.0.0")] . #[rustc_const_stable(feature = "const_unsafecell_get", since = "1.32.0")] . pub const fn get(&self) -> *mut T { . // We can just cast the pointer from `UnsafeCell` to `T` because of . // #[repr(transparent)]. This exploits libstd's special status, there is . // no guarantee for user code that this will work in future versions of the compiler! 5,897,418 ( 0.15%) self as *const UnsafeCell as *const T as *mut T . } . . /// Returns a mutable reference to the underlying data. . /// . /// This call borrows the `UnsafeCell` mutably (at compile-time) which . /// guarantees that we possess the only reference. . /// . /// # Examples -- line 1925 ---------------------------------------- 10,582,826 ( 0.27%) -------------------------------------------------------------------------------- -- Auto-annotated source: /usr/home/liquid/rust/worktree-benchmarking/library/core/src/iter/adapters/zip.rs -------------------------------------------------------------------------------- Ir -- line 63 ---------------------------------------- . /// assert!(iter.next().is_none()); . /// ``` . #[stable(feature = "iter_zip", since = "1.59.0")] . pub fn zip(a: A, b: B) -> Zip . where . A: IntoIterator, . B: IntoIterator, . { 45,561 ( 0.00%) ZipImpl::new(a.into_iter(), b.into_iter()) . } . . #[stable(feature = "rust1", since = "1.0.0")] . impl Iterator for Zip . where . A: Iterator, . B: Iterator, . { -- line 79 ---------------------------------------- -- line 147 ---------------------------------------- . index: 0, // unused . len: 0, // unused . a_len: 0, // unused . } . } . . #[inline] . default fn next(&mut self) -> Option<(A::Item, B::Item)> { 4,943 ( 0.00%) let x = self.a.next()?; 2,530 ( 0.00%) let y = self.b.next()?; 2,400 ( 0.00%) Some((x, y)) 684 ( 0.00%) } . . #[inline] . default fn nth(&mut self, n: usize) -> Option { . self.super_nth(n) . } . . #[inline] . default fn next_back(&mut self) -> Option<(A::Item, B::Item)> -- line 166 ---------------------------------------- -- line 203 ---------------------------------------- . B: Iterator, . { . type Item = (A::Item, B::Item); . . zip_impl_general_defaults! {} . . #[inline] . default fn size_hint(&self) -> (usize, Option) { 30 ( 0.00%) let (a_lower, a_upper) = self.a.size_hint(); 8 ( 0.00%) let (b_lower, b_upper) = self.b.size_hint(); . . let lower = cmp::min(a_lower, b_lower); . . let upper = match (a_upper, b_upper) { . (Some(x), Some(y)) => Some(cmp::min(x, y)), . (Some(x), None) => Some(x), . (None, Some(y)) => Some(y), . (None, None) => None, -- line 220 ---------------------------------------- -- line 236 ---------------------------------------- . where . A: TrustedRandomAccessNoCoerce + Iterator, . B: TrustedRandomAccessNoCoerce + Iterator, . { . zip_impl_general_defaults! {} . . #[inline] . default fn size_hint(&self) -> (usize, Option) { 78 ( 0.00%) let size = cmp::min(self.a.size(), self.b.size()); . (size, Some(size)) . } . . #[inline] . unsafe fn get_unchecked(&mut self, idx: usize) -> ::Item { 76 ( 0.00%) let idx = self.index + idx; . // SAFETY: the caller must uphold the contract for . // `Iterator::__iterator_get_unchecked`. . unsafe { (self.a.__iterator_get_unchecked(idx), self.b.__iterator_get_unchecked(idx)) } . } . } . . #[doc(hidden)] . impl ZipImpl for Zip -- line 258 ---------------------------------------- -- line 263 ---------------------------------------- . fn new(a: A, b: B) -> Self { . let a_len = a.size(); . let len = cmp::min(a_len, b.size()); . Zip { a, b, index: 0, len, a_len } . } . . #[inline] . fn next(&mut self) -> Option<(A::Item, B::Item)> { 5,194,753 ( 0.13%) if self.index < self.len { . let i = self.index; . // since get_unchecked executes code which can panic we increment the counters beforehand . // so that the same index won't be accessed twice, as required by TrustedRandomAccess 8,465,832 ( 0.22%) self.index += 1; . // SAFETY: `i` is smaller than `self.len`, thus smaller than `self.a.len()` and `self.b.len()` . unsafe { 102 ( 0.00%) Some((self.a.__iterator_get_unchecked(i), self.b.__iterator_get_unchecked(i))) . } 12 ( 0.00%) } else if A::MAY_HAVE_SIDE_EFFECT && self.index < self.a_len { . let i = self.index; . // as above, increment before executing code that may panic . self.index += 1; . self.len += 1; . // match the base implementation's potential side effects . // SAFETY: we just checked that `i` < `self.a.len()` . unsafe { . self.a.__iterator_get_unchecked(i); -- line 288 ---------------------------------------- -- line 290 ---------------------------------------- . None . } else { . None . } . } . . #[inline] . fn size_hint(&self) -> (usize, Option) { 36,513 ( 0.00%) let len = self.len - self.index; . (len, Some(len)) . } . . #[inline] . fn nth(&mut self, n: usize) -> Option { . let delta = cmp::min(n, self.len - self.index); . let end = self.index + delta; . while self.index < end { -- line 306 ---------------------------------------- -- line 535 ---------------------------------------- . #[unstable(feature = "trusted_random_access", issue = "none")] . #[rustc_specialization_trait] . pub unsafe trait TrustedRandomAccessNoCoerce: Sized { . // Convenience method. . fn size(&self) -> usize . where . Self: Iterator, . { 502 ( 0.00%) self.size_hint().0 . } . /// `true` if getting an iterator element may have side effects. . /// Remember to take inner iterators into account. . const MAY_HAVE_SIDE_EFFECT: bool; . } . . /// Like `Iterator::__iterator_get_unchecked`, but doesn't require the compiler to . /// know that `U: TrustedRandomAccess`. -- line 551 ---------------------------------------- -- line 555 ---------------------------------------- . /// Same requirements calling `get_unchecked` directly. . #[doc(hidden)] . pub(in crate::iter::adapters) unsafe fn try_get_unchecked(it: &mut I, idx: usize) -> I::Item . where . I: Iterator, . { . // SAFETY: the caller must uphold the contract for . // `Iterator::__iterator_get_unchecked`. 3,693 ( 0.00%) unsafe { it.try_get_unchecked(idx) } . } . . unsafe trait SpecTrustedRandomAccess: Iterator { . /// If `Self: TrustedRandomAccess`, it must be safe to call . /// `Iterator::__iterator_get_unchecked(self, index)`. . unsafe fn try_get_unchecked(&mut self, index: usize) -> Self::Item; . } . -- line 571 ---------------------------------------- 335,559 ( 0.01%) -------------------------------------------------------------------------------- -- Auto-annotated source: /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_span/src/caching_source_map_view.rs -------------------------------------------------------------------------------- Ir -- line 27 ---------------------------------------- . impl CacheEntry { . #[inline] . fn update( . &mut self, . new_file_and_idx: Option<(Lrc, usize)>, . pos: BytePos, . time_stamp: usize, . ) { 12,917 ( 0.00%) if let Some((file, file_idx)) = new_file_and_idx { 1,735 ( 0.00%) self.file = file; 1,307 ( 0.00%) self.file_index = file_idx; . } . 11,998 ( 0.00%) let line_index = self.file.lookup_line(pos).unwrap(); . let line_bounds = self.file.line_bounds(line_index); 26,024 ( 0.00%) self.line_number = line_index + 1; 39,444 ( 0.00%) self.line = line_bounds; . self.touch(time_stamp); . } . . #[inline] . fn touch(&mut self, time_stamp: usize) { 281,861 ( 0.01%) self.time_stamp = time_stamp; . } . } . . #[derive(Clone)] . pub struct CachingSourceMapView<'sm> { . source_map: &'sm SourceMap, . line_cache: [CacheEntry; 3], . time_stamp: usize, . } . . impl<'sm> CachingSourceMapView<'sm> { 860 ( 0.00%) pub fn new(source_map: &'sm SourceMap) -> CachingSourceMapView<'sm> { . let files = source_map.files(); 430 ( 0.00%) let first_file = files[0].clone(); . let entry = CacheEntry { . time_stamp: 0, . line_number: 0, . line: BytePos(0)..BytePos(0), . file: first_file, . file_index: 0, . }; . 2,150 ( 0.00%) CachingSourceMapView { . source_map, 3,010 ( 0.00%) line_cache: [entry.clone(), entry.clone(), entry], . time_stamp: 0, . } 1,720 ( 0.00%) } . . pub fn byte_pos_to_line_and_col( . &mut self, . pos: BytePos, . ) -> Option<(Lrc, usize, BytePos)> { . self.time_stamp += 1; . . // Check if the position is in one of the cached lines -- line 85 ---------------------------------------- -- line 106 ---------------------------------------- . }; . . let cache_entry = &mut self.line_cache[oldest]; . cache_entry.update(new_file_and_idx, pos, self.time_stamp); . . Some((cache_entry.file.clone(), cache_entry.line_number, pos - cache_entry.line.start)) . } . 1,029,532 ( 0.03%) pub fn span_data_to_lines_and_cols( . &mut self, . span_data: &SpanData, . ) -> Option<(Lrc, usize, BytePos, usize, BytePos)> { 588,304 ( 0.01%) self.time_stamp += 1; . . // Check if lo and hi are in the cached lines. 147,076 ( 0.00%) let lo_cache_idx = self.cache_entry_index(span_data.lo); 147,076 ( 0.00%) let hi_cache_idx = self.cache_entry_index(span_data.hi); . 269,600 ( 0.01%) if lo_cache_idx != -1 && hi_cache_idx != -1 { . // Cache hit for span lo and hi. Check if they belong to the same file. . let result = { 269,570 ( 0.01%) let lo = &self.line_cache[lo_cache_idx as usize]; . let hi = &self.line_cache[hi_cache_idx as usize]; . 808,710 ( 0.02%) if lo.file_index != hi.file_index { . return None; . } . . ( 269,570 ( 0.01%) lo.file.clone(), . lo.line_number, . span_data.lo - lo.line.start, 134,785 ( 0.00%) hi.line_number, . span_data.hi - hi.line.start, . ) . }; . 134,785 ( 0.00%) self.line_cache[lo_cache_idx as usize].touch(self.time_stamp); 134,785 ( 0.00%) self.line_cache[hi_cache_idx as usize].touch(self.time_stamp); . 539,140 ( 0.01%) return Some(result); . } . . // No cache hit or cache hit for only one of span lo and hi. 24,552 ( 0.00%) let oldest = if lo_cache_idx != -1 || hi_cache_idx != -1 { . let avoid_idx = if lo_cache_idx != -1 { lo_cache_idx } else { hi_cache_idx }; . self.oldest_cache_entry_index_avoid(avoid_idx as usize) . } else { . self.oldest_cache_entry_index() . }; . . // If the entry doesn't point to the correct file, get the new file and index. . // Return early if the file containing beginning of span doesn't contain end of span. 98,328 ( 0.00%) let new_file_and_idx = if !file_contains(&self.line_cache[oldest].file, span_data.lo) { 1,465 ( 0.00%) let new_file_and_idx = self.file_for_position(span_data.lo)?; 1,758 ( 0.00%) if !file_contains(&new_file_and_idx.0, span_data.hi) { . return None; . } . 1,172 ( 0.00%) Some(new_file_and_idx) . } else { . let file = &self.line_cache[oldest].file; 35,994 ( 0.00%) if !file_contains(&file, span_data.hi) { . return None; . } . 35,994 ( 0.00%) None . }; . . // Update the cache entries. 61,455 ( 0.00%) let (lo_idx, hi_idx) = match (lo_cache_idx, hi_cache_idx) { . // Oldest cache entry is for span_data.lo line. . (-1, -1) => { . let lo = &mut self.line_cache[oldest]; . lo.update(new_file_and_idx, span_data.lo, self.time_stamp); . 35,889 ( 0.00%) if !lo.line.contains(&span_data.hi) { . let new_file_and_idx = Some((lo.file.clone(), lo.file_index)); . let next_oldest = self.oldest_cache_entry_index_avoid(oldest); . let hi = &mut self.line_cache[next_oldest]; . hi.update(new_file_and_idx, span_data.hi, self.time_stamp); . (oldest, next_oldest) . } else { . (oldest, oldest) . } . } . // Oldest cache entry is for span_data.lo line. . (-1, _) => { . let lo = &mut self.line_cache[oldest]; . lo.update(new_file_and_idx, span_data.lo, self.time_stamp); 30 ( 0.00%) let hi = &mut self.line_cache[hi_cache_idx as usize]; 45 ( 0.00%) hi.touch(self.time_stamp); . (oldest, hi_cache_idx as usize) . } . // Oldest cache entry is for span_data.hi line. . (_, -1) => { . let hi = &mut self.line_cache[oldest]; 313 ( 0.00%) hi.update(new_file_and_idx, span_data.hi, self.time_stamp); 626 ( 0.00%) let lo = &mut self.line_cache[lo_cache_idx as usize]; 1,252 ( 0.00%) lo.touch(self.time_stamp); . (lo_cache_idx as usize, oldest) . } . _ => { . panic!(); . } . }; . . let lo = &self.line_cache[lo_idx]; . let hi = &self.line_cache[hi_idx]; . . // Span lo and hi may equal line end when last line doesn't . // end in newline, hence the inclusive upper bounds below. 24,582 ( 0.00%) assert!(span_data.lo >= lo.line.start); 12,291 ( 0.00%) assert!(span_data.lo <= lo.line.end); 24,582 ( 0.00%) assert!(span_data.hi >= hi.line.start); 12,291 ( 0.00%) assert!(span_data.hi <= hi.line.end); 61,455 ( 0.00%) assert!(lo.file.contains(span_data.lo)); 36,873 ( 0.00%) assert!(lo.file.contains(span_data.hi)); 36,873 ( 0.00%) assert_eq!(lo.file_index, hi.file_index); . 36,873 ( 0.00%) Some(( 12,291 ( 0.00%) lo.file.clone(), . lo.line_number, . span_data.lo - lo.line.start, 12,291 ( 0.00%) hi.line_number, . span_data.hi - hi.line.start, . )) 1,323,684 ( 0.03%) } . . fn cache_entry_index(&self, pos: BytePos) -> isize { . for (idx, cache_entry) in self.line_cache.iter().enumerate() { 1,761,121 ( 0.04%) if cache_entry.line.contains(&pos) { . return idx as isize; . } . } . . -1 . } . . fn oldest_cache_entry_index(&self) -> usize { . let mut oldest = 0; . . for idx in 1..self.line_cache.len() { 71,778 ( 0.00%) if self.line_cache[idx].time_stamp < self.line_cache[oldest].time_stamp { . oldest = idx; . } . } . . oldest . } . . fn oldest_cache_entry_index_avoid(&self, avoid_idx: usize) -> usize { . let mut oldest = if avoid_idx != 0 { 0 } else { 1 }; . . for idx in 0..self.line_cache.len() { 6,771 ( 0.00%) if idx != avoid_idx 3,230 ( 0.00%) && self.line_cache[idx].time_stamp < self.line_cache[oldest].time_stamp . { . oldest = idx; . } . } . . oldest . } . 1,465 ( 0.00%) fn file_for_position(&self, pos: BytePos) -> Option<(Lrc, usize)> { 293 ( 0.00%) if !self.source_map.files().is_empty() { 586 ( 0.00%) let file_idx = self.source_map.lookup_source_file_idx(pos); . let file = &self.source_map.files()[file_idx]; . 2,344 ( 0.00%) if file_contains(file, pos) { . return Some((file.clone(), file_idx)); . } . } . . None 1,465 ( 0.00%) } . } . . #[inline] . fn file_contains(file: &SourceFile, pos: BytePos) -> bool { . // `SourceMap::lookup_source_file_idx` and `SourceFile::contains` both consider the position . // one past the end of a file to belong to it. Normally, that's what we want. But for the . // purposes of converting a byte position to a line and column number, we can't come up with a . // line and column number if the file is empty, because an empty file doesn't contain any -- line 290 ---------------------------------------- 1,691,465 ( 0.04%) -------------------------------------------------------------------------------- -- Auto-annotated source: /usr/home/liquid/rust/worktree-benchmarking/library/core/src/result.rs -------------------------------------------------------------------------------- Ir -- line 491 ---------------------------------------- . . use crate::iter::{self, FromIterator, FusedIterator, TrustedLen}; . use crate::ops::{self, ControlFlow, Deref, DerefMut}; . use crate::{convert, fmt, hint}; . . /// `Result` is a type that represents either success ([`Ok`]) or failure ([`Err`]). . /// . /// See the [module documentation](self) for details. 120 ( 0.00%) #[derive(Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)] . #[must_use = "this `Result` may be an `Err` variant, which should be handled"] . #[rustc_diagnostic_item = "Result"] . #[stable(feature = "rust1", since = "1.0.0")] . pub enum Result { . /// Contains the success value . #[lang = "Ok"] . #[stable(feature = "rust1", since = "1.0.0")] 3 ( 0.00%) Ok(#[stable(feature = "rust1", since = "1.0.0")] T), . . /// Contains the error value . #[lang = "Err"] . #[stable(feature = "rust1", since = "1.0.0")] . Err(#[stable(feature = "rust1", since = "1.0.0")] E), . } . . ///////////////////////////////////////////////////////////////////////////// -- line 515 ---------------------------------------- -- line 534 ---------------------------------------- . /// let x: Result = Err("Some error message"); . /// assert_eq!(x.is_ok(), false); . /// ``` . #[must_use = "if you intended to assert that this is ok, consider `.unwrap()` instead"] . #[rustc_const_stable(feature = "const_result", since = "1.48.0")] . #[inline] . #[stable(feature = "rust1", since = "1.0.0")] . pub const fn is_ok(&self) -> bool { 21,226 ( 0.00%) matches!(*self, Ok(_)) . } . . /// Returns `true` if the result is [`Ok`] wrapping a value matching the predicate. . /// . /// # Examples . /// . /// ``` . /// #![feature(is_some_with)] -- line 550 ---------------------------------------- -- line 628 ---------------------------------------- . /// assert_eq!(x.ok(), Some(2)); . /// . /// let x: Result = Err("Nothing here"); . /// assert_eq!(x.ok(), None); . /// ``` . #[inline] . #[stable(feature = "rust1", since = "1.0.0")] . pub fn ok(self) -> Option { 64,287 ( 0.00%) match self { 1,912 ( 0.00%) Ok(x) => Some(x), . Err(_) => None, . } . } . . /// Converts from `Result` to [`Option`]. . /// . /// Converts `self` into an [`Option`], consuming `self`, . /// and discarding the success value, if any. -- line 645 ---------------------------------------- -- line 657 ---------------------------------------- . /// ``` . #[inline] . #[stable(feature = "rust1", since = "1.0.0")] . pub fn err(self) -> Option { . match self { . Ok(_) => None, . Err(x) => Some(x), . } 4 ( 0.00%) } . . ///////////////////////////////////////////////////////////////////////// . // Adapter for working with references . ///////////////////////////////////////////////////////////////////////// . . /// Converts from `&Result` to `Result<&T, &E>`. . /// . /// Produces a new `Result`, containing a reference -- line 673 ---------------------------------------- -- line 683 ---------------------------------------- . /// . /// let x: Result = Err("Error"); . /// assert_eq!(x.as_ref(), Err(&"Error")); . /// ``` . #[inline] . #[rustc_const_stable(feature = "const_result", since = "1.48.0")] . #[stable(feature = "rust1", since = "1.0.0")] . pub const fn as_ref(&self) -> Result<&T, &E> { 62 ( 0.00%) match *self { . Ok(ref x) => Ok(x), . Err(ref x) => Err(x), . } . } . . /// Converts from `&mut Result` to `Result<&mut T, &mut E>`. . /// . /// # Examples -- line 699 ---------------------------------------- -- line 715 ---------------------------------------- . /// let mut x: Result = Err(13); . /// mutate(&mut x); . /// assert_eq!(x.unwrap_err(), 0); . /// ``` . #[inline] . #[stable(feature = "rust1", since = "1.0.0")] . #[rustc_const_unstable(feature = "const_result", issue = "82814")] . pub const fn as_mut(&mut self) -> Result<&mut T, &mut E> { 3,391,691 ( 0.09%) match *self { . Ok(ref mut x) => Ok(x), . Err(ref mut x) => Err(x), . } . } . . ///////////////////////////////////////////////////////////////////////// . // Transforming contained values . ///////////////////////////////////////////////////////////////////////// -- line 731 ---------------------------------------- -- line 747 ---------------------------------------- . /// Ok(n) => println!("{}", n), . /// Err(..) => {} . /// } . /// } . /// ``` . #[inline] . #[stable(feature = "rust1", since = "1.0.0")] . pub fn map U>(self, op: F) -> Result { 833,279 ( 0.02%) match self { 971,571 ( 0.02%) Ok(t) => Ok(op(t)), 110,088 ( 0.00%) Err(e) => Err(e), . } 90,315 ( 0.00%) } . . /// Returns the provided default (if [`Err`]), or . /// applies a function to the contained value (if [`Ok`]), . /// . /// Arguments passed to `map_or` are eagerly evaluated; if you are passing . /// the result of a function call, it is recommended to use [`map_or_else`], . /// which is lazily evaluated. . /// -- line 767 ---------------------------------------- -- line 774 ---------------------------------------- . /// assert_eq!(x.map_or(42, |v| v.len()), 3); . /// . /// let x: Result<&str, _> = Err("bar"); . /// assert_eq!(x.map_or(42, |v| v.len()), 42); . /// ``` . #[inline] . #[stable(feature = "result_map_or", since = "1.41.0")] . pub fn map_or U>(self, default: U, f: F) -> U { 10,121 ( 0.00%) match self { 108 ( 0.00%) Ok(t) => f(t), . Err(_) => default, . } . } . . /// Maps a `Result` to `U` by applying fallback function `default` to . /// a contained [`Err`] value, or function `f` to a contained [`Ok`] value. . /// . /// This function can be used to unpack a successful result -- line 791 ---------------------------------------- -- line 831 ---------------------------------------- . /// let x: Result = Ok(2); . /// assert_eq!(x.map_err(stringify), Ok(2)); . /// . /// let x: Result = Err(13); . /// assert_eq!(x.map_err(stringify), Err("error code: 13".to_string())); . /// ``` . #[inline] . #[stable(feature = "rust1", since = "1.0.0")] 125 ( 0.00%) pub fn map_err F>(self, op: O) -> Result { 1,841,234 ( 0.05%) match self { 1,593,640 ( 0.04%) Ok(t) => Ok(t), 621 ( 0.00%) Err(e) => Err(op(e)), . } 305 ( 0.00%) } . . /// Calls the provided closure with a reference to the contained value (if [`Ok`]). . /// . /// # Examples . /// . /// ``` . /// #![feature(result_option_inspect)] . /// -- line 852 ---------------------------------------- -- line 1012 ---------------------------------------- . /// ``` . #[inline] . #[track_caller] . #[stable(feature = "result_expect", since = "1.4.0")] . pub fn expect(self, msg: &str) -> T . where . E: fmt::Debug, . { 106,220 ( 0.00%) match self { 162 ( 0.00%) Ok(t) => t, . Err(e) => unwrap_failed(msg, &e), . } . } . . /// Returns the contained [`Ok`] value, consuming the `self` value. . /// . /// Because this function may panic, its use is generally discouraged. . /// Instead, prefer to use pattern matching and handle the [`Err`] -- line 1029 ---------------------------------------- -- line 1051 ---------------------------------------- . /// . /// ```should_panic . /// let x: Result = Err("emergency failure"); . /// x.unwrap(); // panics with `emergency failure` . /// ``` . #[inline] . #[track_caller] . #[stable(feature = "rust1", since = "1.0.0")] 100,992 ( 0.00%) pub fn unwrap(self) -> T . where . E: fmt::Debug, . { 1,121,747 ( 0.03%) match self { 1,271,838 ( 0.03%) Ok(t) => t, . Err(e) => unwrap_failed("called `Result::unwrap()` on an `Err` value", &e), . } 151,488 ( 0.00%) } . . /// Returns the contained [`Ok`] value or a default . /// . /// Consumes the `self` argument then, if [`Ok`], returns the contained . /// value, otherwise if [`Err`], returns the default value for that . /// type. . /// . /// # Examples -- line 1075 ---------------------------------------- -- line 1092 ---------------------------------------- . /// [`parse`]: str::parse . /// [`FromStr`]: crate::str::FromStr . #[inline] . #[stable(feature = "result_unwrap_or_default", since = "1.16.0")] . pub fn unwrap_or_default(self) -> T . where . T: Default, . { 30,724 ( 0.00%) match self { 20,443 ( 0.00%) Ok(x) => x, . Err(_) => Default::default(), . } . } . . /// Returns the contained [`Err`] value, consuming the `self` value. . /// . /// # Panics . /// -- line 1109 ---------------------------------------- -- line 1152 ---------------------------------------- . /// ``` . #[inline] . #[track_caller] . #[stable(feature = "rust1", since = "1.0.0")] . pub fn unwrap_err(self) -> E . where . T: fmt::Debug, . { 80 ( 0.00%) match self { . Ok(t) => unwrap_failed("called `Result::unwrap_err()` on an `Ok` value", &t), . Err(e) => e, . } . } . . /// Returns the contained [`Ok`] value, but never panics. . /// . /// Unlike [`unwrap`], this method is known to never panic on the -- line 1168 ---------------------------------------- -- line 1190 ---------------------------------------- . /// ``` . #[unstable(feature = "unwrap_infallible", reason = "newly added", issue = "61695")] . #[inline] . pub fn into_ok(self) -> T . where . E: Into, . { . match self { 726,781 ( 0.02%) Ok(x) => x, . Err(e) => e.into(), . } . } . . /// Returns the contained [`Err`] value, but never panics. . /// . /// Unlike [`unwrap_err`], this method is known to never panic on the . /// result types it is implemented for. Therefore, it can be used -- line 1206 ---------------------------------------- -- line 1290 ---------------------------------------- . /// assert_eq!(Ok(2).and_then(sq).and_then(sq), Ok(16)); . /// assert_eq!(Ok(2).and_then(sq).and_then(err), Err(4)); . /// assert_eq!(Ok(2).and_then(err).and_then(sq), Err(2)); . /// assert_eq!(Err(3).and_then(sq).and_then(sq), Err(3)); . /// ``` . #[inline] . #[stable(feature = "rust1", since = "1.0.0")] . pub fn and_then Result>(self, op: F) -> Result { 237,858 ( 0.01%) match self { 491,283 ( 0.01%) Ok(t) => op(t), 22,272 ( 0.00%) Err(e) => Err(e), . } . } . . /// Returns `res` if the result is [`Err`], otherwise returns the [`Ok`] value of `self`. . /// . /// Arguments passed to `or` are eagerly evaluated; if you are passing the . /// result of a function call, it is recommended to use [`or_else`], which is . /// lazily evaluated. -- line 1308 ---------------------------------------- -- line 1355 ---------------------------------------- . /// assert_eq!(Ok(2).or_else(sq).or_else(sq), Ok(2)); . /// assert_eq!(Ok(2).or_else(err).or_else(sq), Ok(2)); . /// assert_eq!(Err(3).or_else(sq).or_else(err), Ok(9)); . /// assert_eq!(Err(3).or_else(err).or_else(err), Err(3)); . /// ``` . #[inline] . #[stable(feature = "rust1", since = "1.0.0")] . pub fn or_else Result>(self, op: O) -> Result { 623,776 ( 0.02%) match self { 1,631,253 ( 0.04%) Ok(t) => Ok(t), . Err(e) => op(e), . } . } . . /// Returns the contained [`Ok`] value or a provided default. . /// . /// Arguments passed to `unwrap_or` are eagerly evaluated; if you are passing . /// the result of a function call, it is recommended to use [`unwrap_or_else`], -- line 1372 ---------------------------------------- -- line 1384 ---------------------------------------- . /// assert_eq!(x.unwrap_or(default), 9); . /// . /// let x: Result = Err("error"); . /// assert_eq!(x.unwrap_or(default), default); . /// ``` . #[inline] . #[stable(feature = "rust1", since = "1.0.0")] . pub fn unwrap_or(self, default: T) -> T { 73 ( 0.00%) match self { 15 ( 0.00%) Ok(t) => t, . Err(_) => default, . } . } . . /// Returns the contained [`Ok`] value or computes it from a closure. . /// . /// . /// # Examples -- line 1401 ---------------------------------------- -- line 1406 ---------------------------------------- . /// fn count(x: &str) -> usize { x.len() } . /// . /// assert_eq!(Ok(2).unwrap_or_else(count), 2); . /// assert_eq!(Err("foo").unwrap_or_else(count), 3); . /// ``` . #[inline] . #[stable(feature = "rust1", since = "1.0.0")] . pub fn unwrap_or_else T>(self, op: F) -> T { 659,131 ( 0.02%) match self { 114,654 ( 0.00%) Ok(t) => t, . Err(e) => op(e), . } . } . . /// Returns the contained [`Ok`] value, consuming the `self` value, . /// without checking that the value is not an [`Err`]. . /// . /// # Safety -- line 1423 ---------------------------------------- -- line 1647 ---------------------------------------- . /// let x: Result, SomeErr> = Ok(Some(5)); . /// let y: Option> = Some(Ok(5)); . /// assert_eq!(x.transpose(), y); . /// ``` . #[inline] . #[stable(feature = "transpose_result", since = "1.33.0")] . #[rustc_const_unstable(feature = "const_result", issue = "82814")] . pub const fn transpose(self) -> Option> { 374 ( 0.00%) match self { . Ok(Some(x)) => Some(Ok(x)), . Ok(None) => None, . Err(e) => Some(Err(e)), . } . } . } . . impl Result, E> { -- line 1663 ---------------------------------------- -- line 1751 ---------------------------------------- . . ///////////////////////////////////////////////////////////////////////////// . // Trait implementations . ///////////////////////////////////////////////////////////////////////////// . . #[stable(feature = "rust1", since = "1.0.0")] . impl Clone for Result { . #[inline] 40,721 ( 0.00%) fn clone(&self) -> Self { 1,395,222 ( 0.04%) match self { 211,777 ( 0.01%) Ok(x) => Ok(x.clone()), 230,890 ( 0.01%) Err(x) => Err(x.clone()), . } 205,322 ( 0.01%) } . . #[inline] . fn clone_from(&mut self, source: &Self) { . match (self, source) { . (Ok(to), Ok(from)) => to.clone_from(from), . (Err(to), Err(from)) => to.clone_from(from), . (to, from) => *to = from.clone(), . } -- line 1772 ---------------------------------------- -- line 2011 ---------------------------------------- . /// . /// Since the third element caused an underflow, no further elements were taken, . /// so the final value of `shared` is 6 (= `3 + 2 + 1`), not 16. . #[inline] . fn from_iter>>(iter: I) -> Result { . // FIXME(#11084): This could be replaced with Iterator::scan when this . // performance bug is closed. . 371 ( 0.00%) iter::process_results(iter.into_iter(), |i| i.collect()) . } . } . . #[unstable(feature = "try_trait_v2", issue = "84277")] . #[rustc_const_unstable(feature = "const_convert", issue = "88674")] . impl const ops::Try for Result { . type Output = T; . type Residual = Result; . . #[inline] . fn from_output(output: Self::Output) -> Self { 2,170 ( 0.00%) Ok(output) . } . . #[inline] . fn branch(self) -> ControlFlow { 8,890,374 ( 0.23%) match self { 24,101,231 ( 0.61%) Ok(v) => ControlFlow::Continue(v), 38,296 ( 0.00%) Err(e) => ControlFlow::Break(Err(e)), . } . } . } . . #[unstable(feature = "try_trait_v2", issue = "84277")] . #[rustc_const_unstable(feature = "const_convert", issue = "88674")] . impl> const ops::FromResidual> . for Result . { . #[inline] . #[track_caller] . fn from_residual(residual: Result) -> Self { . match residual { 57,619 ( 0.00%) Err(e) => Err(From::from(e)), . } . } . } . . #[unstable(feature = "try_trait_v2_residual", issue = "91285")] . impl ops::Residual for Result { . type TryType = Result; . } -- line 2060 ---------------------------------------- 7,218,671 ( 0.18%) -------------------------------------------------------------------------------- -- Auto-annotated source: /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_parse/src/parser/expr.rs -------------------------------------------------------------------------------- Ir -- line 71 ---------------------------------------- . AlreadyParsed(P), . } . . impl From> for LhsExpr { . /// Converts `Some(attrs)` into `LhsExpr::AttributesParsed(attrs)` . /// and `None` into `LhsExpr::NotYetParsed`. . /// . /// This conversion does not allocate. 1 ( 0.00%) fn from(o: Option) -> Self { 86,845 ( 0.00%) if let Some(attrs) = o { LhsExpr::AttributesParsed(attrs) } else { LhsExpr::NotYetParsed } 1 ( 0.00%) } . } . . impl From> for LhsExpr { . /// Converts the `expr: P` into `LhsExpr::AlreadyParsed(expr)`. . /// . /// This conversion does not allocate. . fn from(expr: P) -> Self { . LhsExpr::AlreadyParsed(expr) -- line 89 ---------------------------------------- -- line 99 ---------------------------------------- . self.parse_expr_res(Restrictions::empty(), None) . } . . /// Parses an expression, forcing tokens to be collected . pub fn parse_expr_force_collect(&mut self) -> PResult<'a, P> { . self.collect_tokens_no_attrs(|this| this.parse_expr()) . } . 132 ( 0.00%) pub fn parse_anon_const_expr(&mut self) -> PResult<'a, AnonConst> { . self.parse_expr().map(|value| AnonConst { id: DUMMY_NODE_ID, value }) 132 ( 0.00%) } . 95,440 ( 0.00%) fn parse_expr_catch_underscore(&mut self) -> PResult<'a, P> { 23,860 ( 0.00%) match self.parse_expr() { . Ok(expr) => Ok(expr), . Err(mut err) => match self.token.ident() { . Some((Ident { name: kw::Underscore, .. }, false)) . if self.look_ahead(1, |t| t == &token::Comma) => . { . // Special-case handling of `foo(_, _, _)` . err.emit(); . self.bump(); . Ok(self.mk_expr(self.prev_token.span, ExprKind::Err, AttrVec::new())) . } . _ => Err(err), . }, . } 119,300 ( 0.00%) } . . /// Parses a sequence of expressions delimited by parentheses. . fn parse_paren_expr_seq(&mut self) -> PResult<'a, Vec>> { 61,354 ( 0.00%) self.parse_paren_comma_seq(|p| p.parse_expr_catch_underscore()).map(|(r, _)| r) . } . . /// Parses an expression, subject to the given restrictions. . #[inline] . pub(super) fn parse_expr_res( . &mut self, . r: Restrictions, . already_parsed_attrs: Option, -- line 138 ---------------------------------------- -- line 144 ---------------------------------------- . /// . /// This parses an expression accounting for associativity and precedence of the operators in . /// the expression. . #[inline] . fn parse_assoc_expr( . &mut self, . already_parsed_attrs: Option, . ) -> PResult<'a, P> { 195,993 ( 0.00%) self.parse_assoc_expr_with(0, already_parsed_attrs.into()) . } . . /// Parses an associative expression with operators of at least `min_prec` precedence. 471,753 ( 0.01%) pub(super) fn parse_assoc_expr_with( . &mut self, . min_prec: usize, . lhs: LhsExpr, . ) -> PResult<'a, P> { 262,084 ( 0.01%) let mut lhs = if let LhsExpr::AlreadyParsed(expr) = lhs { 560 ( 0.00%) expr . } else { 104,554 ( 0.00%) let attrs = match lhs { 105,179 ( 0.00%) LhsExpr::AttributesParsed(attrs) => Some(attrs), . _ => None, . }; 52,277 ( 0.00%) if [token::DotDot, token::DotDotDot, token::DotDotEq].contains(&self.token.kind) { 24 ( 0.00%) return self.parse_prefix_range_expr(attrs); . } else { 627,252 ( 0.02%) self.parse_prefix_expr(attrs)? . } . }; 104,822 ( 0.00%) let last_type_ascription_set = self.last_type_ascription.is_some(); . . if !self.should_continue_as_assoc_expr(&lhs) { 267 ( 0.00%) self.last_type_ascription = None; . return Ok(lhs); . } . . self.expected_tokens.push(TokenType::Operator); 796 ( 0.00%) while let Some(op) = self.check_assoc_op() { . // Adjust the span for interpolated LHS to point to the `$lhs` token . // and not to what it refers to. 1,194 ( 0.00%) let lhs_span = match self.prev_token.kind { . TokenKind::Interpolated(..) => self.prev_token.span, . _ => lhs.span, . }; . 398 ( 0.00%) let cur_op_span = self.token.span; 1,592 ( 0.00%) let restrictions = if op.node.is_assign_like() { . self.restrictions & Restrictions::NO_STRUCT_LITERAL . } else { . self.restrictions . }; 597 ( 0.00%) let prec = op.node.precedence(); 398 ( 0.00%) if prec < min_prec { . break; . } . // Check for deprecated `...` syntax 644 ( 0.00%) if self.token == token::DotDotDot && op.node == AssocOp::DotDotEq { . self.err_dotdotdot_syntax(self.token.span); . } . 644 ( 0.00%) if self.token == token::LArrow { . self.err_larrow_operator(self.token.span); . } . 161 ( 0.00%) self.bump(); 644 ( 0.00%) if op.node.is_comparison() { . if let Some(expr) = self.check_no_chained_comparison(&lhs, &op)? { . return Ok(expr); . } . } . . // Look for JS' `===` and `!==` and recover 237 ( 0.00%) if (op.node == AssocOp::Equal || op.node == AssocOp::NotEqual) 76 ( 0.00%) && self.token.kind == token::Eq . && self.prev_token.span.hi() == self.token.span.lo() . { . let sp = op.span.to(self.token.span); . let sugg = match op.node { . AssocOp::Equal => "==", . AssocOp::NotEqual => "!=", . _ => unreachable!(), . }; -- line 226 ---------------------------------------- -- line 231 ---------------------------------------- . sugg.to_string(), . Applicability::MachineApplicable, . ) . .emit(); . self.bump(); . } . . // Look for PHP's `<>` and recover 52 ( 0.00%) if op.node == AssocOp::Less 14 ( 0.00%) && self.token.kind == token::Gt . && self.prev_token.span.hi() == self.token.span.lo() . { . let sp = op.span.to(self.token.span); . self.struct_span_err(sp, "invalid comparison operator `<>`") . .span_suggestion_short( . sp, . "`<>` is not a valid comparison operator, use `!=`", . "!=".to_string(), . Applicability::MachineApplicable, . ) . .emit(); . self.bump(); . } . . // Look for C++'s `<=>` and recover 12 ( 0.00%) if op.node == AssocOp::LessEqual 12 ( 0.00%) && self.token.kind == token::Gt . && self.prev_token.span.hi() == self.token.span.lo() . { . let sp = op.span.to(self.token.span); . self.struct_span_err(sp, "invalid comparison operator `<=>`") . .span_label( . sp, . "`<=>` is not a valid comparison operator, use `std::cmp::Ordering`", . ) . .emit(); . self.bump(); . } . 322 ( 0.00%) let op = op.node; . // Special cases: . if op == AssocOp::As { 60 ( 0.00%) lhs = self.parse_assoc_op_cast(lhs, lhs_span, ExprKind::Cast)?; . continue; . } else if op == AssocOp::Colon { . lhs = self.parse_assoc_op_ascribe(lhs, lhs_span)?; . continue; . } else if op == AssocOp::DotDot || op == AssocOp::DotDotEq { . // If we didn’t have to handle `x..`/`x..=`, it would be pretty easy to . // generalise it to the Fixity::None code. 48 ( 0.00%) lhs = self.parse_range_expr(prec, lhs, op, cur_op_span)?; . break; . } . 137 ( 0.00%) let fixity = op.fixity(); 411 ( 0.00%) let prec_adjustment = match fixity { . Fixity::Right => 0, . Fixity::Left => 1, . // We currently have no non-associative operators that are not handled above by . // the special cases. The code is here only for future convenience. . Fixity::None => 1, . }; 274 ( 0.00%) let rhs = self.with_res(restrictions - Restrictions::STMT_EXPR, |this| { 685 ( 0.00%) this.parse_assoc_expr_with(prec + prec_adjustment, LhsExpr::NotYetParsed) . })?; . . let span = self.mk_expr_sp(&lhs, lhs_span, rhs.span); 1,274 ( 0.00%) lhs = match op { . AssocOp::Add . | AssocOp::Subtract . | AssocOp::Multiply . | AssocOp::Divide . | AssocOp::Modulus . | AssocOp::LAnd . | AssocOp::LOr . | AssocOp::BitXor -- line 306 ---------------------------------------- -- line 309 ---------------------------------------- . | AssocOp::ShiftLeft . | AssocOp::ShiftRight . | AssocOp::Equal . | AssocOp::Less . | AssocOp::LessEqual . | AssocOp::NotEqual . | AssocOp::Greater . | AssocOp::GreaterEqual => { 208 ( 0.00%) let ast_op = op.to_ast_binop().unwrap(); . let binary = self.mk_binary(source_map::respan(cur_op_span, ast_op), lhs, rhs); . self.mk_expr(span, binary, AttrVec::new()) . } . AssocOp::Assign => { . self.mk_expr(span, ExprKind::Assign(lhs, rhs, cur_op_span), AttrVec::new()) . } . AssocOp::AssignOp(k) => { . let aop = match k { -- line 325 ---------------------------------------- -- line 337 ---------------------------------------- . let aopexpr = self.mk_assign_op(source_map::respan(cur_op_span, aop), lhs, rhs); . self.mk_expr(span, aopexpr, AttrVec::new()) . } . AssocOp::As | AssocOp::Colon | AssocOp::DotDot | AssocOp::DotDotEq => { . self.span_bug(span, "AssocOp should have been handled by special case") . } . }; . 274 ( 0.00%) if let Fixity::None = fixity { . break; . } . } 52,322 ( 0.00%) if last_type_ascription_set { . self.last_type_ascription = None; . } 104,644 ( 0.00%) Ok(lhs) 890,853 ( 0.02%) } . . fn should_continue_as_assoc_expr(&mut self, lhs: &Expr) -> bool { 367,055 ( 0.01%) match (self.expr_is_complete(lhs), AssocOp::from_token(&self.token)) { . // Semi-statement forms are odd: . // See https://github.com/rust-lang/rust/issues/29071 . (true, None) => false, . (false, _) => true, // Continue parsing the expression. . // An exhaustive check is done in the following block, but these are checked first . // because they *are* ambiguous but also reasonable looking incorrect syntax, so we . // want to keep their span info to improve diagnostics in these cases in a later stage. . (true, Some(AssocOp::Multiply)) | // `{ 42 } *foo = bar;` or `{ 42 } * 3` -- line 364 ---------------------------------------- -- line 401 ---------------------------------------- . err.emit(); . } . . /// Possibly translate the current token to an associative operator. . /// The method does not advance the current token. . /// . /// Also performs recovery for `and` / `or` which are mistaken for `&&` and `||` respectively. . fn check_assoc_op(&self) -> Option> { 577,388 ( 0.01%) let (op, span) = match (AssocOp::from_token(&self.token), self.token.ident()) { . // When parsing const expressions, stop parsing when encountering `>`. . ( . Some( . AssocOp::ShiftRight . | AssocOp::Greater . | AssocOp::GreaterEqual . | AssocOp::AssignOp(token::BinOpToken::Shr), . ), . _, 4 ( 0.00%) ) if self.restrictions.contains(Restrictions::CONST_EXPR) => { . return None; . } 398 ( 0.00%) (Some(op), _) => (op, self.token.span), . (None, Some((Ident { name: sym::and, span }, false))) => { . self.error_bad_logical_op("and", "&&", "conjunction"); . (AssocOp::LAnd, span) . } . (None, Some((Ident { name: sym::or, span }, false))) => { . self.error_bad_logical_op("or", "||", "disjunction"); . (AssocOp::LOr, span) . } -- line 430 ---------------------------------------- -- line 443 ---------------------------------------- . Applicability::MachineApplicable, . ) . .note("unlike in e.g., python and PHP, `&&` and `||` are used for logical operators") . .emit(); . } . . /// Checks if this expression is a successfully parsed statement. . fn expr_is_complete(&self, e: &Expr) -> bool { 114,915 ( 0.00%) self.restrictions.contains(Restrictions::STMT_EXPR) 1,540 ( 0.00%) && !classify::expr_requires_semi_to_be_stmt(e) . } . . /// Parses `x..y`, `x..=y`, and `x..`/`x..=`. . /// The other two variants are handled in `parse_prefix_range_expr` below. . fn parse_range_expr( . &mut self, . prec: usize, . lhs: P, . op: AssocOp, . cur_op_span: Span, . ) -> PResult<'a, P> { . let rhs = if self.is_at_start_of_range_notation_rhs() { 72 ( 0.00%) Some(self.parse_assoc_expr_with(prec + 1, LhsExpr::NotYetParsed)?) . } else { 8 ( 0.00%) None . }; 16 ( 0.00%) let rhs_span = rhs.as_ref().map_or(cur_op_span, |x| x.span); . let span = self.mk_expr_sp(&lhs, lhs.span, rhs_span); . let limits = . if op == AssocOp::DotDot { RangeLimits::HalfOpen } else { RangeLimits::Closed }; 36 ( 0.00%) let range = self.mk_range(Some(lhs), rhs, limits); . Ok(self.mk_expr(span, range, AttrVec::new())) . } . . fn is_at_start_of_range_notation_rhs(&self) -> bool { 78 ( 0.00%) if self.token.can_begin_expr() { . // Parse `for i in 1.. { }` as infinite loop, not as `for i in (1..{})`. 70 ( 0.00%) if self.token == token::OpenDelim(token::Brace) { . return !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL); . } . true . } else { . false . } . } . . /// Parses prefix-forms of range notation: `..expr`, `..`, `..=expr`. . fn parse_prefix_range_expr(&mut self, attrs: Option) -> PResult<'a, P> { . // Check for deprecated `...` syntax. 30 ( 0.00%) if self.token == token::DotDotDot { . self.err_dotdotdot_syntax(self.token.span); . } . . debug_assert!( . [token::DotDot, token::DotDotDot, token::DotDotEq].contains(&self.token.kind), . "parse_prefix_range_expr: token {:?} is not DotDot/DotDotEq", . self.token . ); . 18 ( 0.00%) let limits = match self.token.kind { . token::DotDot => RangeLimits::HalfOpen, . _ => RangeLimits::Closed, . }; 12 ( 0.00%) let op = AssocOp::from_token(&self.token); . // FIXME: `parse_prefix_range_expr` is called when the current . // token is `DotDot`, `DotDotDot`, or `DotDotEq`. If we haven't already . // parsed attributes, then trying to parse them here will always fail. . // We should figure out how we want attributes on range expressions to work. 24 ( 0.00%) let attrs = self.parse_or_use_outer_attributes(attrs)?; . self.collect_tokens_for_expr(attrs, |this, attrs| { 12 ( 0.00%) let lo = this.token.span; 12 ( 0.00%) this.bump(); . let (span, opt_end) = if this.is_at_start_of_range_notation_rhs() { . // RHS must be parsed with more associativity than the dots. 60 ( 0.00%) this.parse_assoc_expr_with(op.unwrap().precedence() + 1, LhsExpr::NotYetParsed) 30 ( 0.00%) .map(|x| (lo.to(x.span), Some(x)))? . } else { . (lo, None) . }; 18 ( 0.00%) let range = this.mk_range(None, opt_end, limits); 42 ( 0.00%) Ok(this.mk_expr(span, range, attrs.into())) . }) . } . . /// Parses a prefix-unary-operator expr. 366,338 ( 0.01%) fn parse_prefix_expr(&mut self, attrs: Option) -> PResult<'a, P> { 418,672 ( 0.01%) let attrs = self.parse_or_use_outer_attributes(attrs)?; 261,670 ( 0.01%) let lo = self.token.span; . . macro_rules! make_it { . ($this:ident, $attrs:expr, |this, _| $body:expr) => { 548 ( 0.00%) $this.collect_tokens_for_expr($attrs, |$this, attrs| { 786 ( 0.00%) let (hi, ex) = $body?; 1,008 ( 0.00%) Ok($this.mk_expr(lo.to(hi), ex, attrs.into())) 611 ( 0.00%) }) . }; . } . . let this = self; . . // Note: when adding new unary operators, don't forget to adjust TokenKind::can_begin_expr() 314,272 ( 0.01%) match this.token.uninterpolate().kind { 15 ( 0.00%) token::Not => make_it!(this, attrs, |this, _| this.parse_unary_expr(lo, UnOp::Not)), // `!expr` . token::Tilde => make_it!(this, attrs, |this, _| this.recover_tilde_expr(lo)), // `~expr` . token::BinOp(token::Minus) => { . make_it!(this, attrs, |this, _| this.parse_unary_expr(lo, UnOp::Neg)) . } // `-expr` . token::BinOp(token::Star) => { 4 ( 0.00%) make_it!(this, attrs, |this, _| this.parse_unary_expr(lo, UnOp::Deref)) . } // `*expr` . token::BinOp(token::And) | token::AndAnd => { 88 ( 0.00%) make_it!(this, attrs, |this, _| this.parse_borrow_expr(lo)) . } . token::BinOp(token::Plus) if this.look_ahead(1, |tok| tok.is_numeric_lit()) => { . let mut err = this.struct_span_err(lo, "leading `+` is not supported"); . err.span_label(lo, "unexpected `+`"); . . // a block on the LHS might have been intended to be an expression instead . if let Some(sp) = this.sess.ambiguous_block_expr_parse.borrow().get(&lo) { . this.sess.expr_parentheses_needed(&mut err, *sp); -- line 562 ---------------------------------------- -- line 568 ---------------------------------------- . Applicability::MachineApplicable, . ); . } . err.emit(); . . this.bump(); . this.parse_prefix_expr(None) . } // `+expr` 42,236 ( 0.00%) token::Ident(..) if this.token.is_keyword(kw::Box) => { . make_it!(this, attrs, |this, _| this.parse_box_expr(lo)) . } . token::Ident(..) if this.is_mistaken_not_ident_negation() => { . make_it!(this, attrs, |this, _| this.recover_not_expr(lo)) . } . _ => return this.parse_dot_or_call_expr(Some(attrs)), . } 523,340 ( 0.01%) } . . fn parse_prefix_expr_common(&mut self, lo: Span) -> PResult<'a, (Span, P)> { 38 ( 0.00%) self.bump(); 76 ( 0.00%) let expr = self.parse_prefix_expr(None); 19 ( 0.00%) let (span, expr) = self.interpolated_or_expr_span(expr)?; 38 ( 0.00%) Ok((lo.to(span), expr)) . } . . fn parse_unary_expr(&mut self, lo: Span, op: UnOp) -> PResult<'a, (Span, ExprKind)> { . let (span, expr) = self.parse_prefix_expr_common(lo)?; . Ok((span, self.mk_unary(op, expr))) . } . . // Recover on `!` suggesting for bitwise negation instead. -- line 598 ---------------------------------------- -- line 619 ---------------------------------------- . fn is_mistaken_not_ident_negation(&self) -> bool { . let token_cannot_continue_expr = |t: &Token| match t.uninterpolate().kind { . // These tokens can start an expression after `!`, but . // can't continue an expression after an ident . token::Ident(name, is_raw) => token::ident_can_begin_expr(name, t.span, is_raw), . token::Literal(..) | token::Pound => true, . _ => t.is_whole_expr(), . }; 42,236 ( 0.00%) self.token.is_ident_named(sym::not) && self.look_ahead(1, token_cannot_continue_expr) . } . . /// Recover on `not expr` in favor of `!expr`. . fn recover_not_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> { . // Emit the error... . let not_token = self.look_ahead(1, |t| t.clone()); . self.struct_span_err( . not_token.span, -- line 635 ---------------------------------------- -- line 651 ---------------------------------------- . . /// Returns the span of expr, if it was not interpolated or the span of the interpolated token. . fn interpolated_or_expr_span( . &self, . expr: PResult<'a, P>, . ) -> PResult<'a, (Span, P)> { . expr.map(|e| { . ( 209,399 ( 0.01%) match self.prev_token.kind { . TokenKind::Interpolated(..) => self.prev_token.span, . _ => e.span, . }, . e, . ) . }) . } . 168 ( 0.00%) fn parse_assoc_op_cast( . &mut self, . lhs: P, . lhs_span: Span, . expr_kind: fn(P, P) -> ExprKind, . ) -> PResult<'a, P> { . let mk_expr = |this: &mut Self, lhs: P, rhs: P| { . this.mk_expr( . this.mk_expr_sp(&lhs, lhs_span, rhs.span), 36 ( 0.00%) expr_kind(lhs, rhs), . AttrVec::new(), . ) . }; . . // Save the state of the parser before parsing type normally, in case there is a . // LessThan comparison after this cast. 24 ( 0.00%) let parser_snapshot_before_type = self.clone(); 36 ( 0.00%) let cast_expr = match self.parse_as_cast_ty() { . Ok(rhs) => mk_expr(self, lhs, rhs), . Err(mut type_err) => { . // Rewind to before attempting to parse the type with generics, to recover . // from situations like `x as usize < y` in which we first tried to parse . // `usize < y` as a type with generic arguments. . let parser_snapshot_after_type = mem::replace(self, parser_snapshot_before_type); . . // Check for typo of `'a: loop { break 'a }` with a missing `'`. -- line 693 ---------------------------------------- -- line 779 ---------------------------------------- . *self = parser_snapshot_after_type; . return Err(type_err); . } . } . } . }; . . self.parse_and_disallow_postfix_after_cast(cast_expr) 144 ( 0.00%) } . . /// Parses a postfix operators such as `.`, `?`, or index (`[]`) after a cast, . /// then emits an error and returns the newly parsed tree. . /// The resulting parse tree for `&x as T[0]` has a precedence of `((&x) as T)[0]`. . fn parse_and_disallow_postfix_after_cast( . &mut self, . cast_expr: P, . ) -> PResult<'a, P> { . // Save the memory location of expr before parsing any following postfix operators. . // This will be compared with the memory location of the output expression. . // If they different we can assume we parsed another expression because the existing expression is not reallocated. . let addr_before = &*cast_expr as *const _ as usize; . let span = cast_expr.span; 72 ( 0.00%) let with_postfix = self.parse_dot_or_call_expr_with_(cast_expr, span)?; . let changed = addr_before != &*with_postfix as *const _ as usize; . . // Check if an illegal postfix operator has been added after the cast. . // If the resulting expression is not a cast, or has a different memory location, it is an illegal postfix operator. 72 ( 0.00%) if !matches!(with_postfix.kind, ExprKind::Cast(_, _) | ExprKind::Type(_, _)) || changed { . let msg = format!( . "casts cannot be followed by {}", . match with_postfix.kind { . ExprKind::Index(_, _) => "indexing", . ExprKind::Try(_) => "`?`", . ExprKind::Field(_, _) => "a field access", . ExprKind::MethodCall(_, _, _) => "a method call", . ExprKind::Call(_, _) => "a function call", -- line 814 ---------------------------------------- -- line 844 ---------------------------------------- . let lhs = self.parse_assoc_op_cast(lhs, lhs_span, ExprKind::Type)?; . self.sess.gated_spans.gate(sym::type_ascription, lhs.span); . Ok(lhs) . } . . /// Parse `& mut? ` or `& raw [ const | mut ] `. . fn parse_borrow_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> { . self.expect_and()?; 220 ( 0.00%) let has_lifetime = self.token.is_lifetime() && self.look_ahead(1, |t| t != &token::Colon); . let lifetime = has_lifetime.then(|| self.expect_lifetime()); // For recovery, see below. . let (borrow_kind, mutbl) = self.parse_borrow_modifiers(lo); 176 ( 0.00%) let expr = self.parse_prefix_expr(None); 88 ( 0.00%) let (hi, expr) = self.interpolated_or_expr_span(expr)?; 44 ( 0.00%) let span = lo.to(hi); 88 ( 0.00%) if let Some(lt) = lifetime { . self.error_remove_borrow_lifetime(span, lt.ident.span); . } . Ok((span, ExprKind::AddrOf(borrow_kind, mutbl, expr))) . } . . fn error_remove_borrow_lifetime(&self, span: Span, lt_span: Span) { . self.struct_span_err(span, "borrow expressions cannot be annotated with lifetimes") . .span_label(lt_span, "annotated with lifetime here") -- line 866 ---------------------------------------- -- line 870 ---------------------------------------- . String::new(), . Applicability::MachineApplicable, . ) . .emit(); . } . . /// Parse `mut?` or `raw [ const | mut ]`. . fn parse_borrow_modifiers(&mut self, lo: Span) -> (ast::BorrowKind, ast::Mutability) { 88 ( 0.00%) if self.check_keyword(kw::Raw) && self.look_ahead(1, Token::is_mutability) { . // `raw [ const | mut ]`. . let found_raw = self.eat_keyword(kw::Raw); . assert!(found_raw); . let mutability = self.parse_const_or_mut().unwrap(); . self.sess.gated_spans.gate(sym::raw_ref_op, lo.to(self.prev_token.span)); . (ast::BorrowKind::Raw, mutability) . } else { . // `mut?` -- line 886 ---------------------------------------- -- line 889 ---------------------------------------- . } . . /// Parses `a.b` or `a(13)` or `a[4]` or just `a`. . fn parse_dot_or_call_expr(&mut self, attrs: Option) -> PResult<'a, P> { . let attrs = self.parse_or_use_outer_attributes(attrs)?; . self.collect_tokens_for_expr(attrs, |this, attrs| { . let base = this.parse_bottom_expr(); . let (span, base) = this.interpolated_or_expr_span(base)?; 209,084 ( 0.01%) this.parse_dot_or_call_expr_with(base, span, attrs) . }) . } . . pub(super) fn parse_dot_or_call_expr_with( . &mut self, . e0: P, . lo: Span, . mut attrs: Vec, . ) -> PResult<'a, P> { . // Stitch the list of outer attributes onto the return value. . // A little bit ugly, but the best way given the current code . // structure 366,877 ( 0.01%) self.parse_dot_or_call_expr_with_(e0, lo).map(|expr| { 366,877 ( 0.01%) expr.map(|mut expr| { 52,411 ( 0.00%) attrs.extend::>(expr.attrs.into()); 104,822 ( 0.00%) expr.attrs = attrs.into(); 733,754 ( 0.02%) expr . }) . }) . } . 1,625,113 ( 0.04%) fn parse_dot_or_call_expr_with_(&mut self, mut e: P, lo: Span) -> PResult<'a, P> { . loop { . if self.eat(&token::Question) { . // `expr?` 12 ( 0.00%) e = self.mk_expr(lo.to(self.prev_token.span), ExprKind::Try(e), AttrVec::new()); . continue; . } . if self.eat(&token::Dot) { . // expr.f 1,128 ( 0.00%) e = self.parse_dot_suffix_expr(lo, e)?; . continue; . } 670 ( 0.00%) if self.expr_is_complete(&e) { . return Ok(e); . } 196,029 ( 0.00%) e = match self.token.kind { 30,132 ( 0.00%) token::OpenDelim(token::Paren) => self.parse_fn_call_expr(lo, e), 74 ( 0.00%) token::OpenDelim(token::Bracket) => self.parse_index_expr(lo, e)?, 52,334 ( 0.00%) _ => return Ok(e), . } . } 471,807 ( 0.01%) } . . fn look_ahead_type_ascription_as_field(&mut self) -> bool { 50,305 ( 0.00%) self.look_ahead(1, |t| t.is_ident()) . && self.look_ahead(2, |t| t == &token::Colon) . && self.look_ahead(3, |t| t.can_begin_expr()) . } . . fn parse_dot_suffix_expr(&mut self, lo: Span, base: P) -> PResult<'a, P> { 3,165 ( 0.00%) match self.token.uninterpolate().kind { . token::Ident(..) => self.parse_dot_suffix(base, lo), 54 ( 0.00%) token::Literal(token::Lit { kind: token::Integer, symbol, suffix }) => { 81 ( 0.00%) Ok(self.parse_tuple_field_access_expr(lo, base, symbol, suffix, None)) . } . token::Literal(token::Lit { kind: token::Float, symbol, suffix }) => { . Ok(self.parse_tuple_field_access_expr_float(lo, base, symbol, suffix)) . } . _ => { . self.error_unexpected_after_dot(); . Ok(base) . } -- line 960 ---------------------------------------- -- line 1071 ---------------------------------------- . // See the FIXME about `TokenCursor` above. . self.error_unexpected_after_dot(); . base . } . _ => panic!("unexpected components in a float token: {:?}", components), . } . } . 117 ( 0.00%) fn parse_tuple_field_access_expr( . &mut self, . lo: Span, . base: P, . field: Symbol, . suffix: Option, . next_token: Option<(Token, Spacing)>, . ) -> P { 18 ( 0.00%) match next_token { . Some(next_token) => self.bump_with(next_token), 27 ( 0.00%) None => self.bump(), . } 9 ( 0.00%) let span = self.prev_token.span; 36 ( 0.00%) let field = ExprKind::Field(base, Ident::new(field, span)); 54 ( 0.00%) self.expect_no_suffix(span, "a tuple index", suffix); 27 ( 0.00%) self.mk_expr(lo.to(span), field, AttrVec::new()) 72 ( 0.00%) } . . /// Parse a function call expression, `expr(...)`. . fn parse_fn_call_expr(&mut self, lo: Span, fun: P) -> P { 50,220 ( 0.00%) let snapshot = if self.token.kind == token::OpenDelim(token::Paren) . && self.look_ahead_type_ascription_as_field() . { . Some((self.clone(), fun.kind.clone())) . } else { 30,132 ( 0.00%) None . }; 10,044 ( 0.00%) let open_paren = self.token.span; . 20,088 ( 0.00%) let mut seq = self.parse_paren_expr_seq().map(|args| { 30,132 ( 0.00%) self.mk_expr(lo.to(self.prev_token.span), self.mk_call(fun, args), AttrVec::new()) . }); . if let Some(expr) = . self.maybe_recover_struct_lit_bad_delims(lo, open_paren, &mut seq, snapshot) . { . return expr; . } 50,220 ( 0.00%) self.recover_seq_parse_error(token::Paren, lo, seq) . } . . /// If we encounter a parser state that looks like the user has written a `struct` literal with . /// parentheses instead of braces, recover the parser state and provide suggestions. . #[instrument(skip(self, seq, snapshot), level = "trace")] . fn maybe_recover_struct_lit_bad_delims( . &mut self, . lo: Span, . open_paren: Span, . seq: &mut PResult<'a, P>, . snapshot: Option<(Self, ExprKind)>, . ) -> Option> { 100,440 ( 0.00%) match (seq.as_mut(), snapshot) { . (Err(ref mut err), Some((mut snapshot, ExprKind::Path(None, path)))) => { . let name = pprust::path_to_string(&path); . snapshot.bump(); // `(` . match snapshot.parse_struct_fields(path, false, token::Paren) { . Ok((fields, ..)) if snapshot.eat(&token::CloseDelim(token::Paren)) => { . // We are certain we have `Enum::Foo(a: 3, b: 4)`, suggest . // `Enum::Foo { a: 3, b: 4 }` or `Enum::Foo(3, 4)`. . *self = snapshot; -- line 1137 ---------------------------------------- -- line 1165 ---------------------------------------- . } . return Some(self.mk_expr_err(span)); . } . Ok(_) => {} . Err(mut err) => err.emit(), . } . } . _ => {} 30,132 ( 0.00%) } . None . } . . /// Parse an indexing expression `expr[...]`. . fn parse_index_expr(&mut self, lo: Span, base: P) -> PResult<'a, P> { 74 ( 0.00%) self.bump(); // `[` 74 ( 0.00%) let index = self.parse_expr()?; 111 ( 0.00%) self.expect(&token::CloseDelim(token::Bracket))?; 111 ( 0.00%) Ok(self.mk_expr(lo.to(self.prev_token.span), self.mk_index(base, index), AttrVec::new())) . } . . /// Assuming we have just parsed `.`, continue parsing into an expression. . fn parse_dot_suffix(&mut self, self_arg: P, lo: Span) -> PResult<'a, P> { 546 ( 0.00%) if self.token.uninterpolated_span().rust_2018() && self.eat_keyword(kw::Await) { . return Ok(self.mk_await_expr(self_arg, lo)); . } . 273 ( 0.00%) let fn_span_lo = self.token.span; 1,638 ( 0.00%) let mut segment = self.parse_path_segment(PathStyle::Expr, None)?; 1,365 ( 0.00%) self.check_trailing_angle_brackets(&segment, &[&token::OpenDelim(token::Paren)]); . self.check_turbofish_missing_angle_brackets(&mut segment); . 1,365 ( 0.00%) if self.check(&token::OpenDelim(token::Paren)) { . // Method call `expr.f()` 212 ( 0.00%) let mut args = self.parse_paren_expr_seq()?; 848 ( 0.00%) args.insert(0, self_arg); . 636 ( 0.00%) let fn_span = fn_span_lo.to(self.prev_token.span); 636 ( 0.00%) let span = lo.to(self.prev_token.span); 1,060 ( 0.00%) Ok(self.mk_expr(span, ExprKind::MethodCall(segment, args, fn_span), AttrVec::new())) . } else { . // Field access `expr.f` 122 ( 0.00%) if let Some(args) = segment.args { . self.struct_span_err( . args.span(), . "field expressions cannot have generic arguments", . ) . .emit(); . } . 183 ( 0.00%) let span = lo.to(self.prev_token.span); 305 ( 0.00%) Ok(self.mk_expr(span, ExprKind::Field(self_arg, segment.ident), AttrVec::new())) . } . } . . /// At the bottom (top?) of the precedence hierarchy, . /// Parses things like parenthesized exprs, macros, `return`, etc. . /// . /// N.B., this does not parse outer attributes, and is private because it only works . /// correctly if called from `parse_dot_or_call_expr()`. . fn parse_bottom_expr(&mut self) -> PResult<'a, P> { 135,147 ( 0.00%) maybe_recover_from_interpolated_ty_qpath!(self, true); 156,813 ( 0.00%) maybe_whole_expr!(self); . . // Outer attributes are already parsed and will be . // added to the return value after the fact. . // . // Therefore, prevent sub-parser from parsing . // attributes by giving them an empty "already-parsed" list. 52,271 ( 0.00%) let attrs = AttrVec::new(); . . // Note: when adding new syntax here, don't forget to adjust `TokenKind::can_begin_expr()`. 21,425 ( 0.00%) let lo = self.token.span; 156,813 ( 0.00%) if let token::Literal(_) = self.token.kind { . // This match arm is a special-case of the `_` match arm below and . // could be removed without changing functionality, but it's faster . // to have it here, especially for programs with large constants. 123,384 ( 0.00%) self.parse_lit_expr(attrs) 107,125 ( 0.00%) } else if self.check(&token::OpenDelim(token::Paren)) { 2,676 ( 0.00%) self.parse_tuple_parens_expr(attrs) 102,665 ( 0.00%) } else if self.check(&token::OpenDelim(token::Brace)) { 96 ( 0.00%) self.parse_block_expr(None, lo, BlockCheckMode::Default, attrs) 205,115 ( 0.01%) } else if self.check(&token::BinOp(token::Or)) || self.check(&token::OrOr) { 76 ( 0.00%) self.parse_closure_expr(attrs) 102,510 ( 0.00%) } else if self.check(&token::OpenDelim(token::Bracket)) { 49,715 ( 0.00%) self.parse_array_or_repeat_expr(attrs, token::Bracket) 42,236 ( 0.00%) } else if self.check_path() { 41,632 ( 0.00%) self.parse_path_start_expr(attrs) 1,510 ( 0.00%) } else if self.check_keyword(kw::Move) || self.check_keyword(kw::Static) { . self.parse_closure_expr(attrs) 755 ( 0.00%) } else if self.eat_keyword(kw::If) { 268 ( 0.00%) self.parse_if_expr(attrs) 420 ( 0.00%) } else if self.check_keyword(kw::For) { 25 ( 0.00%) if self.choose_generics_over_qpath(1) { . // NOTE(Centril, eddyb): DO NOT REMOVE! Beyond providing parser recovery, . // this is an insurance policy in case we allow qpaths in (tuple-)struct patterns. . // When `for ::Proj in $expr $block` is wanted, . // you can disambiguate in favor of a pattern with `(...)`. . self.recover_quantified_closure_expr(attrs) . } else { 25 ( 0.00%) assert!(self.eat_keyword(kw::For)); 35 ( 0.00%) self.parse_for_expr(None, self.prev_token.span, attrs) . } 395 ( 0.00%) } else if self.eat_keyword(kw::While) { 14 ( 0.00%) self.parse_while_expr(None, self.prev_token.span, attrs) 308 ( 0.00%) } else if let Some(label) = self.eat_label() { . self.parse_labeled_expr(label, attrs, true) 385 ( 0.00%) } else if self.eat_keyword(kw::Loop) { . self.parse_loop_expr(None, self.prev_token.span, attrs) 385 ( 0.00%) } else if self.eat_keyword(kw::Continue) { . let kind = ExprKind::Continue(self.eat_label()); . Ok(self.mk_expr(lo.to(self.prev_token.span), kind, attrs)) 308 ( 0.00%) } else if self.eat_keyword(kw::Match) { 10 ( 0.00%) let match_sp = self.prev_token.span; 40 ( 0.00%) self.parse_match_expr(attrs).map_err(|mut err| { . err.span_label(match_sp, "while parsing this match expression"); . err . }) 288 ( 0.00%) } else if self.eat_keyword(kw::Unsafe) { 24 ( 0.00%) self.parse_block_expr(None, lo, BlockCheckMode::Unsafe(ast::UserProvided), attrs) 276 ( 0.00%) } else if self.check_inline_const(0) { . self.parse_const_block(lo.to(self.token.span), false) 207 ( 0.00%) } else if self.is_do_catch_block() { . self.recover_do_catch(attrs) 207 ( 0.00%) } else if self.is_try_block() { . self.expect_keyword(kw::Try)?; . self.parse_try_block(lo, attrs) 276 ( 0.00%) } else if self.eat_keyword(kw::Return) { 112 ( 0.00%) self.parse_return_expr(attrs) 164 ( 0.00%) } else if self.eat_keyword(kw::Break) { . self.parse_break_expr(attrs) 164 ( 0.00%) } else if self.eat_keyword(kw::Yield) { . self.parse_yield_expr(attrs) 164 ( 0.00%) } else if self.eat_keyword(kw::Let) { 100 ( 0.00%) self.parse_let_expr(attrs) 64 ( 0.00%) } else if self.eat_keyword(kw::Underscore) { . Ok(self.mk_expr(self.prev_token.span, ExprKind::Underscore, attrs)) 16 ( 0.00%) } else if !self.unclosed_delims.is_empty() && self.check(&token::Semi) { . // Don't complain about bare semicolons after unclosed braces . // recovery in order to keep the error count down. Fixing the . // delimiters will possibly also fix the bare semicolon found in . // expression context. For example, silence the following error: . // . // error: expected expression, found `;` . // --> file.rs:2:13 . // | . // 2 | foo(bar(; . // | ^ expected expression . self.bump(); . Ok(self.mk_expr_err(self.token.span)) 32 ( 0.00%) } else if self.token.uninterpolated_span().rust_2018() { . // `Span::rust_2018()` is somewhat expensive; don't get it repeatedly. 64 ( 0.00%) if self.check_keyword(kw::Async) { . if self.is_async_block() { . // Check for `async {` and `async move {`. . self.parse_async_block(attrs) . } else { . self.parse_closure_expr(attrs) . } 64 ( 0.00%) } else if self.eat_keyword(kw::Await) { . self.recover_incorrect_await_syntax(lo, self.prev_token.span, attrs) . } else { 64 ( 0.00%) self.parse_lit_expr(attrs) . } . } else { . self.parse_lit_expr(attrs) . } . } . 308,620 ( 0.01%) fn parse_lit_expr(&mut self, attrs: AttrVec) -> PResult<'a, P> { 61,724 ( 0.00%) let lo = self.token.span; 123,448 ( 0.00%) match self.parse_opt_lit() { 185,172 ( 0.00%) Some(literal) => { 277,758 ( 0.01%) let expr = self.mk_expr(lo.to(self.prev_token.span), ExprKind::Lit(literal), attrs); 308,620 ( 0.01%) self.maybe_recover_from_bad_qpath(expr, true) . } . None => self.try_macro_suggestion(), . } . } . . fn parse_tuple_parens_expr(&mut self, attrs: AttrVec) -> PResult<'a, P> { 1,784 ( 0.00%) let lo = self.token.span; 2,676 ( 0.00%) self.expect(&token::OpenDelim(token::Paren))?; . let (es, trailing_comma) = match self.parse_seq_to_end( . &token::CloseDelim(token::Paren), . SeqSep::trailing_allowed(token::Comma), 3,530 ( 0.00%) |p| p.parse_expr_catch_underscore(), . ) { . Ok(x) => x, . Err(err) => return Ok(self.recover_seq_parse_error(token::Paren, lo, Err(err))), . }; 4,460 ( 0.00%) let kind = if es.len() == 1 && !trailing_comma { . // `(e)` is parenthesized `e`. 21 ( 0.00%) ExprKind::Paren(es.into_iter().next().unwrap()) . } else { . // `(e,)` is a tuple with only one field, `e`. 4,425 ( 0.00%) ExprKind::Tup(es) . }; 2,676 ( 0.00%) let expr = self.mk_expr(lo.to(self.prev_token.span), kind, attrs); 2,676 ( 0.00%) self.maybe_recover_from_bad_qpath(expr, true) . } . 109,373 ( 0.00%) fn parse_array_or_repeat_expr( . &mut self, . attrs: AttrVec, . close_delim: token::DelimToken, . ) -> PResult<'a, P> { 29,829 ( 0.00%) let lo = self.token.span; 9,943 ( 0.00%) self.bump(); // `[` or other open delim . 29,829 ( 0.00%) let close = &token::CloseDelim(close_delim); . let kind = if self.eat(close) { . // Empty vector 1 ( 0.00%) ExprKind::Array(Vec::new()) . } else { . // Non-empty vector 19,884 ( 0.00%) let first_expr = self.parse_expr()?; . if self.eat(&token::Semi) { . // Repeating array syntax: `[ 0; 512 ]` 15 ( 0.00%) let count = self.parse_anon_const_expr()?; 10 ( 0.00%) self.expect(close)?; 25 ( 0.00%) ExprKind::Repeat(first_expr, count) . } else if self.eat(&token::Comma) { . // Vector with two or more elements. . let sep = SeqSep::trailing_allowed(token::Comma); . let (remaining_exprs, _) = self.parse_seq_to_end(close, sep, |p| p.parse_expr())?; 9,936 ( 0.00%) let mut exprs = vec![first_expr]; . exprs.extend(remaining_exprs); 49,680 ( 0.00%) ExprKind::Array(exprs) . } else { . // Vector with one element 2 ( 0.00%) self.expect(close)?; 5 ( 0.00%) ExprKind::Array(vec![first_expr]) . } . }; 29,829 ( 0.00%) let expr = self.mk_expr(lo.to(self.prev_token.span), kind, attrs); 29,829 ( 0.00%) self.maybe_recover_from_bad_qpath(expr, true) 99,430 ( 0.00%) } . 104,080 ( 0.00%) fn parse_path_start_expr(&mut self, attrs: AttrVec) -> PResult<'a, P> { 83,264 ( 0.00%) let (qself, path) = if self.eat_lt() { . let (qself, path) = self.parse_qpath(PathStyle::Expr)?; . (Some(qself), path) . } else { 20,816 ( 0.00%) (None, self.parse_path(PathStyle::Expr)?) . }; 10,408 ( 0.00%) let lo = path.span; . . // `!`, as an operator, is prefix, so we know this isn't that. 156,030 ( 0.00%) let (hi, kind) = if self.eat(&token::Not) { . // MACRO INVOCATION expression . if qself.is_some() { . self.struct_span_err(path.span, "macros cannot use qualified paths").emit(); . } . let mac = MacCall { . path, . args: self.parse_mac_args()?, . prior_type_ascription: self.last_type_ascription, . }; . (self.prev_token.span, ExprKind::MacCall(mac)) 52,040 ( 0.00%) } else if self.check(&token::OpenDelim(token::Brace)) { 12 ( 0.00%) if let Some(expr) = self.maybe_parse_struct_expr(qself.as_ref(), &path, &attrs) { 6 ( 0.00%) if qself.is_some() { . self.sess.gated_spans.gate(sym::more_qualified_paths, path.span); . } . return expr; . } else { . (path.span, ExprKind::Path(qself, path)) . } . } else { . (path.span, ExprKind::Path(qself, path)) . }; . 20,804 ( 0.00%) let expr = self.mk_expr(lo.to(hi), kind, attrs); 31,206 ( 0.00%) self.maybe_recover_from_bad_qpath(expr, true) 124,884 ( 0.00%) } . . /// Parse `'label: $expr`. The label is already parsed. . fn parse_labeled_expr( . &mut self, . label: Label, . attrs: AttrVec, . mut consume_colon: bool, . ) -> PResult<'a, P> { -- line 1447 ---------------------------------------- -- line 1507 ---------------------------------------- . .note("following RFC #2388, the new non-placeholder syntax is `try`") . .emit(); . . self.parse_try_block(lo, attrs) . } . . /// Parse an expression if the token can begin one. . fn parse_expr_opt(&mut self) -> PResult<'a, Option>> { 140 ( 0.00%) Ok(if self.token.can_begin_expr() { Some(self.parse_expr()?) } else { None }) . } . . /// Parse `"return" expr?`. 280 ( 0.00%) fn parse_return_expr(&mut self, attrs: AttrVec) -> PResult<'a, P> { 28 ( 0.00%) let lo = self.prev_token.span; 56 ( 0.00%) let kind = ExprKind::Ret(self.parse_expr_opt()?); 84 ( 0.00%) let expr = self.mk_expr(lo.to(self.prev_token.span), kind, attrs); 168 ( 0.00%) self.maybe_recover_from_bad_qpath(expr, true) 280 ( 0.00%) } . . /// Parse `"break" (('label (:? expr)?) | expr?)` with `"break"` token already eaten. . /// If the label is followed immediately by a `:` token, the label and `:` are . /// parsed as part of the expression (i.e. a labeled loop). The language team has . /// decided in #87026 to require parentheses as a visual aid to avoid confusion if . /// the break expression of an unlabeled break is a labeled loop (as in . /// `break 'lbl: loop {}`); a labeled break with an unlabeled loop as its value . /// expression only gets a warning for compatibility reasons; and a labeled break -- line 1532 ---------------------------------------- -- line 1607 ---------------------------------------- . symbol_unescaped, . }), . _ => Err(Some(lit)), . }, . None => Err(None), . } . } . 774 ( 0.00%) pub(super) fn parse_lit(&mut self) -> PResult<'a, Lit> { 86 ( 0.00%) self.parse_opt_lit().ok_or_else(|| { 162 ( 0.00%) if let token::Interpolated(inner) = &self.token.kind { . let expr = match inner.as_ref() { . token::NtExpr(expr) => Some(expr), . token::NtLiteral(expr) => Some(expr), . _ => None, . }; . if let Some(expr) = expr { . if matches!(expr.kind, ExprKind::Err) { . self.diagnostic() . .delay_span_bug(self.token.span, &"invalid interpolated expression"); . return self.diagnostic().struct_dummy(); . } . } . } 891 ( 0.00%) let msg = format!("unexpected token: {}", super::token_descr(&self.token)); 81 ( 0.00%) self.struct_span_err(self.token.span, &msg) . }) 602 ( 0.00%) } . . /// Matches `lit = true | false | token_lit`. . /// Returns `None` if the next token is not a literal. 278,532 ( 0.01%) pub(super) fn parse_opt_lit(&mut self) -> Option { 30,948 ( 0.00%) let mut recovered = None; 185,688 ( 0.00%) if self.token == token::Dot { . // Attempt to recover `.4` as `0.4`. We don't currently have any syntax where . // dot would follow an optional literal, so we do this unconditionally. . recovered = self.look_ahead(1, |next_token| { . if let token::Literal(token::Lit { kind: token::Integer, symbol, suffix }) = . next_token.kind . { . if self.token.span.hi() == next_token.span.lo() { . let s = String::from("0.") + symbol.as_str(); -- line 1648 ---------------------------------------- -- line 1654 ---------------------------------------- . }); . if let Some(token) = &recovered { . self.bump(); . self.error_float_lits_must_have_int_part(&token); . } . } . . let token = recovered.as_ref().unwrap_or(&self.token); 93,087 ( 0.00%) match Lit::from_token(token) { 185,202 ( 0.00%) Ok(lit) => { 61,734 ( 0.00%) self.bump(); 185,202 ( 0.00%) Some(lit) . } 81 ( 0.00%) Err(LitError::NotLiteral) => None, . Err(err) => { . let span = token.span; . let lit = match token.kind { . token::Literal(lit) => lit, . _ => unreachable!(), . }; . self.bump(); . self.report_lit_error(err, lit, span); -- line 1675 ---------------------------------------- -- line 1676 ---------------------------------------- . // Pack possible quotes and prefixes from the original literal into . // the error literal's symbol so they can be pretty-printed faithfully. . let suffixless_lit = token::Lit::new(lit.kind, lit.symbol, None); . let symbol = Symbol::intern(&suffixless_lit.to_string()); . let lit = token::Lit::new(token::Err, symbol, lit.suffix); . Some(Lit::from_lit_token(lit, span).unwrap_or_else(|_| unreachable!())) . } . } 247,584 ( 0.01%) } . . fn error_float_lits_must_have_int_part(&self, token: &Token) { . self.struct_span_err(token.span, "float literals must have an integer part") . .span_suggestion( . token.span, . "must have an integer part", . pprust::token_to_string(token).into(), . Applicability::MachineApplicable, -- line 1692 ---------------------------------------- -- line 1759 ---------------------------------------- . .emit(); . } . LitError::IntTooLarge => { . self.struct_span_err(span, "integer literal is too large").emit(); . } . } . } . 63 ( 0.00%) pub(super) fn expect_no_suffix(&self, sp: Span, kind: &str, suffix: Option) { 18 ( 0.00%) if let Some(suf) = suffix { . let mut err = if kind == "a tuple index" . && [sym::i32, sym::u32, sym::isize, sym::usize].contains(&suf) . { . // #59553: warn instead of reject out of hand to allow the fix to percolate . // through the ecosystem when people fix their macros . let mut err = self . .sess . .span_diagnostic -- line 1776 ---------------------------------------- -- line 1791 ---------------------------------------- . ); . err . } else { . self.struct_span_err(sp, &format!("suffixes on {} are invalid", kind)) . }; . err.span_label(sp, format!("invalid suffix `{}`", suf)); . err.emit(); . } 54 ( 0.00%) } . . /// Matches `'-' lit | lit` (cf. `ast_validation::AstValidator::check_expr_within_pat`). . /// Keep this in sync with `Token::can_begin_literal_maybe_minus`. 32 ( 0.00%) pub fn parse_literal_maybe_minus(&mut self) -> PResult<'a, P> { 8 ( 0.00%) maybe_whole_expr!(self); . 4 ( 0.00%) let lo = self.token.span; . let minus_present = self.eat(&token::BinOp(token::Minus)); 8 ( 0.00%) let lit = self.parse_lit()?; 4 ( 0.00%) let expr = self.mk_expr(lit.span, ExprKind::Lit(lit), AttrVec::new()); . 8 ( 0.00%) if minus_present { . Ok(self.mk_expr( . lo.to(self.prev_token.span), . self.mk_unary(UnOp::Neg, expr), . AttrVec::new(), . )) . } else { . Ok(expr) . } 36 ( 0.00%) } . . fn is_array_like_block(&mut self) -> bool { 55 ( 0.00%) self.look_ahead(1, |t| matches!(t.kind, TokenKind::Ident(..) | TokenKind::Literal(_))) . && self.look_ahead(2, |t| t == &token::Comma) . && self.look_ahead(3, |t| t.can_begin_expr()) . } . . /// Emits a suggestion if it looks like the user meant an array but . /// accidentally used braces, causing the code to be interpreted as a block . /// expression. . fn maybe_suggest_brackets_instead_of_braces( -- line 1831 ---------------------------------------- -- line 1855 ---------------------------------------- . Err(mut e) => { . e.cancel(); . None . } . } . } . . /// Parses a block or unsafe block. 210 ( 0.00%) pub(super) fn parse_block_expr( . &mut self, . opt_label: Option