diff --git a/Cargo.lock b/Cargo.lock index f0e035c025edc..ea17d3ddf476f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3301,6 +3301,7 @@ version = "0.0.0" dependencies = [ "itertools", "rustc_ast", + "rustc_data_structures", "rustc_lexer", "rustc_span", "thin-vec", diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 1d6abbef06c95..3b9edef061593 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -368,7 +368,7 @@ impl Clone for TokenKind { // a copy. This is faster than the `derive(Clone)` version which has a // separate path for every variant. match self { - Interpolated(nt) => Interpolated(nt.clone()), + Interpolated(nt) => Interpolated(Lrc::clone(nt)), _ => unsafe { std::ptr::read(self) }, } } diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index a1a16d0ca2632..5b6b4eaa0393d 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -3,6 +3,7 @@ use std::assert_matches::assert_matches; use rustc_ast::ptr::P as AstP; use rustc_ast::*; use rustc_data_structures::stack::ensure_sufficient_stack; +use rustc_data_structures::sync::Lrc; use rustc_hir as hir; use rustc_hir::HirId; use rustc_hir::def::{DefKind, Res}; @@ -143,7 +144,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ExprKind::IncludedBytes(bytes) => { let lit = self.arena.alloc(respan( self.lower_span(e.span), - LitKind::ByteStr(bytes.clone(), StrStyle::Cooked), + LitKind::ByteStr(Lrc::clone(bytes), StrStyle::Cooked), )); hir::ExprKind::Lit(lit) } @@ -521,7 +522,7 @@ impl<'hir> LoweringContext<'_, 'hir> { this.mark_span_with_reason( DesugaringKind::TryBlock, expr.span, - Some(this.allow_try_trait.clone()), + Some(Lrc::clone(&this.allow_try_trait)), ), expr, ) @@ -529,7 +530,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let try_span = this.mark_span_with_reason( DesugaringKind::TryBlock, this.tcx.sess.source_map().end_point(body.span), - Some(this.allow_try_trait.clone()), + Some(Lrc::clone(&this.allow_try_trait)), ); (try_span, this.expr_unit(try_span)) @@ -638,7 +639,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let unstable_span = self.mark_span_with_reason( DesugaringKind::Async, self.lower_span(span), - Some(self.allow_gen_future.clone()), + Some(Lrc::clone(&self.allow_gen_future)), ); let resume_ty = self.make_lang_item_qpath(hir::LangItem::ResumeTy, unstable_span, None); @@ -724,7 +725,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let unstable_span = self.mark_span_with_reason( DesugaringKind::Async, span, - Some(self.allow_gen_future.clone()), + Some(Lrc::clone(&self.allow_gen_future)), ); self.lower_attrs(inner_hir_id, &[Attribute { kind: AttrKind::Normal(ptr::P(NormalAttr::from_ident(Ident::new( @@ -800,13 +801,13 @@ impl<'hir> LoweringContext<'_, 'hir> { let features = match await_kind { FutureKind::Future => None, - FutureKind::AsyncIterator => Some(self.allow_for_await.clone()), + FutureKind::AsyncIterator => Some(Lrc::clone(&self.allow_for_await)), }; let span = self.mark_span_with_reason(DesugaringKind::Await, await_kw_span, features); let gen_future_span = self.mark_span_with_reason( DesugaringKind::Await, full_span, - Some(self.allow_gen_future.clone()), + Some(Lrc::clone(&self.allow_gen_future)), ); let expr_hir_id = expr.hir_id; @@ -1812,13 +1813,13 @@ impl<'hir> LoweringContext<'_, 'hir> { let unstable_span = self.mark_span_with_reason( DesugaringKind::QuestionMark, span, - Some(self.allow_try_trait.clone()), + Some(Lrc::clone(&self.allow_try_trait)), ); let try_span = self.tcx.sess.source_map().end_point(span); let try_span = self.mark_span_with_reason( DesugaringKind::QuestionMark, try_span, - Some(self.allow_try_trait.clone()), + Some(Lrc::clone(&self.allow_try_trait)), ); // `Try::branch()` @@ -1912,7 +1913,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let unstable_span = self.mark_span_with_reason( DesugaringKind::YeetExpr, span, - Some(self.allow_try_trait.clone()), + Some(Lrc::clone(&self.allow_try_trait)), ); let from_yeet_expr = self.wrap_in_try_constructor( diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 34b8137aea8ef..15221b3eba038 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1865,7 +1865,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { CoroutineKind::Async { return_impl_trait_id, .. } => (return_impl_trait_id, None), CoroutineKind::Gen { return_impl_trait_id, .. } => (return_impl_trait_id, None), CoroutineKind::AsyncGen { return_impl_trait_id, .. } => { - (return_impl_trait_id, Some(self.allow_async_iterator.clone())) + (return_impl_trait_id, Some(Lrc::clone(&self.allow_async_iterator))) } }; diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index 6a0f03c8b3196..133793e26ea3c 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -73,7 +73,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let bound_modifier_allowed_features = if let Res::Def(DefKind::Trait, async_def_id) = res && self.tcx.async_fn_trait_kind_from_def_id(async_def_id).is_some() { - Some(self.allow_async_fn_traits.clone()) + Some(Lrc::clone(&self.allow_async_fn_traits)) } else { None }; diff --git a/compiler/rustc_ast_pretty/Cargo.toml b/compiler/rustc_ast_pretty/Cargo.toml index 9ae5c9b3cec6c..f290fedcd8b9a 100644 --- a/compiler/rustc_ast_pretty/Cargo.toml +++ b/compiler/rustc_ast_pretty/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" # tidy-alphabetical-start itertools = "0.12" rustc_ast = { path = "../rustc_ast" } +rustc_data_structures = { path = "../rustc_data_structures" } rustc_lexer = { path = "../rustc_lexer" } rustc_span = { path = "../rustc_span" } thin-vec = "0.2.12" diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 1e18f0779f005..de9f5187be738 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -21,6 +21,7 @@ use rustc_ast::{ GenericBound, InlineAsmOperand, InlineAsmOptions, InlineAsmRegOrRegClass, InlineAsmTemplatePiece, PatKind, RangeEnd, RangeSyntax, Safety, SelfKind, Term, attr, }; +use rustc_data_structures::sync::Lrc; use rustc_span::edition::Edition; use rustc_span::source_map::{SourceMap, Spanned}; use rustc_span::symbol::{Ident, IdentPrinter, Symbol, kw, sym}; @@ -105,7 +106,7 @@ fn split_block_comment_into_lines(text: &str, col: CharPos) -> Vec { fn gather_comments(sm: &SourceMap, path: FileName, src: String) -> Vec { let sm = SourceMap::new(sm.path_mapping().clone()); let source_file = sm.new_source_file(path, src); - let text = (*source_file.src.as_ref().unwrap()).clone(); + let text = Lrc::clone(&(*source_file.src.as_ref().unwrap())); let text: &str = text.as_str(); let start_bpos = source_file.start_pos; diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index 3674053409b8d..f76603d567962 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -107,13 +107,13 @@ pub(crate) fn compute_regions<'a, 'tcx>( param_env, body, promoted, - universal_regions.clone(), + Rc::clone(&universal_regions), location_table, borrow_set, &mut all_facts, flow_inits, move_data, - elements.clone(), + Rc::clone(&elements), upvars, ); diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index e85f529bf0ee1..d5c2796932e10 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -733,7 +733,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { } // Now take member constraints into account. - let member_constraints = self.member_constraints.clone(); + let member_constraints = Rc::clone(&self.member_constraints); for m_c_i in member_constraints.indices(scc_a) { self.apply_member_constraint(scc_a, m_c_i, member_constraints.choice_regions(m_c_i)); } @@ -1679,7 +1679,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { infcx: &InferCtxt<'tcx>, errors_buffer: &mut RegionErrors<'tcx>, ) { - let member_constraints = self.member_constraints.clone(); + let member_constraints = Rc::clone(&self.member_constraints); for m_c_i in member_constraints.all_indices() { debug!(?m_c_i); let m_c = &member_constraints[m_c_i]; diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index a544d88e8321e..26919bfd48861 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -134,7 +134,7 @@ pub(crate) fn type_check<'a, 'tcx>( let mut constraints = MirTypeckRegionConstraints { placeholder_indices: PlaceholderIndices::default(), placeholder_index_to_region: IndexVec::default(), - liveness_constraints: LivenessValues::with_specific_points(elements.clone()), + liveness_constraints: LivenessValues::with_specific_points(Rc::clone(&elements)), outlives_constraints: OutlivesConstraintSet::default(), member_constraints: MemberConstraintSet::default(), type_tests: Vec::default(), @@ -150,7 +150,7 @@ pub(crate) fn type_check<'a, 'tcx>( infcx, param_env, implicit_region_bound, - universal_regions.clone(), + Rc::clone(&universal_regions), &mut constraints, ); diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs index 1f7a923dd2c68..74bc0eced32a6 100644 --- a/compiler/rustc_codegen_llvm/src/back/lto.rs +++ b/compiler/rustc_codegen_llvm/src/back/lto.rs @@ -569,7 +569,7 @@ fn thin_lto( info!(" - {}: re-compiled", module_name); opt_jobs.push(LtoModuleCodegen::Thin(ThinModule { - shared: shared.clone(), + shared: Arc::clone(&shared), idx: module_index, })); } diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index e3d11cfaf4fe3..8445d16befb3a 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -514,7 +514,7 @@ pub(crate) fn start_async_codegen( future: Some(coordinator_thread), phantom: PhantomData, }, - output_filenames: tcx.output_filenames(()).clone(), + output_filenames: Arc::clone(tcx.output_filenames(())), } } @@ -1203,7 +1203,7 @@ fn start_executing_work( coordinator_send, expanded_args: tcx.sess.expanded_args.clone(), diag_emitter: shared_emitter.clone(), - output_filenames: tcx.output_filenames(()).clone(), + output_filenames: Arc::clone(tcx.output_filenames(())), regular_module_config: regular_config, metadata_module_config: metadata_config, allocator_module_config: allocator_config, diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index a726ee73aaa26..b954633f4532d 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -7,7 +7,7 @@ use rustc_ast::expand::allocator::{ALLOCATOR_METHODS, AllocatorKind, global_fn_n use rustc_attr as attr; use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry}; -use rustc_data_structures::sync::par_map; +use rustc_data_structures::sync::{Lrc, par_map}; use rustc_data_structures::unord::UnordMap; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_hir::lang_items::LangItem; @@ -923,7 +923,7 @@ impl CrateInfo { crate_name: UnordMap::with_capacity(n_crates), used_crates, used_crate_source: UnordMap::with_capacity(n_crates), - dependency_formats: tcx.dependency_formats(()).clone(), + dependency_formats: Lrc::clone(tcx.dependency_formats(())), windows_subsystem, natvis_debugger_visualizers: Default::default(), }; @@ -936,7 +936,7 @@ impl CrateInfo { info.crate_name.insert(cnum, tcx.crate_name(cnum)); let used_crate_source = tcx.used_crate_source(cnum); - info.used_crate_source.insert(cnum, used_crate_source.clone()); + info.used_crate_source.insert(cnum, Lrc::clone(used_crate_source)); if tcx.is_profiler_runtime(cnum) { info.profiler_runtime = Some(cnum); } diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index a59dea557bb96..e2585c023883a 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -1395,7 +1395,7 @@ pub fn install_ice_hook( } let using_internal_features = Arc::new(std::sync::atomic::AtomicBool::default()); - let using_internal_features_hook = using_internal_features.clone(); + let using_internal_features_hook = Arc::clone(&using_internal_features); panic::update_hook(Box::new( move |default_hook: &(dyn Fn(&PanicHookInfo<'_>) + Send + Sync + 'static), info: &PanicHookInfo<'_>| { diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs index 335432c9cfec3..b4a651b10b10a 100644 --- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs +++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs @@ -173,7 +173,7 @@ impl AnnotateSnippetEmitter { source_map.ensure_source_file_source_present(&file); ( format!("{}", source_map.filename_for_diagnostics(&file.name)), - source_string(file.clone(), &line), + source_string(Lrc::clone(&file), &line), line.line_index, line.annotations, ) diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 0ccc71ae06c45..6552cf224eaa8 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -1555,7 +1555,7 @@ impl HumanEmitter { // Get the left-side margin to remove it let mut whitespace_margin = usize::MAX; for line_idx in 0..annotated_file.lines.len() { - let file = annotated_file.file.clone(); + let file = Lrc::clone(&annotated_file.file); let line = &annotated_file.lines[line_idx]; if let Some(source_string) = line.line_index.checked_sub(1).and_then(|l| file.get_line(l)) @@ -1646,7 +1646,7 @@ impl HumanEmitter { let depths = self.render_source_line( &mut buffer, - annotated_file.file.clone(), + Lrc::clone(&annotated_file.file), &annotated_file.lines[line_idx], width_offset, code_offset, @@ -2529,7 +2529,12 @@ impl FileWithAnnotatedLines { // | | | // | |______foo // | baz - add_annotation_to_file(&mut output, file.clone(), ann.line_start, ann.as_start()); + add_annotation_to_file( + &mut output, + Lrc::clone(&file), + ann.line_start, + ann.as_start(), + ); // 4 is the minimum vertical length of a multiline span when presented: two lines // of code and two lines of underline. This is not true for the special case where // the beginning doesn't have an underline, but the current logic seems to be @@ -2545,11 +2550,11 @@ impl FileWithAnnotatedLines { .unwrap_or(ann.line_start); for line in ann.line_start + 1..until { // Every `|` that joins the beginning of the span (`___^`) to the end (`|__^`). - add_annotation_to_file(&mut output, file.clone(), line, ann.as_line()); + add_annotation_to_file(&mut output, Lrc::clone(&file), line, ann.as_line()); } let line_end = ann.line_end - 1; if middle < line_end { - add_annotation_to_file(&mut output, file.clone(), line_end, ann.as_line()); + add_annotation_to_file(&mut output, Lrc::clone(&file), line_end, ann.as_line()); } } else { end_ann.annotation_type = AnnotationType::Singleline; diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs index 1534e25652077..91e2b9996cd50 100644 --- a/compiler/rustc_errors/src/json.rs +++ b/compiler/rustc_errors/src/json.rs @@ -367,9 +367,9 @@ impl Diagnostic { ColorConfig::Always | ColorConfig::Auto => dst = Box::new(termcolor::Ansi::new(dst)), ColorConfig::Never => {} } - HumanEmitter::new(dst, je.fallback_bundle.clone()) + HumanEmitter::new(dst, Lrc::clone(&je.fallback_bundle)) .short_message(short) - .sm(Some(je.sm.clone())) + .sm(Some(Lrc::clone(&je.sm))) .fluent_bundle(je.fluent_bundle.clone()) .diagnostic_width(je.diagnostic_width) .macro_backtrace(je.macro_backtrace) diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs index 3903203da3dbf..a08db612bbedb 100644 --- a/compiler/rustc_expand/src/mbe/macro_parser.rs +++ b/compiler/rustc_expand/src/mbe/macro_parser.rs @@ -622,7 +622,7 @@ impl TtParser { // possible next positions into `next_mps`. After some post-processing, the contents of // `next_mps` replenish `cur_mps` and we start over again. self.cur_mps.clear(); - self.cur_mps.push(MatcherPos { idx: 0, matches: self.empty_matches.clone() }); + self.cur_mps.push(MatcherPos { idx: 0, matches: Rc::clone(&self.empty_matches) }); loop { self.next_mps.clear(); diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index 34811ca2b3566..b77d02e630a21 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -5,6 +5,7 @@ use rustc_ast::mut_visit::{self, MutVisitor}; use rustc_ast::token::{self, Delimiter, IdentIsRaw, Lit, LitKind, Nonterminal, Token, TokenKind}; use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree}; use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::sync::Lrc; use rustc_errors::{Diag, DiagCtxtHandle, PResult, pluralize}; use rustc_parse::lexer::nfc_normalize; use rustc_parse::parser::ParseNtResult; @@ -293,7 +294,7 @@ pub(super) fn transcribe<'a>( // `Delimiter::Invisible` to maintain parsing priorities. // `Interpolated` is currently used for such groups in rustc parser. marker.visit_span(&mut sp); - TokenTree::token_alone(token::Interpolated(nt.clone()), sp) + TokenTree::token_alone(token::Interpolated(Lrc::clone(nt)), sp) } MatchedSeq(..) => { // We were unable to descend far enough. This is an error. diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index ac922f184dd8c..e910415c34574 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -224,6 +224,8 @@ declare_features! ( (accepted, i128_type, "1.26.0", Some(35118)), /// Allows the use of `if let` expressions. (accepted, if_let, "1.0.0", None), + /// Rescoping temporaries in `if let` to align with Rust 2024. + (accepted, if_let_rescope, "CURRENT_RUSTC_VERSION", Some(124085)), /// Allows top level or-patterns (`p | q`) in `if let` and `while let`. (accepted, if_while_or_patterns, "1.33.0", Some(48215)), /// Allows lifetime elision in `impl` headers. For example: diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 93047d420ad9e..a99d90488861c 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -505,8 +505,6 @@ declare_features! ( (unstable, half_open_range_patterns_in_slices, "1.66.0", Some(67264)), /// Allows `if let` guard in match arms. (unstable, if_let_guard, "1.47.0", Some(51114)), - /// Rescoping temporaries in `if let` to align with Rust 2024. - (unstable, if_let_rescope, "1.83.0", Some(124085)), /// Allows `impl Trait` to be used inside associated types (RFC 2515). (unstable, impl_trait_in_assoc_type, "1.70.0", Some(63063)), /// Allows `impl Trait` as output type in `Fn` traits in return position of functions. diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index bfa088fdefc96..679f6ccb8165d 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -464,8 +464,7 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h hir::ExprKind::If(cond, then, Some(otherwise)) => { let expr_cx = visitor.cx; - let data = if expr.span.at_least_rust_2024() && visitor.tcx.features().if_let_rescope() - { + let data = if expr.span.at_least_rust_2024() { ScopeData::IfThenRescope } else { ScopeData::IfThen @@ -480,8 +479,7 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h hir::ExprKind::If(cond, then, None) => { let expr_cx = visitor.cx; - let data = if expr.span.at_least_rust_2024() && visitor.tcx.features().if_let_rescope() - { + let data = if expr.span.at_least_rust_2024() { ScopeData::IfThenRescope } else { ScopeData::IfThen diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs index b2ad42be6c7fc..5c4cecc02f0ee 100644 --- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs +++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs @@ -367,20 +367,8 @@ pub(super) fn explicit_item_bounds_with_filter( // a projection self type. Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => { let opaque_ty = tcx.hir_node_by_def_id(opaque_def_id.expect_local()).expect_opaque_ty(); - let item_ty = Ty::new_projection_from_args( - tcx, - def_id.to_def_id(), - ty::GenericArgs::identity_for_item(tcx, def_id), - ); - let bounds = opaque_type_bounds( - tcx, - opaque_def_id.expect_local(), - opaque_ty.bounds, - item_ty, - opaque_ty.span, - filter, - ); - assert_only_contains_predicates_from(filter, bounds, item_ty); + let bounds = + associated_type_bounds(tcx, def_id, opaque_ty.bounds, opaque_ty.span, filter); return ty::EarlyBinder::bind(bounds); } Some(ty::ImplTraitInTraitData::Impl { .. }) => span_bug!( diff --git a/compiler/rustc_infer/src/infer/opaque_types/mod.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs index 853ae6d26412a..c38b7114e43eb 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/mod.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs @@ -364,7 +364,7 @@ impl<'tcx> InferCtxt<'tcx> { span, concrete_ty, r, - choice_regions.clone(), + Lrc::clone(&choice_regions), ) }, }); diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index 3a1833452d4b6..b6837ec764f24 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -142,7 +142,7 @@ impl Linker { Ok(Linker { dep_graph: tcx.dep_graph.clone(), - output_filenames: tcx.output_filenames(()).clone(), + output_filenames: Arc::clone(tcx.output_filenames(())), crate_hash: if tcx.needs_crate_hash() { Some(tcx.crate_hash(LOCAL_CRATE)) } else { diff --git a/compiler/rustc_lint/src/if_let_rescope.rs b/compiler/rustc_lint/src/if_let_rescope.rs index bdfcc2c0a1006..afcfbebc14b31 100644 --- a/compiler/rustc_lint/src/if_let_rescope.rs +++ b/compiler/rustc_lint/src/if_let_rescope.rs @@ -24,7 +24,6 @@ declare_lint! { /// ### Example /// /// ```rust,edition2021 - /// #![feature(if_let_rescope)] /// #![warn(if_let_rescope)] /// #![allow(unused_variables)] /// @@ -243,7 +242,7 @@ impl_lint_pass!( impl<'tcx> LateLintPass<'tcx> for IfLetRescope { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) { - if expr.span.edition().at_least_rust_2024() || !cx.tcx.features().if_let_rescope() { + if expr.span.edition().at_least_rust_2024() { return; } if let (Level::Allow, _) = cx.tcx.lint_level_at_node(IF_LET_RESCOPE, expr.hir_id) { diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 47f7a8b7c2017..b5ac302c597de 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -278,7 +278,7 @@ impl<'a, 'tcx> Encodable> for SpanData { let source_map = s.tcx.sess.source_map(); let source_file_index = source_map.lookup_source_file_idx(self.lo); s.source_file_cache = - (source_map.files()[source_file_index].clone(), source_file_index); + (Lrc::clone(&source_map.files()[source_file_index]), source_file_index); } let (ref source_file, source_file_index) = s.source_file_cache; debug_assert!(source_file.contains(self.lo)); @@ -2275,7 +2275,7 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) { encoder.emit_raw_bytes(&0u64.to_le_bytes()); let source_map_files = tcx.sess.source_map().files(); - let source_file_cache = (source_map_files[0].clone(), 0); + let source_file_cache = (Lrc::clone(&source_map_files[0]), 0); let required_source_files = Some(FxIndexSet::default()); drop(source_map_files); diff --git a/compiler/rustc_middle/src/middle/debugger_visualizer.rs b/compiler/rustc_middle/src/middle/debugger_visualizer.rs index 615a7402139e1..c241c06fce44f 100644 --- a/compiler/rustc_middle/src/middle/debugger_visualizer.rs +++ b/compiler/rustc_middle/src/middle/debugger_visualizer.rs @@ -32,7 +32,7 @@ impl DebuggerVisualizerFile { pub fn path_erased(&self) -> Self { DebuggerVisualizerFile { - src: self.src.clone(), + src: Lrc::clone(&self.src), visualizer_type: self.visualizer_type, path: None, } diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs index 35a16684615d6..8b77a4a81ca8d 100644 --- a/compiler/rustc_middle/src/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/query/on_disk_cache.rs @@ -472,32 +472,27 @@ impl<'a, 'tcx> CacheDecoder<'a, 'tcx> { let CacheDecoder { tcx, file_index_to_file, file_index_to_stable_id, source_map, .. } = *self; - file_index_to_file - .borrow_mut() - .entry(index) - .or_insert_with(|| { - let source_file_id = &file_index_to_stable_id[&index]; - let source_file_cnum = - tcx.stable_crate_id_to_crate_num(source_file_id.stable_crate_id); - - // If this `SourceFile` is from a foreign crate, then make sure - // that we've imported all of the source files from that crate. - // This has usually already been done during macro invocation. - // However, when encoding query results like `TypeckResults`, - // we might encode an `AdtDef` for a foreign type (because it - // was referenced in the body of the function). There is no guarantee - // that we will load the source files from that crate during macro - // expansion, so we use `import_source_files` to ensure that the foreign - // source files are actually imported before we call `source_file_by_stable_id`. - if source_file_cnum != LOCAL_CRATE { - self.tcx.import_source_files(source_file_cnum); - } + Lrc::clone(file_index_to_file.borrow_mut().entry(index).or_insert_with(|| { + let source_file_id = &file_index_to_stable_id[&index]; + let source_file_cnum = tcx.stable_crate_id_to_crate_num(source_file_id.stable_crate_id); + + // If this `SourceFile` is from a foreign crate, then make sure + // that we've imported all of the source files from that crate. + // This has usually already been done during macro invocation. + // However, when encoding query results like `TypeckResults`, + // we might encode an `AdtDef` for a foreign type (because it + // was referenced in the body of the function). There is no guarantee + // that we will load the source files from that crate during macro + // expansion, so we use `import_source_files` to ensure that the foreign + // source files are actually imported before we call `source_file_by_stable_id`. + if source_file_cnum != LOCAL_CRATE { + self.tcx.import_source_files(source_file_cnum); + } - source_map - .source_file_by_stable_id(source_file_id.stable_source_file_id) - .expect("failed to lookup `SourceFile` in new context") - }) - .clone() + source_map + .source_file_by_stable_id(source_file_id.stable_source_file_id) + .expect("failed to lookup `SourceFile` in new context") + })) } } diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index e282345647731..d20e5fcf4ec6d 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -784,7 +784,7 @@ impl<'tcx> Cx<'tcx> { if_then_scope: region::Scope { id: then.hir_id.local_id, data: { - if expr.span.at_least_rust_2024() && tcx.features().if_let_rescope() { + if expr.span.at_least_rust_2024() { region::ScopeData::IfThenRescope } else { region::ScopeData::IfThen diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index a9384501547e8..a1fe550897073 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -14,6 +14,7 @@ use rustc_ast::{ }; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::sync::Lrc; use rustc_errors::{ Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed, FatalError, PErr, PResult, Subdiagnostic, Suggestions, pluralize, @@ -2437,7 +2438,7 @@ impl<'a> Parser<'a> { let mut labels = vec![]; while let TokenKind::Interpolated(nt) = &tok.kind { let tokens = nt.tokens(); - labels.push(nt.clone()); + labels.push(Lrc::clone(nt)); if let Some(tokens) = tokens && let tokens = tokens.to_attr_token_stream() && let tokens = tokens.0.deref() diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index cd7725d2d70df..5e30f17d6269a 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -134,7 +134,7 @@ impl DepGraph { encoder, record_graph, record_stats, - prev_graph.clone(), + Arc::clone(&prev_graph), ); let colors = DepNodeColorMap::new(prev_graph_node_count); diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs index ca3efc11201e1..5af41b9e68737 100644 --- a/compiler/rustc_query_system/src/query/job.rs +++ b/compiler/rustc_query_system/src/query/job.rs @@ -237,7 +237,7 @@ impl QueryLatch { // the `wait` call below, by 1) the `set` method or 2) by deadlock detection. // Both of these will remove it from the `waiters` list before resuming // this thread. - info.waiters.push(waiter.clone()); + info.waiters.push(Arc::clone(waiter)); // If this detects a deadlock and the deadlock handler wants to resume this thread // we have to be in the `wait` call. This is ensured by the deadlock handler diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 35d491cfc18e7..9abb3180388b3 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1694,9 +1694,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { fn dummy_ext(&self, macro_kind: MacroKind) -> Lrc { match macro_kind { - MacroKind::Bang => self.dummy_ext_bang.clone(), - MacroKind::Derive => self.dummy_ext_derive.clone(), - MacroKind::Attr => self.non_macro_attr.ext.clone(), + MacroKind::Bang => Lrc::clone(&self.dummy_ext_bang), + MacroKind::Derive => Lrc::clone(&self.dummy_ext_derive), + MacroKind::Attr => Lrc::clone(&self.non_macro_attr.ext), } } diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 1dc27776cb0f5..0b4d0e04c295c 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -826,7 +826,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } _ => None, }, - None => self.get_macro(res).map(|macro_data| macro_data.ext.clone()), + None => self.get_macro(res).map(|macro_data| Lrc::clone(¯o_data.ext)), }; Ok((ext, res)) } diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index 3d44810e7dd36..f20ae85b8e8a7 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -241,7 +241,7 @@ impl ParseSess { let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); let emitter = Box::new( HumanEmitter::new(stderr_destination(ColorConfig::Auto), fallback_bundle) - .sm(Some(sm.clone())), + .sm(Some(Lrc::clone(&sm))), ); let dcx = DiagCtxt::new(emitter); ParseSess::with_dcx(dcx, sm) @@ -278,7 +278,7 @@ impl ParseSess { let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); let emitter = Box::new(HumanEmitter::new( stderr_destination(ColorConfig::Auto), - fallback_bundle.clone(), + Lrc::clone(&fallback_bundle), )); let fatal_dcx = DiagCtxt::new(emitter); let dcx = DiagCtxt::new(Box::new(SilentEmitter { @@ -297,7 +297,7 @@ impl ParseSess { } pub fn clone_source_map(&self) -> Lrc { - self.source_map.clone() + Lrc::clone(&self.source_map) } pub fn buffer_lint( diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 1963cf4eb7c06..45434534c75ea 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -1036,7 +1036,8 @@ pub fn build_session( sopts.unstable_opts.translate_directionality_markers, ); let source_map = rustc_span::source_map::get_source_map().unwrap(); - let emitter = default_emitter(&sopts, registry, source_map.clone(), bundle, fallback_bundle); + let emitter = + default_emitter(&sopts, registry, Lrc::clone(&source_map), bundle, fallback_bundle); let mut dcx = DiagCtxt::new(emitter).with_flags(sopts.unstable_opts.dcx_flags(can_emit_warnings)); @@ -1079,7 +1080,7 @@ pub fn build_session( let target_tlib_path = if host_triple == target_triple { // Use the same `SearchPath` if host and target triple are identical to avoid unnecessary // rescanning of the target lib path and an unnecessary allocation. - host_tlib_path.clone() + Lrc::clone(&host_tlib_path) } else { Lrc::new(SearchPath::from_sysroot_and_triple(&sysroot, target_triple)) }; diff --git a/compiler/rustc_span/src/caching_source_map_view.rs b/compiler/rustc_span/src/caching_source_map_view.rs index 26aa782e5d7a8..9f977b98b82b6 100644 --- a/compiler/rustc_span/src/caching_source_map_view.rs +++ b/compiler/rustc_span/src/caching_source_map_view.rs @@ -63,7 +63,7 @@ pub struct CachingSourceMapView<'sm> { impl<'sm> CachingSourceMapView<'sm> { pub fn new(source_map: &'sm SourceMap) -> CachingSourceMapView<'sm> { let files = source_map.files(); - let first_file = files[0].clone(); + let first_file = Lrc::clone(&files[0]); let entry = CacheEntry { time_stamp: 0, line_number: 0, @@ -92,7 +92,7 @@ impl<'sm> CachingSourceMapView<'sm> { cache_entry.touch(self.time_stamp); let col = RelativeBytePos(pos.to_u32() - cache_entry.line.start.to_u32()); - return Some((cache_entry.file.clone(), cache_entry.line_number, col)); + return Some((Lrc::clone(&cache_entry.file), cache_entry.line_number, col)); } // No cache hit ... @@ -109,7 +109,7 @@ impl<'sm> CachingSourceMapView<'sm> { cache_entry.update(new_file_and_idx, pos, self.time_stamp); let col = RelativeBytePos(pos.to_u32() - cache_entry.line.start.to_u32()); - Some((cache_entry.file.clone(), cache_entry.line_number, col)) + Some((Lrc::clone(&cache_entry.file), cache_entry.line_number, col)) } pub fn span_data_to_lines_and_cols( @@ -133,7 +133,7 @@ impl<'sm> CachingSourceMapView<'sm> { } ( - lo.file.clone(), + Lrc::clone(&lo.file), lo.line_number, span_data.lo - lo.line.start, hi.line_number, @@ -181,7 +181,7 @@ impl<'sm> CachingSourceMapView<'sm> { lo.update(new_file_and_idx, span_data.lo, self.time_stamp); if !lo.line.contains(&span_data.hi) { - let new_file_and_idx = Some((lo.file.clone(), lo.file_index)); + let new_file_and_idx = Some((Lrc::clone(&lo.file), 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); @@ -227,7 +227,7 @@ impl<'sm> CachingSourceMapView<'sm> { assert_eq!(lo.file_index, hi.file_index); Some(( - lo.file.clone(), + Lrc::clone(&lo.file), lo.line_number, span_data.lo - lo.line.start, hi.line_number, @@ -277,7 +277,7 @@ impl<'sm> CachingSourceMapView<'sm> { let file = &self.source_map.files()[file_idx]; if file_contains(file, pos) { - return Some((file.clone(), file_idx)); + return Some((Lrc::clone(file), file_idx)); } } diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs index 8a02330593711..f36bb38623e5d 100644 --- a/compiler/rustc_span/src/source_map.rs +++ b/compiler/rustc_span/src/source_map.rs @@ -286,8 +286,8 @@ impl SourceMap { }); let file = Lrc::new(file); - files.source_files.push(file.clone()); - files.stable_id_to_source_file.insert(file_id, file.clone()); + files.source_files.push(Lrc::clone(&file)); + files.stable_id_to_source_file.insert(file_id, Lrc::clone(&file)); Ok(file) } @@ -386,7 +386,7 @@ impl SourceMap { /// Return the SourceFile that contains the given `BytePos` pub fn lookup_source_file(&self, pos: BytePos) -> Lrc { let idx = self.lookup_source_file_idx(pos); - (*self.files.borrow().source_files)[idx].clone() + Lrc::clone(&(*self.files.borrow().source_files)[idx]) } /// Looks up source information about a `BytePos`. @@ -468,7 +468,7 @@ impl SourceMap { if lo != hi { return true; } - let f = (*self.files.borrow().source_files)[lo].clone(); + let f = Lrc::clone(&(*self.files.borrow().source_files)[lo]); let lo = f.relative_position(sp.lo()); let hi = f.relative_position(sp.hi()); f.lookup_line(lo) != f.lookup_line(hi) @@ -994,7 +994,7 @@ impl SourceMap { let filename = self.path_mapping().map_filename_prefix(filename).0; for sf in self.files.borrow().source_files.iter() { if filename == sf.name { - return Some(sf.clone()); + return Some(Lrc::clone(&sf)); } } None @@ -1003,7 +1003,7 @@ impl SourceMap { /// For a global `BytePos`, computes the local offset within the containing `SourceFile`. pub fn lookup_byte_offset(&self, bpos: BytePos) -> SourceFileAndBytePos { let idx = self.lookup_source_file_idx(bpos); - let sf = (*self.files.borrow().source_files)[idx].clone(); + let sf = Lrc::clone(&(*self.files.borrow().source_files)[idx]); let offset = bpos - sf.start_pos; SourceFileAndBytePos { sf, pos: offset } } diff --git a/compiler/rustc_type_ir/src/outlives.rs b/compiler/rustc_type_ir/src/outlives.rs index ac35215fbaa0d..0e94e989b978e 100644 --- a/compiler/rustc_type_ir/src/outlives.rs +++ b/compiler/rustc_type_ir/src/outlives.rs @@ -110,6 +110,18 @@ impl TypeVisitor for OutlivesCollector<'_, I> { ty::Coroutine(_, args) => { args.as_coroutine().tupled_upvars_ty().visit_with(self); + // Coroutines may not outlive a region unless the resume + // ty outlives a region. This is because the resume ty may + // store data that lives shorter than this outlives region + // across yield points, which may subsequently be accessed + // after the coroutine is resumed again. + // + // Conceptually, you may think of the resume arg as an upvar + // of `&mut Option`, since it is kinda like + // storage shared between the callee of the coroutine and the + // coroutine body. + args.as_coroutine().resume_ty().visit_with(self); + // We ignore regions in the coroutine interior as we don't // want these to affect region inference } diff --git a/compiler/stable_mir/src/mir/pretty.rs b/compiler/stable_mir/src/mir/pretty.rs index 13e3d229d06ac..8241b3f01b535 100644 --- a/compiler/stable_mir/src/mir/pretty.rs +++ b/compiler/stable_mir/src/mir/pretty.rs @@ -1,13 +1,14 @@ +//! Implement methods to pretty print stable MIR body. use std::fmt::Debug; use std::io::Write; use std::{fmt, io, iter}; use fmt::{Display, Formatter}; -use super::{AssertMessage, BinOp, BorrowKind, FakeBorrowKind, TerminatorKind}; +use super::{AggregateKind, AssertMessage, BinOp, BorrowKind, FakeBorrowKind, TerminatorKind}; use crate::mir::{Operand, Place, Rvalue, StatementKind, UnwindAction, VarDebugInfoContents}; -use crate::ty::{IndexedVal, MirConst, Ty, TyConst}; -use crate::{Body, Mutability, with}; +use crate::ty::{AdtKind, IndexedVal, MirConst, Ty, TyConst}; +use crate::{Body, CrateDef, Mutability, with}; impl Display for Ty { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { @@ -23,10 +24,11 @@ impl Debug for Place { pub(crate) fn function_body(writer: &mut W, body: &Body, name: &str) -> io::Result<()> { write!(writer, "fn {name}(")?; - body.arg_locals() - .iter() - .enumerate() - .try_for_each(|(index, local)| write!(writer, "_{}: {}", index + 1, local.ty))?; + let mut sep = ""; + for (index, local) in body.arg_locals().iter().enumerate() { + write!(writer, "{}_{}: {}", sep, index + 1, local.ty)?; + sep = ", "; + } write!(writer, ")")?; let return_local = body.ret_local(); @@ -73,39 +75,40 @@ pub(crate) fn function_body(writer: &mut W, body: &Body, name: &str) - } fn pretty_statement(writer: &mut W, statement: &StatementKind) -> io::Result<()> { + const INDENT: &str = " "; match statement { StatementKind::Assign(place, rval) => { - write!(writer, " {place:?} = ")?; + write!(writer, "{INDENT}{place:?} = ")?; pretty_rvalue(writer, rval)?; writeln!(writer, ";") } // FIXME: Add rest of the statements StatementKind::FakeRead(cause, place) => { - writeln!(writer, "FakeRead({cause:?}, {place:?});") + writeln!(writer, "{INDENT}FakeRead({cause:?}, {place:?});") } StatementKind::SetDiscriminant { place, variant_index } => { - writeln!(writer, "discriminant({place:?} = {};", variant_index.to_index()) + writeln!(writer, "{INDENT}discriminant({place:?} = {};", variant_index.to_index()) } StatementKind::Deinit(place) => writeln!(writer, "Deinit({place:?};"), StatementKind::StorageLive(local) => { - writeln!(writer, "StorageLive(_{local});") + writeln!(writer, "{INDENT}StorageLive(_{local});") } StatementKind::StorageDead(local) => { - writeln!(writer, "StorageDead(_{local});") + writeln!(writer, "{INDENT}StorageDead(_{local});") } StatementKind::Retag(kind, place) => writeln!(writer, "Retag({kind:?}, {place:?});"), StatementKind::PlaceMention(place) => { - writeln!(writer, "PlaceMention({place:?};") + writeln!(writer, "{INDENT}PlaceMention({place:?};") } StatementKind::ConstEvalCounter => { - writeln!(writer, "ConstEvalCounter;") + writeln!(writer, "{INDENT}ConstEvalCounter;") } - StatementKind::Nop => writeln!(writer, "nop;"), + StatementKind::Nop => writeln!(writer, "{INDENT}nop;"), StatementKind::AscribeUserType { .. } | StatementKind::Coverage(_) | StatementKind::Intrinsic(_) => { // FIX-ME: Make them pretty. - writeln!(writer, "{statement:?};") + writeln!(writer, "{INDENT}{statement:?};") } } } @@ -322,15 +325,11 @@ fn pretty_ty_const(ct: &TyConst) -> String { fn pretty_rvalue(writer: &mut W, rval: &Rvalue) -> io::Result<()> { match rval { Rvalue::AddressOf(mutability, place) => { - write!(writer, "&raw {}(*{:?})", pretty_mut(*mutability), place) + write!(writer, "&raw {} {:?}", pretty_mut(*mutability), place) } Rvalue::Aggregate(aggregate_kind, operands) => { // FIXME: Add pretty_aggregate function that returns a pretty string - write!(writer, "{aggregate_kind:?} (")?; - let mut op_iter = operands.iter(); - op_iter.next().map_or(Ok(()), |op| write!(writer, "{}", pretty_operand(op)))?; - op_iter.try_for_each(|op| write!(writer, ", {}", pretty_operand(op)))?; - write!(writer, ")") + pretty_aggregate(writer, aggregate_kind, operands) } Rvalue::BinaryOp(bin, op1, op2) => { write!(writer, "{:?}({}, {})", bin, pretty_operand(op1), pretty_operand(op2)) @@ -360,22 +359,74 @@ fn pretty_rvalue(writer: &mut W, rval: &Rvalue) -> io::Result<()> { write!(writer, "{kind}{place:?}") } Rvalue::Repeat(op, cnst) => { - write!(writer, "{} \" \" {}", pretty_operand(op), pretty_ty_const(cnst)) + write!(writer, "[{}; {}]", pretty_operand(op), pretty_ty_const(cnst)) } Rvalue::ShallowInitBox(_, _) => Ok(()), Rvalue::ThreadLocalRef(item) => { write!(writer, "thread_local_ref{item:?}") } Rvalue::NullaryOp(nul, ty) => { - write!(writer, "{nul:?} {ty} \" \"") + write!(writer, "{nul:?}::<{ty}>() \" \"") } Rvalue::UnaryOp(un, op) => { - write!(writer, "{} \" \" {:?}", pretty_operand(op), un) + write!(writer, "{:?}({})", un, pretty_operand(op)) } Rvalue::Use(op) => write!(writer, "{}", pretty_operand(op)), } } +fn pretty_aggregate( + writer: &mut W, + aggregate_kind: &AggregateKind, + operands: &Vec, +) -> io::Result<()> { + let suffix = match aggregate_kind { + AggregateKind::Array(_) => { + write!(writer, "[")?; + "]" + } + AggregateKind::Tuple => { + write!(writer, "(")?; + ")" + } + AggregateKind::Adt(def, var, _, _, _) => { + if def.kind() == AdtKind::Enum { + write!(writer, "{}::{}", def.name(), def.variant(*var).unwrap().name())?; + } else { + write!(writer, "{}", def.variant(*var).unwrap().name())?; + } + if operands.is_empty() { + return Ok(()); + } + // FIXME: Change this once we have CtorKind in StableMIR. + write!(writer, "(")?; + ")" + } + AggregateKind::Closure(def, _) => { + write!(writer, "{{closure@{:?}}}(", def.span())?; + ")" + } + AggregateKind::Coroutine(def, _, _) => { + write!(writer, "{{coroutine@{:?}}}(", def.span())?; + ")" + } + AggregateKind::RawPtr(ty, mutability) => { + write!( + writer, + "*{} {ty} from (", + if *mutability == Mutability::Mut { "mut" } else { "const" } + )?; + ")" + } + }; + let mut separator = ""; + for op in operands { + write!(writer, "{}{}", separator, pretty_operand(op))?; + separator = ", "; + } + write!(writer, "{suffix}") +} + fn pretty_mut(mutability: Mutability) -> &'static str { match mutability { Mutability::Not => " ", diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index bc354650a8ebc..e4956c7c53c8d 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -183,15 +183,14 @@ #![stable(feature = "rust1", since = "1.0.0")] -use core::any::Any; -use core::async_iter::AsyncIterator; +use core::borrow::{Borrow, BorrowMut}; #[cfg(not(no_global_oom_handling))] use core::clone::CloneToUninit; use core::cmp::Ordering; -use core::error::Error; +use core::error::{self, Error}; +use core::fmt; use core::future::Future; use core::hash::{Hash, Hasher}; -use core::iter::FusedIterator; use core::marker::{Tuple, Unsize}; use core::mem::{self, SizedTypeProperties}; use core::ops::{ @@ -201,27 +200,24 @@ use core::ops::{ use core::pin::{Pin, PinCoerceUnsized}; use core::ptr::{self, NonNull, Unique}; use core::task::{Context, Poll}; -use core::{borrow, fmt, slice}; - -#[unstable(feature = "thin_box", issue = "92791")] -pub use thin::ThinBox; #[cfg(not(no_global_oom_handling))] use crate::alloc::handle_alloc_error; use crate::alloc::{AllocError, Allocator, Global, Layout}; -#[cfg(not(no_global_oom_handling))] -use crate::borrow::Cow; use crate::raw_vec::RawVec; #[cfg(not(no_global_oom_handling))] use crate::str::from_boxed_utf8_unchecked; -#[cfg(not(no_global_oom_handling))] -use crate::string::String; -use crate::vec; -#[cfg(not(no_global_oom_handling))] -use crate::vec::Vec; +/// Conversion related impls for `Box<_>` (`From`, `downcast`, etc) +mod convert; +/// Iterator related impls for `Box<_>`. +mod iter; +/// [`ThinBox`] implementation. mod thin; +#[unstable(feature = "thin_box", issue = "92791")] +pub use thin::ThinBox; + /// A pointer type that uniquely owns a heap allocation of type `T`. /// /// See the [module-level documentation](../../std/boxed/index.html) for more. @@ -1766,6 +1762,41 @@ impl Clone for Box { } } +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "box_slice_clone", since = "1.3.0")] +impl Clone for Box<[T], A> { + fn clone(&self) -> Self { + let alloc = Box::allocator(self).clone(); + self.to_vec_in(alloc).into_boxed_slice() + } + + /// Copies `source`'s contents into `self` without creating a new allocation, + /// so long as the two are of the same length. + /// + /// # Examples + /// + /// ``` + /// let x = Box::new([5, 6, 7]); + /// let mut y = Box::new([8, 9, 10]); + /// let yp: *const [i32] = &*y; + /// + /// y.clone_from(&x); + /// + /// // The value is the same + /// assert_eq!(x, y); + /// + /// // And no allocation occurred + /// assert_eq!(yp, &*y); + /// ``` + fn clone_from(&mut self, source: &Self) { + if self.len() == source.len() { + self.clone_from_slice(&source); + } else { + *self = source.clone(); + } + } +} + #[cfg(not(no_global_oom_handling))] #[stable(feature = "box_slice_clone", since = "1.3.0")] impl Clone for Box { @@ -1787,6 +1818,7 @@ impl PartialEq for Box { PartialEq::ne(&**self, &**other) } } + #[stable(feature = "rust1", since = "1.0.0")] impl PartialOrd for Box { #[inline] @@ -1810,6 +1842,7 @@ impl PartialOrd for Box { PartialOrd::gt(&**self, &**other) } } + #[stable(feature = "rust1", since = "1.0.0")] impl Ord for Box { #[inline] @@ -1817,6 +1850,7 @@ impl Ord for Box { Ord::cmp(&**self, &**other) } } + #[stable(feature = "rust1", since = "1.0.0")] impl Eq for Box {} @@ -1879,797 +1913,143 @@ impl Hasher for Box { } } -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "from_for_ptrs", since = "1.6.0")] -impl From for Box { - /// Converts a `T` into a `Box` - /// - /// The conversion allocates on the heap and moves `t` - /// from the stack into it. - /// - /// # Examples - /// - /// ```rust - /// let x = 5; - /// let boxed = Box::new(5); - /// - /// assert_eq!(Box::from(x), boxed); - /// ``` - fn from(t: T) -> Self { - Box::new(t) +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for Box { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(&**self, f) } } -#[stable(feature = "pin", since = "1.33.0")] -impl From> for Pin> -where - A: 'static, -{ - /// Converts a `Box` into a `Pin>`. If `T` does not implement [`Unpin`], then - /// `*boxed` will be pinned in memory and unable to be moved. - /// - /// This conversion does not allocate on the heap and happens in place. - /// - /// This is also available via [`Box::into_pin`]. - /// - /// Constructing and pinning a `Box` with >>::from([Box::new]\(x)) - /// can also be written more concisely using [Box::pin]\(x). - /// This `From` implementation is useful if you already have a `Box`, or you are - /// constructing a (pinned) `Box` in a different way than with [`Box::new`]. - fn from(boxed: Box) -> Self { - Box::into_pin(boxed) +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for Box { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&**self, f) } } -/// Specialization trait used for `From<&[T]>`. -#[cfg(not(no_global_oom_handling))] -trait BoxFromSlice { - fn from_slice(slice: &[T]) -> Self; +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Pointer for Box { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // It's not possible to extract the inner Uniq directly from the Box, + // instead we cast it to a *const which aliases the Unique + let ptr: *const T = &**self; + fmt::Pointer::fmt(&ptr, f) + } } -#[cfg(not(no_global_oom_handling))] -impl BoxFromSlice for Box<[T]> { - #[inline] - default fn from_slice(slice: &[T]) -> Self { - slice.to_vec().into_boxed_slice() +#[stable(feature = "rust1", since = "1.0.0")] +impl Deref for Box { + type Target = T; + + fn deref(&self) -> &T { + &**self } } -#[cfg(not(no_global_oom_handling))] -impl BoxFromSlice for Box<[T]> { - #[inline] - fn from_slice(slice: &[T]) -> Self { - let len = slice.len(); - let buf = RawVec::with_capacity(len); - unsafe { - ptr::copy_nonoverlapping(slice.as_ptr(), buf.ptr(), len); - buf.into_box(slice.len()).assume_init() - } +#[stable(feature = "rust1", since = "1.0.0")] +impl DerefMut for Box { + fn deref_mut(&mut self) -> &mut T { + &mut **self } } -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "box_from_slice", since = "1.17.0")] -impl From<&[T]> for Box<[T]> { - /// Converts a `&[T]` into a `Box<[T]>` - /// - /// This conversion allocates on the heap - /// and performs a copy of `slice` and its contents. - /// - /// # Examples - /// ```rust - /// // create a &[u8] which will be used to create a Box<[u8]> - /// let slice: &[u8] = &[104, 101, 108, 108, 111]; - /// let boxed_slice: Box<[u8]> = Box::from(slice); - /// - /// println!("{boxed_slice:?}"); - /// ``` - #[inline] - fn from(slice: &[T]) -> Box<[T]> { - >::from_slice(slice) +#[unstable(feature = "deref_pure_trait", issue = "87121")] +unsafe impl DerefPure for Box {} + +#[unstable(feature = "legacy_receiver_trait", issue = "none")] +impl LegacyReceiver for Box {} + +#[stable(feature = "boxed_closure_impls", since = "1.35.0")] +impl + ?Sized, A: Allocator> FnOnce for Box { + type Output = >::Output; + + extern "rust-call" fn call_once(self, args: Args) -> Self::Output { + >::call_once(*self, args) } } -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "box_from_cow", since = "1.45.0")] -impl From> for Box<[T]> { - /// Converts a `Cow<'_, [T]>` into a `Box<[T]>` - /// - /// When `cow` is the `Cow::Borrowed` variant, this - /// conversion allocates on the heap and copies the - /// underlying slice. Otherwise, it will try to reuse the owned - /// `Vec`'s allocation. - #[inline] - fn from(cow: Cow<'_, [T]>) -> Box<[T]> { - match cow { - Cow::Borrowed(slice) => Box::from(slice), - Cow::Owned(slice) => Box::from(slice), - } +#[stable(feature = "boxed_closure_impls", since = "1.35.0")] +impl + ?Sized, A: Allocator> FnMut for Box { + extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output { + >::call_mut(self, args) } } -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "box_from_slice", since = "1.17.0")] -impl From<&str> for Box { - /// Converts a `&str` into a `Box` - /// - /// This conversion allocates on the heap - /// and performs a copy of `s`. - /// - /// # Examples - /// - /// ```rust - /// let boxed: Box = Box::from("hello"); - /// println!("{boxed}"); - /// ``` - #[inline] - fn from(s: &str) -> Box { - unsafe { from_boxed_utf8_unchecked(Box::from(s.as_bytes())) } +#[stable(feature = "boxed_closure_impls", since = "1.35.0")] +impl + ?Sized, A: Allocator> Fn for Box { + extern "rust-call" fn call(&self, args: Args) -> Self::Output { + >::call(self, args) } } -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "box_from_cow", since = "1.45.0")] -impl From> for Box { - /// Converts a `Cow<'_, str>` into a `Box` - /// - /// When `cow` is the `Cow::Borrowed` variant, this - /// conversion allocates on the heap and copies the - /// underlying `str`. Otherwise, it will try to reuse the owned - /// `String`'s allocation. - /// - /// # Examples - /// - /// ```rust - /// use std::borrow::Cow; - /// - /// let unboxed = Cow::Borrowed("hello"); - /// let boxed: Box = Box::from(unboxed); - /// println!("{boxed}"); - /// ``` - /// - /// ```rust - /// # use std::borrow::Cow; - /// let unboxed = Cow::Owned("hello".to_string()); - /// let boxed: Box = Box::from(unboxed); - /// println!("{boxed}"); - /// ``` - #[inline] - fn from(cow: Cow<'_, str>) -> Box { - match cow { - Cow::Borrowed(s) => Box::from(s), - Cow::Owned(s) => Box::from(s), - } +#[unstable(feature = "async_fn_traits", issue = "none")] +impl + ?Sized, A: Allocator> AsyncFnOnce for Box { + type Output = F::Output; + type CallOnceFuture = F::CallOnceFuture; + + extern "rust-call" fn async_call_once(self, args: Args) -> Self::CallOnceFuture { + F::async_call_once(*self, args) } } -#[stable(feature = "boxed_str_conv", since = "1.19.0")] -impl From> for Box<[u8], A> { - /// Converts a `Box` into a `Box<[u8]>` - /// - /// This conversion does not allocate on the heap and happens in place. - /// - /// # Examples - /// ```rust - /// // create a Box which will be used to create a Box<[u8]> - /// let boxed: Box = Box::from("hello"); - /// let boxed_str: Box<[u8]> = Box::from(boxed); - /// - /// // create a &[u8] which will be used to create a Box<[u8]> - /// let slice: &[u8] = &[104, 101, 108, 108, 111]; - /// let boxed_slice = Box::from(slice); - /// - /// assert_eq!(boxed_slice, boxed_str); - /// ``` - #[inline] - fn from(s: Box) -> Self { - let (raw, alloc) = Box::into_raw_with_allocator(s); - unsafe { Box::from_raw_in(raw as *mut [u8], alloc) } +#[unstable(feature = "async_fn_traits", issue = "none")] +impl + ?Sized, A: Allocator> AsyncFnMut for Box { + type CallRefFuture<'a> + = F::CallRefFuture<'a> + where + Self: 'a; + + extern "rust-call" fn async_call_mut(&mut self, args: Args) -> Self::CallRefFuture<'_> { + F::async_call_mut(self, args) } } -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "box_from_array", since = "1.45.0")] -impl From<[T; N]> for Box<[T]> { - /// Converts a `[T; N]` into a `Box<[T]>` - /// - /// This conversion moves the array to newly heap-allocated memory. - /// - /// # Examples - /// - /// ```rust - /// let boxed: Box<[u8]> = Box::from([4, 2]); - /// println!("{boxed:?}"); - /// ``` - fn from(array: [T; N]) -> Box<[T]> { - Box::new(array) +#[unstable(feature = "async_fn_traits", issue = "none")] +impl + ?Sized, A: Allocator> AsyncFn for Box { + extern "rust-call" fn async_call(&self, args: Args) -> Self::CallRefFuture<'_> { + F::async_call(self, args) } } -/// Casts a boxed slice to a boxed array. -/// -/// # Safety -/// -/// `boxed_slice.len()` must be exactly `N`. -unsafe fn boxed_slice_as_array_unchecked( - boxed_slice: Box<[T], A>, -) -> Box<[T; N], A> { - debug_assert_eq!(boxed_slice.len(), N); - - let (ptr, alloc) = Box::into_raw_with_allocator(boxed_slice); - // SAFETY: Pointer and allocator came from an existing box, - // and our safety condition requires that the length is exactly `N` - unsafe { Box::from_raw_in(ptr as *mut [T; N], alloc) } -} +#[unstable(feature = "coerce_unsized", issue = "18598")] +impl, U: ?Sized, A: Allocator> CoerceUnsized> for Box {} -#[stable(feature = "boxed_slice_try_from", since = "1.43.0")] -impl TryFrom> for Box<[T; N]> { - type Error = Box<[T]>; +#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")] +unsafe impl PinCoerceUnsized for Box {} - /// Attempts to convert a `Box<[T]>` into a `Box<[T; N]>`. - /// - /// The conversion occurs in-place and does not require a - /// new memory allocation. - /// - /// # Errors - /// - /// Returns the old `Box<[T]>` in the `Err` variant if - /// `boxed_slice.len()` does not equal `N`. - fn try_from(boxed_slice: Box<[T]>) -> Result { - if boxed_slice.len() == N { - Ok(unsafe { boxed_slice_as_array_unchecked(boxed_slice) }) - } else { - Err(boxed_slice) - } +// It is quite crucial that we only allow the `Global` allocator here. +// Handling arbitrary custom allocators (which can affect the `Box` layout heavily!) +// would need a lot of codegen and interpreter adjustments. +#[unstable(feature = "dispatch_from_dyn", issue = "none")] +impl, U: ?Sized> DispatchFromDyn> for Box {} + +#[stable(feature = "box_borrow", since = "1.1.0")] +impl Borrow for Box { + fn borrow(&self) -> &T { + &**self } } -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "boxed_array_try_from_vec", since = "1.66.0")] -impl TryFrom> for Box<[T; N]> { - type Error = Vec; +#[stable(feature = "box_borrow", since = "1.1.0")] +impl BorrowMut for Box { + fn borrow_mut(&mut self) -> &mut T { + &mut **self + } +} - /// Attempts to convert a `Vec` into a `Box<[T; N]>`. - /// - /// Like [`Vec::into_boxed_slice`], this is in-place if `vec.capacity() == N`, - /// but will require a reallocation otherwise. - /// - /// # Errors - /// - /// Returns the original `Vec` in the `Err` variant if - /// `boxed_slice.len()` does not equal `N`. - /// - /// # Examples - /// - /// This can be used with [`vec!`] to create an array on the heap: - /// - /// ``` - /// let state: Box<[f32; 100]> = vec![1.0; 100].try_into().unwrap(); - /// assert_eq!(state.len(), 100); - /// ``` - fn try_from(vec: Vec) -> Result { - if vec.len() == N { - let boxed_slice = vec.into_boxed_slice(); - Ok(unsafe { boxed_slice_as_array_unchecked(boxed_slice) }) - } else { - Err(vec) - } +#[stable(since = "1.5.0", feature = "smart_ptr_as_ref")] +impl AsRef for Box { + fn as_ref(&self) -> &T { + &**self } } -impl Box { - /// Attempts to downcast the box to a concrete type. - /// - /// # Examples - /// - /// ``` - /// use std::any::Any; - /// - /// fn print_if_string(value: Box) { - /// if let Ok(string) = value.downcast::() { - /// println!("String ({}): {}", string.len(), string); - /// } - /// } - /// - /// let my_string = "Hello World".to_string(); - /// print_if_string(Box::new(my_string)); - /// print_if_string(Box::new(0i8)); - /// ``` - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn downcast(self) -> Result, Self> { - if self.is::() { unsafe { Ok(self.downcast_unchecked::()) } } else { Err(self) } +#[stable(since = "1.5.0", feature = "smart_ptr_as_ref")] +impl AsMut for Box { + fn as_mut(&mut self) -> &mut T { + &mut **self } - - /// Downcasts the box to a concrete type. - /// - /// For a safe alternative see [`downcast`]. - /// - /// # Examples - /// - /// ``` - /// #![feature(downcast_unchecked)] - /// - /// use std::any::Any; - /// - /// let x: Box = Box::new(1_usize); - /// - /// unsafe { - /// assert_eq!(*x.downcast_unchecked::(), 1); - /// } - /// ``` - /// - /// # Safety - /// - /// The contained value must be of type `T`. Calling this method - /// with the incorrect type is *undefined behavior*. - /// - /// [`downcast`]: Self::downcast - #[inline] - #[unstable(feature = "downcast_unchecked", issue = "90850")] - pub unsafe fn downcast_unchecked(self) -> Box { - debug_assert!(self.is::()); - unsafe { - let (raw, alloc): (*mut dyn Any, _) = Box::into_raw_with_allocator(self); - Box::from_raw_in(raw as *mut T, alloc) - } - } -} - -impl Box { - /// Attempts to downcast the box to a concrete type. - /// - /// # Examples - /// - /// ``` - /// use std::any::Any; - /// - /// fn print_if_string(value: Box) { - /// if let Ok(string) = value.downcast::() { - /// println!("String ({}): {}", string.len(), string); - /// } - /// } - /// - /// let my_string = "Hello World".to_string(); - /// print_if_string(Box::new(my_string)); - /// print_if_string(Box::new(0i8)); - /// ``` - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn downcast(self) -> Result, Self> { - if self.is::() { unsafe { Ok(self.downcast_unchecked::()) } } else { Err(self) } - } - - /// Downcasts the box to a concrete type. - /// - /// For a safe alternative see [`downcast`]. - /// - /// # Examples - /// - /// ``` - /// #![feature(downcast_unchecked)] - /// - /// use std::any::Any; - /// - /// let x: Box = Box::new(1_usize); - /// - /// unsafe { - /// assert_eq!(*x.downcast_unchecked::(), 1); - /// } - /// ``` - /// - /// # Safety - /// - /// The contained value must be of type `T`. Calling this method - /// with the incorrect type is *undefined behavior*. - /// - /// [`downcast`]: Self::downcast - #[inline] - #[unstable(feature = "downcast_unchecked", issue = "90850")] - pub unsafe fn downcast_unchecked(self) -> Box { - debug_assert!(self.is::()); - unsafe { - let (raw, alloc): (*mut (dyn Any + Send), _) = Box::into_raw_with_allocator(self); - Box::from_raw_in(raw as *mut T, alloc) - } - } -} - -impl Box { - /// Attempts to downcast the box to a concrete type. - /// - /// # Examples - /// - /// ``` - /// use std::any::Any; - /// - /// fn print_if_string(value: Box) { - /// if let Ok(string) = value.downcast::() { - /// println!("String ({}): {}", string.len(), string); - /// } - /// } - /// - /// let my_string = "Hello World".to_string(); - /// print_if_string(Box::new(my_string)); - /// print_if_string(Box::new(0i8)); - /// ``` - #[inline] - #[stable(feature = "box_send_sync_any_downcast", since = "1.51.0")] - pub fn downcast(self) -> Result, Self> { - if self.is::() { unsafe { Ok(self.downcast_unchecked::()) } } else { Err(self) } - } - - /// Downcasts the box to a concrete type. - /// - /// For a safe alternative see [`downcast`]. - /// - /// # Examples - /// - /// ``` - /// #![feature(downcast_unchecked)] - /// - /// use std::any::Any; - /// - /// let x: Box = Box::new(1_usize); - /// - /// unsafe { - /// assert_eq!(*x.downcast_unchecked::(), 1); - /// } - /// ``` - /// - /// # Safety - /// - /// The contained value must be of type `T`. Calling this method - /// with the incorrect type is *undefined behavior*. - /// - /// [`downcast`]: Self::downcast - #[inline] - #[unstable(feature = "downcast_unchecked", issue = "90850")] - pub unsafe fn downcast_unchecked(self) -> Box { - debug_assert!(self.is::()); - unsafe { - let (raw, alloc): (*mut (dyn Any + Send + Sync), _) = - Box::into_raw_with_allocator(self); - Box::from_raw_in(raw as *mut T, alloc) - } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Display for Box { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(&**self, f) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Debug for Box { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(&**self, f) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Pointer for Box { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - // It's not possible to extract the inner Uniq directly from the Box, - // instead we cast it to a *const which aliases the Unique - let ptr: *const T = &**self; - fmt::Pointer::fmt(&ptr, f) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Deref for Box { - type Target = T; - - fn deref(&self) -> &T { - &**self - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl DerefMut for Box { - fn deref_mut(&mut self) -> &mut T { - &mut **self - } -} - -#[unstable(feature = "deref_pure_trait", issue = "87121")] -unsafe impl DerefPure for Box {} - -#[unstable(feature = "legacy_receiver_trait", issue = "none")] -impl LegacyReceiver for Box {} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for Box { - type Item = I::Item; - fn next(&mut self) -> Option { - (**self).next() - } - fn size_hint(&self) -> (usize, Option) { - (**self).size_hint() - } - fn nth(&mut self, n: usize) -> Option { - (**self).nth(n) - } - fn last(self) -> Option { - BoxIter::last(self) - } -} - -trait BoxIter { - type Item; - fn last(self) -> Option; -} - -impl BoxIter for Box { - type Item = I::Item; - default fn last(self) -> Option { - #[inline] - fn some(_: Option, x: T) -> Option { - Some(x) - } - - self.fold(None, some) - } -} - -/// Specialization for sized `I`s that uses `I`s implementation of `last()` -/// instead of the default. -#[stable(feature = "rust1", since = "1.0.0")] -impl BoxIter for Box { - fn last(self) -> Option { - (*self).last() - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl DoubleEndedIterator for Box { - fn next_back(&mut self) -> Option { - (**self).next_back() - } - fn nth_back(&mut self, n: usize) -> Option { - (**self).nth_back(n) - } -} -#[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for Box { - fn len(&self) -> usize { - (**self).len() - } - fn is_empty(&self) -> bool { - (**self).is_empty() - } -} - -#[stable(feature = "fused", since = "1.26.0")] -impl FusedIterator for Box {} - -#[stable(feature = "boxed_closure_impls", since = "1.35.0")] -impl + ?Sized, A: Allocator> FnOnce for Box { - type Output = >::Output; - - extern "rust-call" fn call_once(self, args: Args) -> Self::Output { - >::call_once(*self, args) - } -} - -#[stable(feature = "boxed_closure_impls", since = "1.35.0")] -impl + ?Sized, A: Allocator> FnMut for Box { - extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output { - >::call_mut(self, args) - } -} - -#[stable(feature = "boxed_closure_impls", since = "1.35.0")] -impl + ?Sized, A: Allocator> Fn for Box { - extern "rust-call" fn call(&self, args: Args) -> Self::Output { - >::call(self, args) - } -} - -#[unstable(feature = "async_fn_traits", issue = "none")] -impl + ?Sized, A: Allocator> AsyncFnOnce for Box { - type Output = F::Output; - type CallOnceFuture = F::CallOnceFuture; - - extern "rust-call" fn async_call_once(self, args: Args) -> Self::CallOnceFuture { - F::async_call_once(*self, args) - } -} - -#[unstable(feature = "async_fn_traits", issue = "none")] -impl + ?Sized, A: Allocator> AsyncFnMut for Box { - type CallRefFuture<'a> - = F::CallRefFuture<'a> - where - Self: 'a; - - extern "rust-call" fn async_call_mut(&mut self, args: Args) -> Self::CallRefFuture<'_> { - F::async_call_mut(self, args) - } -} - -#[unstable(feature = "async_fn_traits", issue = "none")] -impl + ?Sized, A: Allocator> AsyncFn for Box { - extern "rust-call" fn async_call(&self, args: Args) -> Self::CallRefFuture<'_> { - F::async_call(self, args) - } -} - -#[unstable(feature = "coerce_unsized", issue = "18598")] -impl, U: ?Sized, A: Allocator> CoerceUnsized> for Box {} - -// It is quite crucial that we only allow the `Global` allocator here. -// Handling arbitrary custom allocators (which can affect the `Box` layout heavily!) -// would need a lot of codegen and interpreter adjustments. -#[unstable(feature = "dispatch_from_dyn", issue = "none")] -impl, U: ?Sized> DispatchFromDyn> for Box {} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "boxed_slice_from_iter", since = "1.32.0")] -impl FromIterator for Box<[I]> { - fn from_iter>(iter: T) -> Self { - iter.into_iter().collect::>().into_boxed_slice() - } -} - -/// This implementation is required to make sure that the `Box<[I]>: IntoIterator` -/// implementation doesn't overlap with `IntoIterator for T where T: Iterator` blanket. -#[stable(feature = "boxed_slice_into_iter", since = "1.80.0")] -impl !Iterator for Box<[I], A> {} - -/// This implementation is required to make sure that the `&Box<[I]>: IntoIterator` -/// implementation doesn't overlap with `IntoIterator for T where T: Iterator` blanket. -#[stable(feature = "boxed_slice_into_iter", since = "1.80.0")] -impl<'a, I, A: Allocator> !Iterator for &'a Box<[I], A> {} - -/// This implementation is required to make sure that the `&mut Box<[I]>: IntoIterator` -/// implementation doesn't overlap with `IntoIterator for T where T: Iterator` blanket. -#[stable(feature = "boxed_slice_into_iter", since = "1.80.0")] -impl<'a, I, A: Allocator> !Iterator for &'a mut Box<[I], A> {} - -// Note: the `#[rustc_skip_during_method_dispatch(boxed_slice)]` on `trait IntoIterator` -// hides this implementation from explicit `.into_iter()` calls on editions < 2024, -// so those calls will still resolve to the slice implementation, by reference. -#[stable(feature = "boxed_slice_into_iter", since = "1.80.0")] -impl IntoIterator for Box<[I], A> { - type IntoIter = vec::IntoIter; - type Item = I; - fn into_iter(self) -> vec::IntoIter { - self.into_vec().into_iter() - } -} - -#[stable(feature = "boxed_slice_into_iter", since = "1.80.0")] -impl<'a, I, A: Allocator> IntoIterator for &'a Box<[I], A> { - type IntoIter = slice::Iter<'a, I>; - type Item = &'a I; - fn into_iter(self) -> slice::Iter<'a, I> { - self.iter() - } -} - -#[stable(feature = "boxed_slice_into_iter", since = "1.80.0")] -impl<'a, I, A: Allocator> IntoIterator for &'a mut Box<[I], A> { - type IntoIter = slice::IterMut<'a, I>; - type Item = &'a mut I; - fn into_iter(self) -> slice::IterMut<'a, I> { - self.iter_mut() - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "boxed_str_from_iter", since = "1.80.0")] -impl FromIterator for Box { - fn from_iter>(iter: T) -> Self { - String::from_iter(iter).into_boxed_str() - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "boxed_str_from_iter", since = "1.80.0")] -impl<'a> FromIterator<&'a char> for Box { - fn from_iter>(iter: T) -> Self { - String::from_iter(iter).into_boxed_str() - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "boxed_str_from_iter", since = "1.80.0")] -impl<'a> FromIterator<&'a str> for Box { - fn from_iter>(iter: T) -> Self { - String::from_iter(iter).into_boxed_str() - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "boxed_str_from_iter", since = "1.80.0")] -impl FromIterator for Box { - fn from_iter>(iter: T) -> Self { - String::from_iter(iter).into_boxed_str() - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "boxed_str_from_iter", since = "1.80.0")] -impl FromIterator> for Box { - fn from_iter>>(iter: T) -> Self { - String::from_iter(iter).into_boxed_str() - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "boxed_str_from_iter", since = "1.80.0")] -impl<'a> FromIterator> for Box { - fn from_iter>>(iter: T) -> Self { - String::from_iter(iter).into_boxed_str() - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "box_slice_clone", since = "1.3.0")] -impl Clone for Box<[T], A> { - fn clone(&self) -> Self { - let alloc = Box::allocator(self).clone(); - self.to_vec_in(alloc).into_boxed_slice() - } - - /// Copies `source`'s contents into `self` without creating a new allocation, - /// so long as the two are of the same length. - /// - /// # Examples - /// - /// ``` - /// let x = Box::new([5, 6, 7]); - /// let mut y = Box::new([8, 9, 10]); - /// let yp: *const [i32] = &*y; - /// - /// y.clone_from(&x); - /// - /// // The value is the same - /// assert_eq!(x, y); - /// - /// // And no allocation occurred - /// assert_eq!(yp, &*y); - /// ``` - fn clone_from(&mut self, source: &Self) { - if self.len() == source.len() { - self.clone_from_slice(&source); - } else { - *self = source.clone(); - } - } -} - -#[stable(feature = "box_borrow", since = "1.1.0")] -impl borrow::Borrow for Box { - fn borrow(&self) -> &T { - &**self - } -} - -#[stable(feature = "box_borrow", since = "1.1.0")] -impl borrow::BorrowMut for Box { - fn borrow_mut(&mut self) -> &mut T { - &mut **self - } -} - -#[stable(since = "1.5.0", feature = "smart_ptr_as_ref")] -impl AsRef for Box { - fn as_ref(&self) -> &T { - &**self - } -} - -#[stable(since = "1.5.0", feature = "smart_ptr_as_ref")] -impl AsMut for Box { - fn as_mut(&mut self) -> &mut T { - &mut **self - } -} +} /* Nota bene * @@ -2728,311 +2108,23 @@ impl Future for Box { } } -#[unstable(feature = "async_iterator", issue = "79024")] -impl AsyncIterator for Box { - type Item = S::Item; - - fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - Pin::new(&mut **self).poll_next(cx) - } - - fn size_hint(&self) -> (usize, Option) { - (**self).size_hint() - } -} - -impl dyn Error { - #[inline] - #[stable(feature = "error_downcast", since = "1.3.0")] - #[rustc_allow_incoherent_impl] - /// Attempts to downcast the box to a concrete type. - pub fn downcast(self: Box) -> Result, Box> { - if self.is::() { - unsafe { - let raw: *mut dyn Error = Box::into_raw(self); - Ok(Box::from_raw(raw as *mut T)) - } - } else { - Err(self) - } - } -} - -impl dyn Error + Send { - #[inline] - #[stable(feature = "error_downcast", since = "1.3.0")] - #[rustc_allow_incoherent_impl] - /// Attempts to downcast the box to a concrete type. - pub fn downcast(self: Box) -> Result, Box> { - let err: Box = self; - ::downcast(err).map_err(|s| unsafe { - // Reapply the `Send` marker. - mem::transmute::, Box>(s) - }) - } -} - -impl dyn Error + Send + Sync { - #[inline] - #[stable(feature = "error_downcast", since = "1.3.0")] - #[rustc_allow_incoherent_impl] - /// Attempts to downcast the box to a concrete type. - pub fn downcast(self: Box) -> Result, Box> { - let err: Box = self; - ::downcast(err).map_err(|s| unsafe { - // Reapply the `Send + Sync` markers. - mem::transmute::, Box>(s) - }) - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, E: Error + 'a> From for Box { - /// Converts a type of [`Error`] into a box of dyn [`Error`]. - /// - /// # Examples - /// - /// ``` - /// use std::error::Error; - /// use std::fmt; - /// use std::mem; - /// - /// #[derive(Debug)] - /// struct AnError; - /// - /// impl fmt::Display for AnError { - /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - /// write!(f, "An error") - /// } - /// } - /// - /// impl Error for AnError {} - /// - /// let an_error = AnError; - /// assert!(0 == mem::size_of_val(&an_error)); - /// let a_boxed_error = Box::::from(an_error); - /// assert!(mem::size_of::>() == mem::size_of_val(&a_boxed_error)) - /// ``` - fn from(err: E) -> Box { - Box::new(err) - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, E: Error + Send + Sync + 'a> From for Box { - /// Converts a type of [`Error`] + [`Send`] + [`Sync`] into a box of - /// dyn [`Error`] + [`Send`] + [`Sync`]. - /// - /// # Examples - /// - /// ``` - /// use std::error::Error; - /// use std::fmt; - /// use std::mem; - /// - /// #[derive(Debug)] - /// struct AnError; - /// - /// impl fmt::Display for AnError { - /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - /// write!(f, "An error") - /// } - /// } - /// - /// impl Error for AnError {} - /// - /// unsafe impl Send for AnError {} - /// - /// unsafe impl Sync for AnError {} - /// - /// let an_error = AnError; - /// assert!(0 == mem::size_of_val(&an_error)); - /// let a_boxed_error = Box::::from(an_error); - /// assert!( - /// mem::size_of::>() == mem::size_of_val(&a_boxed_error)) - /// ``` - fn from(err: E) -> Box { - Box::new(err) - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a> From for Box { - /// Converts a [`String`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. - /// - /// # Examples - /// - /// ``` - /// use std::error::Error; - /// use std::mem; - /// - /// let a_string_error = "a string error".to_string(); - /// let a_boxed_error = Box::::from(a_string_error); - /// assert!( - /// mem::size_of::>() == mem::size_of_val(&a_boxed_error)) - /// ``` - #[inline] - fn from(err: String) -> Box { - struct StringError(String); - - impl Error for StringError { - #[allow(deprecated)] - fn description(&self) -> &str { - &self.0 - } - } - - impl fmt::Display for StringError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(&self.0, f) - } - } - - // Purposefully skip printing "StringError(..)" - impl fmt::Debug for StringError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(&self.0, f) - } - } - - Box::new(StringError(err)) - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "string_box_error", since = "1.6.0")] -impl<'a> From for Box { - /// Converts a [`String`] into a box of dyn [`Error`]. - /// - /// # Examples - /// - /// ``` - /// use std::error::Error; - /// use std::mem; - /// - /// let a_string_error = "a string error".to_string(); - /// let a_boxed_error = Box::::from(a_string_error); - /// assert!(mem::size_of::>() == mem::size_of_val(&a_boxed_error)) - /// ``` - fn from(str_err: String) -> Box { - let err1: Box = From::from(str_err); - let err2: Box = err1; - err2 - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a> From<&str> for Box { - /// Converts a [`str`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. - /// - /// [`str`]: prim@str - /// - /// # Examples - /// - /// ``` - /// use std::error::Error; - /// use std::mem; - /// - /// let a_str_error = "a str error"; - /// let a_boxed_error = Box::::from(a_str_error); - /// assert!( - /// mem::size_of::>() == mem::size_of_val(&a_boxed_error)) - /// ``` - #[inline] - fn from(err: &str) -> Box { - From::from(String::from(err)) - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "string_box_error", since = "1.6.0")] -impl<'a> From<&str> for Box { - /// Converts a [`str`] into a box of dyn [`Error`]. - /// - /// [`str`]: prim@str - /// - /// # Examples - /// - /// ``` - /// use std::error::Error; - /// use std::mem; - /// - /// let a_str_error = "a str error"; - /// let a_boxed_error = Box::::from(a_str_error); - /// assert!(mem::size_of::>() == mem::size_of_val(&a_boxed_error)) - /// ``` - fn from(err: &str) -> Box { - From::from(String::from(err)) - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "cow_box_error", since = "1.22.0")] -impl<'a, 'b> From> for Box { - /// Converts a [`Cow`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. - /// - /// # Examples - /// - /// ``` - /// use std::error::Error; - /// use std::mem; - /// use std::borrow::Cow; - /// - /// let a_cow_str_error = Cow::from("a str error"); - /// let a_boxed_error = Box::::from(a_cow_str_error); - /// assert!( - /// mem::size_of::>() == mem::size_of_val(&a_boxed_error)) - /// ``` - fn from(err: Cow<'b, str>) -> Box { - From::from(String::from(err)) - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "cow_box_error", since = "1.22.0")] -impl<'a, 'b> From> for Box { - /// Converts a [`Cow`] into a box of dyn [`Error`]. - /// - /// # Examples - /// - /// ``` - /// use std::error::Error; - /// use std::mem; - /// use std::borrow::Cow; - /// - /// let a_cow_str_error = Cow::from("a str error"); - /// let a_boxed_error = Box::::from(a_cow_str_error); - /// assert!(mem::size_of::>() == mem::size_of_val(&a_boxed_error)) - /// ``` - fn from(err: Cow<'b, str>) -> Box { - From::from(String::from(err)) - } -} - #[stable(feature = "box_error", since = "1.8.0")] -impl core::error::Error for Box { +impl Error for Box { #[allow(deprecated, deprecated_in_future)] fn description(&self) -> &str { - core::error::Error::description(&**self) + Error::description(&**self) } #[allow(deprecated)] - fn cause(&self) -> Option<&dyn core::error::Error> { - core::error::Error::cause(&**self) + fn cause(&self) -> Option<&dyn Error> { + Error::cause(&**self) } - fn source(&self) -> Option<&(dyn core::error::Error + 'static)> { - core::error::Error::source(&**self) + fn source(&self) -> Option<&(dyn Error + 'static)> { + Error::source(&**self) } - fn provide<'b>(&'b self, request: &mut core::error::Request<'b>) { - core::error::Error::provide(&**self, request); + fn provide<'b>(&'b self, request: &mut error::Request<'b>) { + Error::provide(&**self, request); } } - -#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")] -unsafe impl PinCoerceUnsized for Box {} diff --git a/library/alloc/src/boxed/convert.rs b/library/alloc/src/boxed/convert.rs new file mode 100644 index 0000000000000..19a583ca546e4 --- /dev/null +++ b/library/alloc/src/boxed/convert.rs @@ -0,0 +1,747 @@ +use core::any::Any; +use core::error::Error; +use core::mem; +use core::pin::Pin; +#[cfg(not(no_global_oom_handling))] +use core::{fmt, ptr}; + +use crate::alloc::Allocator; +#[cfg(not(no_global_oom_handling))] +use crate::borrow::Cow; +use crate::boxed::Box; +#[cfg(not(no_global_oom_handling))] +use crate::raw_vec::RawVec; +#[cfg(not(no_global_oom_handling))] +use crate::str::from_boxed_utf8_unchecked; +#[cfg(not(no_global_oom_handling))] +use crate::string::String; +#[cfg(not(no_global_oom_handling))] +use crate::vec::Vec; + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "from_for_ptrs", since = "1.6.0")] +impl From for Box { + /// Converts a `T` into a `Box` + /// + /// The conversion allocates on the heap and moves `t` + /// from the stack into it. + /// + /// # Examples + /// + /// ```rust + /// let x = 5; + /// let boxed = Box::new(5); + /// + /// assert_eq!(Box::from(x), boxed); + /// ``` + fn from(t: T) -> Self { + Box::new(t) + } +} + +#[stable(feature = "pin", since = "1.33.0")] +impl From> for Pin> +where + A: 'static, +{ + /// Converts a `Box` into a `Pin>`. If `T` does not implement [`Unpin`], then + /// `*boxed` will be pinned in memory and unable to be moved. + /// + /// This conversion does not allocate on the heap and happens in place. + /// + /// This is also available via [`Box::into_pin`]. + /// + /// Constructing and pinning a `Box` with >>::from([Box::new]\(x)) + /// can also be written more concisely using [Box::pin]\(x). + /// This `From` implementation is useful if you already have a `Box`, or you are + /// constructing a (pinned) `Box` in a different way than with [`Box::new`]. + fn from(boxed: Box) -> Self { + Box::into_pin(boxed) + } +} + +/// Specialization trait used for `From<&[T]>`. +#[cfg(not(no_global_oom_handling))] +trait BoxFromSlice { + fn from_slice(slice: &[T]) -> Self; +} + +#[cfg(not(no_global_oom_handling))] +impl BoxFromSlice for Box<[T]> { + #[inline] + default fn from_slice(slice: &[T]) -> Self { + slice.to_vec().into_boxed_slice() + } +} + +#[cfg(not(no_global_oom_handling))] +impl BoxFromSlice for Box<[T]> { + #[inline] + fn from_slice(slice: &[T]) -> Self { + let len = slice.len(); + let buf = RawVec::with_capacity(len); + unsafe { + ptr::copy_nonoverlapping(slice.as_ptr(), buf.ptr(), len); + buf.into_box(slice.len()).assume_init() + } + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "box_from_slice", since = "1.17.0")] +impl From<&[T]> for Box<[T]> { + /// Converts a `&[T]` into a `Box<[T]>` + /// + /// This conversion allocates on the heap + /// and performs a copy of `slice` and its contents. + /// + /// # Examples + /// ```rust + /// // create a &[u8] which will be used to create a Box<[u8]> + /// let slice: &[u8] = &[104, 101, 108, 108, 111]; + /// let boxed_slice: Box<[u8]> = Box::from(slice); + /// + /// println!("{boxed_slice:?}"); + /// ``` + #[inline] + fn from(slice: &[T]) -> Box<[T]> { + >::from_slice(slice) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "box_from_cow", since = "1.45.0")] +impl From> for Box<[T]> { + /// Converts a `Cow<'_, [T]>` into a `Box<[T]>` + /// + /// When `cow` is the `Cow::Borrowed` variant, this + /// conversion allocates on the heap and copies the + /// underlying slice. Otherwise, it will try to reuse the owned + /// `Vec`'s allocation. + #[inline] + fn from(cow: Cow<'_, [T]>) -> Box<[T]> { + match cow { + Cow::Borrowed(slice) => Box::from(slice), + Cow::Owned(slice) => Box::from(slice), + } + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "box_from_slice", since = "1.17.0")] +impl From<&str> for Box { + /// Converts a `&str` into a `Box` + /// + /// This conversion allocates on the heap + /// and performs a copy of `s`. + /// + /// # Examples + /// + /// ```rust + /// let boxed: Box = Box::from("hello"); + /// println!("{boxed}"); + /// ``` + #[inline] + fn from(s: &str) -> Box { + unsafe { from_boxed_utf8_unchecked(Box::from(s.as_bytes())) } + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "box_from_cow", since = "1.45.0")] +impl From> for Box { + /// Converts a `Cow<'_, str>` into a `Box` + /// + /// When `cow` is the `Cow::Borrowed` variant, this + /// conversion allocates on the heap and copies the + /// underlying `str`. Otherwise, it will try to reuse the owned + /// `String`'s allocation. + /// + /// # Examples + /// + /// ```rust + /// use std::borrow::Cow; + /// + /// let unboxed = Cow::Borrowed("hello"); + /// let boxed: Box = Box::from(unboxed); + /// println!("{boxed}"); + /// ``` + /// + /// ```rust + /// # use std::borrow::Cow; + /// let unboxed = Cow::Owned("hello".to_string()); + /// let boxed: Box = Box::from(unboxed); + /// println!("{boxed}"); + /// ``` + #[inline] + fn from(cow: Cow<'_, str>) -> Box { + match cow { + Cow::Borrowed(s) => Box::from(s), + Cow::Owned(s) => Box::from(s), + } + } +} + +#[stable(feature = "boxed_str_conv", since = "1.19.0")] +impl From> for Box<[u8], A> { + /// Converts a `Box` into a `Box<[u8]>` + /// + /// This conversion does not allocate on the heap and happens in place. + /// + /// # Examples + /// ```rust + /// // create a Box which will be used to create a Box<[u8]> + /// let boxed: Box = Box::from("hello"); + /// let boxed_str: Box<[u8]> = Box::from(boxed); + /// + /// // create a &[u8] which will be used to create a Box<[u8]> + /// let slice: &[u8] = &[104, 101, 108, 108, 111]; + /// let boxed_slice = Box::from(slice); + /// + /// assert_eq!(boxed_slice, boxed_str); + /// ``` + #[inline] + fn from(s: Box) -> Self { + let (raw, alloc) = Box::into_raw_with_allocator(s); + unsafe { Box::from_raw_in(raw as *mut [u8], alloc) } + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "box_from_array", since = "1.45.0")] +impl From<[T; N]> for Box<[T]> { + /// Converts a `[T; N]` into a `Box<[T]>` + /// + /// This conversion moves the array to newly heap-allocated memory. + /// + /// # Examples + /// + /// ```rust + /// let boxed: Box<[u8]> = Box::from([4, 2]); + /// println!("{boxed:?}"); + /// ``` + fn from(array: [T; N]) -> Box<[T]> { + Box::new(array) + } +} + +/// Casts a boxed slice to a boxed array. +/// +/// # Safety +/// +/// `boxed_slice.len()` must be exactly `N`. +unsafe fn boxed_slice_as_array_unchecked( + boxed_slice: Box<[T], A>, +) -> Box<[T; N], A> { + debug_assert_eq!(boxed_slice.len(), N); + + let (ptr, alloc) = Box::into_raw_with_allocator(boxed_slice); + // SAFETY: Pointer and allocator came from an existing box, + // and our safety condition requires that the length is exactly `N` + unsafe { Box::from_raw_in(ptr as *mut [T; N], alloc) } +} + +#[stable(feature = "boxed_slice_try_from", since = "1.43.0")] +impl TryFrom> for Box<[T; N]> { + type Error = Box<[T]>; + + /// Attempts to convert a `Box<[T]>` into a `Box<[T; N]>`. + /// + /// The conversion occurs in-place and does not require a + /// new memory allocation. + /// + /// # Errors + /// + /// Returns the old `Box<[T]>` in the `Err` variant if + /// `boxed_slice.len()` does not equal `N`. + fn try_from(boxed_slice: Box<[T]>) -> Result { + if boxed_slice.len() == N { + Ok(unsafe { boxed_slice_as_array_unchecked(boxed_slice) }) + } else { + Err(boxed_slice) + } + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "boxed_array_try_from_vec", since = "1.66.0")] +impl TryFrom> for Box<[T; N]> { + type Error = Vec; + + /// Attempts to convert a `Vec` into a `Box<[T; N]>`. + /// + /// Like [`Vec::into_boxed_slice`], this is in-place if `vec.capacity() == N`, + /// but will require a reallocation otherwise. + /// + /// # Errors + /// + /// Returns the original `Vec` in the `Err` variant if + /// `boxed_slice.len()` does not equal `N`. + /// + /// # Examples + /// + /// This can be used with [`vec!`] to create an array on the heap: + /// + /// ``` + /// let state: Box<[f32; 100]> = vec![1.0; 100].try_into().unwrap(); + /// assert_eq!(state.len(), 100); + /// ``` + fn try_from(vec: Vec) -> Result { + if vec.len() == N { + let boxed_slice = vec.into_boxed_slice(); + Ok(unsafe { boxed_slice_as_array_unchecked(boxed_slice) }) + } else { + Err(vec) + } + } +} + +impl Box { + /// Attempts to downcast the box to a concrete type. + /// + /// # Examples + /// + /// ``` + /// use std::any::Any; + /// + /// fn print_if_string(value: Box) { + /// if let Ok(string) = value.downcast::() { + /// println!("String ({}): {}", string.len(), string); + /// } + /// } + /// + /// let my_string = "Hello World".to_string(); + /// print_if_string(Box::new(my_string)); + /// print_if_string(Box::new(0i8)); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn downcast(self) -> Result, Self> { + if self.is::() { unsafe { Ok(self.downcast_unchecked::()) } } else { Err(self) } + } + + /// Downcasts the box to a concrete type. + /// + /// For a safe alternative see [`downcast`]. + /// + /// # Examples + /// + /// ``` + /// #![feature(downcast_unchecked)] + /// + /// use std::any::Any; + /// + /// let x: Box = Box::new(1_usize); + /// + /// unsafe { + /// assert_eq!(*x.downcast_unchecked::(), 1); + /// } + /// ``` + /// + /// # Safety + /// + /// The contained value must be of type `T`. Calling this method + /// with the incorrect type is *undefined behavior*. + /// + /// [`downcast`]: Self::downcast + #[inline] + #[unstable(feature = "downcast_unchecked", issue = "90850")] + pub unsafe fn downcast_unchecked(self) -> Box { + debug_assert!(self.is::()); + unsafe { + let (raw, alloc): (*mut dyn Any, _) = Box::into_raw_with_allocator(self); + Box::from_raw_in(raw as *mut T, alloc) + } + } +} + +impl Box { + /// Attempts to downcast the box to a concrete type. + /// + /// # Examples + /// + /// ``` + /// use std::any::Any; + /// + /// fn print_if_string(value: Box) { + /// if let Ok(string) = value.downcast::() { + /// println!("String ({}): {}", string.len(), string); + /// } + /// } + /// + /// let my_string = "Hello World".to_string(); + /// print_if_string(Box::new(my_string)); + /// print_if_string(Box::new(0i8)); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn downcast(self) -> Result, Self> { + if self.is::() { unsafe { Ok(self.downcast_unchecked::()) } } else { Err(self) } + } + + /// Downcasts the box to a concrete type. + /// + /// For a safe alternative see [`downcast`]. + /// + /// # Examples + /// + /// ``` + /// #![feature(downcast_unchecked)] + /// + /// use std::any::Any; + /// + /// let x: Box = Box::new(1_usize); + /// + /// unsafe { + /// assert_eq!(*x.downcast_unchecked::(), 1); + /// } + /// ``` + /// + /// # Safety + /// + /// The contained value must be of type `T`. Calling this method + /// with the incorrect type is *undefined behavior*. + /// + /// [`downcast`]: Self::downcast + #[inline] + #[unstable(feature = "downcast_unchecked", issue = "90850")] + pub unsafe fn downcast_unchecked(self) -> Box { + debug_assert!(self.is::()); + unsafe { + let (raw, alloc): (*mut (dyn Any + Send), _) = Box::into_raw_with_allocator(self); + Box::from_raw_in(raw as *mut T, alloc) + } + } +} + +impl Box { + /// Attempts to downcast the box to a concrete type. + /// + /// # Examples + /// + /// ``` + /// use std::any::Any; + /// + /// fn print_if_string(value: Box) { + /// if let Ok(string) = value.downcast::() { + /// println!("String ({}): {}", string.len(), string); + /// } + /// } + /// + /// let my_string = "Hello World".to_string(); + /// print_if_string(Box::new(my_string)); + /// print_if_string(Box::new(0i8)); + /// ``` + #[inline] + #[stable(feature = "box_send_sync_any_downcast", since = "1.51.0")] + pub fn downcast(self) -> Result, Self> { + if self.is::() { unsafe { Ok(self.downcast_unchecked::()) } } else { Err(self) } + } + + /// Downcasts the box to a concrete type. + /// + /// For a safe alternative see [`downcast`]. + /// + /// # Examples + /// + /// ``` + /// #![feature(downcast_unchecked)] + /// + /// use std::any::Any; + /// + /// let x: Box = Box::new(1_usize); + /// + /// unsafe { + /// assert_eq!(*x.downcast_unchecked::(), 1); + /// } + /// ``` + /// + /// # Safety + /// + /// The contained value must be of type `T`. Calling this method + /// with the incorrect type is *undefined behavior*. + /// + /// [`downcast`]: Self::downcast + #[inline] + #[unstable(feature = "downcast_unchecked", issue = "90850")] + pub unsafe fn downcast_unchecked(self) -> Box { + debug_assert!(self.is::()); + unsafe { + let (raw, alloc): (*mut (dyn Any + Send + Sync), _) = + Box::into_raw_with_allocator(self); + Box::from_raw_in(raw as *mut T, alloc) + } + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, E: Error + 'a> From for Box { + /// Converts a type of [`Error`] into a box of dyn [`Error`]. + /// + /// # Examples + /// + /// ``` + /// use std::error::Error; + /// use std::fmt; + /// use std::mem; + /// + /// #[derive(Debug)] + /// struct AnError; + /// + /// impl fmt::Display for AnError { + /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + /// write!(f, "An error") + /// } + /// } + /// + /// impl Error for AnError {} + /// + /// let an_error = AnError; + /// assert!(0 == mem::size_of_val(&an_error)); + /// let a_boxed_error = Box::::from(an_error); + /// assert!(mem::size_of::>() == mem::size_of_val(&a_boxed_error)) + /// ``` + fn from(err: E) -> Box { + Box::new(err) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, E: Error + Send + Sync + 'a> From for Box { + /// Converts a type of [`Error`] + [`Send`] + [`Sync`] into a box of + /// dyn [`Error`] + [`Send`] + [`Sync`]. + /// + /// # Examples + /// + /// ``` + /// use std::error::Error; + /// use std::fmt; + /// use std::mem; + /// + /// #[derive(Debug)] + /// struct AnError; + /// + /// impl fmt::Display for AnError { + /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + /// write!(f, "An error") + /// } + /// } + /// + /// impl Error for AnError {} + /// + /// unsafe impl Send for AnError {} + /// + /// unsafe impl Sync for AnError {} + /// + /// let an_error = AnError; + /// assert!(0 == mem::size_of_val(&an_error)); + /// let a_boxed_error = Box::::from(an_error); + /// assert!( + /// mem::size_of::>() == mem::size_of_val(&a_boxed_error)) + /// ``` + fn from(err: E) -> Box { + Box::new(err) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a> From for Box { + /// Converts a [`String`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. + /// + /// # Examples + /// + /// ``` + /// use std::error::Error; + /// use std::mem; + /// + /// let a_string_error = "a string error".to_string(); + /// let a_boxed_error = Box::::from(a_string_error); + /// assert!( + /// mem::size_of::>() == mem::size_of_val(&a_boxed_error)) + /// ``` + #[inline] + fn from(err: String) -> Box { + struct StringError(String); + + impl Error for StringError { + #[allow(deprecated)] + fn description(&self) -> &str { + &self.0 + } + } + + impl fmt::Display for StringError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(&self.0, f) + } + } + + // Purposefully skip printing "StringError(..)" + impl fmt::Debug for StringError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&self.0, f) + } + } + + Box::new(StringError(err)) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "string_box_error", since = "1.6.0")] +impl<'a> From for Box { + /// Converts a [`String`] into a box of dyn [`Error`]. + /// + /// # Examples + /// + /// ``` + /// use std::error::Error; + /// use std::mem; + /// + /// let a_string_error = "a string error".to_string(); + /// let a_boxed_error = Box::::from(a_string_error); + /// assert!(mem::size_of::>() == mem::size_of_val(&a_boxed_error)) + /// ``` + fn from(str_err: String) -> Box { + let err1: Box = From::from(str_err); + let err2: Box = err1; + err2 + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a> From<&str> for Box { + /// Converts a [`str`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. + /// + /// [`str`]: prim@str + /// + /// # Examples + /// + /// ``` + /// use std::error::Error; + /// use std::mem; + /// + /// let a_str_error = "a str error"; + /// let a_boxed_error = Box::::from(a_str_error); + /// assert!( + /// mem::size_of::>() == mem::size_of_val(&a_boxed_error)) + /// ``` + #[inline] + fn from(err: &str) -> Box { + From::from(String::from(err)) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "string_box_error", since = "1.6.0")] +impl<'a> From<&str> for Box { + /// Converts a [`str`] into a box of dyn [`Error`]. + /// + /// [`str`]: prim@str + /// + /// # Examples + /// + /// ``` + /// use std::error::Error; + /// use std::mem; + /// + /// let a_str_error = "a str error"; + /// let a_boxed_error = Box::::from(a_str_error); + /// assert!(mem::size_of::>() == mem::size_of_val(&a_boxed_error)) + /// ``` + fn from(err: &str) -> Box { + From::from(String::from(err)) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "cow_box_error", since = "1.22.0")] +impl<'a, 'b> From> for Box { + /// Converts a [`Cow`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. + /// + /// # Examples + /// + /// ``` + /// use std::error::Error; + /// use std::mem; + /// use std::borrow::Cow; + /// + /// let a_cow_str_error = Cow::from("a str error"); + /// let a_boxed_error = Box::::from(a_cow_str_error); + /// assert!( + /// mem::size_of::>() == mem::size_of_val(&a_boxed_error)) + /// ``` + fn from(err: Cow<'b, str>) -> Box { + From::from(String::from(err)) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "cow_box_error", since = "1.22.0")] +impl<'a, 'b> From> for Box { + /// Converts a [`Cow`] into a box of dyn [`Error`]. + /// + /// # Examples + /// + /// ``` + /// use std::error::Error; + /// use std::mem; + /// use std::borrow::Cow; + /// + /// let a_cow_str_error = Cow::from("a str error"); + /// let a_boxed_error = Box::::from(a_cow_str_error); + /// assert!(mem::size_of::>() == mem::size_of_val(&a_boxed_error)) + /// ``` + fn from(err: Cow<'b, str>) -> Box { + From::from(String::from(err)) + } +} + +impl dyn Error { + /// Attempts to downcast the box to a concrete type. + #[inline] + #[stable(feature = "error_downcast", since = "1.3.0")] + #[rustc_allow_incoherent_impl] + pub fn downcast(self: Box) -> Result, Box> { + if self.is::() { + unsafe { + let raw: *mut dyn Error = Box::into_raw(self); + Ok(Box::from_raw(raw as *mut T)) + } + } else { + Err(self) + } + } +} + +impl dyn Error + Send { + /// Attempts to downcast the box to a concrete type. + #[inline] + #[stable(feature = "error_downcast", since = "1.3.0")] + #[rustc_allow_incoherent_impl] + pub fn downcast(self: Box) -> Result, Box> { + let err: Box = self; + ::downcast(err).map_err(|s| unsafe { + // Reapply the `Send` marker. + mem::transmute::, Box>(s) + }) + } +} + +impl dyn Error + Send + Sync { + /// Attempts to downcast the box to a concrete type. + #[inline] + #[stable(feature = "error_downcast", since = "1.3.0")] + #[rustc_allow_incoherent_impl] + pub fn downcast(self: Box) -> Result, Box> { + let err: Box = self; + ::downcast(err).map_err(|s| unsafe { + // Reapply the `Send + Sync` markers. + mem::transmute::, Box>(s) + }) + } +} diff --git a/library/alloc/src/boxed/iter.rs b/library/alloc/src/boxed/iter.rs new file mode 100644 index 0000000000000..90582aa49c6d7 --- /dev/null +++ b/library/alloc/src/boxed/iter.rs @@ -0,0 +1,194 @@ +use core::async_iter::AsyncIterator; +use core::iter::FusedIterator; +use core::pin::Pin; +use core::slice; +use core::task::{Context, Poll}; + +use crate::alloc::Allocator; +#[cfg(not(no_global_oom_handling))] +use crate::borrow::Cow; +use crate::boxed::Box; +#[cfg(not(no_global_oom_handling))] +use crate::string::String; +use crate::vec; +#[cfg(not(no_global_oom_handling))] +use crate::vec::Vec; + +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for Box { + type Item = I::Item; + fn next(&mut self) -> Option { + (**self).next() + } + fn size_hint(&self) -> (usize, Option) { + (**self).size_hint() + } + fn nth(&mut self, n: usize) -> Option { + (**self).nth(n) + } + fn last(self) -> Option { + BoxIter::last(self) + } +} + +trait BoxIter { + type Item; + fn last(self) -> Option; +} + +impl BoxIter for Box { + type Item = I::Item; + default fn last(self) -> Option { + #[inline] + fn some(_: Option, x: T) -> Option { + Some(x) + } + + self.fold(None, some) + } +} + +/// Specialization for sized `I`s that uses `I`s implementation of `last()` +/// instead of the default. +#[stable(feature = "rust1", since = "1.0.0")] +impl BoxIter for Box { + fn last(self) -> Option { + (*self).last() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl DoubleEndedIterator for Box { + fn next_back(&mut self) -> Option { + (**self).next_back() + } + fn nth_back(&mut self, n: usize) -> Option { + (**self).nth_back(n) + } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for Box { + fn len(&self) -> usize { + (**self).len() + } + fn is_empty(&self) -> bool { + (**self).is_empty() + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Box {} + +#[unstable(feature = "async_iterator", issue = "79024")] +impl AsyncIterator for Box { + type Item = S::Item; + + fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + Pin::new(&mut **self).poll_next(cx) + } + + fn size_hint(&self) -> (usize, Option) { + (**self).size_hint() + } +} + +/// This implementation is required to make sure that the `Box<[I]>: IntoIterator` +/// implementation doesn't overlap with `IntoIterator for T where T: Iterator` blanket. +#[stable(feature = "boxed_slice_into_iter", since = "1.80.0")] +impl !Iterator for Box<[I], A> {} + +/// This implementation is required to make sure that the `&Box<[I]>: IntoIterator` +/// implementation doesn't overlap with `IntoIterator for T where T: Iterator` blanket. +#[stable(feature = "boxed_slice_into_iter", since = "1.80.0")] +impl<'a, I, A: Allocator> !Iterator for &'a Box<[I], A> {} + +/// This implementation is required to make sure that the `&mut Box<[I]>: IntoIterator` +/// implementation doesn't overlap with `IntoIterator for T where T: Iterator` blanket. +#[stable(feature = "boxed_slice_into_iter", since = "1.80.0")] +impl<'a, I, A: Allocator> !Iterator for &'a mut Box<[I], A> {} + +// Note: the `#[rustc_skip_during_method_dispatch(boxed_slice)]` on `trait IntoIterator` +// hides this implementation from explicit `.into_iter()` calls on editions < 2024, +// so those calls will still resolve to the slice implementation, by reference. +#[stable(feature = "boxed_slice_into_iter", since = "1.80.0")] +impl IntoIterator for Box<[I], A> { + type IntoIter = vec::IntoIter; + type Item = I; + fn into_iter(self) -> vec::IntoIter { + self.into_vec().into_iter() + } +} + +#[stable(feature = "boxed_slice_into_iter", since = "1.80.0")] +impl<'a, I, A: Allocator> IntoIterator for &'a Box<[I], A> { + type IntoIter = slice::Iter<'a, I>; + type Item = &'a I; + fn into_iter(self) -> slice::Iter<'a, I> { + self.iter() + } +} + +#[stable(feature = "boxed_slice_into_iter", since = "1.80.0")] +impl<'a, I, A: Allocator> IntoIterator for &'a mut Box<[I], A> { + type IntoIter = slice::IterMut<'a, I>; + type Item = &'a mut I; + fn into_iter(self) -> slice::IterMut<'a, I> { + self.iter_mut() + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "boxed_slice_from_iter", since = "1.32.0")] +impl FromIterator for Box<[I]> { + fn from_iter>(iter: T) -> Self { + iter.into_iter().collect::>().into_boxed_slice() + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "boxed_str_from_iter", since = "1.80.0")] +impl FromIterator for Box { + fn from_iter>(iter: T) -> Self { + String::from_iter(iter).into_boxed_str() + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "boxed_str_from_iter", since = "1.80.0")] +impl<'a> FromIterator<&'a char> for Box { + fn from_iter>(iter: T) -> Self { + String::from_iter(iter).into_boxed_str() + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "boxed_str_from_iter", since = "1.80.0")] +impl<'a> FromIterator<&'a str> for Box { + fn from_iter>(iter: T) -> Self { + String::from_iter(iter).into_boxed_str() + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "boxed_str_from_iter", since = "1.80.0")] +impl FromIterator for Box { + fn from_iter>(iter: T) -> Self { + String::from_iter(iter).into_boxed_str() + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "boxed_str_from_iter", since = "1.80.0")] +impl FromIterator> for Box { + fn from_iter>>(iter: T) -> Self { + String::from_iter(iter).into_boxed_str() + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "boxed_str_from_iter", since = "1.80.0")] +impl<'a> FromIterator> for Box { + fn from_iter>>(iter: T) -> Self { + String::from_iter(iter).into_boxed_str() + } +} diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 8a0d2a7f5cfcf..3079c8b1d905a 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -1197,7 +1197,7 @@ impl OpenOptions { /// Sets the option for truncating a previous file. /// - /// If a file is successfully opened with this option set it will truncate + /// If a file is successfully opened with this option set to true, it will truncate /// the file to 0 length if it already exists. /// /// The file must be opened with write access for truncate to work. diff --git a/src/ci/docker/host-x86_64/mingw-check/Dockerfile b/src/ci/docker/host-x86_64/mingw-check/Dockerfile index 0f8ebb987c3aa..fdc8a7310c8fe 100644 --- a/src/ci/docker/host-x86_64/mingw-check/Dockerfile +++ b/src/ci/docker/host-x86_64/mingw-check/Dockerfile @@ -51,7 +51,8 @@ ENV SCRIPT \ /scripts/check-default-config-profiles.sh && \ python3 ../x.py check --target=i686-pc-windows-gnu --host=i686-pc-windows-gnu && \ python3 ../x.py clippy bootstrap -Dwarnings && \ - python3 ../x.py clippy compiler library -Aclippy::all -Dclippy::correctness && \ + python3 ../x.py clippy library -Aclippy::all -Dclippy::correctness && \ + python3 ../x.py clippy compiler -Aclippy::all -Dclippy::correctness -Dclippy::clone_on_ref_ptr && \ python3 ../x.py build --stage 0 src/tools/build-manifest && \ python3 ../x.py test --stage 0 src/tools/compiletest && \ python3 ../x.py test --stage 0 core alloc std test proc_macro && \ diff --git a/src/tools/miri/tests/fail/coroutine-pinned-moved.stderr b/src/tools/miri/tests/fail/coroutine-pinned-moved.stderr index c2c6ce987e555..9b4890c7cc641 100644 --- a/src/tools/miri/tests/fail/coroutine-pinned-moved.stderr +++ b/src/tools/miri/tests/fail/coroutine-pinned-moved.stderr @@ -23,7 +23,7 @@ note: inside `> as std::iter::Iterator>::next` at RUSTLIB/alloc/src/boxed.rs:LL:CC + = note: inside `std::boxed::iter::>>::next` at RUSTLIB/alloc/src/boxed/iter.rs:LL:CC note: inside `main` --> tests/fail/coroutine-pinned-moved.rs:LL:CC | diff --git a/tests/ui/associated-type-bounds/implied-from-self-where-clause.rs b/tests/ui/associated-type-bounds/implied-from-self-where-clause.rs new file mode 100644 index 0000000000000..38f556969140a --- /dev/null +++ b/tests/ui/associated-type-bounds/implied-from-self-where-clause.rs @@ -0,0 +1,21 @@ +// Make sure that, like associated type where clauses on traits, we gather item +// bounds for RPITITs from RTN where clauses. + +//@ check-pass + +#![feature(return_type_notation)] + +trait Foo +where + Self::method(..): Send, +{ + fn method() -> impl Sized; +} + +fn is_send(_: impl Send) {} + +fn test() { + is_send(T::method()); +} + +fn main() {} diff --git a/tests/ui/coroutine/resume-arg-outlives-2.rs b/tests/ui/coroutine/resume-arg-outlives-2.rs new file mode 100644 index 0000000000000..387b143ea279e --- /dev/null +++ b/tests/ui/coroutine/resume-arg-outlives-2.rs @@ -0,0 +1,34 @@ +// Regression test for 132104 + +#![feature(coroutine_trait, coroutines)] + +use std::ops::Coroutine; +use std::{thread, time}; + +fn demo<'not_static>(s: &'not_static str) -> thread::JoinHandle<()> { + let mut generator = Box::pin({ + #[coroutine] + move |_ctx| { + let ctx: &'not_static str = yield; + yield; + dbg!(ctx); + } + }); + + // exploit: + generator.as_mut().resume(""); + generator.as_mut().resume(s); // <- generator hoards it as `let ctx`. + //~^ ERROR borrowed data escapes outside of function + thread::spawn(move || { + thread::sleep(time::Duration::from_millis(200)); + generator.as_mut().resume(""); // <- resumes from the last `yield`, running `dbg!(ctx)`. + }) +} + +fn main() { + let local = String::from("..."); + let thread = demo(&local); + drop(local); + let _unrelated = String::from("UAF"); + thread.join().unwrap(); +} diff --git a/tests/ui/coroutine/resume-arg-outlives-2.stderr b/tests/ui/coroutine/resume-arg-outlives-2.stderr new file mode 100644 index 0000000000000..3d630d7e7e483 --- /dev/null +++ b/tests/ui/coroutine/resume-arg-outlives-2.stderr @@ -0,0 +1,17 @@ +error[E0521]: borrowed data escapes outside of function + --> $DIR/resume-arg-outlives-2.rs:20:5 + | +LL | fn demo<'not_static>(s: &'not_static str) -> thread::JoinHandle<()> { + | ----------- - `s` is a reference that is only valid in the function body + | | + | lifetime `'not_static` defined here +... +LL | generator.as_mut().resume(s); // <- generator hoards it as `let ctx`. + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `s` escapes the function body here + | argument requires that `'not_static` must outlive `'static` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/coroutine/resume-arg-outlives.rs b/tests/ui/coroutine/resume-arg-outlives.rs new file mode 100644 index 0000000000000..258be28e0631c --- /dev/null +++ b/tests/ui/coroutine/resume-arg-outlives.rs @@ -0,0 +1,27 @@ +// Regression test for 132104 + +#![feature(coroutine_trait, coroutines)] + +use std::ops::Coroutine; +use std::pin::Pin; + +fn demo<'not_static>(s: &'not_static str) -> Pin + 'static>> { + let mut generator = Box::pin({ + #[coroutine] + move |ctx: &'not_static str| { + yield; + dbg!(ctx); + } + }); + generator.as_mut().resume(s); + generator + //~^ ERROR lifetime may not live long enough +} + +fn main() { + let local = String::from("..."); + let mut coro = demo(&local); + drop(local); + let _unrelated = String::from("UAF"); + coro.as_mut().resume(""); +} diff --git a/tests/ui/coroutine/resume-arg-outlives.stderr b/tests/ui/coroutine/resume-arg-outlives.stderr new file mode 100644 index 0000000000000..2a6337b494515 --- /dev/null +++ b/tests/ui/coroutine/resume-arg-outlives.stderr @@ -0,0 +1,20 @@ +error: lifetime may not live long enough + --> $DIR/resume-arg-outlives.rs:17:5 + | +LL | fn demo<'not_static>(s: &'not_static str) -> Pin + 'static>> { + | ----------- lifetime `'not_static` defined here +... +LL | generator + | ^^^^^^^^^ returning this value requires that `'not_static` must outlive `'static` + | +help: consider changing `impl Coroutine<&'not_static str> + 'static`'s explicit `'static` bound to the lifetime of argument `s` + | +LL | fn demo<'not_static>(s: &'not_static str) -> Pin + 'not_static>> { + | ~~~~~~~~~~~ +help: alternatively, add an explicit `'static` bound to this reference + | +LL | fn demo<'not_static>(s: &'static str) -> Pin + 'static>> { + | ~~~~~~~~~~~~ + +error: aborting due to 1 previous error + diff --git a/tests/ui/drop/drop_order.rs b/tests/ui/drop/drop_order.rs index 29b68d666fc6e..7a999c7c330a1 100644 --- a/tests/ui/drop/drop_order.rs +++ b/tests/ui/drop/drop_order.rs @@ -4,8 +4,8 @@ //@ [edition2021] edition: 2021 //@ [edition2024] compile-flags: -Z unstable-options //@ [edition2024] edition: 2024 + #![feature(let_chains)] -#![cfg_attr(edition2024, feature(if_let_rescope))] use std::cell::RefCell; use std::convert::TryInto; diff --git a/tests/ui/drop/drop_order_if_let_rescope.rs b/tests/ui/drop/drop_order_if_let_rescope.rs index ae9f381820e16..cea84bbaa2b92 100644 --- a/tests/ui/drop/drop_order_if_let_rescope.rs +++ b/tests/ui/drop/drop_order_if_let_rescope.rs @@ -3,7 +3,6 @@ //@ compile-flags: -Z validate-mir -Zunstable-options #![feature(let_chains)] -#![feature(if_let_rescope)] use std::cell::RefCell; use std::convert::TryInto; diff --git a/tests/ui/drop/if-let-rescope-borrowck-suggestions.rs b/tests/ui/drop/if-let-rescope-borrowck-suggestions.rs index 2476f7cf2580a..e055c20d777bc 100644 --- a/tests/ui/drop/if-let-rescope-borrowck-suggestions.rs +++ b/tests/ui/drop/if-let-rescope-borrowck-suggestions.rs @@ -1,7 +1,6 @@ //@ edition: 2024 //@ compile-flags: -Z validate-mir -Zunstable-options -#![feature(if_let_rescope)] #![deny(if_let_rescope)] struct Droppy; diff --git a/tests/ui/drop/if-let-rescope-borrowck-suggestions.stderr b/tests/ui/drop/if-let-rescope-borrowck-suggestions.stderr index 0c6f1ea28d2ae..3c87e196af6e5 100644 --- a/tests/ui/drop/if-let-rescope-borrowck-suggestions.stderr +++ b/tests/ui/drop/if-let-rescope-borrowck-suggestions.stderr @@ -1,5 +1,5 @@ error[E0716]: temporary value dropped while borrowed - --> $DIR/if-let-rescope-borrowck-suggestions.rs:22:39 + --> $DIR/if-let-rescope-borrowck-suggestions.rs:21:39 | LL | do_something(if let Some(value) = Droppy.get_ref() { value } else { &0 }); | ^^^^^^ - temporary value is freed at the end of this statement @@ -7,7 +7,7 @@ LL | do_something(if let Some(value) = Droppy.get_ref() { value } else { &0 | creates a temporary value which is freed while still in use | note: lifetimes for temporaries generated in `if let`s have been shortened in Edition 2024 so that they are dropped here instead - --> $DIR/if-let-rescope-borrowck-suggestions.rs:22:64 + --> $DIR/if-let-rescope-borrowck-suggestions.rs:21:64 | LL | do_something(if let Some(value) = Droppy.get_ref() { value } else { &0 }); | ^ @@ -22,7 +22,7 @@ LL | do_something({ match Droppy.get_ref() { Some(value) => { value } _ => | ~~~~~~~ ++++++++++++++++ ~~~~ ++ error[E0716]: temporary value dropped while borrowed - --> $DIR/if-let-rescope-borrowck-suggestions.rs:24:39 + --> $DIR/if-let-rescope-borrowck-suggestions.rs:23:39 | LL | do_something(if let Some(value) = Droppy.get_ref() { | ^^^^^^ creates a temporary value which is freed while still in use @@ -31,7 +31,7 @@ LL | } else if let Some(value) = Droppy.get_ref() { | - temporary value is freed at the end of this statement | note: lifetimes for temporaries generated in `if let`s have been shortened in Edition 2024 so that they are dropped here instead - --> $DIR/if-let-rescope-borrowck-suggestions.rs:27:5 + --> $DIR/if-let-rescope-borrowck-suggestions.rs:26:5 | LL | } else if let Some(value) = Droppy.get_ref() { | ^ @@ -53,7 +53,7 @@ LL ~ }}}); | error[E0716]: temporary value dropped while borrowed - --> $DIR/if-let-rescope-borrowck-suggestions.rs:27:33 + --> $DIR/if-let-rescope-borrowck-suggestions.rs:26:33 | LL | } else if let Some(value) = Droppy.get_ref() { | ^^^^^^ creates a temporary value which is freed while still in use @@ -62,7 +62,7 @@ LL | } else { | - temporary value is freed at the end of this statement | note: lifetimes for temporaries generated in `if let`s have been shortened in Edition 2024 so that they are dropped here instead - --> $DIR/if-let-rescope-borrowck-suggestions.rs:30:5 + --> $DIR/if-let-rescope-borrowck-suggestions.rs:29:5 | LL | } else { | ^ diff --git a/tests/ui/drop/lint-if-let-rescope-gated.with_feature_gate.stderr b/tests/ui/drop/lint-if-let-rescope-gated.edition2021.stderr similarity index 100% rename from tests/ui/drop/lint-if-let-rescope-gated.with_feature_gate.stderr rename to tests/ui/drop/lint-if-let-rescope-gated.edition2021.stderr diff --git a/tests/ui/drop/lint-if-let-rescope-gated.rs b/tests/ui/drop/lint-if-let-rescope-gated.rs index cef5de5a8fe56..ba0246573b406 100644 --- a/tests/ui/drop/lint-if-let-rescope-gated.rs +++ b/tests/ui/drop/lint-if-let-rescope-gated.rs @@ -1,13 +1,13 @@ // This test checks that the lint `if_let_rescope` only actions -// when the feature gate is enabled. -// Edition 2021 is used here because the lint should work especially -// when edition migration towards 2024 is run. +// when Edition 2021 or prior is targeted here because the lint should work especially +// when edition migration towards 2024 is executed. -//@ revisions: with_feature_gate without_feature_gate -//@ [without_feature_gate] check-pass -//@ edition: 2021 +//@ revisions: edition2021 edition2024 +//@ [edition2021] edition: 2021 +//@ [edition2024] edition: 2024 +//@ [edition2024] compile-flags: -Zunstable-options +//@ [edition2024] check-pass -#![cfg_attr(with_feature_gate, feature(if_let_rescope))] #![deny(if_let_rescope)] #![allow(irrefutable_let_patterns)] @@ -25,10 +25,10 @@ impl Droppy { fn main() { if let Some(_value) = Droppy.get() { - //[with_feature_gate]~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 - //[with_feature_gate]~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021 - //[with_feature_gate]~| WARN: this changes meaning in Rust 2024 + //[edition2021]~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 + //[edition2021]~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021 + //[edition2021]~| WARN: this changes meaning in Rust 2024 } else { - //[with_feature_gate]~^ HELP: the value is now dropped here in Edition 2024 + //[edition2021]~^ HELP: the value is now dropped here in Edition 2024 } } diff --git a/tests/ui/drop/lint-if-let-rescope-with-macro.rs b/tests/ui/drop/lint-if-let-rescope-with-macro.rs index 282b3320d3004..e7aeb81f4d1a5 100644 --- a/tests/ui/drop/lint-if-let-rescope-with-macro.rs +++ b/tests/ui/drop/lint-if-let-rescope-with-macro.rs @@ -4,7 +4,6 @@ //@ edition:2021 //@ compile-flags: -Z unstable-options -#![feature(if_let_rescope)] #![deny(if_let_rescope)] #![allow(irrefutable_let_patterns)] diff --git a/tests/ui/drop/lint-if-let-rescope-with-macro.stderr b/tests/ui/drop/lint-if-let-rescope-with-macro.stderr index 5fd0c61d17a57..de6cf6e8500ee 100644 --- a/tests/ui/drop/lint-if-let-rescope-with-macro.stderr +++ b/tests/ui/drop/lint-if-let-rescope-with-macro.stderr @@ -1,5 +1,5 @@ error: `if let` assigns a shorter lifetime since Edition 2024 - --> $DIR/lint-if-let-rescope-with-macro.rs:13:12 + --> $DIR/lint-if-let-rescope-with-macro.rs:12:12 | LL | if let $p = $e { $($conseq)* } else { $($alt)* } | ^^^ @@ -16,7 +16,7 @@ LL | | }; = warning: this changes meaning in Rust 2024 = note: for more information, see issue #124085 help: the value is now dropped here in Edition 2024 - --> $DIR/lint-if-let-rescope-with-macro.rs:13:38 + --> $DIR/lint-if-let-rescope-with-macro.rs:12:38 | LL | if let $p = $e { $($conseq)* } else { $($alt)* } | ^ @@ -29,7 +29,7 @@ LL | | {} LL | | }; | |_____- in this macro invocation note: the lint level is defined here - --> $DIR/lint-if-let-rescope-with-macro.rs:8:9 + --> $DIR/lint-if-let-rescope-with-macro.rs:7:9 | LL | #![deny(if_let_rescope)] | ^^^^^^^^^^^^^^ diff --git a/tests/ui/drop/lint-if-let-rescope.fixed b/tests/ui/drop/lint-if-let-rescope.fixed index 199068d0fd265..fec2e3b2ae705 100644 --- a/tests/ui/drop/lint-if-let-rescope.fixed +++ b/tests/ui/drop/lint-if-let-rescope.fixed @@ -1,7 +1,7 @@ //@ run-rustfix #![deny(if_let_rescope)] -#![feature(if_let_rescope, stmt_expr_attributes)] +#![feature(stmt_expr_attributes)] #![allow(irrefutable_let_patterns, unused_parens)] fn droppy() -> Droppy { diff --git a/tests/ui/drop/lint-if-let-rescope.rs b/tests/ui/drop/lint-if-let-rescope.rs index 4c043c0266cc4..ee184695b97ac 100644 --- a/tests/ui/drop/lint-if-let-rescope.rs +++ b/tests/ui/drop/lint-if-let-rescope.rs @@ -1,7 +1,7 @@ //@ run-rustfix #![deny(if_let_rescope)] -#![feature(if_let_rescope, stmt_expr_attributes)] +#![feature(stmt_expr_attributes)] #![allow(irrefutable_let_patterns, unused_parens)] fn droppy() -> Droppy { diff --git a/tests/ui/feature-gates/feature-gate-if-let-rescope.rs b/tests/ui/feature-gates/feature-gate-if-let-rescope.rs deleted file mode 100644 index bd1efd4fb7c1f..0000000000000 --- a/tests/ui/feature-gates/feature-gate-if-let-rescope.rs +++ /dev/null @@ -1,27 +0,0 @@ -// This test shows the code that could have been accepted by enabling #![feature(if_let_rescope)] - -struct A; -struct B<'a, T>(&'a mut T); - -impl A { - fn f(&mut self) -> Option> { - Some(B(self)) - } -} - -impl<'a, T> Drop for B<'a, T> { - fn drop(&mut self) { - // this is needed to keep NLL's hands off and to ensure - // the inner mutable borrow stays alive - } -} - -fn main() { - let mut a = A; - if let None = a.f().as_ref() { - unreachable!() - } else { - a.f().unwrap(); - //~^ ERROR cannot borrow `a` as mutable more than once at a time - }; -} diff --git a/tests/ui/feature-gates/feature-gate-if-let-rescope.stderr b/tests/ui/feature-gates/feature-gate-if-let-rescope.stderr deleted file mode 100644 index ff1846ae0b1f5..0000000000000 --- a/tests/ui/feature-gates/feature-gate-if-let-rescope.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error[E0499]: cannot borrow `a` as mutable more than once at a time - --> $DIR/feature-gate-if-let-rescope.rs:24:9 - | -LL | if let None = a.f().as_ref() { - | ----- - | | - | first mutable borrow occurs here - | a temporary with access to the first borrow is created here ... -... -LL | a.f().unwrap(); - | ^ second mutable borrow occurs here -LL | -LL | }; - | - ... and the first borrow might be used here, when that temporary is dropped and runs the destructor for type `Option>` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/mir/mir_let_chains_drop_order.rs b/tests/ui/mir/mir_let_chains_drop_order.rs index daf0a62fc85f3..92199625207e9 100644 --- a/tests/ui/mir/mir_let_chains_drop_order.rs +++ b/tests/ui/mir/mir_let_chains_drop_order.rs @@ -8,7 +8,6 @@ // See `mir_drop_order.rs` for more information #![feature(let_chains)] -#![cfg_attr(edition2024, feature(if_let_rescope))] #![allow(irrefutable_let_patterns)] use std::cell::RefCell; diff --git a/tests/ui/nll/issue-54556-niconii.edition2021.stderr b/tests/ui/nll/issue-54556-niconii.edition2021.stderr index 31a03abbc9826..abee09ed95037 100644 --- a/tests/ui/nll/issue-54556-niconii.edition2021.stderr +++ b/tests/ui/nll/issue-54556-niconii.edition2021.stderr @@ -1,5 +1,5 @@ error[E0597]: `counter` does not live long enough - --> $DIR/issue-54556-niconii.rs:30:20 + --> $DIR/issue-54556-niconii.rs:28:20 | LL | let counter = Mutex; | ------- binding `counter` declared here diff --git a/tests/ui/nll/issue-54556-niconii.rs b/tests/ui/nll/issue-54556-niconii.rs index 1a7ad17cc84c0..f01e0523cbf9d 100644 --- a/tests/ui/nll/issue-54556-niconii.rs +++ b/tests/ui/nll/issue-54556-niconii.rs @@ -12,8 +12,6 @@ //@ [edition2024] compile-flags: -Z unstable-options //@ [edition2024] check-pass -#![cfg_attr(edition2024, feature(if_let_rescope))] - struct Mutex; struct MutexGuard<'a>(&'a Mutex); diff --git a/tests/ui/stable-mir-print/operands.rs b/tests/ui/stable-mir-print/operands.rs new file mode 100644 index 0000000000000..ceaa6efa91822 --- /dev/null +++ b/tests/ui/stable-mir-print/operands.rs @@ -0,0 +1,45 @@ +//@ compile-flags: -Z unpretty=stable-mir --crate-type lib -C panic=abort +//@ check-pass +//@ only-x86_64 +//@ needs-unwind unwind edges are different with panic=abort +//! Check how stable mir pretty printer prints different operands and abort strategy. + +pub fn operands(val: u8) { + let array = [val; 10]; + let first = array[0]; + let last = array[10 - 1]; + assert_eq!(first, last); + + let reference = &first; + let dereferenced = *reference; + assert_eq!(dereferenced, first); + + let tuple = (first, last); + let (first_again, _) = tuple; + let first_again_again = tuple.0; + assert_eq!(first_again, first_again_again); + + let length = array.len(); + let size_of = std::mem::size_of_val(&length); + assert_eq!(length, size_of); +} + +pub struct Dummy { c: char, i: i32 } + +pub enum Ctors { + Unit, + StructLike { d: Dummy }, + TupLike(bool), +} + +pub fn more_operands() -> [Ctors; 3] { + let dummy = Dummy { c: 'a', i: i32::MIN }; + let unit = Ctors::Unit; + let struct_like = Ctors::StructLike { d: dummy }; + let tup_like = Ctors::TupLike(false); + [unit, struct_like, tup_like] +} + +pub fn closures(x: bool, z: bool) -> impl FnOnce(bool) -> bool { + move |y: bool| { (x ^ y) || z } +} diff --git a/tests/ui/stable-mir-print/operands.stdout b/tests/ui/stable-mir-print/operands.stdout new file mode 100644 index 0000000000000..b0d095cf17824 --- /dev/null +++ b/tests/ui/stable-mir-print/operands.stdout @@ -0,0 +1,263 @@ +// WARNING: This is highly experimental output it's intended for stable-mir developers only. +// If you find a bug or want to improve the output open a issue at https://github.com/rust-lang/project-stable-mir. +fn operands(_1: u8) -> () { + let mut _0: (); + let _2: [u8; 10]; + let _3: u8; + let _4: usize; + let mut _5: usize; + let mut _6: bool; + let _7: u8; + let _8: usize; + let mut _9: (usize, bool); + let mut _10: usize; + let mut _11: bool; + let mut _12: (&u8, &u8); + let mut _13: &u8; + let mut _14: &u8; + let _15: &u8; + let _16: &u8; + let mut _17: bool; + let mut _18: u8; + let mut _19: u8; + let _20: core::panicking::AssertKind; + let _21: !; + let mut _22: Option>; + let _23: &u8; + let _24: u8; + let mut _25: (&u8, &u8); + let mut _26: &u8; + let mut _27: &u8; + let _28: &u8; + let _29: &u8; + let mut _30: bool; + let mut _31: u8; + let mut _32: u8; + let _33: core::panicking::AssertKind; + let _34: !; + let mut _35: Option>; + let _36: (u8, u8); + let _37: u8; + let _38: u8; + let mut _39: (&u8, &u8); + let mut _40: &u8; + let mut _41: &u8; + let _42: &u8; + let _43: &u8; + let mut _44: bool; + let mut _45: u8; + let mut _46: u8; + let _47: core::panicking::AssertKind; + let _48: !; + let mut _49: Option>; + let _50: usize; + let mut _51: &[u8]; + let mut _52: &[u8; 10]; + let _53: usize; + let _54: &usize; + let mut _55: (&usize, &usize); + let mut _56: &usize; + let mut _57: &usize; + let _58: &usize; + let _59: &usize; + let mut _60: bool; + let mut _61: usize; + let mut _62: usize; + let _63: core::panicking::AssertKind; + let _64: !; + let mut _65: Option>; + debug val => _1; + debug array => _2; + debug first => _3; + debug last => _7; + debug left_val => _15; + debug right_val => _16; + debug kind => _20; + debug reference => _23; + debug dereferenced => _24; + debug left_val => _28; + debug right_val => _29; + debug kind => _33; + debug tuple => _36; + debug first_again => _37; + debug first_again_again => _38; + debug left_val => _42; + debug right_val => _43; + debug kind => _47; + debug length => _50; + debug size_of => _53; + debug left_val => _58; + debug right_val => _59; + debug kind => _63; + bb0: { + _2 = [_1; 10]; + _4 = 0_usize; + _5 = 10_usize; + _6 = Lt(_4, _5); + assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, _4) -> [success: bb1, unwind unreachable]; + } + bb1: { + _3 = _2[_4]; + _9 = CheckedSub(10_usize, 1_usize); + assert(!move (_9.1: bool), "attempt to compute `{} - {}`, which would overflow", 10_usize, 1_usize) -> [success: bb2, unwind unreachable]; + } + bb2: { + _8 = move (_9.0: usize); + _10 = 10_usize; + _11 = Lt(_8, _10); + assert(move _11, "index out of bounds: the length is {} but the index is {}", move _10, _8) -> [success: bb3, unwind unreachable]; + } + bb3: { + _7 = _2[_8]; + _13 = &_3; + _14 = &_7; + _12 = (move _13, move _14); + _15 = (_12.0: &u8); + _16 = (_12.1: &u8); + _18 = (*_15); + _19 = (*_16); + _17 = Eq(move _18, move _19); + switchInt(move _17) -> [0: bb5, otherwise: bb4]; + } + bb4: { + _23 = &_3; + _24 = (*_23); + _26 = &_24; + _27 = &_3; + _25 = (move _26, move _27); + _28 = (_25.0: &u8); + _29 = (_25.1: &u8); + _31 = (*_28); + _32 = (*_29); + _30 = Eq(move _31, move _32); + switchInt(move _30) -> [0: bb7, otherwise: bb6]; + } + bb5: { + _20 = core::panicking::AssertKind::Eq; + _22 = std::option::Option::None; + _21 = core::panicking::assert_failed::(move _20, _15, _16, move _22) -> unwind unreachable; + } + bb6: { + _36 = (_3, _7); + _37 = (_36.0: u8); + _38 = (_36.0: u8); + _40 = &_37; + _41 = &_38; + _39 = (move _40, move _41); + _42 = (_39.0: &u8); + _43 = (_39.1: &u8); + _45 = (*_42); + _46 = (*_43); + _44 = Eq(move _45, move _46); + switchInt(move _44) -> [0: bb9, otherwise: bb8]; + } + bb7: { + _33 = core::panicking::AssertKind::Eq; + _35 = std::option::Option::None; + _34 = core::panicking::assert_failed::(move _33, _28, _29, move _35) -> unwind unreachable; + } + bb8: { + _52 = &_2; + _51 = move _52 as &[u8]; + _50 = PtrMetadata(move _51); + _54 = &_50; + _53 = std::mem::size_of_val::(_54) -> [return: bb10, unwind unreachable]; + } + bb9: { + _47 = core::panicking::AssertKind::Eq; + _49 = std::option::Option::None; + _48 = core::panicking::assert_failed::(move _47, _42, _43, move _49) -> unwind unreachable; + } + bb10: { + _56 = &_50; + _57 = &_53; + _55 = (move _56, move _57); + _58 = (_55.0: &usize); + _59 = (_55.1: &usize); + _61 = (*_58); + _62 = (*_59); + _60 = Eq(move _61, move _62); + switchInt(move _60) -> [0: bb12, otherwise: bb11]; + } + bb11: { + return; + } + bb12: { + _63 = core::panicking::AssertKind::Eq; + _65 = std::option::Option::None; + _64 = core::panicking::assert_failed::(move _63, _58, _59, move _65) -> unwind unreachable; + } +} +fn operands::{constant#0}() -> usize { + let mut _0: usize; + bb0: { + _0 = 10_usize; + return; + } +} +fn more_operands() -> [Ctors; 3] { + let mut _0: [Ctors; 3]; + let _1: Dummy; + let _2: Ctors; + let _3: Ctors; + let _4: Ctors; + debug dummy => _1; + debug unit => _2; + debug struct_like => _3; + debug tup_like => _4; + bb0: { + _1 = Dummy('a', core::num::::MIN); + _2 = Ctors::Unit; + _3 = Ctors::StructLike(move _1); + _4 = Ctors::TupLike(false); + _0 = [move _2, move _3, move _4]; + return; + } +} +fn more_operands::{constant#0}() -> usize { + let mut _0: usize; + bb0: { + _0 = 3_usize; + return; + } +} +fn closures(_1: bool, _2: bool) -> {closure@$DIR/operands.rs:44:5: 44:19} { + let mut _0: {closure@$DIR/operands.rs:44:5: 44:19}; + debug x => _1; + debug z => _2; + bb0: { + _0 = {closure@Span { id: 105, repr: "$DIR/operands.rs:44:5: 44:19" }}(_1, _2); + return; + } +} +fn closures::{closure#0}(_1: {closure@$DIR/operands.rs:44:5: 44:19}, _2: bool) -> bool { + let mut _0: bool; + let mut _3: bool; + let mut _4: bool; + debug y => _2; + debug x => (_1.0: bool); + debug z => (_1.1: bool); + bb0: { + _4 = (_1.0: bool); + _3 = BitXor(move _4, _2); + switchInt(move _3) -> [0: bb2, otherwise: bb1]; + } + bb1: { + _0 = true; + goto -> bb3; + } + bb2: { + _0 = (_1.1: bool); + goto -> bb3; + } + bb3: { + return; + } +} +fn Ctors::TupLike(_1: bool) -> Ctors { + let mut _0: Ctors; + bb0: { + _0 = Ctors::TupLike(move _1); + return; + } +} diff --git a/triagebot.toml b/triagebot.toml index 2e8851e7ec24d..baf0da467e1e6 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -725,9 +725,6 @@ please modify the tool then regenerate the library source file with the tool instead of editing the library source file manually. """ -[mentions."src/librustdoc/clean/types.rs"] -cc = ["@camelid"] - [mentions."src/librustdoc/html/static"] message = "Some changes occurred in HTML/CSS/JS." cc = [