diff options
123 files changed, 4470 insertions, 1602 deletions
diff --git a/.github/ISSUE_TEMPLATE/library_tracking_issue.md b/.github/ISSUE_TEMPLATE/library_tracking_issue.md index 32fccfcfb16..91c06402ca1 100644 --- a/.github/ISSUE_TEMPLATE/library_tracking_issue.md +++ b/.github/ISSUE_TEMPLATE/library_tracking_issue.md @@ -50,7 +50,7 @@ If the feature is changed later, please add those PRs here as well. --> - [ ] Implementation: #... -- [ ] Final comment period (FCP) +- [ ] Final comment period (FCP)[^1] - [ ] Stabilization PR <!-- @@ -81,3 +81,5 @@ Zulip, or the internals forum) here. --> - None yet. + +[^1]: https://std-dev-guide.rust-lang.org/feature-lifecycle/stabilization.html diff --git a/compiler/rustc_borrowck/src/constraint_generation.rs b/compiler/rustc_borrowck/src/constraint_generation.rs index e4ffae38c33..d34c6d9dee5 100644 --- a/compiler/rustc_borrowck/src/constraint_generation.rs +++ b/compiler/rustc_borrowck/src/constraint_generation.rs @@ -149,7 +149,7 @@ impl<'cg, 'cx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'tcx> { fn visit_ascribe_user_ty( &mut self, _place: &Place<'tcx>, - _variance: &ty::Variance, + _variance: ty::Variance, _user_ty: &UserTypeProjection, _location: Location, ) { diff --git a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs index ac8670a5138..d5c401ae1c6 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs @@ -1,11 +1,11 @@ +use itertools::{Either, Itertools}; use rustc_data_structures::fx::FxHashSet; use rustc_middle::mir::{Body, Local}; use rustc_middle::ty::{RegionVid, TyCtxt}; -use std::rc::Rc; - use rustc_mir_dataflow::impls::MaybeInitializedPlaces; use rustc_mir_dataflow::move_paths::MoveData; use rustc_mir_dataflow::ResultsCursor; +use std::rc::Rc; use crate::{ constraints::OutlivesConstraintSet, @@ -46,7 +46,8 @@ pub(super) fn generate<'mir, 'tcx>( &typeck.borrowck_context.universal_regions, &typeck.borrowck_context.constraints.outlives_constraints, ); - let live_locals = compute_live_locals(typeck.tcx(), &free_regions, &body); + let (relevant_live_locals, boring_locals) = + compute_relevant_live_locals(typeck.tcx(), &free_regions, &body); let facts_enabled = use_polonius || AllFacts::enabled(typeck.tcx()); let polonius_drop_used = if facts_enabled { @@ -57,48 +58,44 @@ pub(super) fn generate<'mir, 'tcx>( None }; - if !live_locals.is_empty() || facts_enabled { - trace::trace( - typeck, - body, - elements, - flow_inits, - move_data, - live_locals, - polonius_drop_used, - ); - } + trace::trace( + typeck, + body, + elements, + flow_inits, + move_data, + relevant_live_locals, + boring_locals, + polonius_drop_used, + ); } -// The purpose of `compute_live_locals` is to define the subset of `Local` +// The purpose of `compute_relevant_live_locals` is to define the subset of `Local` // variables for which we need to do a liveness computation. We only need // to compute whether a variable `X` is live if that variable contains // some region `R` in its type where `R` is not known to outlive a free // region (i.e., where `R` may be valid for just a subset of the fn body). -fn compute_live_locals<'tcx>( +fn compute_relevant_live_locals<'tcx>( tcx: TyCtxt<'tcx>, free_regions: &FxHashSet<RegionVid>, body: &Body<'tcx>, -) -> Vec<Local> { - let live_locals: Vec<Local> = body - .local_decls - .iter_enumerated() - .filter_map(|(local, local_decl)| { +) -> (Vec<Local>, Vec<Local>) { + let (boring_locals, relevant_live_locals): (Vec<_>, Vec<_>) = + body.local_decls.iter_enumerated().partition_map(|(local, local_decl)| { if tcx.all_free_regions_meet(&local_decl.ty, |r| { free_regions.contains(&r.to_region_vid()) }) { - None + Either::Left(local) } else { - Some(local) + Either::Right(local) } - }) - .collect(); + }); debug!("{} total variables", body.local_decls.len()); - debug!("{} variables need liveness", live_locals.len()); + debug!("{} variables need liveness", relevant_live_locals.len()); debug!("{} regions outlive free regions", free_regions.len()); - live_locals + (relevant_live_locals, boring_locals) } /// Computes all regions that are (currently) known to outlive free diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs index 169de23facc..a69eec47c7b 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs @@ -41,12 +41,13 @@ pub(super) fn trace<'mir, 'tcx>( elements: &Rc<RegionValueElements>, flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'mir, 'tcx>>, move_data: &MoveData<'tcx>, - live_locals: Vec<Local>, + relevant_live_locals: Vec<Local>, + boring_locals: Vec<Local>, polonius_drop_used: Option<Vec<(Local, Location)>>, ) { debug!("trace()"); - let local_use_map = &LocalUseMap::build(&live_locals, elements, body); + let local_use_map = &LocalUseMap::build(&relevant_live_locals, elements, body); let cx = LivenessContext { typeck, @@ -61,10 +62,12 @@ pub(super) fn trace<'mir, 'tcx>( let mut results = LivenessResults::new(cx); if let Some(drop_used) = polonius_drop_used { - results.add_extra_drop_facts(drop_used, live_locals.iter().copied().collect()) + results.add_extra_drop_facts(drop_used, relevant_live_locals.iter().copied().collect()) } - results.compute_for_all_locals(live_locals); + results.compute_for_all_locals(relevant_live_locals); + + results.dropck_boring_locals(boring_locals); } /// Contextual state for the type-liveness generator. @@ -133,8 +136,8 @@ impl<'me, 'typeck, 'flow, 'tcx> LivenessResults<'me, 'typeck, 'flow, 'tcx> { } } - fn compute_for_all_locals(&mut self, live_locals: Vec<Local>) { - for local in live_locals { + fn compute_for_all_locals(&mut self, relevant_live_locals: Vec<Local>) { + for local in relevant_live_locals { self.reset_local_state(); self.add_defs_for(local); self.compute_use_live_points_for(local); @@ -157,6 +160,24 @@ impl<'me, 'typeck, 'flow, 'tcx> LivenessResults<'me, 'typeck, 'flow, 'tcx> { } } + // Runs dropck for locals whose liveness isn't relevant. This is + // necessary to eagerly detect unbound recursion during drop glue computation. + fn dropck_boring_locals(&mut self, boring_locals: Vec<Local>) { + for local in boring_locals { + let local_ty = self.cx.body.local_decls[local].ty; + let drop_data = self.cx.drop_data.entry(local_ty).or_insert_with({ + let typeck = &mut self.cx.typeck; + move || LivenessContext::compute_drop_data(typeck, local_ty) + }); + + drop_data.dropck_result.report_overflows( + self.cx.typeck.infcx.tcx, + self.cx.body.local_decls[local].source_info.span, + local_ty, + ); + } + } + /// Add extra drop facts needed for Polonius. /// /// Add facts for all locals with free regions, since regions may outlive @@ -164,12 +185,12 @@ impl<'me, 'typeck, 'flow, 'tcx> LivenessResults<'me, 'typeck, 'flow, 'tcx> { fn add_extra_drop_facts( &mut self, drop_used: Vec<(Local, Location)>, - live_locals: FxHashSet<Local>, + relevant_live_locals: FxHashSet<Local>, ) { let locations = IntervalSet::new(self.cx.elements.num_points()); for (local, location) in drop_used { - if !live_locals.contains(&local) { + if !relevant_live_locals.contains(&local) { let local_ty = self.cx.body.local_decls[local].ty; if local_ty.has_free_regions() { self.cx.add_drop_live_facts_for(local, local_ty, &[location], &locations); diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index ff431c8de5d..2a9e37081e0 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -66,7 +66,7 @@ //! //! # "`cs`" functions //! -//! The `cs_...` functions ("combine substructure) are designed to +//! The `cs_...` functions ("combine substructure") are designed to //! make life easier by providing some pre-made recipes for common //! threads; mostly calling the function being derived on all the //! arguments and then combining them back together in some way (or @@ -429,6 +429,7 @@ impl<'a> TraitDef<'a> { generics, from_scratch, use_temporaries, + is_packed, ), ast::ItemKind::Enum(ref enum_def, ref generics) => { // We ignore `use_temporaries` here, because @@ -448,6 +449,7 @@ impl<'a> TraitDef<'a> { generics, from_scratch, use_temporaries, + is_packed, ) } else { cx.span_err(mitem.span, "this trait cannot be derived for unions"); @@ -729,6 +731,7 @@ impl<'a> TraitDef<'a> { generics: &Generics, from_scratch: bool, use_temporaries: bool, + is_packed: bool, ) -> P<ast::Item> { let field_tys: Vec<P<ast::Ty>> = struct_def.fields().iter().map(|field| field.ty.clone()).collect(); @@ -757,6 +760,7 @@ impl<'a> TraitDef<'a> { &self_args, &nonself_args, use_temporaries, + is_packed, ) }; @@ -945,6 +949,7 @@ impl<'a> MethodDef<'a> { }) } + /// The normal case uses field access. /// ``` /// #[derive(PartialEq)] /// # struct Dummy; @@ -953,33 +958,21 @@ impl<'a> MethodDef<'a> { /// // equivalent to: /// impl PartialEq for A { /// fn eq(&self, other: &A) -> bool { - /// match *self { - /// A {x: ref __self_0_0, y: ref __self_0_1} => { - /// match *other { - /// A {x: ref __self_1_0, y: ref __self_1_1} => { - /// __self_0_0.eq(__self_1_0) && __self_0_1.eq(__self_1_1) - /// } - /// } - /// } - /// } + /// self.x == other.x && self.y == other.y /// } /// } /// ``` - /// or if A is repr(packed) - note fields are matched by-value - /// instead of by-reference. + /// But if the struct is `repr(packed)`, we can't use something like + /// `&self.x` on a packed type (as required for e.g. `Debug` and `Hash`) + /// because that might cause an unaligned ref. So we use let-destructuring + /// instead. /// ``` /// # struct A { x: i32, y: i32 } /// impl PartialEq for A { /// fn eq(&self, other: &A) -> bool { - /// match *self { - /// A {x: __self_0_0, y: __self_0_1} => { - /// match other { - /// A {x: __self_1_0, y: __self_1_1} => { - /// __self_0_0.eq(&__self_1_0) && __self_0_1.eq(&__self_1_1) - /// } - /// } - /// } - /// } + /// let Self { x: ref __self_0_0, y: ref __self_0_1 } = *self; + /// let Self { x: ref __self_1_0, y: ref __self_1_1 } = *other; + /// *__self_0_0 == *__self_1_0 && *__self_0_1 == *__self_1_1 /// } /// } /// ``` @@ -992,24 +985,33 @@ impl<'a> MethodDef<'a> { self_args: &[P<Expr>], nonself_args: &[P<Expr>], use_temporaries: bool, + is_packed: bool, ) -> P<Expr> { let mut raw_fields = Vec::new(); // Vec<[fields of self], [fields of next Self arg], [etc]> let span = trait_.span; let mut patterns = Vec::new(); - for i in 0..self_args.len() { - // We could use `type_ident` instead of `Self`, but in the case of a type parameter - // shadowing the struct name, that causes a second, unnecessary E0578 error. #97343 - let struct_path = cx.path(span, vec![Ident::new(kw::SelfUpper, type_ident.span)]); - let (pat, ident_expr) = trait_.create_struct_pattern( - cx, - struct_path, - struct_def, - &format!("__self_{}", i), - ast::Mutability::Not, - use_temporaries, - ); - patterns.push(pat); - raw_fields.push(ident_expr); + + for (i, self_arg) in self_args.iter().enumerate() { + let ident_exprs = if !is_packed { + trait_.create_struct_field_accesses(cx, self_arg, struct_def) + } else { + // Get the pattern for the let-destructuring. + // + // We could use `type_ident` instead of `Self`, but in the case of a type parameter + // shadowing the struct name, that causes a second, unnecessary E0578 error. #97343 + let struct_path = cx.path(span, vec![Ident::new(kw::SelfUpper, type_ident.span)]); + let (pat, ident_exprs) = trait_.create_struct_pattern( + cx, + struct_path, + struct_def, + &format!("__self_{}", i), + ast::Mutability::Not, + use_temporaries, + ); + patterns.push(pat); + ident_exprs + }; + raw_fields.push(ident_exprs); } // transpose raw_fields @@ -1036,7 +1038,6 @@ impl<'a> MethodDef<'a> { cx.span_bug(span, "no `self` parameter for method in generic `derive`") }; - // body of the inner most destructuring match let mut body = self.call_substructure_method( cx, trait_, @@ -1045,14 +1046,18 @@ impl<'a> MethodDef<'a> { &Struct(struct_def, fields), ); - // make a series of nested matches, to destructure the - // structs. This is actually right-to-left, but it shouldn't - // matter. - for (arg_expr, pat) in iter::zip(self_args, patterns) { - body = cx.expr_match(span, arg_expr.clone(), vec![cx.arm(span, pat.clone(), body)]) - } + if !is_packed { + body.span = span; + body + } else { + // Do the let-destructuring. + let mut stmts: Vec<_> = iter::zip(self_args, patterns) + .map(|(arg_expr, pat)| cx.stmt_let_pat(span, pat, arg_expr.clone())) + .collect(); + stmts.push(cx.stmt_expr(body)); - body + cx.expr_block(cx.block(span, stmts)) + } } fn expand_static_struct_method_body( @@ -1522,8 +1527,6 @@ impl<'a> TraitDef<'a> { paths.push(ident.with_span_pos(sp)); let val = cx.expr_path(cx.path_ident(sp, ident)); let val = if use_temporaries { val } else { cx.expr_deref(sp, val) }; - let val = cx.expr(sp, ast::ExprKind::Paren(val)); - ident_exprs.push((sp, struct_field.ident, val, &struct_field.attrs[..])); } @@ -1555,6 +1558,39 @@ impl<'a> TraitDef<'a> { (pattern, ident_exprs) } + fn create_struct_field_accesses( + &self, + cx: &mut ExtCtxt<'_>, + mut self_arg: &P<Expr>, + struct_def: &'a VariantData, + ) -> Vec<(Span, Option<Ident>, P<Expr>, &'a [ast::Attribute])> { + let mut ident_exprs = Vec::new(); + for (i, struct_field) in struct_def.fields().iter().enumerate() { + let sp = struct_field.span.with_ctxt(self.span.ctxt()); + + // We don't the need the deref, if there is one. + if let ast::ExprKind::Unary(ast::UnOp::Deref, inner) = &self_arg.kind { + self_arg = inner; + } + + // Note: we must use `struct_field.span` rather than `span` in the + // `unwrap_or_else` case otherwise the hygiene is wrong and we get + // "field `0` of struct `Point` is private" errors on tuple + // structs. + let val = cx.expr( + sp, + ast::ExprKind::Field( + self_arg.clone(), + struct_field.ident.unwrap_or_else(|| { + Ident::from_str_and_span(&i.to_string(), struct_field.span) + }), + ), + ); + ident_exprs.push((sp, struct_field.ident, val, &struct_field.attrs[..])); + } + ident_exprs + } + fn create_enum_variant_pattern( &self, cx: &mut ExtCtxt<'_>, @@ -1643,7 +1679,6 @@ where /// fields. /// When the `substructure` is an `EnumNonMatchingCollapsed`, the result of `enum_nonmatch_f` /// is returned. Statics may not be folded over. -/// See `cs_op` in `partial_ord.rs` for a model example. pub fn cs_fold1<F, B>( use_foldl: bool, f: F, diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 66c73624501..031d508d70f 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -808,7 +808,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.stack_mut().pop().expect("tried to pop a stack frame, but there were none"); if !unwinding { - let op = self.access_local(&frame, mir::RETURN_PLACE, None)?; + let op = self.local_to_op(&frame, mir::RETURN_PLACE, None)?; self.copy_op_transmute(&op, &frame.return_place)?; trace!("{:?}", self.dump_place(*frame.return_place)); } @@ -981,8 +981,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> std::fmt::Debug LocalValue::Live(Operand::Indirect(mplace)) => { write!( fmt, - " by align({}){} ref {:?}:", - mplace.align.bytes(), + " by {} ref {:?}:", match mplace.meta { MemPlaceMeta::Meta(meta) => format!(" meta({:?})", meta), MemPlaceMeta::Poison | MemPlaceMeta::None => String::new(), @@ -1011,13 +1010,9 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> std::fmt::Debug write!(fmt, ": {:?}", self.ecx.dump_allocs(allocs.into_iter().flatten().collect())) } Place::Ptr(mplace) => match mplace.ptr.provenance.and_then(Provenance::get_alloc_id) { - Some(alloc_id) => write!( - fmt, - "by align({}) ref {:?}: {:?}", - mplace.align.bytes(), - mplace.ptr, - self.ecx.dump_alloc(alloc_id) - ), + Some(alloc_id) => { + write!(fmt, "by ref {:?}: {:?}", mplace.ptr, self.ecx.dump_alloc(alloc_id)) + } ptr => write!(fmt, " integral by ref: {:?}", ptr), }, } diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index c2a5b71b8f9..509fe576893 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -276,7 +276,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { kind: MemoryKind<M::MemoryKind>, ) -> InterpResult<'tcx> { let (alloc_id, offset, tag) = self.ptr_get_alloc_id(ptr)?; - trace!("deallocating: {}", alloc_id); + trace!("deallocating: {alloc_id:?}"); if offset.bytes() != 0 { throw_ub_format!( @@ -289,10 +289,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Deallocating global memory -- always an error return Err(match self.tcx.get_global_alloc(alloc_id) { Some(GlobalAlloc::Function(..)) => { - err_ub_format!("deallocating {}, which is a function", alloc_id) + err_ub_format!("deallocating {alloc_id:?}, which is a function") } Some(GlobalAlloc::Static(..) | GlobalAlloc::Memory(..)) => { - err_ub_format!("deallocating {}, which is static memory", alloc_id) + err_ub_format!("deallocating {alloc_id:?}, which is static memory") } None => err_ub!(PointerUseAfterFree(alloc_id)), } @@ -302,21 +302,17 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { debug!(?alloc); if alloc.mutability == Mutability::Not { - throw_ub_format!("deallocating immutable allocation {}", alloc_id); + throw_ub_format!("deallocating immutable allocation {alloc_id:?}"); } if alloc_kind != kind { throw_ub_format!( - "deallocating {}, which is {} memory, using {} deallocation operation", - alloc_id, - alloc_kind, - kind + "deallocating {alloc_id:?}, which is {alloc_kind} memory, using {kind} deallocation operation" ); } if let Some((size, align)) = old_size_and_align { if size != alloc.size() || align != alloc.align { throw_ub_format!( - "incorrect layout on deallocation: {} has size {} and alignment {}, but gave size {} and alignment {}", - alloc_id, + "incorrect layout on deallocation: {alloc_id:?} has size {} and alignment {}, but gave size {} and alignment {}", alloc.size().bytes(), alloc.align.bytes(), size.bytes(), @@ -815,7 +811,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> std::fmt::Debug for DumpAllocs<'a, continue; } - write!(fmt, "{}", id)?; + write!(fmt, "{id:?}")?; match self.ecx.memory.alloc_map.get(id) { Some(&(kind, ref alloc)) => { // normal alloc @@ -859,25 +855,21 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> std::fmt::Debug for DumpAllocs<'a, /// Reading and writing. impl<'tcx, 'a, Tag: Provenance, Extra> AllocRefMut<'a, 'tcx, Tag, Extra> { + /// `range` is relative to this allocation reference, not the base of the allocation. pub fn write_scalar( &mut self, range: AllocRange, val: ScalarMaybeUninit<Tag>, ) -> InterpResult<'tcx> { let range = self.range.subrange(range); - debug!( - "write_scalar in {} at {:#x}, size {}: {:?}", - self.alloc_id, - range.start.bytes(), - range.size.bytes(), - val - ); + debug!("write_scalar at {:?}{range:?}: {val:?}", self.alloc_id); Ok(self .alloc .write_scalar(&self.tcx, range, val) .map_err(|e| e.to_interp_error(self.alloc_id))?) } + /// `offset` is relative to this allocation reference, not the base of the allocation. pub fn write_ptr_sized( &mut self, offset: Size, @@ -896,6 +888,7 @@ impl<'tcx, 'a, Tag: Provenance, Extra> AllocRefMut<'a, 'tcx, Tag, Extra> { } impl<'tcx, 'a, Tag: Provenance, Extra> AllocRef<'a, 'tcx, Tag, Extra> { + /// `range` is relative to this allocation reference, not the base of the allocation. pub fn read_scalar( &self, range: AllocRange, @@ -906,24 +899,16 @@ impl<'tcx, 'a, Tag: Provenance, Extra> AllocRef<'a, 'tcx, Tag, Extra> { .alloc .read_scalar(&self.tcx, range, read_provenance) .map_err(|e| e.to_interp_error(self.alloc_id))?; - debug!( - "read_scalar in {} at {:#x}, size {}: {:?}", - self.alloc_id, - range.start.bytes(), - range.size.bytes(), - res - ); + debug!("read_scalar at {:?}{range:?}: {res:?}", self.alloc_id); Ok(res) } - pub fn read_integer( - &self, - offset: Size, - size: Size, - ) -> InterpResult<'tcx, ScalarMaybeUninit<Tag>> { - self.read_scalar(alloc_range(offset, size), /*read_provenance*/ false) + /// `range` is relative to this allocation reference, not the base of the allocation. + pub fn read_integer(&self, range: AllocRange) -> InterpResult<'tcx, ScalarMaybeUninit<Tag>> { + self.read_scalar(range, /*read_provenance*/ false) } + /// `offset` is relative to this allocation reference, not the base of the allocation. pub fn read_pointer(&self, offset: Size) -> InterpResult<'tcx, ScalarMaybeUninit<Tag>> { self.read_scalar( alloc_range(offset, self.tcx.data_layout().pointer_size), @@ -931,6 +916,7 @@ impl<'tcx, 'a, Tag: Provenance, Extra> AllocRef<'a, 'tcx, Tag, Extra> { ) } + /// `range` is relative to this allocation reference, not the base of the allocation. pub fn check_bytes( &self, range: AllocRange, diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index e7a08e05275..d48f6521ba2 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -10,7 +10,7 @@ use rustc_middle::ty::layout::{LayoutOf, PrimitiveExt, TyAndLayout}; use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Printer}; use rustc_middle::ty::{ConstInt, DelaySpanBugEmitted, Ty}; use rustc_middle::{mir, ty}; -use rustc_target::abi::{self, Abi, HasDataLayout, Size, TagEncoding}; +use rustc_target::abi::{self, Abi, Align, HasDataLayout, Size, TagEncoding}; use rustc_target::abi::{VariantIdx, Variants}; use super::{ @@ -177,10 +177,18 @@ pub enum Operand<Tag: Provenance = AllocId> { pub struct OpTy<'tcx, Tag: Provenance = AllocId> { op: Operand<Tag>, // Keep this private; it helps enforce invariants. pub layout: TyAndLayout<'tcx>, + /// rustc does not have a proper way to represent the type of a field of a `repr(packed)` struct: + /// it needs to have a different alignment than the field type would usually have. + /// So we represent this here with a separate field that "overwrites" `layout.align`. + /// This means `layout.align` should never be used for an `OpTy`! + /// `None` means "alignment does not matter since this is a by-value operand" + /// (`Operand::Immediate`); this field is only relevant for `Operand::Indirect`. + /// Also CTFE ignores alignment anyway, so this is for Miri only. + pub align: Option<Align>, } #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(OpTy<'_>, 80); +rustc_data_structures::static_assert_size!(OpTy<'_>, 88); impl<'tcx, Tag: Provenance> std::ops::Deref for OpTy<'tcx, Tag> { type Target = Operand<Tag>; @@ -193,28 +201,28 @@ impl<'tcx, Tag: Provenance> std::ops::Deref for OpTy<'tcx, Tag> { impl<'tcx, Tag: Provenance> From<MPlaceTy<'tcx, Tag>> for OpTy<'tcx, Tag> { #[inline(always)] fn from(mplace: MPlaceTy<'tcx, Tag>) -> Self { - OpTy { op: Operand::Indirect(*mplace), layout: mplace.layout } + OpTy { op: Operand::Indirect(*mplace), layout: mplace.layout, align: Some(mplace.align) } } } impl<'tcx, Tag: Provenance> From<&'_ MPlaceTy<'tcx, Tag>> for OpTy<'tcx, Tag> { #[inline(always)] fn from(mplace: &MPlaceTy<'tcx, Tag>) -> Self { - OpTy { op: Operand::Indirect(**mplace), layout: mplace.layout } + OpTy { op: Operand::Indirect(**mplace), layout: mplace.layout, align: Some(mplace.align) } } } impl<'tcx, Tag: Provenance> From<&'_ mut MPlaceTy<'tcx, Tag>> for OpTy<'tcx, Tag> { #[inline(always)] fn from(mplace: &mut MPlaceTy<'tcx, Tag>) -> Self { - OpTy { op: Operand::Indirect(**mplace), layout: mplace.layout } + OpTy { op: Operand::Indirect(**mplace), layout: mplace.layout, align: Some(mplace.align) } } } impl<'tcx, Tag: Provenance> From<ImmTy<'tcx, Tag>> for OpTy<'tcx, Tag> { #[inline(always)] fn from(val: ImmTy<'tcx, Tag>) -> Self { - OpTy { op: Operand::Immediate(val.imm), layout: val.layout } + OpTy { op: Operand::Immediate(val.imm), layout: val.layout, align: None } } } @@ -450,7 +458,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ), }; - Ok(OpTy { op: Operand::Immediate(field_val), layout: field_layout }) + Ok(OpTy { op: Operand::Immediate(field_val), layout: field_layout, align: None }) } pub fn operand_index( @@ -522,7 +530,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// /// This is public because it is used by [priroda](https://github.com/oli-obk/priroda) to get an /// OpTy from a local - pub fn access_local( + pub fn local_to_op( &self, frame: &super::Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>, local: mir::Local, @@ -535,7 +543,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } else { M::access_local(&self, frame, local)? }; - Ok(OpTy { op, layout }) + Ok(OpTy { op, layout, align: Some(layout.align.abi) }) } /// Every place can be read from, so we can turn them into an operand. @@ -549,10 +557,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let op = match **place { Place::Ptr(mplace) => Operand::Indirect(mplace), Place::Local { frame, local } => { - *self.access_local(&self.stack()[frame], local, None)? + *self.local_to_op(&self.stack()[frame], local, None)? } }; - Ok(OpTy { op, layout: place.layout }) + Ok(OpTy { op, layout: place.layout, align: Some(place.align) }) } /// Evaluate a place with the goal of reading from it. This lets us sometimes @@ -566,7 +574,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // here is not the entire place. let layout = if place.projection.is_empty() { layout } else { None }; - let base_op = self.access_local(self.frame(), place.local, layout)?; + let base_op = self.local_to_op(self.frame(), place.local, layout)?; let op = place .projection @@ -603,11 +611,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Constant(ref constant) => { let val = self.subst_from_current_frame_and_normalize_erasing_regions(constant.literal)?; + // This can still fail: // * During ConstProp, with `TooGeneric` or since the `required_consts` were not all // checked yet. // * During CTFE, since promoteds in `const`/`static` initializer bodies can fail. - self.mir_const_to_op(&val, layout)? } }; @@ -683,7 +691,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // We rely on mutability being set correctly in that allocation to prevent writes // where none should happen. let ptr = self.global_base_pointer(Pointer::new(id, offset))?; - Operand::Indirect(MemPlace::from_ptr(ptr.into(), layout.align.abi)) + Operand::Indirect(MemPlace::from_ptr(ptr.into())) } ConstValue::Scalar(x) => Operand::Immediate(tag_scalar(x)?.into()), ConstValue::Slice { data, start, end } => { @@ -700,7 +708,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { )) } }; - Ok(OpTy { op, layout }) + Ok(OpTy { op, layout, align: Some(layout.align.abi) }) } /// Read discriminant, return the runtime value as well as the variant index. diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs index 85ee88e9e47..dec7fa8c4aa 100644 --- a/compiler/rustc_const_eval/src/interpret/operator.rs +++ b/compiler/rustc_const_eval/src/interpret/operator.rs @@ -5,6 +5,7 @@ use rustc_middle::mir; use rustc_middle::mir::interpret::{InterpResult, Scalar}; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_middle::ty::{self, FloatTy, Ty}; +use rustc_target::abi::Abi; use super::{ImmTy, Immediate, InterpCx, Machine, PlaceTy}; @@ -25,8 +26,22 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { "type mismatch for result of {:?}", op, ); - let val = Immediate::ScalarPair(val.into(), Scalar::from_bool(overflowed).into()); - self.write_immediate(val, dest) + if let Abi::ScalarPair(..) = dest.layout.abi { + // We can use the optimized path and avoid `place_field` (which might do + // `force_allocation`). + let pair = Immediate::ScalarPair(val.into(), Scalar::from_bool(overflowed).into()); + self.write_immediate(pair, dest)?; + } else { + assert!(self.tcx.sess.opts.debugging_opts.randomize_layout); + // With randomized layout, `(int, bool)` might cease to be a `ScalarPair`, so we have to + // do a component-wise write here. This code path is slower than the above because + // `place_field` will have to `force_allocate` locals here. + let val_field = self.place_field(&dest, 0)?; + self.write_scalar(val, &val_field)?; + let overflowed_field = self.place_field(&dest, 1)?; + self.write_scalar(Scalar::from_bool(overflowed), &overflowed_field)?; + } + Ok(()) } /// Applies the binary operation `op` to the arguments and writes the result to the diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 337fcd28c66..98a3a50afaa 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -57,7 +57,6 @@ impl<Tag: Provenance> MemPlaceMeta<Tag> { pub struct MemPlace<Tag: Provenance = AllocId> { /// The pointer can be a pure integer, with the `None` tag. pub ptr: Pointer<Option<Tag>>, - pub align: Align, /// Metadata for unsized places. Interpretation is up to the type. /// Must not be present for sized types, but can be missing for unsized types /// (e.g., `extern type`). @@ -65,7 +64,7 @@ pub struct MemPlace<Tag: Provenance = AllocId> { } #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(MemPlace, 48); +rustc_data_structures::static_assert_size!(MemPlace, 40); #[derive(Copy, Clone, Hash, PartialEq, Eq, HashStable, Debug)] pub enum Place<Tag: Provenance = AllocId> { @@ -78,12 +77,17 @@ pub enum Place<Tag: Provenance = AllocId> { } #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(Place, 56); +rustc_data_structures::static_assert_size!(Place, 48); #[derive(Copy, Clone, Debug)] pub struct PlaceTy<'tcx, Tag: Provenance = AllocId> { place: Place<Tag>, // Keep this private; it helps enforce invariants. pub layout: TyAndLayout<'tcx>, + /// rustc does not have a proper way to represent the type of a field of a `repr(packed)` struct: + /// it needs to have a different alignment than the field type would usually have. + /// So we represent this here with a separate field that "overwrites" `layout.align`. + /// This means `layout.align` should never be used for a `PlaceTy`! + pub align: Align, } #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] @@ -102,6 +106,11 @@ impl<'tcx, Tag: Provenance> std::ops::Deref for PlaceTy<'tcx, Tag> { pub struct MPlaceTy<'tcx, Tag: Provenance = AllocId> { mplace: MemPlace<Tag>, pub layout: TyAndLayout<'tcx>, + /// rustc does not have a proper way to represent the type of a field of a `repr(packed)` struct: + /// it needs to have a different alignment than the field type would usually have. + /// So we represent this here with a separate field that "overwrites" `layout.align`. + /// This means `layout.align` should never be used for a `MPlaceTy`! + pub align: Align, } #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] @@ -118,28 +127,28 @@ impl<'tcx, Tag: Provenance> std::ops::Deref for MPlaceTy<'tcx, Tag> { impl<'tcx, Tag: Provenance> From<MPlaceTy<'tcx, Tag>> for PlaceTy<'tcx, Tag> { #[inline(always)] fn from(mplace: MPlaceTy<'tcx, Tag>) -> Self { - PlaceTy { place: Place::Ptr(*mplace), layout: mplace.layout } + PlaceTy { place: Place::Ptr(*mplace), layout: mplace.layout, align: mplace.align } } } impl<'tcx, Tag: Provenance> From<&'_ MPlaceTy<'tcx, Tag>> for PlaceTy<'tcx, Tag> { #[inline(always)] fn from(mplace: &MPlaceTy<'tcx, Tag>) -> Self { - PlaceTy { place: Place::Ptr(**mplace), layout: mplace.layout } + PlaceTy { place: Place::Ptr(**mplace), layout: mplace.layout, align: mplace.align } } } impl<'tcx, Tag: Provenance> From<&'_ mut MPlaceTy<'tcx, Tag>> for PlaceTy<'tcx, Tag> { #[inline(always)] fn from(mplace: &mut MPlaceTy<'tcx, Tag>) -> Self { - PlaceTy { place: Place::Ptr(**mplace), layout: mplace.layout } + PlaceTy { place: Place::Ptr(**mplace), layout: mplace.layout, align: mplace.align } } } impl<Tag: Provenance> MemPlace<Tag> { #[inline(always)] - pub fn from_ptr(ptr: Pointer<Option<Tag>>, align: Align) -> Self { - MemPlace { ptr, align, meta: MemPlaceMeta::None } + pub fn from_ptr(ptr: Pointer<Option<Tag>>) -> Self { + MemPlace { ptr, meta: MemPlaceMeta::None } } /// Adjust the provenance of the main pointer (metadata is unaffected). @@ -170,11 +179,7 @@ impl<Tag: Provenance> MemPlace<Tag> { meta: MemPlaceMeta<Tag>, cx: &impl HasDataLayout, ) -> InterpResult<'tcx, Self> { - Ok(MemPlace { - ptr: self.ptr.offset(offset, cx)?, - align: self.align.restrict_for_offset(offset), - meta, - }) + Ok(MemPlace { ptr: self.ptr.offset(offset, cx)?, meta }) } } @@ -185,7 +190,7 @@ impl<'tcx, Tag: Provenance> MPlaceTy<'tcx, Tag> { let align = layout.align.abi; let ptr = Pointer::new(None, Size::from_bytes(align.bytes())); // no provenance, absolute address // `Poison` this to make sure that the pointer value `ptr` is never observable by the program. - MPlaceTy { mplace: MemPlace { ptr, align, meta: MemPlaceMeta::Poison }, layout } + MPlaceTy { mplace: MemPlace { ptr, meta: MemPlaceMeta::Poison }, layout, align } } #[inline] @@ -196,12 +201,16 @@ impl<'tcx, Tag: Provenance> MPlaceTy<'tcx, Tag> { layout: TyAndLayout<'tcx>, cx: &impl HasDataLayout, ) -> InterpResult<'tcx, Self> { - Ok(MPlaceTy { mplace: self.mplace.offset(offset, meta, cx)?, layout }) + Ok(MPlaceTy { + mplace: self.mplace.offset(offset, meta, cx)?, + align: self.align.restrict_for_offset(offset), + layout, + }) } #[inline] pub fn from_aligned_ptr(ptr: Pointer<Option<Tag>>, layout: TyAndLayout<'tcx>) -> Self { - MPlaceTy { mplace: MemPlace::from_ptr(ptr, layout.align.abi), layout } + MPlaceTy { mplace: MemPlace::from_ptr(ptr), layout, align: layout.align.abi } } #[inline] @@ -210,10 +219,10 @@ impl<'tcx, Tag: Provenance> MPlaceTy<'tcx, Tag> { layout: TyAndLayout<'tcx>, meta: MemPlaceMeta<Tag>, ) -> Self { - let mut mplace = MemPlace::from_ptr(ptr, layout.align.abi); + let mut mplace = MemPlace::from_ptr(ptr); mplace.meta = meta; - MPlaceTy { mplace, layout } + MPlaceTy { mplace, layout, align: layout.align.abi } } #[inline] @@ -250,7 +259,9 @@ impl<'tcx, Tag: Provenance> OpTy<'tcx, Tag> { /// read from the resulting mplace, not to get its address back. pub fn try_as_mplace(&self) -> Result<MPlaceTy<'tcx, Tag>, ImmTy<'tcx, Tag>> { match **self { - Operand::Indirect(mplace) => Ok(MPlaceTy { mplace, layout: self.layout }), + Operand::Indirect(mplace) => { + Ok(MPlaceTy { mplace, layout: self.layout, align: self.align.unwrap() }) + } Operand::Immediate(_) if self.layout.is_zst() => Ok(MPlaceTy::dangling(self.layout)), Operand::Immediate(imm) => Err(ImmTy::from_immediate(imm, self.layout)), } @@ -264,20 +275,19 @@ impl<'tcx, Tag: Provenance> OpTy<'tcx, Tag> { } } -impl<Tag: Provenance> Place<Tag> { +impl<'tcx, Tag: Provenance> PlaceTy<'tcx, Tag> { + /// A place is either an mplace or some local. #[inline] - pub fn assert_mem_place(self) -> MemPlace<Tag> { - match self { - Place::Ptr(mplace) => mplace, - _ => bug!("assert_mem_place: expected Place::Ptr, got {:?}", self), + pub fn try_as_mplace(&self) -> Result<MPlaceTy<'tcx, Tag>, (usize, mir::Local)> { + match **self { + Place::Ptr(mplace) => Ok(MPlaceTy { mplace, layout: self.layout, align: self.align }), + Place::Local { frame, local } => Err((frame, local)), } } -} -impl<'tcx, Tag: Provenance> PlaceTy<'tcx, Tag> { #[inline] pub fn assert_mem_place(self) -> MPlaceTy<'tcx, Tag> { - MPlaceTy { mplace: self.place.assert_mem_place(), layout: self.layout } + self.try_as_mplace().unwrap() } } @@ -306,16 +316,10 @@ where Immediate::ScalarPair(ptr, meta) => (ptr, MemPlaceMeta::Meta(meta.check_init()?)), }; - let mplace = MemPlace { - ptr: self.scalar_to_ptr(ptr.check_init()?)?, - // We could use the run-time alignment here. For now, we do not, because - // the point of tracking the alignment here is to make sure that the *static* - // alignment information emitted with the loads is correct. The run-time - // alignment can only be more restrictive. - align: layout.align.abi, - meta, - }; - Ok(MPlaceTy { mplace, layout }) + let mplace = MemPlace { ptr: self.scalar_to_ptr(ptr.check_init()?)?, meta }; + // When deref'ing a pointer, the *static* alignment given by the type is what matters. + let align = layout.align.abi; + Ok(MPlaceTy { mplace, layout, align }) } /// Take an operand, representing a pointer, and dereference it to a place -- that @@ -368,7 +372,7 @@ where let (size, align) = self .size_and_align_of_mplace(&mplace)? .unwrap_or((mplace.layout.size, mplace.layout.align.abi)); - assert!(mplace.mplace.align <= align, "dynamic alignment less strict than static one?"); + assert!(mplace.align <= align, "dynamic alignment less strict than static one?"); let align = M::enforce_alignment(self).then_some(align); self.check_ptr_access_align(mplace.ptr, size, align.unwrap_or(Align::ONE), msg)?; Ok(()) @@ -533,7 +537,7 @@ where Index(local) => { let layout = self.layout_of(self.tcx.types.usize)?; - let n = self.access_local(self.frame(), local, Some(layout))?; + let n = self.local_to_op(self.frame(), local, Some(layout))?; let n = self.read_scalar(&n)?; let n = n.to_machine_usize(self)?; self.mplace_index(base, n)? @@ -608,11 +612,9 @@ where variant: VariantIdx, ) -> InterpResult<'tcx, PlaceTy<'tcx, M::PointerTag>> { // Downcast just changes the layout - Ok(match base.place { - Place::Ptr(mplace) => { - self.mplace_downcast(&MPlaceTy { mplace, layout: base.layout }, variant)?.into() - } - Place::Local { .. } => { + Ok(match base.try_as_mplace() { + Ok(mplace) => self.mplace_downcast(&mplace, variant)?.into(), + Err(..) => { let layout = base.layout.for_variant(self, variant); PlaceTy { layout, ..*base } } @@ -649,6 +651,16 @@ where self.mplace_to_simd(&mplace) } + pub fn local_to_place( + &self, + frame: usize, + local: mir::Local, + ) -> InterpResult<'tcx, PlaceTy<'tcx, M::PointerTag>> { + let layout = self.layout_of_local(&self.stack()[frame], local, None)?; + let place = Place::Local { frame, local }; + Ok(PlaceTy { place, layout, align: layout.align.abi }) + } + /// Computes a place. You should only use this if you intend to write into this /// place; for reading, a more efficient alternative is `eval_place_to_op`. #[instrument(skip(self), level = "debug")] @@ -656,11 +668,7 @@ where &mut self, place: mir::Place<'tcx>, ) -> InterpResult<'tcx, PlaceTy<'tcx, M::PointerTag>> { - let mut place_ty = PlaceTy { - // This works even for dead/uninitialized locals; we check further when writing - place: Place::Local { frame: self.frame_idx(), local: place.local }, - layout: self.layout_of_local(self.frame(), place.local, None)?, - }; + let mut place_ty = self.local_to_place(self.frame_idx(), place.local)?; for elem in place.projection.iter() { place_ty = self.place_projection(&place_ty, &elem)? @@ -668,14 +676,19 @@ where trace!("{:?}", self.dump_place(place_ty.place)); // Sanity-check the type we ended up with. - debug_assert!(mir_assign_valid_types( - *self.tcx, - self.param_env, - self.layout_of(self.subst_from_current_frame_and_normalize_erasing_regions( - place.ty(&self.frame().body.local_decls, *self.tcx).ty - )?)?, - place_ty.layout, - )); + debug_assert!( + mir_assign_valid_types( + *self.tcx, + self.param_env, + self.layout_of(self.subst_from_current_frame_and_normalize_erasing_regions( + place.ty(&self.frame().body.local_decls, *self.tcx).ty + )?)?, + place_ty.layout, + ), + "eval_place of a MIR place with type {:?} produced an interpret place with type {:?}", + place.ty(&self.frame().body.local_decls, *self.tcx).ty, + place_ty.layout.ty, + ); Ok(place_ty) } @@ -746,7 +759,7 @@ where } Place::Ptr(mplace) => mplace, // already referring to memory }; - let dest = MPlaceTy { mplace, layout: dest.layout }; + let dest = MPlaceTy { mplace, layout: dest.layout, align: dest.align }; // This is already in memory, write there. self.write_immediate_to_mplace_no_validate(src, &dest) @@ -808,9 +821,9 @@ where } pub fn write_uninit(&mut self, dest: &PlaceTy<'tcx, M::PointerTag>) -> InterpResult<'tcx> { - let mplace = match dest.place { - Place::Ptr(mplace) => MPlaceTy { mplace, layout: dest.layout }, - Place::Local { frame, local } => { + let mplace = match dest.try_as_mplace() { + Ok(mplace) => mplace, + Err((frame, local)) => { match M::access_local_mut(self, frame, local)? { Ok(local) => match dest.layout.abi { Abi::Scalar(_) => { @@ -830,7 +843,7 @@ where }, Err(mplace) => { // The local is in memory, go on below. - MPlaceTy { mplace, layout: dest.layout } + MPlaceTy { mplace, layout: dest.layout, align: dest.align } } } } @@ -948,7 +961,7 @@ where let dest = self.force_allocation(dest)?; self.copy_op_no_validate( src, - &PlaceTy::from(MPlaceTy { mplace: *dest, layout: src.layout }), + &PlaceTy::from(MPlaceTy { mplace: *dest, layout: src.layout, align: dest.align }), )?; if M::enforce_validity(self) { @@ -989,12 +1002,16 @@ where .size_and_align_of(&meta, &local_layout)? .expect("Cannot allocate for non-dyn-sized type"); let ptr = self.allocate_ptr(size, align, MemoryKind::Stack)?; - let mplace = MemPlace { ptr: ptr.into(), align, meta }; + let mplace = MemPlace { ptr: ptr.into(), meta }; if let LocalValue::Live(Operand::Immediate(value)) = local_val { // Preserve old value. // We don't have to validate as we can assume the local // was already valid for its type. - let mplace = MPlaceTy { mplace, layout: local_layout }; + let mplace = MPlaceTy { + mplace, + layout: local_layout, + align: local_layout.align.abi, + }; self.write_immediate_to_mplace_no_validate(value, &mplace)?; } // Now we can call `access_mut` again, asserting it goes well, @@ -1009,7 +1026,7 @@ where Place::Ptr(mplace) => (mplace, None), }; // Return with the original layout, so that the caller can go on - Ok((MPlaceTy { mplace, layout: place.layout }, size)) + Ok((MPlaceTy { mplace, layout: place.layout, align: place.align }, size)) } #[inline(always)] @@ -1038,15 +1055,14 @@ where ) -> MPlaceTy<'tcx, M::PointerTag> { let ptr = self.allocate_bytes_ptr(str.as_bytes(), Align::ONE, kind, mutbl); let meta = Scalar::from_machine_usize(u64::try_from(str.len()).unwrap(), self); - let mplace = - MemPlace { ptr: ptr.into(), align: Align::ONE, meta: MemPlaceMeta::Meta(meta) }; + let mplace = MemPlace { ptr: ptr.into(), meta: MemPlaceMeta::Meta(meta) }; let ty = self.tcx.mk_ref( self.tcx.lifetimes.re_static, ty::TypeAndMut { ty: self.tcx.types.str_, mutbl }, ); let layout = self.layout_of(ty).unwrap(); - MPlaceTy { mplace, layout } + MPlaceTy { mplace, layout, align: layout.align.abi } } /// Writes the discriminant of the given variant. @@ -1166,7 +1182,11 @@ where assert_eq!(align, layout.align.abi); } - let mplace = MPlaceTy { mplace: MemPlace { meta: MemPlaceMeta::None, ..**mplace }, layout }; + let mplace = MPlaceTy { + mplace: MemPlace { meta: MemPlaceMeta::None, ..**mplace }, + layout, + align: layout.align.abi, + }; Ok((instance, mplace)) } } diff --git a/compiler/rustc_const_eval/src/interpret/traits.rs b/compiler/rustc_const_eval/src/interpret/traits.rs index 9c48f3e8337..22c23df7b1a 100644 --- a/compiler/rustc_const_eval/src/interpret/traits.rs +++ b/compiler/rustc_const_eval/src/interpret/traits.rs @@ -1,6 +1,6 @@ use std::convert::TryFrom; -use rustc_middle::mir::interpret::{InterpResult, Pointer, PointerArithmetic}; +use rustc_middle::mir::interpret::{alloc_range, InterpResult, Pointer, PointerArithmetic}; use rustc_middle::ty::{ self, Ty, TyCtxt, COMMON_VTABLE_ENTRIES_ALIGN, COMMON_VTABLE_ENTRIES_DROPINPLACE, COMMON_VTABLE_ENTRIES_SIZE, @@ -102,18 +102,18 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { )? .expect("cannot be a ZST"); let size = vtable - .read_integer( + .read_integer(alloc_range( pointer_size * u64::try_from(COMMON_VTABLE_ENTRIES_SIZE).unwrap(), pointer_size, - )? + ))? .check_init()?; let size = size.to_machine_usize(self)?; let size = Size::from_bytes(size); let align = vtable - .read_integer( + .read_integer(alloc_range( pointer_size * u64::try_from(COMMON_VTABLE_ENTRIES_ALIGN).unwrap(), pointer_size, - )? + ))? .check_init()?; let align = align.to_machine_usize(self)?; let align = Align::from_bytes(align).map_err(|e| err_ub!(InvalidVtableAlignment(e)))?; diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 847694cbd10..0bf78446e37 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -593,16 +593,6 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' self.check_safe_pointer(value, "reference")?; Ok(true) } - ty::Adt(def, ..) if def.is_box() => { - let unique = self.ecx.operand_field(value, 0)?; - let nonnull = self.ecx.operand_field(&unique, 0)?; - let ptr = self.ecx.operand_field(&nonnull, 0)?; - self.check_safe_pointer(&ptr, "box")?; - - // Check other fields of Box - self.walk_value(value)?; - Ok(true) - } ty::FnPtr(_sig) => { let value = try_validation!( self.ecx.read_scalar(value).and_then(|v| v.check_init()), @@ -814,6 +804,12 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> } #[inline] + fn visit_box(&mut self, op: &OpTy<'tcx, M::PointerTag>) -> InterpResult<'tcx> { + self.check_safe_pointer(op, "box")?; + Ok(()) + } + + #[inline] fn visit_value(&mut self, op: &OpTy<'tcx, M::PointerTag>) -> InterpResult<'tcx> { trace!("visit_value: {:?}, {:?}", *op, op.layout); @@ -821,8 +817,6 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> if self.try_visit_primitive(op)? { return Ok(()); } - // Sanity check: `builtin_deref` does not know any pointers that are not primitive. - assert!(op.layout.ty.builtin_deref(true).is_none()); // Special check preventing `UnsafeCell` in the inner part of constants if let Some(def) = op.layout.ty.ty_adt_def() { diff --git a/compiler/rustc_const_eval/src/interpret/visitor.rs b/compiler/rustc_const_eval/src/interpret/visitor.rs index 2b77ed89893..ded4c6a557a 100644 --- a/compiler/rustc_const_eval/src/interpret/visitor.rs +++ b/compiler/rustc_const_eval/src/interpret/visitor.rs @@ -151,6 +151,14 @@ macro_rules! make_value_visitor { { Ok(()) } + /// Visits the given value as the pointer of a `Box`. There is nothing to recurse into. + /// The type of `v` will be a raw pointer, but this is a field of `Box<T>` and the + /// pointee type is the actual `T`. + #[inline(always)] + fn visit_box(&mut self, _v: &Self::V) -> InterpResult<'tcx> + { + Ok(()) + } /// Visits this value as an aggregate, you are getting an iterator yielding /// all the fields (still in an `InterpResult`, you have to do error handling yourself). /// Recurses into the fields. @@ -221,6 +229,47 @@ macro_rules! make_value_visitor { // Slices do not need special handling here: they have `Array` field // placement with length 0, so we enter the `Array` case below which // indirectly uses the metadata to determine the actual length. + + // However, `Box`... let's talk about `Box`. + ty::Adt(def, ..) if def.is_box() => { + // `Box` is a hybrid primitive-library-defined type that one the one hand is + // a dereferenceable pointer, on the other hand has *basically arbitrary + // user-defined layout* since the user controls the 'allocator' field. So it + // cannot be treated like a normal pointer, since it does not fit into an + // `Immediate`. Yeah, it is quite terrible. But many visitors want to do + // something with "all boxed pointers", so we handle this mess for them. + // + // When we hit a `Box`, we do not do the usual `visit_aggregate`; instead, + // we (a) call `visit_box` on the pointer value, and (b) recurse on the + // allocator field. We also assert tons of things to ensure we do not miss + // any other fields. + + // `Box` has two fields: the pointer we care about, and the allocator. + assert_eq!(v.layout().fields.count(), 2, "`Box` must have exactly 2 fields"); + let (unique_ptr, alloc) = + (v.project_field(self.ecx(), 0)?, v.project_field(self.ecx(), 1)?); + // Unfortunately there is some type junk in the way here: `unique_ptr` is a `Unique`... + // (which means another 2 fields, the second of which is a `PhantomData`) + assert_eq!(unique_ptr.layout().fields.count(), 2); + let (nonnull_ptr, phantom) = ( + unique_ptr.project_field(self.ecx(), 0)?, + unique_ptr.project_field(self.ecx(), 1)?, + ); + assert!( + phantom.layout().ty.ty_adt_def().is_some_and(|adt| adt.is_phantom_data()), + "2nd field of `Unique` should be PhantomData but is {:?}", + phantom.layout().ty, + ); + // ... that contains a `NonNull`... (gladly, only a single field here) + assert_eq!(nonnull_ptr.layout().fields.count(), 1); + let raw_ptr = nonnull_ptr.project_field(self.ecx(), 0)?; // the actual raw ptr + // ... whose only field finally is a raw ptr we can dereference. + self.visit_box(&raw_ptr)?; + + // The second `Box` field is the allocator, which we recursively check for validity + // like in regular structs. + self.visit_field(v, 1, &alloc)?; + } _ => {}, }; diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index 5bf91879066..2d42ae236ad 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -21,6 +21,7 @@ Rust MIR: a lowered representation of Rust. #![feature(trusted_step)] #![feature(try_blocks)] #![feature(yeet_expr)] +#![feature(is_some_with)] #![recursion_limit = "256"] #![allow(rustc::potential_query_instability)] diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index 3096af90d47..b71cdad718a 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -849,10 +849,10 @@ Available lint options: }; println!("Lint checks provided by rustc:\n"); - println!(" {} {:7.7} {}", padded("name"), "default", "meaning"); - println!(" {} {:7.7} {}", padded("----"), "-------", "-------"); let print_lints = |lints: Vec<&Lint>| { + println!(" {} {:7.7} {}", padded("name"), "default", "meaning"); + println!(" {} {:7.7} {}", padded("----"), "-------", "-------"); for lint in lints { let name = lint.name_lower().replace('_', "-"); println!( @@ -884,11 +884,15 @@ Available lint options: }; println!("Lint groups provided by rustc:\n"); - println!(" {} sub-lints", padded("name")); - println!(" {} ---------", padded("----")); - println!(" {} all lints that are set to issue warnings", padded("warnings")); - let print_lint_groups = |lints: Vec<(&'static str, Vec<LintId>)>| { + let print_lint_groups = |lints: Vec<(&'static str, Vec<LintId>)>, all_warnings| { + println!(" {} sub-lints", padded("name")); + println!(" {} ---------", padded("----")); + + if all_warnings { + println!(" {} all lints that are set to issue warnings", padded("warnings")); + } + for (name, to) in lints { let name = name.to_lowercase().replace('_', "-"); let desc = to @@ -901,7 +905,7 @@ Available lint options: println!("\n"); }; - print_lint_groups(builtin_groups); + print_lint_groups(builtin_groups, true); match (loaded_plugins, plugin.len(), plugin_groups.len()) { (false, 0, _) | (false, _, 0) => { @@ -916,7 +920,7 @@ Available lint options: } if g > 0 { println!("Lint groups provided by plugins loaded by this crate:\n"); - print_lint_groups(plugin_groups); + print_lint_groups(plugin_groups, false); } } } diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index 1694a8865dd..74e9bbeeeaf 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -152,6 +152,19 @@ impl<'a> ExtCtxt<'a> { ast::Stmt { id: ast::DUMMY_NODE_ID, span: expr.span, kind: ast::StmtKind::Expr(expr) } } + pub fn stmt_let_pat(&self, sp: Span, pat: P<ast::Pat>, ex: P<ast::Expr>) -> ast::Stmt { + let local = P(ast::Local { + pat, + ty: None, + id: ast::DUMMY_NODE_ID, + kind: LocalKind::Init(ex), + span: sp, + attrs: AttrVec::new(), + tokens: None, + }); + self.stmt_local(local, sp) + } + pub fn stmt_let(&self, sp: Span, mutbl: bool, ident: Ident, ex: P<ast::Expr>) -> ast::Stmt { self.stmt_let_ty(sp, mutbl, ident, None, ex) } diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index 07dcf3876c8..4d29fc46946 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -315,8 +315,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { body_id: Option<hir::BodyId>, failure_span: Span, arg: GenericArg<'tcx>, - // FIXME(#94483): Either use this or remove it. - _impl_candidates: Vec<ty::TraitRef<'tcx>>, error_code: TypeAnnotationNeeded, should_label_span: bool, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { @@ -534,6 +532,23 @@ enum InferSourceKind<'tcx> { }, } +impl<'tcx> InferSource<'tcx> { + fn from_expansion(&self) -> bool { + let source_from_expansion = match self.kind { + InferSourceKind::LetBinding { insert_span, .. } + | InferSourceKind::ClosureArg { insert_span, .. } + | InferSourceKind::GenericArg { insert_span, .. } => insert_span.from_expansion(), + InferSourceKind::FullyQualifiedMethodCall { receiver, .. } => { + receiver.span.from_expansion() + } + InferSourceKind::ClosureReturn { data, should_wrap_expr, .. } => { + data.span().from_expansion() || should_wrap_expr.map_or(false, Span::from_expansion) + } + }; + source_from_expansion || self.span.from_expansion() + } +} + impl<'tcx> InferSourceKind<'tcx> { fn ty_msg(&self, infcx: &InferCtxt<'_, 'tcx>) -> String { match *self { @@ -604,43 +619,65 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { /// Sources with a small cost are prefer and should result /// in a clearer and idiomatic suggestion. fn source_cost(&self, source: &InferSource<'tcx>) -> usize { - let tcx = self.infcx.tcx; - - fn arg_cost<'tcx>(arg: GenericArg<'tcx>) -> usize { - match arg.unpack() { - GenericArgKind::Lifetime(_) => 0, // erased - GenericArgKind::Type(ty) => ty_cost(ty), - GenericArgKind::Const(_) => 3, // some non-zero value - } + #[derive(Clone, Copy)] + struct CostCtxt<'tcx> { + tcx: TyCtxt<'tcx>, } - fn ty_cost<'tcx>(ty: Ty<'tcx>) -> usize { - match ty.kind() { - ty::Closure(..) => 100, - ty::FnDef(..) => 20, - ty::FnPtr(..) => 10, - ty::Infer(..) => 0, - _ => 1, + impl<'tcx> CostCtxt<'tcx> { + fn arg_cost(self, arg: GenericArg<'tcx>) -> usize { + match arg.unpack() { + GenericArgKind::Lifetime(_) => 0, // erased + GenericArgKind::Type(ty) => self.ty_cost(ty), + GenericArgKind::Const(_) => 3, // some non-zero value + } + } + fn ty_cost(self, ty: Ty<'tcx>) -> usize { + match *ty.kind() { + ty::Closure(..) => 1000, + ty::FnDef(..) => 150, + ty::FnPtr(..) => 30, + ty::Adt(def, substs) => { + 5 + self + .tcx + .generics_of(def.did()) + .own_substs_no_defaults(self.tcx, substs) + .iter() + .map(|&arg| self.arg_cost(arg)) + .sum::<usize>() + } + ty::Tuple(args) => 5 + args.iter().map(|arg| self.ty_cost(arg)).sum::<usize>(), + ty::Ref(_, ty, _) => 2 + self.ty_cost(ty), + ty::Infer(..) => 0, + _ => 1, + } } } // The sources are listed in order of preference here. - match source.kind { - InferSourceKind::LetBinding { ty, .. } => ty_cost(ty), - InferSourceKind::ClosureArg { ty, .. } => 5 + ty_cost(ty), + let tcx = self.infcx.tcx; + let ctx = CostCtxt { tcx }; + let base_cost = match source.kind { + InferSourceKind::LetBinding { ty, .. } => ctx.ty_cost(ty), + InferSourceKind::ClosureArg { ty, .. } => ctx.ty_cost(ty), InferSourceKind::GenericArg { def_id, generic_args, .. } => { let variant_cost = match tcx.def_kind(def_id) { - DefKind::Variant | DefKind::Ctor(CtorOf::Variant, _) => 15, // `None::<u32>` and friends are ugly. - _ => 12, + // `None::<u32>` and friends are ugly. + DefKind::Variant | DefKind::Ctor(CtorOf::Variant, _) => 15, + _ => 10, }; - variant_cost + generic_args.iter().map(|&arg| arg_cost(arg)).sum::<usize>() + variant_cost + generic_args.iter().map(|&arg| ctx.arg_cost(arg)).sum::<usize>() } InferSourceKind::FullyQualifiedMethodCall { substs, .. } => { - 20 + substs.iter().map(|arg| arg_cost(arg)).sum::<usize>() + 20 + substs.iter().map(|arg| ctx.arg_cost(arg)).sum::<usize>() } InferSourceKind::ClosureReturn { ty, should_wrap_expr, .. } => { - 30 + ty_cost(ty) + if should_wrap_expr.is_some() { 10 } else { 0 } + 30 + ctx.ty_cost(ty) + if should_wrap_expr.is_some() { 10 } else { 0 } } - } + }; + + let suggestion_may_apply = if source.from_expansion() { 10000 } else { 0 }; + + base_cost + suggestion_may_apply } /// Uses `fn source_cost` to determine whether this inference source is preferable to @@ -648,6 +685,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { #[instrument(level = "debug", skip(self))] fn update_infer_source(&mut self, new_source: InferSource<'tcx>) { let cost = self.source_cost(&new_source) + self.attempt; + debug!(?cost); self.attempt += 1; if cost < self.infer_source_cost { self.infer_source_cost = cost; @@ -655,6 +693,11 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { } } + fn node_substs_opt(&self, hir_id: HirId) -> Option<SubstsRef<'tcx>> { + let substs = self.typeck_results.node_substs_opt(hir_id); + self.infcx.resolve_vars_if_possible(substs) + } + fn opt_node_type(&self, hir_id: HirId) -> Option<Ty<'tcx>> { let ty = self.typeck_results.node_type_opt(hir_id); self.infcx.resolve_vars_if_possible(ty) @@ -737,7 +780,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { let tcx = self.infcx.tcx; match expr.kind { hir::ExprKind::Path(ref path) => { - if let Some(substs) = self.typeck_results.node_substs_opt(expr.hir_id) { + if let Some(substs) = self.node_substs_opt(expr.hir_id) { return self.path_inferred_subst_iter(expr.hir_id, substs, path); } } @@ -765,7 +808,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { if generics.has_impl_trait() { None? } - let substs = self.typeck_results.node_substs_opt(expr.hir_id)?; + let substs = self.node_substs_opt(expr.hir_id)?; let span = tcx.hir().span(segment.hir_id?); let insert_span = segment.ident.span.shrink_to_hi().with_hi(span.hi()); InsertableGenericArgs { @@ -980,8 +1023,10 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> { debug!(?args); let InsertableGenericArgs { insert_span, substs, generics_def_id, def_id } = args; let generics = tcx.generics_of(generics_def_id); - if let Some(argument_index) = - generics.own_substs(substs).iter().position(|&arg| self.generic_arg_is_target(arg)) + if let Some(argument_index) = generics + .own_substs(substs) + .iter() + .position(|&arg| self.generic_arg_contains_target(arg)) { let substs = self.infcx.resolve_vars_if_possible(substs); let generic_args = &generics.own_substs_no_defaults(tcx, substs) @@ -1037,7 +1082,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> { .any(|generics| generics.has_impl_trait()) }; if let ExprKind::MethodCall(path, args, span) = expr.kind - && let Some(substs) = self.typeck_results.node_substs_opt(expr.hir_id) + && let Some(substs) = self.node_substs_opt(expr.hir_id) && substs.iter().any(|arg| self.generic_arg_contains_target(arg)) && let Some(def_id) = self.typeck_results.type_dependent_def_id(expr.hir_id) && self.infcx.tcx.trait_of_item(def_id).is_some() diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index 1e2b53040d2..1bbd71c3f1f 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -160,12 +160,18 @@ impl AllocError { } /// The information that makes up a memory access: offset and size. -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone)] pub struct AllocRange { pub start: Size, pub size: Size, } +impl fmt::Debug for AllocRange { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "[{:#x}..{:#x}]", self.start.bytes(), self.end().bytes()) + } +} + /// Free-starting constructor for less syntactic overhead. #[inline(always)] pub fn alloc_range(start: Size, size: Size) -> AllocRange { diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index a33a2921f57..f30769248c0 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -334,36 +334,30 @@ impl fmt::Display for UndefinedBehaviorInfo<'_> { p, ), PointerUseAfterFree(a) => { - write!(f, "pointer to {} was dereferenced after this allocation got freed", a) + write!(f, "pointer to {a:?} was dereferenced after this allocation got freed") } PointerOutOfBounds { alloc_id, alloc_size, ptr_offset, ptr_size: Size::ZERO, msg } => { write!( f, - "{}{alloc_id} has size {alloc_size}, so pointer at offset {ptr_offset} is out-of-bounds", - msg, - alloc_id = alloc_id, + "{msg}{alloc_id:?} has size {alloc_size}, so pointer at offset {ptr_offset} is out-of-bounds", alloc_size = alloc_size.bytes(), - ptr_offset = ptr_offset, ) } PointerOutOfBounds { alloc_id, alloc_size, ptr_offset, ptr_size, msg } => write!( f, - "{}{alloc_id} has size {alloc_size}, so pointer to {ptr_size} byte{ptr_size_p} starting at offset {ptr_offset} is out-of-bounds", - msg, - alloc_id = alloc_id, + "{msg}{alloc_id:?} has size {alloc_size}, so pointer to {ptr_size} byte{ptr_size_p} starting at offset {ptr_offset} is out-of-bounds", alloc_size = alloc_size.bytes(), ptr_size = ptr_size.bytes(), ptr_size_p = pluralize!(ptr_size.bytes()), - ptr_offset = ptr_offset, ), DanglingIntPointer(0, CheckInAllocMsg::InboundsTest) => { write!(f, "null pointer is not a valid pointer for this operation") } DanglingIntPointer(0, msg) => { - write!(f, "{}null pointer is not a valid pointer", msg) + write!(f, "{msg}null pointer is not a valid pointer") } DanglingIntPointer(i, msg) => { - write!(f, "{}0x{:x} is not a valid pointer", msg, i) + write!(f, "{msg}{i:#x} is not a valid pointer") } AlignmentCheckFailed { required, has } => write!( f, @@ -371,8 +365,8 @@ impl fmt::Display for UndefinedBehaviorInfo<'_> { has.bytes(), required.bytes() ), - WriteToReadOnly(a) => write!(f, "writing to {} which is read-only", a), - DerefFunctionPointer(a) => write!(f, "accessing {} which contains a function", a), + WriteToReadOnly(a) => write!(f, "writing to {a:?} which is read-only"), + DerefFunctionPointer(a) => write!(f, "accessing {a:?} which contains a function"), ValidationFailure { path: None, msg } => { write!(f, "constructing invalid value: {}", msg) } diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index 8733a85ef3f..698024b2330 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -190,11 +190,7 @@ impl fmt::Debug for AllocId { } } -impl fmt::Display for AllocId { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(self, f) - } -} +// No "Display" since AllocIds are not usually user-visible. #[derive(TyDecodable, TyEncodable)] enum AllocDiscriminant { @@ -470,7 +466,7 @@ impl<'tcx> TyCtxt<'tcx> { return alloc_id; } let id = alloc_map.reserve(); - debug!("creating alloc {:?} with id {}", alloc, id); + debug!("creating alloc {alloc:?} with id {id:?}"); alloc_map.alloc_map.insert(id, alloc.clone()); alloc_map.dedup.insert(alloc, id); id @@ -538,7 +534,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn global_alloc(self, id: AllocId) -> GlobalAlloc<'tcx> { match self.get_global_alloc(id) { Some(alloc) => alloc, - None => bug!("could not find allocation for {}", id), + None => bug!("could not find allocation for {id:?}"), } } @@ -546,7 +542,7 @@ impl<'tcx> TyCtxt<'tcx> { /// call this function twice, even with the same `Allocation` will ICE the compiler. pub fn set_alloc_id_memory(self, id: AllocId, mem: ConstAllocation<'tcx>) { if let Some(old) = self.alloc_map.lock().alloc_map.insert(id, GlobalAlloc::Memory(mem)) { - bug!("tried to set allocation ID {}, but it was already existing as {:#?}", id, old); + bug!("tried to set allocation ID {id:?}, but it was already existing as {old:#?}"); } } diff --git a/compiler/rustc_middle/src/mir/interpret/pointer.rs b/compiler/rustc_middle/src/mir/interpret/pointer.rs index 26da93b9dce..81d744107fd 100644 --- a/compiler/rustc_middle/src/mir/interpret/pointer.rs +++ b/compiler/rustc_middle/src/mir/interpret/pointer.rs @@ -144,7 +144,7 @@ impl Provenance for AllocId { } // Print offset only if it is non-zero. if ptr.offset.bytes() > 0 { - write!(f, "+0x{:x}", ptr.offset.bytes())?; + write!(f, "+{:#x}", ptr.offset.bytes())?; } Ok(()) } @@ -181,7 +181,7 @@ impl<Tag: Provenance> fmt::Debug for Pointer<Option<Tag>> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.provenance { Some(tag) => Provenance::fmt(&Pointer::new(tag, self.offset), f), - None => write!(f, "0x{:x}", self.offset.bytes()), + None => write!(f, "{:#x}", self.offset.bytes()), } } } diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs index e80918d5e5d..8ecbb5ab0b3 100644 --- a/compiler/rustc_middle/src/mir/interpret/value.rs +++ b/compiler/rustc_middle/src/mir/interpret/value.rs @@ -167,7 +167,7 @@ impl<Tag: Provenance> fmt::LowerHex for Scalar<Tag> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Scalar::Ptr(ptr, _size) => write!(f, "pointer to {:?}", ptr), - Scalar::Int(int) => write!(f, "0x{:x}", int), + Scalar::Int(int) => write!(f, "{:#x}", int), } } } diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 462c0ada3cf..24c6cd91d0a 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -716,12 +716,12 @@ pub fn write_allocations<'tcx>( } write!(w, "{}", display_allocation(tcx, alloc.inner())) }; - write!(w, "\n{}", id)?; + write!(w, "\n{id:?}")?; match tcx.get_global_alloc(id) { // This can't really happen unless there are bugs, but it doesn't cost us anything to // gracefully handle it and allow buggy rustc to be debugged via allocation printing. None => write!(w, " (deallocated)")?, - Some(GlobalAlloc::Function(inst)) => write!(w, " (fn: {})", inst)?, + Some(GlobalAlloc::Function(inst)) => write!(w, " (fn: {inst})")?, Some(GlobalAlloc::Static(did)) if !tcx.is_foreign_item(did) => { match tcx.eval_static_initializer(did) { Ok(alloc) => { diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index f8ee59f306f..3b7eb820df8 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -311,6 +311,7 @@ pub enum StatementKind<'tcx> { /// Describes what kind of retag is to be performed. #[derive(Copy, Clone, TyEncodable, TyDecodable, Debug, PartialEq, Eq, Hash, HashStable)] +#[rustc_pass_by_value] pub enum RetagKind { /// The initial retag when entering a function. FnEntry, @@ -990,11 +991,19 @@ pub enum Rvalue<'tcx> { /// matching types and return a value of that type. BinaryOp(BinOp, Box<(Operand<'tcx>, Operand<'tcx>)>), - /// Same as `BinaryOp`, but yields `(T, bool)` instead of `T`. In addition to performing the - /// same computation as the matching `BinaryOp`, checks if the infinite precison result would be - /// unequal to the actual result and sets the `bool` if this is the case. + /// Same as `BinaryOp`, but yields `(T, bool)` with a `bool` indicating an error condition. /// - /// This only supports addition, subtraction, multiplication, and shift operations on integers. + /// When overflow checking is disabled, the error condition is false. Otherwise, the error + /// condition is determined as described below. + /// + /// For addition, subtraction, and multiplication on integers the error condition is set when + /// the infinite precision result would be unequal to the actual result. + /// + /// For shift operations on integers the error condition is set when the value of right-hand + /// side is greater than or equal to the number of bits in the type of the left-hand side, or + /// when the value of right-hand side is negative. + /// + /// Other combinations of types and operators are unsupported. CheckedBinaryOp(BinOp, Box<(Operand<'tcx>, Operand<'tcx>)>), /// Computes a value as described by the operation. diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 9285246eb79..d1477f9e2ae 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -147,7 +147,7 @@ macro_rules! make_mir_visitor { fn visit_ascribe_user_ty( &mut self, place: & $($mutability)? Place<'tcx>, - variance: & $($mutability)? ty::Variance, + variance: $(& $mutability)? ty::Variance, user_ty: & $($mutability)? UserTypeProjection, location: Location, ) { @@ -164,7 +164,7 @@ macro_rules! make_mir_visitor { fn visit_retag( &mut self, - kind: & $($mutability)? RetagKind, + kind: $(& $mutability)? RetagKind, place: & $($mutability)? Place<'tcx>, location: Location, ) { @@ -425,7 +425,7 @@ macro_rules! make_mir_visitor { self.visit_source_info(source_info); match kind { StatementKind::Assign( - box(ref $($mutability)? place, ref $($mutability)? rvalue) + box (place, rvalue) ) => { self.visit_assign(place, rvalue, location); } @@ -465,13 +465,13 @@ macro_rules! make_mir_visitor { ); } StatementKind::Retag(kind, place) => { - self.visit_retag(kind, place, location); + self.visit_retag($(& $mutability)? *kind, place, location); } StatementKind::AscribeUserType( - box(ref $($mutability)? place, ref $($mutability)? user_ty), + box (place, user_ty), variance ) => { - self.visit_ascribe_user_ty(place, variance, user_ty, location); + self.visit_ascribe_user_ty(place, $(& $mutability)? *variance, user_ty, location); } StatementKind::Coverage(coverage) => { self.visit_coverage( @@ -480,9 +480,9 @@ macro_rules! make_mir_visitor { ) } StatementKind::CopyNonOverlapping(box crate::mir::CopyNonOverlapping{ - ref $($mutability)? src, - ref $($mutability)? dst, - ref $($mutability)? count, + src, + dst, + count, }) => { self.visit_operand(src, location); self.visit_operand(dst, location); @@ -517,8 +517,7 @@ macro_rules! make_mir_visitor { TerminatorKind::GeneratorDrop | TerminatorKind::Unreachable | TerminatorKind::FalseEdge { .. } | - TerminatorKind::FalseUnwind { .. } => { - } + TerminatorKind::FalseUnwind { .. } => {} TerminatorKind::Return => { // `return` logically moves from the return place `_0`. Note that the place @@ -830,7 +829,7 @@ macro_rules! make_mir_visitor { fn super_ascribe_user_ty(&mut self, place: & $($mutability)? Place<'tcx>, - _variance: & $($mutability)? ty::Variance, + _variance: $(& $mutability)? ty::Variance, user_ty: & $($mutability)? UserTypeProjection, location: Location) { self.visit_place( @@ -847,7 +846,7 @@ macro_rules! make_mir_visitor { } fn super_retag(&mut self, - _kind: & $($mutability)? RetagKind, + _kind: $(& $mutability)? RetagKind, place: & $($mutability)? Place<'tcx>, location: Location) { self.visit_place( diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 294f56d16b1..b8bb93891c2 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1825,7 +1825,8 @@ rustc_queries! { remap_env_constness } - /// Do not call this query directly: invoke `infcx.at().dropck_outlives()` instead. + /// Do not call this query directly: + /// invoke `DropckOutlives::new(dropped_ty)).fully_perform(typeck.infcx)` instead. query dropck_outlives( goal: CanonicalTyGoal<'tcx> ) -> Result< diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs index 51e51a63fd0..c7c2692281e 100644 --- a/compiler/rustc_middle/src/ty/consts/int.rs +++ b/compiler/rustc_middle/src/ty/consts/int.rs @@ -452,6 +452,10 @@ impl fmt::Debug for ScalarInt { impl fmt::LowerHex for ScalarInt { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.check_data(); + if f.alternate() { + // Like regular ints, alternate flag adds leading `0x`. + write!(f, "0x")?; + } // Format as hex number wide enough to fit any value of the given `size`. // So data=20, size=1 will be "0x14", but with size=4 it'll be "0x00000014". // Using a block `{self.data}` here to force a copy instead of using `self.data` diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index ce387cb4453..12f5764152e 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -180,16 +180,20 @@ impl<'tcx> Inliner<'tcx> { return Err("failed to normalize return type"); } if callsite.fn_sig.abi() == Abi::RustCall { - let mut args = args.into_iter(); - let _ = args.next(); // Skip `self` argument. - let arg_tuple_ty = args.next().unwrap().ty(&caller_body.local_decls, self.tcx); - assert!(args.next().is_none()); + let (arg_tuple, skipped_args) = match &args[..] { + [arg_tuple] => (arg_tuple, 0), + [_, arg_tuple] => (arg_tuple, 1), + _ => bug!("Expected `rust-call` to have 1 or 2 args"), + }; + let arg_tuple_ty = arg_tuple.ty(&caller_body.local_decls, self.tcx); let ty::Tuple(arg_tuple_tys) = arg_tuple_ty.kind() else { bug!("Closure arguments are not passed as a tuple"); }; - for (arg_ty, input) in arg_tuple_tys.iter().zip(callee_body.args_iter().skip(1)) { + for (arg_ty, input) in + arg_tuple_tys.iter().zip(callee_body.args_iter().skip(skipped_args)) + { let input_type = callee_body.local_decls[input].ty; if !equal_up_to_regions(self.tcx, self.param_env, arg_ty, input_type) { trace!(?arg_ty, ?input_type); diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs index f9e67310452..1add91fc9c5 100644 --- a/compiler/rustc_passes/src/entry.rs +++ b/compiler/rustc_passes/src/entry.rs @@ -1,4 +1,4 @@ -use rustc_ast::entry::EntryPointType; +use rustc_ast::{entry::EntryPointType, Attribute}; use rustc_errors::struct_span_err; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE}; @@ -7,9 +7,8 @@ use rustc_middle::ty::query::Providers; use rustc_middle::ty::{DefIdTree, TyCtxt}; use rustc_session::config::{CrateType, EntryFnType}; use rustc_session::parse::feature_err; -use rustc_session::Session; use rustc_span::symbol::sym; -use rustc_span::{Span, DUMMY_SP}; +use rustc_span::{Span, Symbol, DUMMY_SP}; struct EntryContext<'tcx> { tcx: TyCtxt<'tcx>, @@ -72,9 +71,16 @@ fn entry_point_type(ctxt: &EntryContext<'_>, id: ItemId, at_root: bool) -> Entry } } -fn throw_attr_err(sess: &Session, span: Span, attr: &str) { - sess.struct_span_err(span, &format!("`{}` attribute can only be used on functions", attr)) - .emit(); +fn err_if_attr_found(ctxt: &EntryContext<'_>, attrs: &[Attribute], sym: Symbol) { + if let Some(attr) = ctxt.tcx.sess.find_by_name(attrs, sym) { + ctxt.tcx + .sess + .struct_span_err( + attr.span, + &format!("`{}` attribute can only be used on functions", sym.as_str()), + ) + .emit(); + } } fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) { @@ -84,12 +90,8 @@ fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) { EntryPointType::None => (), _ if !matches!(ctxt.tcx.def_kind(id.def_id), DefKind::Fn) => { let attrs = ctxt.tcx.hir().attrs(id.hir_id()); - if let Some(attr) = ctxt.tcx.sess.find_by_name(attrs, sym::start) { - throw_attr_err(&ctxt.tcx.sess, attr.span, "start"); - } - if let Some(attr) = ctxt.tcx.sess.find_by_name(attrs, sym::rustc_main) { - throw_attr_err(&ctxt.tcx.sess, attr.span, "rustc_main"); - } + err_if_attr_found(ctxt, attrs, sym::start); + err_if_attr_found(ctxt, attrs, sym::rustc_main); } EntryPointType::MainNamed => (), EntryPointType::OtherMain => { diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 74cd88ea0dd..e7717f1367c 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -2724,8 +2724,8 @@ pub(crate) mod dep_tracking { use super::{ BranchProtection, CFGuard, CFProtection, CrateType, DebugInfo, ErrorOutputType, InstrumentCoverage, LdImpl, LinkerPluginLto, LocationDetail, LtoCli, OomStrategy, OptLevel, - OutputType, OutputTypes, Passes, SourceFileHashAlgorithm, SwitchWithOptPath, - SymbolManglingVersion, TrimmedDefPaths, + OutputType, OutputTypes, Passes, SourceFileHashAlgorithm, SplitDwarfKind, + SwitchWithOptPath, SymbolManglingVersion, TrimmedDefPaths, }; use crate::lint; use crate::options::WasiExecModel; @@ -2812,6 +2812,7 @@ pub(crate) mod dep_tracking { Edition, LinkerPluginLto, SplitDebuginfo, + SplitDwarfKind, StackProtector, SwitchWithOptPath, SymbolManglingVersion, diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 441e1f9f6a2..be70ea5d5e4 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1496,7 +1496,7 @@ options! { "control if mem::uninitialized and mem::zeroed panic on more UB"), strip: Strip = (Strip::None, parse_strip, [UNTRACKED], "tell the linker which information to strip (`none` (default), `debuginfo` or `symbols`)"), - split_dwarf_kind: SplitDwarfKind = (SplitDwarfKind::Split, parse_split_dwarf_kind, [UNTRACKED], + split_dwarf_kind: SplitDwarfKind = (SplitDwarfKind::Split, parse_split_dwarf_kind, [TRACKED], "split dwarf variant (only if -Csplit-debuginfo is enabled and on relevant platform) (default: `split`) @@ -1504,7 +1504,7 @@ options! { file which is ignored by the linker `single`: sections which do not require relocation are written into object file but ignored by the linker"), - split_dwarf_inlining: bool = (true, parse_bool, [UNTRACKED], + split_dwarf_inlining: bool = (true, parse_bool, [TRACKED], "provide minimal debug info in the object/executable to facilitate online \ symbolication/stack traces in the absence of .dwo/.dwp files when using Split DWARF"), symbol_mangling_version: Option<SymbolManglingVersion> = (None, diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index fa56219b409..88b09f4de0a 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1980,7 +1980,6 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { body_id, span, trait_ref.self_ty().skip_binder().into(), - vec![], ErrorCode::E0282, false, ) @@ -2005,19 +2004,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { let subst = data.trait_ref.substs.iter().find(|s| s.has_infer_types_or_consts()); let mut err = if let Some(subst) = subst { - let impl_candidates = self - .find_similar_impl_candidates(trait_ref) - .into_iter() - .map(|candidate| candidate.trait_ref) - .collect(); - self.emit_inference_failure_err( - body_id, - span, - subst, - impl_candidates, - ErrorCode::E0283, - true, - ) + self.emit_inference_failure_err(body_id, span, subst, ErrorCode::E0283, true) } else { struct_span_err!( self.tcx.sess, @@ -2117,7 +2104,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { return; } - self.emit_inference_failure_err(body_id, span, arg, vec![], ErrorCode::E0282, false) + self.emit_inference_failure_err(body_id, span, arg, ErrorCode::E0282, false) } ty::PredicateKind::Subtype(data) => { @@ -2131,14 +2118,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { let SubtypePredicate { a_is_expected: _, a, b } = data; // both must be type variables, or the other would've been instantiated assert!(a.is_ty_var() && b.is_ty_var()); - self.emit_inference_failure_err( - body_id, - span, - a.into(), - vec![], - ErrorCode::E0282, - true, - ) + self.emit_inference_failure_err(body_id, span, a.into(), ErrorCode::E0282, true) } ty::PredicateKind::Projection(data) => { if predicate.references_error() || self.is_tainted_by_errors() { @@ -2155,7 +2135,6 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { body_id, span, subst, - vec![], ErrorCode::E0284, true, ); diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index f9708d6d919..6744536338c 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -599,6 +599,7 @@ impl UnifyKey for FloatVid { } #[derive(Copy, Clone, PartialEq, Decodable, Encodable, Hash)] +#[rustc_pass_by_value] pub enum Variance { Covariant, // T<A> <: T<B> iff A <: B -- e.g., function return type Invariant, // T<A> <: T<B> iff B == A -- e.g., type of mutable cell diff --git a/compiler/rustc_typeck/src/check/callee.rs b/compiler/rustc_typeck/src/check/callee.rs index 83a8c5ea021..96b1847f8bb 100644 --- a/compiler/rustc_typeck/src/check/callee.rs +++ b/compiler/rustc_typeck/src/check/callee.rs @@ -280,15 +280,36 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { callee_node: &hir::ExprKind<'_>, callee_span: Span, ) { - let hir_id = self.tcx.hir().get_parent_node(hir_id); - let parent_node = self.tcx.hir().get(hir_id); + let hir = self.tcx.hir(); + let parent_hir_id = hir.get_parent_node(hir_id); + let parent_node = hir.get(parent_hir_id); if let ( hir::Node::Expr(hir::Expr { - kind: hir::ExprKind::Closure { fn_decl_span, .. }, .. + kind: hir::ExprKind::Closure { fn_decl_span, body, .. }, + .. }), hir::ExprKind::Block(..), ) = (parent_node, callee_node) { + let fn_decl_span = if hir.body(*body).generator_kind + == Some(hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Closure)) + { + // Actually need to unwrap a few more layers of HIR to get to + // the _real_ closure... + let async_closure = hir.get_parent_node(hir.get_parent_node(parent_hir_id)); + if let hir::Node::Expr(hir::Expr { + kind: hir::ExprKind::Closure { fn_decl_span, .. }, + .. + }) = hir.get(async_closure) + { + *fn_decl_span + } else { + return; + } + } else { + *fn_decl_span + }; + let start = fn_decl_span.shrink_to_lo(); let end = callee_span.shrink_to_hi(); err.multipart_suggestion( diff --git a/compiler/rustc_typeck/src/check/dropck.rs b/compiler/rustc_typeck/src/check/dropck.rs index ed3b9f2db1f..a4013e10525 100644 --- a/compiler/rustc_typeck/src/check/dropck.rs +++ b/compiler/rustc_typeck/src/check/dropck.rs @@ -8,8 +8,6 @@ use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::util::IgnoreRegions; use rustc_middle::ty::{self, Predicate, Ty, TyCtxt}; use rustc_span::Span; -use rustc_trait_selection::traits::query::dropck_outlives::AtExt; -use rustc_trait_selection::traits::ObligationCause; /// This function confirms that the `Drop` implementation identified by /// `drop_impl_did` is not any more specialized than the type it is @@ -234,18 +232,14 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>( /// This function is not only checking that the dropck obligations are met for /// the given type, but it's also currently preventing non-regular recursion in /// types from causing stack overflows (dropck_no_diverge_on_nonregular_*.rs). +/// +/// FIXME: Completely rip out dropck and regionck. pub(crate) fn check_drop_obligations<'a, 'tcx>( - rcx: &mut RegionCtxt<'a, 'tcx>, - ty: Ty<'tcx>, - span: Span, - body_id: hir::HirId, + _rcx: &mut RegionCtxt<'a, 'tcx>, + _ty: Ty<'tcx>, + _span: Span, + _body_id: hir::HirId, ) { - debug!("check_drop_obligations typ: {:?}", ty); - - let cause = &ObligationCause::misc(span, body_id); - let infer_ok = rcx.infcx.at(cause, rcx.fcx.param_env).dropck_outlives(ty); - debug!("dropck_outlives = {:#?}", infer_ok); - rcx.fcx.register_infer_ok_obligations(infer_ok); } // This is an implementation of the TypeRelation trait with the diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index bce2e85de84..5297c48b4c3 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -1538,15 +1538,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty } else { if !self.is_tainted_by_errors() { - self.emit_inference_failure_err( - (**self).body_id, - sp, - ty.into(), - vec![], - E0282, - true, - ) - .emit(); + self.emit_inference_failure_err((**self).body_id, sp, ty.into(), E0282, true) + .emit(); } let err = self.tcx.ty_error(); self.demand_suptype(sp, err, ty); diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs index 67160b98b9d..16e5639096c 100644 --- a/compiler/rustc_typeck/src/check/writeback.rs +++ b/compiler/rustc_typeck/src/check/writeback.rs @@ -692,7 +692,6 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> { Some(self.body.id()), self.span.to_span(self.tcx), t.into(), - vec![], E0282, false, ) @@ -707,7 +706,6 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> { Some(self.body.id()), self.span.to_span(self.tcx), c.into(), - vec![], E0282, false, ) diff --git a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs index f07396ce74f..4d22e168bb6 100644 --- a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs @@ -279,11 +279,16 @@ fn check_predicates<'tcx>( span: Span, ) { let tcx = infcx.tcx; - let impl1_predicates: Vec<_> = traits::elaborate_predicates( + let instantiated = tcx.predicates_of(impl1_def_id).instantiate(tcx, impl1_substs); + let impl1_predicates: Vec<_> = traits::elaborate_predicates_with_span( tcx, - tcx.predicates_of(impl1_def_id).instantiate(tcx, impl1_substs).predicates.into_iter(), + std::iter::zip( + instantiated.predicates, + // Don't drop predicates (unsound!) because `spans` is too short + instantiated.spans.into_iter().chain(std::iter::repeat(span)), + ), ) - .map(|obligation| obligation.predicate) + .map(|obligation| (obligation.predicate, obligation.cause.span)) .collect(); let mut impl2_predicates = if impl2_node.is_from_trait() { @@ -321,7 +326,7 @@ fn check_predicates<'tcx>( // which is sound because we forbid impls like the following // // impl<D: Debug> AlwaysApplicable for D { } - let always_applicable_traits = impl1_predicates.iter().copied().filter(|&predicate| { + let always_applicable_traits = impl1_predicates.iter().copied().filter(|&(predicate, _)| { matches!( trait_predicate_kind(tcx, predicate), Some(TraitSpecializationKind::AlwaysApplicable) @@ -345,11 +350,11 @@ fn check_predicates<'tcx>( } } impl2_predicates.extend( - traits::elaborate_predicates(tcx, always_applicable_traits) + traits::elaborate_predicates_with_span(tcx, always_applicable_traits) .map(|obligation| obligation.predicate), ); - for predicate in impl1_predicates { + for (predicate, span) in impl1_predicates { if !impl2_predicates.contains(&predicate) { check_specialization_on(tcx, predicate, span) } @@ -384,9 +389,17 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc .emit(); } } + ty::PredicateKind::Projection(ty::ProjectionPredicate { projection_ty, term }) => { + tcx.sess + .struct_span_err( + span, + &format!("cannot specialize on associated type `{projection_ty} == {term}`",), + ) + .emit(); + } _ => { tcx.sess - .struct_span_err(span, &format!("cannot specialize on `{:?}`", predicate)) + .struct_span_err(span, &format!("cannot specialize on predicate `{}`", predicate)) .emit(); } } diff --git a/library/std/src/net/tcp.rs b/library/std/src/net/tcp.rs index 06300035633..69b72a81c5b 100644 --- a/library/std/src/net/tcp.rs +++ b/library/std/src/net/tcp.rs @@ -7,6 +7,7 @@ use crate::io::prelude::*; use crate::fmt; use crate::io::{self, IoSlice, IoSliceMut}; +use crate::iter::FusedIterator; use crate::net::{Shutdown, SocketAddr, ToSocketAddrs}; use crate::sys_common::net as net_imp; use crate::sys_common::{AsInner, FromInner, IntoInner}; @@ -1009,6 +1010,9 @@ impl<'a> Iterator for Incoming<'a> { } } +#[stable(feature = "tcp_listener_incoming_fused_iterator", since = "1.64.0")] +impl FusedIterator for Incoming<'_> {} + #[unstable(feature = "tcplistener_into_incoming", issue = "88339")] impl Iterator for IntoIncoming { type Item = io::Result<TcpStream>; @@ -1017,6 +1021,9 @@ impl Iterator for IntoIncoming { } } +#[unstable(feature = "tcplistener_into_incoming", issue = "88339")] +impl FusedIterator for IntoIncoming {} + impl AsInner<net_imp::TcpListener> for TcpListener { fn as_inner(&self) -> &net_imp::TcpListener { &self.0 diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock index 6fcbd7a2156..664ffa1ddd2 100644 --- a/src/bootstrap/Cargo.lock +++ b/src/bootstrap/Cargo.lock @@ -47,6 +47,7 @@ version = "0.0.0" dependencies = [ "cc", "cmake", + "fd-lock", "filetime", "getopts", "hex", @@ -202,6 +203,38 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" [[package]] +name = "errno" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" +dependencies = [ + "errno-dragonfly", + "libc", + "winapi", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "fd-lock" +version = "3.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e11dcc7e4d79a8c89b9ab4c6f5c30b1fc4a83c420792da3542fd31179ed5f517" +dependencies = [ + "cfg-if", + "rustix", + "windows-sys", +] + +[[package]] name = "filetime" version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -285,6 +318,12 @@ dependencies = [ ] [[package]] +name = "io-lifetimes" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24c3f4eff5495aee4c0399d7b6a0dc2b6e81be84242ffbfcf253ebacccc1d0cb" + +[[package]] name = "itoa" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -303,6 +342,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" [[package]] +name = "linux-raw-sys" +version = "0.0.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4d2456c373231a208ad294c33dc5bff30051eafd954cd4caae83a712b12854d" + +[[package]] name = "log" version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -474,6 +519,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64" [[package]] +name = "rustix" +version = "0.35.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef258c11e17f5c01979a10543a30a4e12faef6aab217a74266e747eefa3aed88" +dependencies = [ + "bitflags", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] name = "ryu" version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -658,6 +717,49 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] +name = "windows-sys" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +dependencies = [ + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" + +[[package]] +name = "windows_i686_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" + +[[package]] +name = "windows_i686_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" + +[[package]] name = "xattr" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index b9bd3d0cf78..84f6aaf99c1 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -36,6 +36,7 @@ test = false [dependencies] cmake = "0.1.38" +fd-lock = "3.0.6" filetime = "0.2" num_cpus = "1.0" getopts = "0.2.19" diff --git a/src/bootstrap/bin/main.rs b/src/bootstrap/bin/main.rs index 9c41ab69c8b..9b4861ccd95 100644 --- a/src/bootstrap/bin/main.rs +++ b/src/bootstrap/bin/main.rs @@ -7,12 +7,28 @@ use std::env; -use bootstrap::{Build, Config, Subcommand, VERSION}; +use bootstrap::{t, Build, Config, Subcommand, VERSION}; fn main() { let args = env::args().skip(1).collect::<Vec<_>>(); let config = Config::parse(&args); + let mut build_lock; + let _build_lock_guard; + if cfg!(any(unix, windows)) { + build_lock = fd_lock::RwLock::new(t!(std::fs::File::create(config.out.join("lock")))); + _build_lock_guard = match build_lock.try_write() { + Ok(lock) => lock, + err => { + println!("warning: build directory locked, waiting for lock"); + drop(err); + t!(build_lock.write()) + } + }; + } else { + println!("warning: file locking not supported for target, not locking build directory"); + } + // check_version warnings are not printed during setup let changelog_suggestion = if matches!(config.cmd, Subcommand::Setup { .. }) { None } else { check_version(&config) }; diff --git a/src/bootstrap/bin/rustdoc.rs b/src/bootstrap/bin/rustdoc.rs index 5f85fc5aa59..87c1d22e771 100644 --- a/src/bootstrap/bin/rustdoc.rs +++ b/src/bootstrap/bin/rustdoc.rs @@ -31,9 +31,7 @@ fn main() { let mut cmd = Command::new(rustdoc); - // cfg(bootstrap) - // NOTE: the `--test` special-casing can be removed when https://github.com/rust-lang/cargo/pull/10594 lands on beta. - if target.is_some() || args.iter().any(|x| x == "--test") { + if target.is_some() { // The stage0 compiler has a special sysroot distinct from what we // actually downloaded, so we just always pass the `--sysroot` option, // unless one is already set. diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 6ead79ef040..3c2f1bdb142 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -15,44 +15,6 @@ import tempfile from time import time, sleep -# Acquire a lock on the build directory to make sure that -# we don't cause a race condition while building -# Lock is created in `build_dir/lock.db` -def acquire_lock(build_dir): - try: - import sqlite3 - - path = os.path.join(build_dir, "lock.db") - try: - con = sqlite3.Connection(path, timeout=0) - curs = con.cursor() - curs.execute("BEGIN EXCLUSIVE") - # The lock is released when the cursor is dropped - return curs - # If the database is busy then lock has already been acquired - # so we wait for the lock. - # We retry every quarter second so that execution is passed back to python - # so that it can handle signals - except sqlite3.OperationalError: - del con - del curs - print("Waiting for lock on build directory") - con = sqlite3.Connection(path, timeout=0.25) - curs = con.cursor() - while True: - try: - curs.execute("BEGIN EXCLUSIVE") - break - except sqlite3.OperationalError: - pass - sleep(0.25) - return curs - except ImportError: - print("warning: sqlite3 not available in python, skipping build directory lock") - print("please file an issue on rust-lang/rust") - print("this is not a problem for non-concurrent x.py invocations") - return None - def support_xz(): try: with tempfile.NamedTemporaryFile(delete=False) as temp_file: @@ -928,11 +890,8 @@ def bootstrap(help_triggered): build.build = args.build or build.build_triple() - # Acquire the lock before doing any build actions - # The lock is released when `lock` is dropped if not os.path.exists(build.build_dir): os.makedirs(build.build_dir) - lock = acquire_lock(build.build_dir) # Fetch/build the bootstrap build.download_toolchain() diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 755c532ab32..fa2a530d9db 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -694,6 +694,7 @@ impl<'a> Builder<'a> { doc::RustcBook, doc::CargoBook, doc::Clippy, + doc::Miri, doc::EmbeddedBook, doc::EditionGuide, ), diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index be6655ddb61..3cf0f9b9f99 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -643,7 +643,7 @@ impl Step for Rustc { } macro_rules! tool_doc { - ($tool: ident, $should_run: literal, $path: literal, [$($krate: literal),+ $(,)?] $(,)?) => { + ($tool: ident, $should_run: literal, $path: literal, [$($krate: literal),+ $(,)?], in_tree = $in_tree:expr $(,)?) => { #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct $tool { target: TargetSelection, @@ -699,6 +699,12 @@ macro_rules! tool_doc { t!(fs::create_dir_all(&out_dir)); t!(symlink_dir_force(&builder.config, &out, &out_dir)); + let source_type = if $in_tree == true { + SourceType::InTree + } else { + SourceType::Submodule + }; + // Build cargo command. let mut cargo = prepare_tool_cargo( builder, @@ -707,7 +713,7 @@ macro_rules! tool_doc { target, "doc", $path, - SourceType::InTree, + source_type, &[], ); @@ -723,20 +729,38 @@ macro_rules! tool_doc { cargo.rustdocflag("--show-type-layout"); cargo.rustdocflag("--generate-link-to-definition"); cargo.rustdocflag("-Zunstable-options"); - builder.run(&mut cargo.into()); + if $in_tree == true { + builder.run(&mut cargo.into()); + } else { + // Allow out-of-tree docs to fail (since the tool might be in a broken state). + if !builder.try_run(&mut cargo.into()) { + builder.info(&format!( + "WARNING: tool {} failed to document; ignoring failure because it is an out-of-tree tool", + stringify!($tool).to_lowercase(), + )); + } + } } } } } -tool_doc!(Rustdoc, "rustdoc-tool", "src/tools/rustdoc", ["rustdoc", "rustdoc-json-types"]); +tool_doc!( + Rustdoc, + "rustdoc-tool", + "src/tools/rustdoc", + ["rustdoc", "rustdoc-json-types"], + in_tree = true +); tool_doc!( Rustfmt, "rustfmt-nightly", "src/tools/rustfmt", ["rustfmt-nightly", "rustfmt-config_proc_macro"], + in_tree = true ); -tool_doc!(Clippy, "clippy", "src/tools/clippy", ["clippy_utils"]); +tool_doc!(Clippy, "clippy", "src/tools/clippy", ["clippy_utils"], in_tree = true); +tool_doc!(Miri, "miri", "src/tools/miri", ["miri"], in_tree = false); #[derive(Ord, PartialOrd, Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct ErrorIndex { diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 40ff0381c8b..73bd588472d 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -118,8 +118,7 @@ use once_cell::sync::OnceCell; use crate::builder::Kind; use crate::config::{LlvmLibunwind, TargetSelection}; use crate::util::{ - check_run, exe, libdir, mtime, output, run, run_suppressed, t, try_run, try_run_suppressed, - CiEnv, + check_run, exe, libdir, mtime, output, run, run_suppressed, try_run, try_run_suppressed, CiEnv, }; mod builder; diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 9958306b576..f3395507bb0 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -1363,13 +1363,10 @@ note: if you're sure you want to do this, please open an issue as to why. In the if let Some(ref npm) = builder.config.npm { cmd.arg("--npm").arg(npm); } - - let mut flags = if is_rustdoc { Vec::new() } else { vec!["-Crpath".to_string()] }; - if !is_rustdoc { - if builder.config.rust_optimize_tests { - flags.push("-O".to_string()); - } + if builder.config.rust_optimize_tests { + cmd.arg("--optimize-tests"); } + let mut flags = if is_rustdoc { Vec::new() } else { vec!["-Crpath".to_string()] }; flags.push(format!("-Cdebuginfo={}", builder.config.rust_debuginfo_level_tests)); flags.push(builder.config.cmd.rustc_args().join(" ")); diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs index 4b2b058a780..6f4266a7f29 100644 --- a/src/bootstrap/util.rs +++ b/src/bootstrap/util.rs @@ -22,6 +22,7 @@ use crate::config::{Config, TargetSelection}; /// /// This is currently used judiciously throughout the build system rather than /// using a `Result` with `try!`, but this may change one day... +#[macro_export] macro_rules! t { ($e:expr) => { match $e { @@ -37,7 +38,7 @@ macro_rules! t { } }; } -pub(crate) use t; +pub use t; /// Given an executable called `name`, return the filename for the /// executable for a particular target. diff --git a/src/ci/docker/host-x86_64/dist-various-2/shared.sh b/src/ci/docker/host-x86_64/dist-various-2/shared.sh index 267d8b79cc2..291f26bdaeb 100644 --- a/src/ci/docker/host-x86_64/dist-various-2/shared.sh +++ b/src/ci/docker/host-x86_64/dist-various-2/shared.sh @@ -33,15 +33,3 @@ function retry { } done } - -# Copied from ../../init_repo.sh -function fetch_github_commit_archive { - local module=$1 - local cached="download-${module//\//-}.tar.gz" - retry sh -c "rm -f $cached && \ - curl -f -sSL -o $cached $2" - mkdir $module - touch "$module/.git" - tar -C $module --strip-components=1 -xf $cached - rm $cached -} diff --git a/src/ci/init_repo.sh b/src/ci/init_repo.sh deleted file mode 100755 index e8c1e2b0f59..00000000000 --- a/src/ci/init_repo.sh +++ /dev/null @@ -1,83 +0,0 @@ -#!/usr/bin/env bash - -set -o errexit -set -o pipefail -set -o nounset - -ci_dir=$(cd $(dirname $0) && pwd) -. "$ci_dir/shared.sh" - -REPO_DIR="$1" -CACHE_DIR="$2" - -cache_src_dir="$CACHE_DIR/src" - -if [ ! -d "$REPO_DIR" -o ! -d "$REPO_DIR/.git" ]; then - echo "Error: $REPO_DIR does not exist or is not a git repo" - exit 1 -fi -cd $REPO_DIR -if [ ! -d "$CACHE_DIR" ]; then - echo "Error: $CACHE_DIR does not exist or is not an absolute path" - exit 1 -fi - -rm -rf "$CACHE_DIR" -mkdir "$CACHE_DIR" - -# On the beta channel we'll be automatically calculating the prerelease version -# via the git history, so unshallow our shallow clone from CI. -if [ "$(releaseChannel)" = "beta" ]; then - git fetch origin --unshallow beta master -fi - -# Duplicated in docker/dist-various-2/shared.sh -function fetch_github_commit_archive { - local module=$1 - local cached="download-${module//\//-}.tar.gz" - retry sh -c "rm -f $cached && \ - curl -f -sSL -o $cached $2" - mkdir $module - touch "$module/.git" - # On Windows, the default behavior is to emulate symlinks by copying - # files. However, that ends up being order-dependent while extracting, - # which can cause a failure if the symlink comes first. This env var - # causes tar to use real symlinks instead, which are allowed to dangle. - export MSYS=winsymlinks:nativestrict - tar -C $module --strip-components=1 -xf $cached - rm $cached -} - -# Archive downloads are temporarily disabled due to sudden 504 -# gateway timeout errors. -# included="src/llvm-project src/doc/book src/doc/rust-by-example" -included="" -modules="$(git config --file .gitmodules --get-regexp '\.path$' | cut -d' ' -f2)" -modules=($modules) -use_git="" -urls="$(git config --file .gitmodules --get-regexp '\.url$' | cut -d' ' -f2)" -urls=($urls) -# shellcheck disable=SC2068 -for i in ${!modules[@]}; do - module=${modules[$i]} - if [[ " $included " = *" $module "* ]]; then - commit="$(git ls-tree HEAD $module | awk '{print $3}')" - git rm $module - url=${urls[$i]} - url=${url/\.git/} - fetch_github_commit_archive $module "$url/archive/$commit.tar.gz" & - bg_pids[${i}]=$! - continue - else - use_git="$use_git $module" - fi -done -retry sh -c "git submodule deinit -f $use_git && \ - git submodule sync && \ - git submodule update -j 16 --init --recursive --depth 1 $use_git" -# STATUS=0 -# for pid in ${bg_pids[*]} -# do -# wait $pid || STATUS=1 -# done -# exit ${STATUS} diff --git a/src/ci/scripts/checkout-submodules.sh b/src/ci/scripts/checkout-submodules.sh index 0b44ea3c90b..3eb4b8f9058 100755 --- a/src/ci/scripts/checkout-submodules.sh +++ b/src/ci/scripts/checkout-submodules.sh @@ -2,16 +2,70 @@ # Check out all our submodules, but more quickly than using git by using one of # our custom scripts -set -euo pipefail -IFS=$'\n\t' +set -o errexit +set -o pipefail +set -o nounset -source "$(cd "$(dirname "$0")" && pwd)/../shared.sh" +if [ ! -d ".git" ]; then + echo "Error: This must run in the root of the repository" + exit 1 +fi + +ci_dir=$(cd $(dirname $0) && pwd)/.. +. "$ci_dir/shared.sh" -if isWindows; then - path="/c/cache/rustsrc" -else - path="${HOME}/rustsrc" +# On the beta channel we'll be automatically calculating the prerelease version +# via the git history, so unshallow our shallow clone from CI. +if [ "$(releaseChannel)" = "beta" ]; then + git fetch origin --unshallow beta master fi -mkdir -p "${path}" -"$(cd "$(dirname "$0")" && pwd)/../init_repo.sh" . "${path}" +function fetch_github_commit_archive { + local module=$1 + local cached="download-${module//\//-}.tar.gz" + retry sh -c "rm -f $cached && \ + curl -f -sSL -o $cached $2" + mkdir $module + touch "$module/.git" + # On Windows, the default behavior is to emulate symlinks by copying + # files. However, that ends up being order-dependent while extracting, + # which can cause a failure if the symlink comes first. This env var + # causes tar to use real symlinks instead, which are allowed to dangle. + export MSYS=winsymlinks:nativestrict + tar -C $module --strip-components=1 -xf $cached + rm $cached +} + +# Archive downloads are temporarily disabled due to sudden 504 +# gateway timeout errors. +# included="src/llvm-project src/doc/book src/doc/rust-by-example" +included="" +modules="$(git config --file .gitmodules --get-regexp '\.path$' | cut -d' ' -f2)" +modules=($modules) +use_git="" +urls="$(git config --file .gitmodules --get-regexp '\.url$' | cut -d' ' -f2)" +urls=($urls) +# shellcheck disable=SC2068 +for i in ${!modules[@]}; do + module=${modules[$i]} + if [[ " $included " = *" $module "* ]]; then + commit="$(git ls-tree HEAD $module | awk '{print $3}')" + git rm $module + url=${urls[$i]} + url=${url/\.git/} + fetch_github_commit_archive $module "$url/archive/$commit.tar.gz" & + bg_pids[${i}]=$! + continue + else + use_git="$use_git $module" + fi +done +retry sh -c "git submodule deinit -f $use_git && \ + git submodule sync && \ + git submodule update -j 16 --init --recursive --depth 1 $use_git" +# STATUS=0 +# for pid in ${bg_pids[*]} +# do +# wait $pid || STATUS=1 +# done +# exit ${STATUS} diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 16574f94c00..22b1e2335fd 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -340,17 +340,98 @@ pub(crate) fn is_literal_expr(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> bool { false } +/// Build a textual representation of an unevaluated constant expression. +/// +/// If the const expression is too complex, an underscore `_` is returned. +/// For const arguments, it's `{ _ }` to be precise. +/// This means that the output is not necessarily valid Rust code. +/// +/// Currently, only +/// +/// * literals (optionally with a leading `-`) +/// * unit `()` +/// * blocks (`{ … }`) around simple expressions and +/// * paths without arguments +/// +/// are considered simple enough. Simple blocks are included since they are +/// necessary to disambiguate unit from the unit type. +/// This list might get extended in the future. +/// +/// Without this censoring, in a lot of cases the output would get too large +/// and verbose. Consider `match` expressions, blocks and deeply nested ADTs. +/// Further, private and `doc(hidden)` fields of structs would get leaked +/// since HIR datatypes like the `body` parameter do not contain enough +/// semantic information for this function to be able to hide them – +/// at least not without significant performance overhead. +/// +/// Whenever possible, prefer to evaluate the constant first and try to +/// use a different method for pretty-printing. Ideally this function +/// should only ever be used as a fallback. pub(crate) fn print_const_expr(tcx: TyCtxt<'_>, body: hir::BodyId) -> String { let hir = tcx.hir(); let value = &hir.body(body).value; - let snippet = if !value.span.from_expansion() { - tcx.sess.source_map().span_to_snippet(value.span).ok() - } else { - None - }; + #[derive(PartialEq, Eq)] + enum Classification { + Literal, + Simple, + Complex, + } - snippet.unwrap_or_else(|| rustc_hir_pretty::id_to_string(&hir, body.hir_id)) + use Classification::*; + + fn classify(expr: &hir::Expr<'_>) -> Classification { + match &expr.kind { + hir::ExprKind::Unary(hir::UnOp::Neg, expr) => { + if matches!(expr.kind, hir::ExprKind::Lit(_)) { Literal } else { Complex } + } + hir::ExprKind::Lit(_) => Literal, + hir::ExprKind::Tup([]) => Simple, + hir::ExprKind::Block(hir::Block { stmts: [], expr: Some(expr), .. }, _) => { + if classify(expr) == Complex { Complex } else { Simple } + } + // Paths with a self-type or arguments are too “complex” following our measure since + // they may leak private fields of structs (with feature `adt_const_params`). + // Consider: `<Self as Trait<{ Struct { private: () } }>>::CONSTANT`. + // Paths without arguments are definitely harmless though. + hir::ExprKind::Path(hir::QPath::Resolved(_, hir::Path { segments, .. })) => { + if segments.iter().all(|segment| segment.args.is_none()) { Simple } else { Complex } + } + // FIXME: Claiming that those kinds of QPaths are simple is probably not true if the Ty + // contains const arguments. Is there a *concise* way to check for this? + hir::ExprKind::Path(hir::QPath::TypeRelative(..)) => Simple, + // FIXME: Can they contain const arguments and thus leak private struct fields? + hir::ExprKind::Path(hir::QPath::LangItem(..)) => Simple, + _ => Complex, + } + } + + let classification = classify(value); + + if classification == Literal + && !value.span.from_expansion() + && let Ok(snippet) = tcx.sess.source_map().span_to_snippet(value.span) { + // For literals, we avoid invoking the pretty-printer and use the source snippet instead to + // preserve certain stylistic choices the user likely made for the sake legibility like + // + // * hexadecimal notation + // * underscores + // * character escapes + // + // FIXME: This passes through `-/*spacer*/0` verbatim. + snippet + } else if classification == Simple { + // Otherwise we prefer pretty-printing to get rid of extraneous whitespace, comments and + // other formatting artifacts. + rustc_hir_pretty::id_to_string(&hir, body.hir_id) + } else if tcx.def_kind(hir.body_owner_def_id(body).to_def_id()) == DefKind::AnonConst { + // FIXME: Omit the curly braces if the enclosing expression is an array literal + // with a repeated element (an `ExprKind::Repeat`) as in such case it + // would not actually need any disambiguation. + "{ _ }".to_owned() + } else { + "_".to_owned() + } } /// Given a type Path, resolve it to a Type using the TyCtxt diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 50d154dd278..04638aa1af6 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -353,11 +353,7 @@ impl Options { print_flag_list("-C", config::CG_OPTIONS); return Err(0); } - let w_flags = matches.opt_strs("W"); - if w_flags.iter().any(|x| *x == "help") { - print_flag_list("-W", config::DB_OPTIONS); - return Err(0); - } + if matches.opt_strs("passes") == ["list"] { println!("Available passes for running rustdoc:"); for pass in passes::PASSES { @@ -439,15 +435,19 @@ impl Options { return Err(0); } - if matches.free.is_empty() { + let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format); + + let input = PathBuf::from(if describe_lints { + "" // dummy, this won't be used + } else if matches.free.is_empty() { diag.struct_err("missing file operand").emit(); return Err(1); - } - if matches.free.len() > 1 { + } else if matches.free.len() > 1 { diag.struct_err("too many file operands").emit(); return Err(1); - } - let input = PathBuf::from(&matches.free[0]); + } else { + &matches.free[0] + }); let libs = matches .opt_strs("L") @@ -698,8 +698,6 @@ impl Options { let with_examples = matches.opt_strs("with-examples"); let call_locations = crate::scrape_examples::load_call_locations(with_examples, &diag)?; - let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format); - Ok(Options { input, proc_macro_crate, diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 056eda089c1..5584ecd287a 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -1283,10 +1283,6 @@ impl clean::FnDecl { let mut args = Buffer::html(); let mut args_plain = Buffer::new(); for (i, input) in self.inputs.values.iter().enumerate() { - if i == 0 { - args.push_str("<br>"); - } - if let Some(selfty) = input.to_self() { match selfty { clean::SelfValue => { @@ -1312,8 +1308,7 @@ impl clean::FnDecl { } } else { if i > 0 { - args.push_str(" <br>"); - args_plain.push_str(" "); + args.push_str("<br>"); } if input.is_const { args.push_str("const "); @@ -1360,13 +1355,14 @@ impl clean::FnDecl { let full_pad = format!("<br>{}", " ".repeat(indent + 4)); let close_pad = format!("<br>{}", " ".repeat(indent)); format!( - "({args}{close}){arrow}", + "({pad}{args}{close}){arrow}", + pad = if self.inputs.values.is_empty() { "" } else { &full_pad }, args = args.replace("<br>", &full_pad), close = close_pad, arrow = arrow ) } else { - format!("({args}){arrow}", args = args.replace("<br>", ""), arrow = arrow) + format!("({args}){arrow}", args = args.replace("<br>", " "), arrow = arrow) }; if f.alternate() { diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 1ef41d62e5e..548f6c3a987 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -716,12 +716,14 @@ fn assoc_const( ty = ty.print(cx), ); if let Some(default) = default { + write!(w, " = "); + // FIXME: `.value()` uses `clean::utils::format_integer_with_underscore_sep` under the // hood which adds noisy underscores and a type suffix to number literals. // This hurts readability in this context especially when more complex expressions // are involved and it doesn't add much of value. // Find a way to print constants here without all that jazz. - write!(w, " = {}", default.value(cx.tcx()).unwrap_or_else(|| default.expr(cx.tcx()))); + write!(w, "{}", Escape(&default.value(cx.tcx()).unwrap_or_else(|| default.expr(cx.tcx())))); } } diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 0fe99463f1d..fe00f952e04 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -1360,6 +1360,15 @@ fn item_constant(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, c: &cle typ = c.type_.print(cx), ); + // FIXME: The code below now prints + // ` = _; // 100i32` + // if the expression is + // `50 + 50` + // which looks just wrong. + // Should we print + // ` = 100i32;` + // instead? + let value = c.value(cx.tcx()); let is_literal = c.is_literal(cx.tcx()); let expr = c.expr(cx.tcx()); diff --git a/src/librustdoc/html/static/.eslintrc.js b/src/librustdoc/html/static/.eslintrc.js index 2817a8fe144..fcd925bb358 100644 --- a/src/librustdoc/html/static/.eslintrc.js +++ b/src/librustdoc/html/static/.eslintrc.js @@ -91,5 +91,6 @@ module.exports = { "no-script-url": "error", "no-sequences": "error", "no-throw-literal": "error", + "no-div-regex": "error", } }; diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index f7b4fdb736c..8d99b85bebe 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -418,7 +418,7 @@ nav.sub { background-color: var(--sidebar-background-color); } -#sidebar-toggle:hover { +#sidebar-toggle > button:hover, #sidebar-toggle > button:focus { background-color: var(--sidebar-background-color-hover); } @@ -1401,7 +1401,6 @@ pre.rust { position: sticky; top: 0; left: 0; - cursor: pointer; font-weight: bold; font-size: 1.25rem; border-bottom: 1px solid; @@ -1422,7 +1421,24 @@ pre.rust { border-bottom: 1px solid; margin-bottom: 6px; } - +#sidebar-toggle > button { + background: none; + color: inherit; + cursor: pointer; + text-align: center; + border: none; + outline: none; + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + /* work around button layout strangeness: https://stackoverflow.com/q/7271561 */ + width: 100%; + /* iOS button gradient: https://stackoverflow.com/q/5438567 */ + -webkit-appearance: none; + opacity: 1; +} #settings-menu, #help-button { margin-left: 4px; outline: none; @@ -1578,38 +1594,23 @@ kbd { margin-bottom: 1em; } -div.children { - padding-left: 27px; - display: none; +details.dir-entry { + padding-left: 4px; } -div.name { + +details.dir-entry > summary { + margin: 0 0 0 13px; + list-style-position: outside; cursor: pointer; - position: relative; - margin-left: 16px; } -div.files > a { - display: block; - padding: 0 3px; -} -div.files > a:hover, div.name:hover { - background-color: #a14b4b; + +details.dir-entry div.folders, details.dir-entry div.files { + padding-left: 23px; } -div.name.expand + .children { + +details.dir-entry a { display: block; } -div.name::before { - content: "\25B6"; - padding-left: 4px; - font-size: 0.625rem; - position: absolute; - left: -16px; - top: 4px; -} -div.name.expand::before { - transform: rotate(90deg); - left: -15px; - top: 2px; -} /* The hideme class is used on summary tags that contain a span with placeholder text shown only when the toggle is closed. For instance, diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css index 7756e877ef7..b25f5e9fdb1 100644 --- a/src/librustdoc/html/static/css/themes/ayu.css +++ b/src/librustdoc/html/static/css/themes/ayu.css @@ -575,11 +575,12 @@ kbd { color: #fff; border-bottom-color: #5c6773; } -#source-sidebar div.files > a:hover, div.name:hover { +#source-sidebar div.files > a:hover, details.dir-entry summary:hover, +#source-sidebar div.files > a:focus, details.dir-entry summary:focus { background-color: #14191f; color: #ffb44c; } -#source-sidebar div.files > .selected { +#source-sidebar div.files > a.selected { background-color: #14191f; color: #ffb44c; } diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css index 04d5778f59c..a678ec1e1c1 100644 --- a/src/librustdoc/html/static/css/themes/dark.css +++ b/src/librustdoc/html/static/css/themes/dark.css @@ -432,10 +432,11 @@ kbd { #source-sidebar > .title { border-bottom-color: #ccc; } -#source-sidebar div.files > a:hover, div.name:hover { +#source-sidebar div.files > a:hover, details.dir-entry summary:hover, +#source-sidebar div.files > a:focus, details.dir-entry summary:focus { background-color: #444; } -#source-sidebar div.files > .selected { +#source-sidebar div.files > a.selected { background-color: #333; } diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css index 5310736037a..e8770ac2124 100644 --- a/src/librustdoc/html/static/css/themes/light.css +++ b/src/librustdoc/html/static/css/themes/light.css @@ -414,13 +414,13 @@ kbd { #source-sidebar > .title { border-bottom-color: #ccc; } -#source-sidebar div.files > a:hover, div.name:hover { +#source-sidebar div.files > a:hover, details.dir-entry summary:hover, +#source-sidebar div.files > a:focus, details.dir-entry summary:focus { background-color: #E0E0E0; } -#source-sidebar div.files > .selected { +#source-sidebar div.files > a.selected { background-color: #fff; } - .scraped-example-list .scrape-help { border-color: #555; color: #333; diff --git a/src/librustdoc/html/static/js/source-script.js b/src/librustdoc/html/static/js/source-script.js index acb1d8d7b5c..45e70c9a7c7 100644 --- a/src/librustdoc/html/static/js/source-script.js +++ b/src/librustdoc/html/static/js/source-script.js @@ -2,7 +2,7 @@ /* global sourcesIndex */ // Local js definitions: -/* global addClass, getCurrentValue, hasClass, onEachLazy, removeClass, browserSupportsHistoryApi */ +/* global addClass, getCurrentValue, onEachLazy, removeClass, browserSupportsHistoryApi */ /* global updateLocalStorage */ "use strict"; @@ -13,33 +13,27 @@ const rootPath = document.getElementById("rustdoc-vars").attributes["data-root-p let oldScrollPosition = 0; function createDirEntry(elem, parent, fullPath, hasFoundFile) { - const name = document.createElement("div"); - name.className = "name"; + const dirEntry = document.createElement("details"); + const summary = document.createElement("summary"); + + dirEntry.className = "dir-entry"; fullPath += elem["name"] + "/"; - name.onclick = ev => { - if (hasClass(ev.target, "expand")) { - removeClass(ev.target, "expand"); - } else { - addClass(ev.target, "expand"); - } - }; - name.innerText = elem["name"]; + summary.innerText = elem["name"]; + dirEntry.appendChild(summary); - const children = document.createElement("div"); - children.className = "children"; const folders = document.createElement("div"); folders.className = "folders"; if (elem.dirs) { for (const dir of elem.dirs) { if (createDirEntry(dir, folders, fullPath, hasFoundFile)) { - addClass(name, "expand"); + dirEntry.open = true; hasFoundFile = true; } } } - children.appendChild(folders); + dirEntry.appendChild(folders); const files = document.createElement("div"); files.className = "files"; @@ -51,20 +45,19 @@ function createDirEntry(elem, parent, fullPath, hasFoundFile) { const w = window.location.href.split("#")[0]; if (!hasFoundFile && w === file.href) { file.className = "selected"; - addClass(name, "expand"); + dirEntry.open = true; hasFoundFile = true; } files.appendChild(file); } } - children.appendChild(files); - parent.appendChild(name); - parent.appendChild(children); + dirEntry.appendChild(files); + parent.appendChild(dirEntry); return hasFoundFile; } function toggleSidebar() { - const child = this.children[0]; + const child = this.parentNode.children[0]; if (child.innerText === ">") { if (window.innerWidth < 701) { // This is to keep the scroll position on mobile. @@ -93,15 +86,15 @@ function toggleSidebar() { function createSidebarToggle() { const sidebarToggle = document.createElement("div"); sidebarToggle.id = "sidebar-toggle"; - sidebarToggle.onclick = toggleSidebar; - const inner = document.createElement("div"); + const inner = document.createElement("button"); if (getCurrentValue("source-sidebar-show") === "true") { inner.innerText = "<"; } else { inner.innerText = ">"; } + inner.onclick = toggleSidebar; sidebarToggle.appendChild(inner); return sidebarToggle; diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 25a66ee23a0..ded3d9951bd 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -75,7 +75,7 @@ use std::env::{self, VarError}; use std::io; use std::process; -use rustc_driver::{abort_on_err, describe_lints}; +use rustc_driver::abort_on_err; use rustc_errors::ErrorGuaranteed; use rustc_interface::interface; use rustc_middle::ty::TyCtxt; @@ -770,15 +770,24 @@ fn main_options(options: config::Options) -> MainResult { let config = core::create_config(options); interface::create_compiler_and_run(config, |compiler| { - compiler.enter(|queries| { - let sess = compiler.session(); + let sess = compiler.session(); - if sess.opts.describe_lints { - let (_, lint_store) = &*queries.register_plugins()?.peek(); - describe_lints(sess, lint_store, true); - return Ok(()); - } + if sess.opts.describe_lints { + let mut lint_store = rustc_lint::new_lint_store( + sess.opts.debugging_opts.no_interleave_lints, + sess.unstable_options(), + ); + let registered_lints = if let Some(register_lints) = compiler.register_lints() { + register_lints(sess, &mut lint_store); + true + } else { + false + }; + rustc_driver::describe_lints(sess, &lint_store, registered_lints); + return Ok(()); + } + compiler.enter(|queries| { // We need to hold on to the complete resolver, so we cause everything to be // cloned for the analysis passes to use. Suboptimal, but necessary in the // current architecture. diff --git a/src/test/incremental/split_debuginfo_mode.rs b/src/test/incremental/split_debuginfo_mode.rs new file mode 100644 index 00000000000..f2533e4146a --- /dev/null +++ b/src/test/incremental/split_debuginfo_mode.rs @@ -0,0 +1,33 @@ +// This test case makes sure that changing split-debuginfo commandline options triggers a full re-compilation. +// We only test on x86_64-unknown-linux-gnu because there all combinations split-debuginfo settings are valid +// and the test is platform-independent otherwise. + +// ignore-tidy-linelength +// only-x86_64-unknown-linux-gnu +// revisions:rpass1 rpass2 rpass3 rpass4 + +// [rpass1]compile-flags: -Zquery-dep-graph -Zunstable-options -Csplit-debuginfo=unpacked -Zsplit-dwarf-kind=single -Zsplit-dwarf-inlining=on +// [rpass2]compile-flags: -Zquery-dep-graph -Zunstable-options -Csplit-debuginfo=packed -Zsplit-dwarf-kind=single -Zsplit-dwarf-inlining=on +// [rpass3]compile-flags: -Zquery-dep-graph -Zunstable-options -Csplit-debuginfo=packed -Zsplit-dwarf-kind=split -Zsplit-dwarf-inlining=on +// [rpass4]compile-flags: -Zquery-dep-graph -Zunstable-options -Csplit-debuginfo=packed -Zsplit-dwarf-kind=split -Zsplit-dwarf-inlining=off + +#![feature(rustc_attrs)] +// For rpass2 we change -Csplit-debuginfo and thus expect every CGU to be recompiled +#![rustc_partition_codegened(module = "split_debuginfo_mode", cfg = "rpass2")] +#![rustc_partition_codegened(module = "split_debuginfo_mode-another_module", cfg = "rpass2")] +// For rpass3 we change -Zsplit-dwarf-kind and thus also expect every CGU to be recompiled +#![rustc_partition_codegened(module = "split_debuginfo_mode", cfg = "rpass3")] +#![rustc_partition_codegened(module = "split_debuginfo_mode-another_module", cfg = "rpass3")] +// For rpass4 we change -Zsplit-dwarf-inlining and thus also expect every CGU to be recompiled +#![rustc_partition_codegened(module = "split_debuginfo_mode", cfg = "rpass4")] +#![rustc_partition_codegened(module = "split_debuginfo_mode-another_module", cfg = "rpass4")] + +mod another_module { + pub fn foo() -> &'static str { + "hello world" + } +} + +pub fn main() { + println!("{}", another_module::foo()); +} diff --git a/src/test/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstCombine.diff b/src/test/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstCombine.diff index fdc016a95d5..b1ff480324f 100644 --- a/src/test/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstCombine.diff +++ b/src/test/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstCombine.diff @@ -4,98 +4,78 @@ fn <impl at $DIR/combine_clone_of_primitives.rs:6:10: 6:15>::clone(_1: &MyThing<T>) -> MyThing<T> { debug self => _1; // in scope 0 at $DIR/combine_clone_of_primitives.rs:6:10: 6:15 let mut _0: MyThing<T>; // return place in scope 0 at $DIR/combine_clone_of_primitives.rs:6:10: 6:15 - let _2: &T; // in scope 0 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9 - let _3: &u64; // in scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 - let _4: &[f32; 3]; // in scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 - let mut _5: T; // in scope 0 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9 - let mut _6: &T; // in scope 0 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9 - let _7: &T; // in scope 0 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9 - let mut _8: u64; // in scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 - let mut _9: &u64; // in scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 - let _10: &u64; // in scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 - let mut _11: [f32; 3]; // in scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 - let mut _12: &[f32; 3]; // in scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 - let _13: &[f32; 3]; // in scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 - scope 1 { - debug __self_0_0 => _2; // in scope 1 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9 - debug __self_0_1 => _3; // in scope 1 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 - debug __self_0_2 => _4; // in scope 1 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 - } + let mut _2: T; // in scope 0 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9 + let mut _3: &T; // in scope 0 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9 + let _4: &T; // in scope 0 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9 + let mut _5: u64; // in scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 + let mut _6: &u64; // in scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 + let _7: &u64; // in scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 + let mut _8: [f32; 3]; // in scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 + let mut _9: &[f32; 3]; // in scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 + let _10: &[f32; 3]; // in scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 bb0: { StorageLive(_2); // scope 0 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9 - _2 = &((*_1).0: T); // scope 0 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9 - StorageLive(_3); // scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 - _3 = &((*_1).1: u64); // scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 - StorageLive(_4); // scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 - _4 = &((*_1).2: [f32; 3]); // scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 - StorageLive(_5); // scope 1 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9 - StorageLive(_6); // scope 1 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9 - StorageLive(_7); // scope 1 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9 -- _7 = &(*_2); // scope 1 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9 -- _6 = &(*_7); // scope 1 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9 -+ _7 = _2; // scope 1 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9 -+ _6 = _7; // scope 1 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9 - _5 = <T as Clone>::clone(move _6) -> bb1; // scope 1 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9 + StorageLive(_3); // scope 0 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9 + StorageLive(_4); // scope 0 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9 + _4 = &((*_1).0: T); // scope 0 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9 +- _3 = &(*_4); // scope 0 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9 ++ _3 = _4; // scope 0 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9 + _2 = <T as Clone>::clone(move _3) -> bb1; // scope 0 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9 // mir::Constant // + span: $DIR/combine_clone_of_primitives.rs:8:5: 8:9 // + literal: Const { ty: for<'r> fn(&'r T) -> T {<T as Clone>::clone}, val: Value(Scalar(<ZST>)) } } bb1: { - StorageDead(_6); // scope 1 at $DIR/combine_clone_of_primitives.rs:8:8: 8:9 - StorageLive(_8); // scope 1 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 - StorageLive(_9); // scope 1 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 - StorageLive(_10); // scope 1 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 -- _10 = &(*_3); // scope 1 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 -- _9 = &(*_10); // scope 1 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 -- _8 = <u64 as Clone>::clone(move _9) -> [return: bb2, unwind: bb4]; // scope 1 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 + StorageDead(_3); // scope 0 at $DIR/combine_clone_of_primitives.rs:8:8: 8:9 + StorageLive(_5); // scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 + StorageLive(_6); // scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 + StorageLive(_7); // scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 + _7 = &((*_1).1: u64); // scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 +- _6 = &(*_7); // scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 +- _5 = <u64 as Clone>::clone(move _6) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 - // mir::Constant - // + span: $DIR/combine_clone_of_primitives.rs:9:5: 9:11 - // + literal: Const { ty: for<'r> fn(&'r u64) -> u64 {<u64 as Clone>::clone}, val: Value(Scalar(<ZST>)) } -+ _10 = _3; // scope 1 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 -+ _9 = _10; // scope 1 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 -+ _8 = (*_9); // scope 1 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 -+ goto -> bb2; // scope 1 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 ++ _6 = _7; // scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 ++ _5 = (*_6); // scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 ++ goto -> bb2; // scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 } bb2: { - StorageDead(_9); // scope 1 at $DIR/combine_clone_of_primitives.rs:9:10: 9:11 - StorageLive(_11); // scope 1 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 - StorageLive(_12); // scope 1 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 - StorageLive(_13); // scope 1 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 -- _13 = &(*_4); // scope 1 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 -- _12 = &(*_13); // scope 1 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 -- _11 = <[f32; 3] as Clone>::clone(move _12) -> [return: bb3, unwind: bb4]; // scope 1 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 + StorageDead(_6); // scope 0 at $DIR/combine_clone_of_primitives.rs:9:10: 9:11 + StorageLive(_8); // scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 + StorageLive(_9); // scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 + StorageLive(_10); // scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 + _10 = &((*_1).2: [f32; 3]); // scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 +- _9 = &(*_10); // scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 +- _8 = <[f32; 3] as Clone>::clone(move _9) -> [return: bb3, unwind: bb4]; // scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 - // mir::Constant - // + span: $DIR/combine_clone_of_primitives.rs:10:5: 10:16 - // + literal: Const { ty: for<'r> fn(&'r [f32; 3]) -> [f32; 3] {<[f32; 3] as Clone>::clone}, val: Value(Scalar(<ZST>)) } -+ _13 = _4; // scope 1 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 -+ _12 = _13; // scope 1 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 -+ _11 = (*_12); // scope 1 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 -+ goto -> bb3; // scope 1 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 ++ _9 = _10; // scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 ++ _8 = (*_9); // scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 ++ goto -> bb3; // scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 } bb3: { - StorageDead(_12); // scope 1 at $DIR/combine_clone_of_primitives.rs:10:15: 10:16 - Deinit(_0); // scope 1 at $DIR/combine_clone_of_primitives.rs:6:10: 6:15 - (_0.0: T) = move _5; // scope 1 at $DIR/combine_clone_of_primitives.rs:6:10: 6:15 - (_0.1: u64) = move _8; // scope 1 at $DIR/combine_clone_of_primitives.rs:6:10: 6:15 - (_0.2: [f32; 3]) = move _11; // scope 1 at $DIR/combine_clone_of_primitives.rs:6:10: 6:15 - StorageDead(_13); // scope 1 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15 - StorageDead(_11); // scope 1 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15 - StorageDead(_10); // scope 1 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15 - StorageDead(_8); // scope 1 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15 - StorageDead(_7); // scope 1 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15 - StorageDead(_5); // scope 1 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15 - StorageDead(_4); // scope 0 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15 - StorageDead(_3); // scope 0 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15 + StorageDead(_9); // scope 0 at $DIR/combine_clone_of_primitives.rs:10:15: 10:16 + Deinit(_0); // scope 0 at $DIR/combine_clone_of_primitives.rs:6:10: 6:15 + (_0.0: T) = move _2; // scope 0 at $DIR/combine_clone_of_primitives.rs:6:10: 6:15 + (_0.1: u64) = move _5; // scope 0 at $DIR/combine_clone_of_primitives.rs:6:10: 6:15 + (_0.2: [f32; 3]) = move _8; // scope 0 at $DIR/combine_clone_of_primitives.rs:6:10: 6:15 + StorageDead(_8); // scope 0 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15 + StorageDead(_5); // scope 0 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15 StorageDead(_2); // scope 0 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15 + StorageDead(_10); // scope 0 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15 + StorageDead(_7); // scope 0 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15 + StorageDead(_4); // scope 0 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15 return; // scope 0 at $DIR/combine_clone_of_primitives.rs:6:15: 6:15 } bb4 (cleanup): { - drop(_5) -> bb5; // scope 1 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15 + drop(_2) -> bb5; // scope 0 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15 } bb5 (cleanup): { diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.uses_crate.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.uses_crate.txt index 55a49548cb5..65eb1008dd8 100644 --- a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.uses_crate.txt +++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.uses_crate.txt @@ -36,12 +36,12 @@ 22| 2| println!("used_only_from_this_lib_crate_generic_function with {:?}", arg); 23| 2|} ------------------ - | used_crate::used_only_from_this_lib_crate_generic_function::<&str>: + | used_crate::used_only_from_this_lib_crate_generic_function::<alloc::vec::Vec<i32>>: | 21| 1|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) { | 22| 1| println!("used_only_from_this_lib_crate_generic_function with {:?}", arg); | 23| 1|} ------------------ - | used_crate::used_only_from_this_lib_crate_generic_function::<alloc::vec::Vec<i32>>: + | used_crate::used_only_from_this_lib_crate_generic_function::<&str>: | 21| 1|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) { | 22| 1| println!("used_only_from_this_lib_crate_generic_function with {:?}", arg); | 23| 1|} diff --git a/src/test/run-make/issue-88756-opt-help/Makefile b/src/test/run-make/issue-88756-opt-help/Makefile deleted file mode 100644 index 8ababbf5b4e..00000000000 --- a/src/test/run-make/issue-88756-opt-help/Makefile +++ /dev/null @@ -1,4 +0,0 @@ --include ../../run-make-fulldeps/tools.mk - -all: - $(RUSTDOC) -W help 2>&1 | diff - output-default.stdout diff --git a/src/test/run-make/issue-88756-opt-help/README.md b/src/test/run-make/issue-88756-opt-help/README.md deleted file mode 100644 index 9b742753f25..00000000000 --- a/src/test/run-make/issue-88756-opt-help/README.md +++ /dev/null @@ -1 +0,0 @@ -This is a test to verify that `rustdoc` behaves the same as rustc and prints out help output for its options like -W (#88756). diff --git a/src/test/run-make/issue-88756-opt-help/output-default.stdout b/src/test/run-make/issue-88756-opt-help/output-default.stdout deleted file mode 100644 index 5cb7ecb649a..00000000000 --- a/src/test/run-make/issue-88756-opt-help/output-default.stdout +++ /dev/null @@ -1,193 +0,0 @@ - -W allow-features=val -- only allow the listed language features to be enabled in code (space separated) - -W always-encode-mir=val -- encode MIR of all functions into the crate metadata (default: no) - -W assume-incomplete-release=val -- make cfg(version) treat the current version as incomplete (default: no) - -W asm-comments=val -- generate comments into the assembly (may change behavior) (default: no) - -W assert-incr-state=val -- assert that the incremental cache is in given state: either `loaded` or `not-loaded`. - -W binary-dep-depinfo=val -- include artifacts (sysroot, crate dependencies) used during compilation in dep-info (default: no) - -W branch-protection=val -- set options for branch target identification and pointer authentication on AArch64 - -W cf-protection=val -- instrument control-flow architecture protection - -W cgu-partitioning-strategy=val -- the codegen unit partitioning strategy to use - -W chalk=val -- enable the experimental Chalk-based trait solving engine - -W codegen-backend=val -- the backend to use - -W combine-cgu=val -- combine CGUs into a single one - -W crate-attr=val -- inject the given attribute in the crate - -W debug-info-for-profiling=val -- emit discriminators and other data necessary for AutoFDO - -W debug-macros=val -- emit line numbers debug info inside macros (default: no) - -W deduplicate-diagnostics=val -- deduplicate identical diagnostics (default: yes) - -W dep-info-omit-d-target=val -- in dep-info output, omit targets for tracking dependencies of the dep-info files themselves (default: no) - -W dep-tasks=val -- print tasks that execute and the color their dep node gets (requires debug build) (default: no) - -W dlltool=val -- import library generation tool (windows-gnu only) - -W dont-buffer-diagnostics=val -- emit diagnostics rather than buffering (breaks NLL error downgrading, sorting) (default: no) - -W drop-tracking=val -- enables drop tracking in generators (default: no) - -W dual-proc-macros=val -- load proc macros for both target and host, but only link to the target (default: no) - -W dump-dep-graph=val -- dump the dependency graph to $RUST_DEP_GRAPH (default: /tmp/dep_graph.gv) (default: no) - -W dump-mir=val -- dump MIR state to file. - `val` is used to select which passes and functions to dump. For example: - `all` matches all passes and functions, - `foo` matches all passes for functions whose name contains 'foo', - `foo & ConstProp` only the 'ConstProp' pass for function names containing 'foo', - `foo | bar` all passes for function names containing 'foo' or 'bar'. - -W dump-mir-dataflow=val -- in addition to `.mir` files, create graphviz `.dot` files with dataflow results (default: no) - -W dump-mir-dir=val -- the directory the MIR is dumped into (default: `mir_dump`) - -W dump-mir-exclude-pass-number=val -- exclude the pass number when dumping MIR (used in tests) (default: no) - -W dump-mir-graphviz=val -- in addition to `.mir` files, create graphviz `.dot` files (and with `-Z instrument-coverage`, also create a `.dot` file for the MIR-derived coverage graph) (default: no) - -W dump-mir-spanview=val -- in addition to `.mir` files, create `.html` files to view spans for all `statement`s (including terminators), only `terminator` spans, or computed `block` spans (one span encompassing a block's terminator and all statements). If `-Z instrument-coverage` is also enabled, create an additional `.html` file showing the computed coverage spans. - -W emit-stack-sizes=val -- emit a section containing stack size metadata (default: no) - -W fewer-names=val -- reduce memory use by retaining fewer names within compilation artifacts (LLVM-IR) (default: no) - -W force-unstable-if-unmarked=val -- force all crates to be `rustc_private` unstable (default: no) - -W fuel=val -- set the optimization fuel quota for a crate - -W function-sections=val -- whether each function should go in its own section - -W future-incompat-test=val -- forces all lints to be future incompatible, used for internal testing (default: no) - -W gcc-ld=val -- implementation of ld used by cc - -W graphviz-dark-mode=val -- use dark-themed colors in graphviz output (default: no) - -W graphviz-font=val -- use the given `fontname` in graphviz output; can be overridden by setting environment variable `RUSTC_GRAPHVIZ_FONT` (default: `Courier, monospace`) - -W hir-stats=val -- print some statistics about AST and HIR (default: no) - -W human-readable-cgu-names=val -- generate human-readable, predictable names for codegen units (default: no) - -W identify-regions=val -- display unnamed regions as `'<id>`, using a non-ident unique id (default: no) - -W incremental-ignore-spans=val -- ignore spans during ICH computation -- used for testing (default: no) - -W incremental-info=val -- print high-level information about incremental reuse (or the lack thereof) (default: no) - -W incremental-relative-spans=val -- hash spans relative to their parent item for incr. comp. (default: no) - -W incremental-verify-ich=val -- verify incr. comp. hashes of green query instances (default: no) - -W inline-mir=val -- enable MIR inlining (default: no) - -W inline-mir-threshold=val -- a default MIR inlining threshold (default: 50) - -W inline-mir-hint-threshold=val -- inlining threshold for functions with inline hint (default: 100) - -W inline-in-all-cgus=val -- control whether `#[inline]` functions are in all CGUs - -W input-stats=val -- gather statistics about the input (default: no) - -W instrument-coverage=val -- instrument the generated code to support LLVM source-based code coverage reports (note, the compiler build config must include `profiler = true`); implies `-C symbol-mangling-version=v0`. Optional values are: - `=all` (implicit value) - `=except-unused-generics` - `=except-unused-functions` - `=off` (default) - -W instrument-mcount=val -- insert function instrument code for mcount-based tracing (default: no) - -W keep-hygiene-data=val -- keep hygiene data after analysis (default: no) - -W link-native-libraries=val -- link native libraries in the linker invocation (default: yes) - -W link-only=val -- link the `.rlink` file generated by `-Z no-link` (default: no) - -W llvm-plugins=val -- a list LLVM plugins to enable (space separated) - -W llvm-time-trace=val -- generate JSON tracing data file from LLVM data (default: no) - -W location-detail=val -- comma separated list of location details to be tracked when using caller_location valid options are `file`, `line`, and `column` (default: all) - -W ls=val -- list the symbols defined by a library crate (default: no) - -W macro-backtrace=val -- show macro backtraces (default: no) - -W merge-functions=val -- control the operation of the MergeFunctions LLVM pass, taking the same values as the target option of the same name - -W meta-stats=val -- gather metadata statistics (default: no) - -W mir-emit-retag=val -- emit Retagging MIR statements, interpreted e.g., by miri; implies -Zmir-opt-level=0 (default: no) - -W mir-enable-passes=val -- use like `-Zmir-enable-passes=+DestProp,-InstCombine`. Forces the specified passes to be enabled, overriding all other checks. Passes that are not specified are enabled or disabled by other flags as usual. - -W mir-opt-level=val -- MIR optimization level (0-4; default: 1 in non optimized builds and 2 in optimized builds) - -W move-size-limit=val -- the size at which the `large_assignments` lint starts to be emitted - -W mutable-noalias=val -- emit noalias metadata for mutable references (default: yes) - -W new-llvm-pass-manager=val -- use new LLVM pass manager (default: no) - -W nll-facts=val -- dump facts from NLL analysis into side files (default: no) - -W nll-facts-dir=val -- the directory the NLL facts are dumped into (default: `nll-facts`) - -W no-analysis=val -- parse and expand the source, but run no analysis - -W no-codegen=val -- run all passes except codegen; no output - -W no-generate-arange-section=val -- omit DWARF address ranges that give faster lookups - -W no-interleave-lints=val -- execute lints separately; allows benchmarking individual lints - -W no-leak-check=val -- disable the 'leak check' for subtyping; unsound, but useful for tests - -W no-link=val -- compile without linking - -W no-parallel-llvm=val -- run LLVM in non-parallel mode (while keeping codegen-units and ThinLTO) - -W no-unique-section-names=val -- do not use unique names for text and data sections when -Z function-sections is used - -W no-profiler-runtime=val -- prevent automatic injection of the profiler_builtins crate - -W normalize-docs=val -- normalize associated items in rustdoc when generating documentation - -W oom=val -- panic strategy for out-of-memory handling - -W osx-rpath-install-name=val -- pass `-install_name @rpath/...` to the macOS linker (default: no) - -W panic-abort-tests=val -- support compiling tests with panic=abort (default: no) - -W panic-in-drop=val -- panic strategy for panics in drops - -W parse-only=val -- parse only; do not compile, assemble, or link (default: no) - -W perf-stats=val -- print some performance-related statistics (default: no) - -W pick-stable-methods-before-any-unstable=val -- try to pick stable methods first before picking any unstable methods (default: yes) - -W plt=val -- whether to use the PLT when calling into shared libraries; - only has effect for PIC code on systems with ELF binaries - (default: PLT is disabled if full relro is enabled) - -W polonius=val -- enable polonius-based borrow-checker (default: no) - -W polymorphize=val -- perform polymorphization analysis - -W pre-link-arg=val -- a single extra argument to prepend the linker invocation (can be used several times) - -W pre-link-args=val -- extra arguments to prepend to the linker invocation (space separated) - -W precise-enum-drop-elaboration=val -- use a more precise version of drop elaboration for matches on enums (default: yes). This results in better codegen, but has caused miscompilations on some tier 2 platforms. See #77382 and #74551. - -W print-fuel=val -- make rustc print the total optimization fuel used by a crate - -W print-llvm-passes=val -- print the LLVM optimization passes being run (default: no) - -W print-mono-items=val -- print the result of the monomorphization collection pass - -W print-type-sizes=val -- print layout information for each type encountered (default: no) - -W proc-macro-backtrace=val -- show backtraces for panics during proc-macro execution (default: no) - -W profile=val -- insert profiling code (default: no) - -W profile-closures=val -- profile size of closures - -W profile-emit=val -- file path to emit profiling data at runtime when using 'profile' (default based on relative source path) - -W profiler-runtime=val -- name of the profiler runtime crate to automatically inject (default: `profiler_builtins`) - -W profile-sample-use=val -- use the given `.prof` file for sampled profile-guided optimization (also known as AutoFDO) - -W query-dep-graph=val -- enable queries of the dependency graph for regression testing (default: no) - -W randomize-layout=val -- randomize the layout of types (default: no) - -W layout-seed=val -- seed layout randomization - -W relax-elf-relocations=val -- whether ELF relocations can be relaxed - -W relro-level=val -- choose which RELRO level to use - -W remap-cwd-prefix=val -- remap paths under the current working directory to this path prefix - -W simulate-remapped-rust-src-base=val -- simulate the effect of remap-debuginfo = true at bootstrapping by remapping path to rust's source base directory. only meant for testing purposes - -W report-delayed-bugs=val -- immediately print bugs registered with `delay_span_bug` (default: no) - -W sanitizer=val -- use a sanitizer - -W sanitizer-memory-track-origins=val -- enable origins tracking in MemorySanitizer - -W sanitizer-recover=val -- enable recovery for selected sanitizers - -W saturating-float-casts=val -- make float->int casts UB-free: numbers outside the integer type's range are clipped to the max/min integer respectively, and NaN is mapped to 0 (default: yes) - -W save-analysis=val -- write syntax and type analysis (in JSON format) information, in addition to normal output (default: no) - -W self-profile=val -- run the self profiler and output the raw event data - -W self-profile-events=val -- specify the events recorded by the self profiler; - for example: `-Z self-profile-events=default,query-keys` - all options: none, all, default, generic-activity, query-provider, query-cache-hit - query-blocked, incr-cache-load, incr-result-hashing, query-keys, function-args, args, llvm, artifact-sizes - -W self-profile-counter=val -- counter used by the self profiler (default: `wall-time`), one of: - `wall-time` (monotonic clock, i.e. `std::time::Instant`) - `instructions:u` (retired instructions, userspace-only) - `instructions-minus-irqs:u` (subtracting hardware interrupt counts for extra accuracy) - -W share-generics=val -- make the current crate share its generic instantiations - -W show-span=val -- show spans for compiler debugging (expr|pat|ty) - -W span-debug=val -- forward proc_macro::Span's `Debug` impl to `Span` - -W span-free-formats=val -- exclude spans when debug-printing compiler state (default: no) - -W src-hash-algorithm=val -- hash algorithm of source files in debug info (`md5`, `sha1`, or `sha256`) - -W stack-protector=val -- control stack smash protection strategy (`rustc --print stack-protector-strategies` for details) - -W strict-init-checks=val -- control if mem::uninitialized and mem::zeroed panic on more UB - -W strip=val -- tell the linker which information to strip (`none` (default), `debuginfo` or `symbols`) - -W split-dwarf-kind=val -- split dwarf variant (only if -Csplit-debuginfo is enabled and on relevant platform) - (default: `split`) - - `split`: sections which do not require relocation are written into a DWARF object (`.dwo`) - file which is ignored by the linker - `single`: sections which do not require relocation are written into object file but ignored - by the linker - -W split-dwarf-inlining=val -- provide minimal debug info in the object/executable to facilitate online symbolication/stack traces in the absence of .dwo/.dwp files when using Split DWARF - -W symbol-mangling-version=val -- which mangling version to use for symbol names ('legacy' (default) or 'v0') - -W teach=val -- show extended diagnostic help (default: no) - -W temps-dir=val -- the directory the intermediate files are written to - -W terminal-width=val -- set the current terminal width - -W translate-lang=val -- language identifier for diagnostic output - -W translate-additional-ftl=val -- additional fluent translation to preferentially use (for testing translation) - -W translate-directionality-markers=val -- emit directionality isolation markers in translated diagnostics - -W tune-cpu=val -- select processor to schedule for (`rustc --print target-cpus` for details) - -W thinlto=val -- enable ThinLTO when possible - -W thir-unsafeck=val -- use the THIR unsafety checker (default: no) - -W threads=val -- use a thread pool with N threads - -W time=val -- measure time of rustc processes (default: no) - -W time-llvm-passes=val -- measure time of each LLVM pass (default: no) - -W time-passes=val -- measure time of each rustc pass (default: no) - -W tls-model=val -- choose the TLS model to use (`rustc --print tls-models` for details) - -W trace-macros=val -- for every macro invocation, print its name and arguments (default: no) - -W translate-remapped-path-to-local-path=val -- translate remapped paths into local paths when possible (default: yes) - -W trap-unreachable=val -- generate trap instructions for unreachable intrinsics (default: use target setting, usually yes) - -W treat-err-as-bug=val -- treat error number `val` that occurs as bug - -W trim-diagnostic-paths=val -- in diagnostics, use heuristics to shorten paths referring to items - -W ui-testing=val -- emit compiler diagnostics in a form suitable for UI testing (default: no) - -W uninit-const-chunk-threshold=val -- allow generating const initializers with mixed init/uninit chunks, and set the maximum number of chunks for which this is allowed (default: 16) - -W unleash-the-miri-inside-of-you=val -- take the brakes off const evaluation. NOTE: this is unsound (default: no) - -W unpretty=val -- present the input source, unstable (and less-pretty) variants; - `normal`, `identified`, - `expanded`, `expanded,identified`, - `expanded,hygiene` (with internal representations), - `ast-tree` (raw AST before expansion), - `ast-tree,expanded` (raw AST after expansion), - `hir` (the HIR), `hir,identified`, - `hir,typed` (HIR with types for each node), - `hir-tree` (dump the raw HIR), - `mir` (the MIR), or `mir-cfg` (graphviz formatted MIR) - -W unsound-mir-opts=val -- enable unsound and buggy MIR optimizations (default: no) - -W unstable-options=val -- adds unstable command line options to rustc interface (default: no) - -W use-ctors-section=val -- use legacy .ctors section for initializers rather than .init_array - -W validate-mir=val -- validate MIR after each transformation - -W verbose=val -- in general, enable more debug printouts (default: no) - -W verify-llvm-ir=val -- verify LLVM IR (default: no) - -W virtual-function-elimination=val -- enables dead virtual function elimination optimization. Requires `-Clto[=[fat,yes]]` - -W wasi-exec-model=val -- whether to build a wasi command or reactor diff --git a/src/test/run-make/issue-88756-opt-help/x.rs b/src/test/run-make/issue-88756-opt-help/x.rs deleted file mode 100644 index 5df7576133a..00000000000 --- a/src/test/run-make/issue-88756-opt-help/x.rs +++ /dev/null @@ -1 +0,0 @@ -// nothing to see here diff --git a/src/test/run-make/native-link-modifier-bundle/Makefile b/src/test/run-make/native-link-modifier-bundle/Makefile index 723bb4689fe..e4b0f74ac26 100644 --- a/src/test/run-make/native-link-modifier-bundle/Makefile +++ b/src/test/run-make/native-link-modifier-bundle/Makefile @@ -3,27 +3,31 @@ -include ../../run-make-fulldeps/tools.mk +# We're using the llvm-nm instead of the system nm to ensure it is compatible +# with the LLVM bitcode generated by rustc. +NM = "$(LLVM_BIN_DIR)"/llvm-nm + all: $(call NATIVE_STATICLIB,native-staticlib) # Build a staticlib and a rlib, the `native_func` symbol will be bundled into them $(RUSTC) bundled.rs --crate-type=staticlib --crate-type=rlib - nm $(TMPDIR)/libbundled.a | $(CGREP) -e "T _*native_func" - nm $(TMPDIR)/libbundled.a | $(CGREP) -e "U _*native_func" - nm $(TMPDIR)/libbundled.rlib | $(CGREP) -e "T _*native_func" - nm $(TMPDIR)/libbundled.rlib | $(CGREP) -e "U _*native_func" + $(NM) $(TMPDIR)/libbundled.a | $(CGREP) -e "T _*native_func" + $(NM) $(TMPDIR)/libbundled.a | $(CGREP) -e "U _*native_func" + $(NM) $(TMPDIR)/libbundled.rlib | $(CGREP) -e "T _*native_func" + $(NM) $(TMPDIR)/libbundled.rlib | $(CGREP) -e "U _*native_func" # Build a staticlib and a rlib, the `native_func` symbol will not be bundled into it $(RUSTC) non-bundled.rs --crate-type=staticlib --crate-type=rlib - nm $(TMPDIR)/libnon_bundled.a | $(CGREP) -ve "T _*native_func" - nm $(TMPDIR)/libnon_bundled.a | $(CGREP) -e "U _*native_func" - nm $(TMPDIR)/libnon_bundled.rlib | $(CGREP) -ve "T _*native_func" - nm $(TMPDIR)/libnon_bundled.rlib | $(CGREP) -e "U _*native_func" + $(NM) $(TMPDIR)/libnon_bundled.a | $(CGREP) -ve "T _*native_func" + $(NM) $(TMPDIR)/libnon_bundled.a | $(CGREP) -e "U _*native_func" + $(NM) $(TMPDIR)/libnon_bundled.rlib | $(CGREP) -ve "T _*native_func" + $(NM) $(TMPDIR)/libnon_bundled.rlib | $(CGREP) -e "U _*native_func" # Build a cdylib, `native-staticlib` will not appear on the linker line because it was bundled previously # The cdylib will contain the `native_func` symbol in the end $(RUSTC) cdylib-bundled.rs --crate-type=cdylib --print link-args | $(CGREP) -ve '-l[" ]*native-staticlib' - nm $(call DYLIB,cdylib_bundled) | $(CGREP) -e "[Tt] _*native_func" + $(NM) $(call DYLIB,cdylib_bundled) | $(CGREP) -e "[Tt] _*native_func" # Build a cdylib, `native-staticlib` will appear on the linker line because it was not bundled previously # The cdylib will contain the `native_func` symbol in the end $(RUSTC) cdylib-non-bundled.rs --crate-type=cdylib --print link-args | $(CGREP) -e '-l[" ]*native-staticlib' - nm $(call DYLIB,cdylib_non_bundled) | $(CGREP) -e "[Tt] _*native_func" + $(NM) $(call DYLIB,cdylib_non_bundled) | $(CGREP) -e "[Tt] _*native_func" diff --git a/src/test/rustdoc-gui/sidebar-source-code-display.goml b/src/test/rustdoc-gui/sidebar-source-code-display.goml index c441f84a821..25699d82e61 100644 --- a/src/test/rustdoc-gui/sidebar-source-code-display.goml +++ b/src/test/rustdoc-gui/sidebar-source-code-display.goml @@ -27,29 +27,52 @@ reload: // Waiting for the sidebar to be displayed... wait-for-css: ("#sidebar-toggle", {"visibility": "visible", "opacity": 1}) assert-css: ( - "#source-sidebar .expand + .children a.selected", + "#source-sidebar details[open] > .files a.selected", {"color": "rgb(0, 0, 0)", "background-color": "rgb(255, 255, 255)"}, ) +// Without hover or focus. +assert-css: ("#sidebar-toggle > button", {"background-color": "rgba(0, 0, 0, 0)"}) +// With focus. +focus: "#sidebar-toggle > button" +assert-css: ("#sidebar-toggle > button", {"background-color": "rgb(224, 224, 224)"}) +focus: ".search-input" +// With hover. +move-cursor-to: "#sidebar-toggle > button" +assert-css: ("#sidebar-toggle > button", {"background-color": "rgb(224, 224, 224)"}) // Without hover. assert-css: ( - "#source-sidebar .expand + .children > .files a:not(.selected)", + "#source-sidebar details[open] > .files a:not(.selected)", {"color": "rgb(0, 0, 0)", "background-color": "rgba(0, 0, 0, 0)"}, ) +// With focus. +focus: "#source-sidebar details[open] > .files a:not(.selected)" +wait-for-css: ( + "#source-sidebar details[open] > .files a:not(.selected)", + {"color": "rgb(0, 0, 0)", "background-color": "rgb(224, 224, 224)"}, +) +focus: ".search-input" // With hover. -move-cursor-to: "#source-sidebar .expand + .children > .files a:not(.selected)" +move-cursor-to: "#source-sidebar details[open] > .files a:not(.selected)" assert-css: ( - "#source-sidebar .expand + .children > .files a:not(.selected)", + "#source-sidebar details[open] > .files a:not(.selected)", {"color": "rgb(0, 0, 0)", "background-color": "rgb(224, 224, 224)"}, ) // Without hover. assert-css: ( - "#source-sidebar .expand + .children .folders .name", + "#source-sidebar details[open] > .folders > details > summary", {"color": "rgb(0, 0, 0)", "background-color": "rgba(0, 0, 0, 0)"}, ) +// With focus. +focus: "#source-sidebar details[open] > .folders > details > summary" +wait-for-css: ( + "#source-sidebar details[open] > .folders > details > summary", + {"color": "rgb(0, 0, 0)", "background-color": "rgb(224, 224, 224)"}, +) +focus: ".search-input" // With hover. -move-cursor-to: "#source-sidebar .expand + .children .folders .name" +move-cursor-to: "#source-sidebar details[open] > .folders > details > summary" assert-css: ( - "#source-sidebar .expand + .children .folders .name", + "#source-sidebar details[open] > .folders > details > summary", {"color": "rgb(0, 0, 0)", "background-color": "rgb(224, 224, 224)"}, ) @@ -59,29 +82,52 @@ reload: // Waiting for the sidebar to be displayed... wait-for-css: ("#sidebar-toggle", {"visibility": "visible", "opacity": 1}) assert-css: ( - "#source-sidebar .expand + .children a.selected", + "#source-sidebar details[open] > .files > a.selected", {"color": "rgb(221, 221, 221)", "background-color": "rgb(51, 51, 51)"}, ) +// Without hover or focus. +assert-css: ("#sidebar-toggle > button", {"background-color": "rgba(0, 0, 0, 0)"}) +// With focus. +focus: "#sidebar-toggle > button" +assert-css: ("#sidebar-toggle > button", {"background-color": "rgb(103, 103, 103)"}) +focus: ".search-input" +// With hover. +move-cursor-to: "#sidebar-toggle > button" +assert-css: ("#sidebar-toggle > button", {"background-color": "rgb(103, 103, 103)"}) // Without hover. assert-css: ( - "#source-sidebar .expand + .children > .files a:not(.selected)", + "#source-sidebar details[open] > .files > a:not(.selected)", {"color": "rgb(221, 221, 221)", "background-color": "rgba(0, 0, 0, 0)"}, ) +// With focus. +focus: "#source-sidebar details[open] > .files a:not(.selected)" +wait-for-css: ( + "#source-sidebar details[open] > .files a:not(.selected)", + {"color": "rgb(221, 221, 221)", "background-color": "rgb(68, 68, 68)"}, +) +focus: ".search-input" // With hover. -move-cursor-to: "#source-sidebar .expand + .children > .files a:not(.selected)" +move-cursor-to: "#source-sidebar details[open] > .files a:not(.selected)" assert-css: ( - "#source-sidebar .expand + .children > .files a:not(.selected)", + "#source-sidebar details[open] > .files a:not(.selected)", {"color": "rgb(221, 221, 221)", "background-color": "rgb(68, 68, 68)"}, ) // Without hover. assert-css: ( - "#source-sidebar .expand + .children .folders .name", + "#source-sidebar details[open] > .folders > details > summary", {"color": "rgb(221, 221, 221)", "background-color": "rgba(0, 0, 0, 0)"}, ) +// With focus. +focus: "#source-sidebar details[open] > .folders > details > summary" +wait-for-css: ( + "#source-sidebar details[open] > .folders > details > summary", + {"color": "rgb(221, 221, 221)", "background-color": "rgb(68, 68, 68)"}, +) +focus: ".search-input" // With hover. -move-cursor-to: "#source-sidebar .expand + .children .folders .name" +move-cursor-to: "#source-sidebar details[open] > .folders > details > summary" assert-css: ( - "#source-sidebar .expand + .children .folders .name", + "#source-sidebar details[open] > .folders > details > summary", {"color": "rgb(221, 221, 221)", "background-color": "rgb(68, 68, 68)"}, ) @@ -91,29 +137,52 @@ reload: // Waiting for the sidebar to be displayed... wait-for-css: ("#sidebar-toggle", {"visibility": "visible", "opacity": 1}) assert-css: ( - "#source-sidebar .expand + .children a.selected", + "#source-sidebar details[open] > .files a.selected", {"color": "rgb(255, 180, 76)", "background-color": "rgb(20, 25, 31)"}, ) +// Without hover or focus. +assert-css: ("#sidebar-toggle > button", {"background-color": "rgba(0, 0, 0, 0)"}) +// With focus. +focus: "#sidebar-toggle > button" +assert-css: ("#sidebar-toggle > button", {"background-color": "rgba(70, 70, 70, 0.33)"}) +focus: ".search-input" +// With hover. +move-cursor-to: "#sidebar-toggle > button" +assert-css: ("#sidebar-toggle > button", {"background-color": "rgba(70, 70, 70, 0.33)"}) // Without hover. assert-css: ( - "#source-sidebar .expand + .children > .files a:not(.selected)", + "#source-sidebar details[open] > .files a:not(.selected)", {"color": "rgb(197, 197, 197)", "background-color": "rgba(0, 0, 0, 0)"}, ) +// With focus. +focus: "#source-sidebar details[open] > .files a:not(.selected)" +wait-for-css: ( + "#source-sidebar details[open] > .files a:not(.selected)", + {"color": "rgb(255, 180, 76)", "background-color": "rgb(20, 25, 31)"}, +) +focus: ".search-input" // With hover. -move-cursor-to: "#source-sidebar .expand + .children > .files a:not(.selected)" +move-cursor-to: "#source-sidebar details[open] > .files a:not(.selected)" assert-css: ( - "#source-sidebar .expand + .children > .files a:not(.selected)", + "#source-sidebar details[open] > .files a:not(.selected)", {"color": "rgb(255, 180, 76)", "background-color": "rgb(20, 25, 31)"}, ) // Without hover. assert-css: ( - "#source-sidebar .expand + .children .folders .name", + "#source-sidebar details[open] > .folders > details > summary", {"color": "rgb(197, 197, 197)", "background-color": "rgba(0, 0, 0, 0)"}, ) +// With focus. +focus: "#source-sidebar details[open] > .folders > details > summary" +wait-for-css: ( + "#source-sidebar details[open] > .folders > details > summary", + {"color": "rgb(255, 180, 76)", "background-color": "rgb(20, 25, 31)"}, +) +focus: ".search-input" // With hover. -move-cursor-to: "#source-sidebar .expand + .children .folders .name" +move-cursor-to: "#source-sidebar details[open] > .folders > details > summary" assert-css: ( - "#source-sidebar .expand + .children .folders .name", + "#source-sidebar details[open] > .folders > details > summary", {"color": "rgb(255, 180, 76)", "background-color": "rgb(20, 25, 31)"}, ) diff --git a/src/test/rustdoc-gui/source-code-page.goml b/src/test/rustdoc-gui/source-code-page.goml index b45512601f2..581f826a3d9 100644 --- a/src/test/rustdoc-gui/source-code-page.goml +++ b/src/test/rustdoc-gui/source-code-page.goml @@ -34,19 +34,16 @@ assert-document-property: ({"URL": "/lib.rs.html"}, ENDS_WITH) click: "#sidebar-toggle" assert: ".source-sidebar-expanded" -// We check that the first entry of the sidebar is collapsed (which, for whatever reason, -// is number 2 and not 1...). -assert-attribute: ("#source-sidebar .name:nth-child(2)", {"class": "name"}) -assert-text: ("#source-sidebar .name:nth-child(2)", "implementors") -// We also check its children are hidden too. -assert-css: ("#source-sidebar .name:nth-child(2) + .children", {"display": "none"}) +// We check that the first entry of the sidebar is collapsed +assert-property: ("#source-sidebar details:first-of-type", {"open": "false"}) +assert-text: ("#source-sidebar details:first-of-type > summary", "implementors") // We now click on it. -click: "#source-sidebar .name:nth-child(2)" -assert-attribute: ("#source-sidebar .name:nth-child(2)", {"class": "name expand"}) -// Checking that its children are displayed as well. -assert-css: ("#source-sidebar .name:nth-child(2) + .children", {"display": "block"}) +click: "#source-sidebar details:first-of-type > summary" +assert-property: ("#source-sidebar details:first-of-type", {"open": "true"}) // And now we collapse it again. -click: "#source-sidebar .name:nth-child(2)" -assert-attribute: ("#source-sidebar .name:nth-child(2)", {"class": "name"}) -assert-css: ("#source-sidebar .name:nth-child(2) + .children", {"display": "none"}) +click: "#source-sidebar details:first-of-type > summary" +assert-property: ("#source-sidebar details:first-of-type", {"open": "false"}) + +// Check the spacing. +assert-css: ("#source-sidebar > details.dir-entry", {"padding-left": "4px"}) diff --git a/src/test/rustdoc-ui/issue-83883-describe-lints.rs b/src/test/rustdoc-ui/issue-83883-describe-lints.rs index a261b782d48..0474d6c143e 100644 --- a/src/test/rustdoc-ui/issue-83883-describe-lints.rs +++ b/src/test/rustdoc-ui/issue-83883-describe-lints.rs @@ -1,8 +1,10 @@ // compile-flags: -W help // check-pass +// check-stdout +// error-pattern:Lint checks provided +// error-pattern:rustdoc::broken-intra-doc-links // // ignore-tidy-linelength // // normalize-stdout-test: "( +name default meaning\n +---- ------- -------\n)?( *[[:word:]:-]+ (allow |warn |deny |forbid ) [^\n]+\n)+" -> " $$NAMES $$LEVELS $$MEANINGS" // normalize-stdout-test: " +name sub-lints\n +---- ---------\n( *[[:word:]:-]+ [^\n]+\n)+" -> " $$NAMES $$SUB_LINTS" -// normalize-stdout-test: " +rustdoc::all( (rustdoc::[[:word:]-]+, )*rustdoc::[[:word:]-]+)?" -> " rustdoc::all $$GROUPS$4" diff --git a/src/test/rustdoc-ui/issue-83883-describe-lints.stdout b/src/test/rustdoc-ui/issue-83883-describe-lints.stdout index 5cb7ecb649a..bbf66a31583 100644 --- a/src/test/rustdoc-ui/issue-83883-describe-lints.stdout +++ b/src/test/rustdoc-ui/issue-83883-describe-lints.stdout @@ -1,193 +1,24 @@ - -W allow-features=val -- only allow the listed language features to be enabled in code (space separated) - -W always-encode-mir=val -- encode MIR of all functions into the crate metadata (default: no) - -W assume-incomplete-release=val -- make cfg(version) treat the current version as incomplete (default: no) - -W asm-comments=val -- generate comments into the assembly (may change behavior) (default: no) - -W assert-incr-state=val -- assert that the incremental cache is in given state: either `loaded` or `not-loaded`. - -W binary-dep-depinfo=val -- include artifacts (sysroot, crate dependencies) used during compilation in dep-info (default: no) - -W branch-protection=val -- set options for branch target identification and pointer authentication on AArch64 - -W cf-protection=val -- instrument control-flow architecture protection - -W cgu-partitioning-strategy=val -- the codegen unit partitioning strategy to use - -W chalk=val -- enable the experimental Chalk-based trait solving engine - -W codegen-backend=val -- the backend to use - -W combine-cgu=val -- combine CGUs into a single one - -W crate-attr=val -- inject the given attribute in the crate - -W debug-info-for-profiling=val -- emit discriminators and other data necessary for AutoFDO - -W debug-macros=val -- emit line numbers debug info inside macros (default: no) - -W deduplicate-diagnostics=val -- deduplicate identical diagnostics (default: yes) - -W dep-info-omit-d-target=val -- in dep-info output, omit targets for tracking dependencies of the dep-info files themselves (default: no) - -W dep-tasks=val -- print tasks that execute and the color their dep node gets (requires debug build) (default: no) - -W dlltool=val -- import library generation tool (windows-gnu only) - -W dont-buffer-diagnostics=val -- emit diagnostics rather than buffering (breaks NLL error downgrading, sorting) (default: no) - -W drop-tracking=val -- enables drop tracking in generators (default: no) - -W dual-proc-macros=val -- load proc macros for both target and host, but only link to the target (default: no) - -W dump-dep-graph=val -- dump the dependency graph to $RUST_DEP_GRAPH (default: /tmp/dep_graph.gv) (default: no) - -W dump-mir=val -- dump MIR state to file. - `val` is used to select which passes and functions to dump. For example: - `all` matches all passes and functions, - `foo` matches all passes for functions whose name contains 'foo', - `foo & ConstProp` only the 'ConstProp' pass for function names containing 'foo', - `foo | bar` all passes for function names containing 'foo' or 'bar'. - -W dump-mir-dataflow=val -- in addition to `.mir` files, create graphviz `.dot` files with dataflow results (default: no) - -W dump-mir-dir=val -- the directory the MIR is dumped into (default: `mir_dump`) - -W dump-mir-exclude-pass-number=val -- exclude the pass number when dumping MIR (used in tests) (default: no) - -W dump-mir-graphviz=val -- in addition to `.mir` files, create graphviz `.dot` files (and with `-Z instrument-coverage`, also create a `.dot` file for the MIR-derived coverage graph) (default: no) - -W dump-mir-spanview=val -- in addition to `.mir` files, create `.html` files to view spans for all `statement`s (including terminators), only `terminator` spans, or computed `block` spans (one span encompassing a block's terminator and all statements). If `-Z instrument-coverage` is also enabled, create an additional `.html` file showing the computed coverage spans. - -W emit-stack-sizes=val -- emit a section containing stack size metadata (default: no) - -W fewer-names=val -- reduce memory use by retaining fewer names within compilation artifacts (LLVM-IR) (default: no) - -W force-unstable-if-unmarked=val -- force all crates to be `rustc_private` unstable (default: no) - -W fuel=val -- set the optimization fuel quota for a crate - -W function-sections=val -- whether each function should go in its own section - -W future-incompat-test=val -- forces all lints to be future incompatible, used for internal testing (default: no) - -W gcc-ld=val -- implementation of ld used by cc - -W graphviz-dark-mode=val -- use dark-themed colors in graphviz output (default: no) - -W graphviz-font=val -- use the given `fontname` in graphviz output; can be overridden by setting environment variable `RUSTC_GRAPHVIZ_FONT` (default: `Courier, monospace`) - -W hir-stats=val -- print some statistics about AST and HIR (default: no) - -W human-readable-cgu-names=val -- generate human-readable, predictable names for codegen units (default: no) - -W identify-regions=val -- display unnamed regions as `'<id>`, using a non-ident unique id (default: no) - -W incremental-ignore-spans=val -- ignore spans during ICH computation -- used for testing (default: no) - -W incremental-info=val -- print high-level information about incremental reuse (or the lack thereof) (default: no) - -W incremental-relative-spans=val -- hash spans relative to their parent item for incr. comp. (default: no) - -W incremental-verify-ich=val -- verify incr. comp. hashes of green query instances (default: no) - -W inline-mir=val -- enable MIR inlining (default: no) - -W inline-mir-threshold=val -- a default MIR inlining threshold (default: 50) - -W inline-mir-hint-threshold=val -- inlining threshold for functions with inline hint (default: 100) - -W inline-in-all-cgus=val -- control whether `#[inline]` functions are in all CGUs - -W input-stats=val -- gather statistics about the input (default: no) - -W instrument-coverage=val -- instrument the generated code to support LLVM source-based code coverage reports (note, the compiler build config must include `profiler = true`); implies `-C symbol-mangling-version=v0`. Optional values are: - `=all` (implicit value) - `=except-unused-generics` - `=except-unused-functions` - `=off` (default) - -W instrument-mcount=val -- insert function instrument code for mcount-based tracing (default: no) - -W keep-hygiene-data=val -- keep hygiene data after analysis (default: no) - -W link-native-libraries=val -- link native libraries in the linker invocation (default: yes) - -W link-only=val -- link the `.rlink` file generated by `-Z no-link` (default: no) - -W llvm-plugins=val -- a list LLVM plugins to enable (space separated) - -W llvm-time-trace=val -- generate JSON tracing data file from LLVM data (default: no) - -W location-detail=val -- comma separated list of location details to be tracked when using caller_location valid options are `file`, `line`, and `column` (default: all) - -W ls=val -- list the symbols defined by a library crate (default: no) - -W macro-backtrace=val -- show macro backtraces (default: no) - -W merge-functions=val -- control the operation of the MergeFunctions LLVM pass, taking the same values as the target option of the same name - -W meta-stats=val -- gather metadata statistics (default: no) - -W mir-emit-retag=val -- emit Retagging MIR statements, interpreted e.g., by miri; implies -Zmir-opt-level=0 (default: no) - -W mir-enable-passes=val -- use like `-Zmir-enable-passes=+DestProp,-InstCombine`. Forces the specified passes to be enabled, overriding all other checks. Passes that are not specified are enabled or disabled by other flags as usual. - -W mir-opt-level=val -- MIR optimization level (0-4; default: 1 in non optimized builds and 2 in optimized builds) - -W move-size-limit=val -- the size at which the `large_assignments` lint starts to be emitted - -W mutable-noalias=val -- emit noalias metadata for mutable references (default: yes) - -W new-llvm-pass-manager=val -- use new LLVM pass manager (default: no) - -W nll-facts=val -- dump facts from NLL analysis into side files (default: no) - -W nll-facts-dir=val -- the directory the NLL facts are dumped into (default: `nll-facts`) - -W no-analysis=val -- parse and expand the source, but run no analysis - -W no-codegen=val -- run all passes except codegen; no output - -W no-generate-arange-section=val -- omit DWARF address ranges that give faster lookups - -W no-interleave-lints=val -- execute lints separately; allows benchmarking individual lints - -W no-leak-check=val -- disable the 'leak check' for subtyping; unsound, but useful for tests - -W no-link=val -- compile without linking - -W no-parallel-llvm=val -- run LLVM in non-parallel mode (while keeping codegen-units and ThinLTO) - -W no-unique-section-names=val -- do not use unique names for text and data sections when -Z function-sections is used - -W no-profiler-runtime=val -- prevent automatic injection of the profiler_builtins crate - -W normalize-docs=val -- normalize associated items in rustdoc when generating documentation - -W oom=val -- panic strategy for out-of-memory handling - -W osx-rpath-install-name=val -- pass `-install_name @rpath/...` to the macOS linker (default: no) - -W panic-abort-tests=val -- support compiling tests with panic=abort (default: no) - -W panic-in-drop=val -- panic strategy for panics in drops - -W parse-only=val -- parse only; do not compile, assemble, or link (default: no) - -W perf-stats=val -- print some performance-related statistics (default: no) - -W pick-stable-methods-before-any-unstable=val -- try to pick stable methods first before picking any unstable methods (default: yes) - -W plt=val -- whether to use the PLT when calling into shared libraries; - only has effect for PIC code on systems with ELF binaries - (default: PLT is disabled if full relro is enabled) - -W polonius=val -- enable polonius-based borrow-checker (default: no) - -W polymorphize=val -- perform polymorphization analysis - -W pre-link-arg=val -- a single extra argument to prepend the linker invocation (can be used several times) - -W pre-link-args=val -- extra arguments to prepend to the linker invocation (space separated) - -W precise-enum-drop-elaboration=val -- use a more precise version of drop elaboration for matches on enums (default: yes). This results in better codegen, but has caused miscompilations on some tier 2 platforms. See #77382 and #74551. - -W print-fuel=val -- make rustc print the total optimization fuel used by a crate - -W print-llvm-passes=val -- print the LLVM optimization passes being run (default: no) - -W print-mono-items=val -- print the result of the monomorphization collection pass - -W print-type-sizes=val -- print layout information for each type encountered (default: no) - -W proc-macro-backtrace=val -- show backtraces for panics during proc-macro execution (default: no) - -W profile=val -- insert profiling code (default: no) - -W profile-closures=val -- profile size of closures - -W profile-emit=val -- file path to emit profiling data at runtime when using 'profile' (default based on relative source path) - -W profiler-runtime=val -- name of the profiler runtime crate to automatically inject (default: `profiler_builtins`) - -W profile-sample-use=val -- use the given `.prof` file for sampled profile-guided optimization (also known as AutoFDO) - -W query-dep-graph=val -- enable queries of the dependency graph for regression testing (default: no) - -W randomize-layout=val -- randomize the layout of types (default: no) - -W layout-seed=val -- seed layout randomization - -W relax-elf-relocations=val -- whether ELF relocations can be relaxed - -W relro-level=val -- choose which RELRO level to use - -W remap-cwd-prefix=val -- remap paths under the current working directory to this path prefix - -W simulate-remapped-rust-src-base=val -- simulate the effect of remap-debuginfo = true at bootstrapping by remapping path to rust's source base directory. only meant for testing purposes - -W report-delayed-bugs=val -- immediately print bugs registered with `delay_span_bug` (default: no) - -W sanitizer=val -- use a sanitizer - -W sanitizer-memory-track-origins=val -- enable origins tracking in MemorySanitizer - -W sanitizer-recover=val -- enable recovery for selected sanitizers - -W saturating-float-casts=val -- make float->int casts UB-free: numbers outside the integer type's range are clipped to the max/min integer respectively, and NaN is mapped to 0 (default: yes) - -W save-analysis=val -- write syntax and type analysis (in JSON format) information, in addition to normal output (default: no) - -W self-profile=val -- run the self profiler and output the raw event data - -W self-profile-events=val -- specify the events recorded by the self profiler; - for example: `-Z self-profile-events=default,query-keys` - all options: none, all, default, generic-activity, query-provider, query-cache-hit - query-blocked, incr-cache-load, incr-result-hashing, query-keys, function-args, args, llvm, artifact-sizes - -W self-profile-counter=val -- counter used by the self profiler (default: `wall-time`), one of: - `wall-time` (monotonic clock, i.e. `std::time::Instant`) - `instructions:u` (retired instructions, userspace-only) - `instructions-minus-irqs:u` (subtracting hardware interrupt counts for extra accuracy) - -W share-generics=val -- make the current crate share its generic instantiations - -W show-span=val -- show spans for compiler debugging (expr|pat|ty) - -W span-debug=val -- forward proc_macro::Span's `Debug` impl to `Span` - -W span-free-formats=val -- exclude spans when debug-printing compiler state (default: no) - -W src-hash-algorithm=val -- hash algorithm of source files in debug info (`md5`, `sha1`, or `sha256`) - -W stack-protector=val -- control stack smash protection strategy (`rustc --print stack-protector-strategies` for details) - -W strict-init-checks=val -- control if mem::uninitialized and mem::zeroed panic on more UB - -W strip=val -- tell the linker which information to strip (`none` (default), `debuginfo` or `symbols`) - -W split-dwarf-kind=val -- split dwarf variant (only if -Csplit-debuginfo is enabled and on relevant platform) - (default: `split`) - `split`: sections which do not require relocation are written into a DWARF object (`.dwo`) - file which is ignored by the linker - `single`: sections which do not require relocation are written into object file but ignored - by the linker - -W split-dwarf-inlining=val -- provide minimal debug info in the object/executable to facilitate online symbolication/stack traces in the absence of .dwo/.dwp files when using Split DWARF - -W symbol-mangling-version=val -- which mangling version to use for symbol names ('legacy' (default) or 'v0') - -W teach=val -- show extended diagnostic help (default: no) - -W temps-dir=val -- the directory the intermediate files are written to - -W terminal-width=val -- set the current terminal width - -W translate-lang=val -- language identifier for diagnostic output - -W translate-additional-ftl=val -- additional fluent translation to preferentially use (for testing translation) - -W translate-directionality-markers=val -- emit directionality isolation markers in translated diagnostics - -W tune-cpu=val -- select processor to schedule for (`rustc --print target-cpus` for details) - -W thinlto=val -- enable ThinLTO when possible - -W thir-unsafeck=val -- use the THIR unsafety checker (default: no) - -W threads=val -- use a thread pool with N threads - -W time=val -- measure time of rustc processes (default: no) - -W time-llvm-passes=val -- measure time of each LLVM pass (default: no) - -W time-passes=val -- measure time of each rustc pass (default: no) - -W tls-model=val -- choose the TLS model to use (`rustc --print tls-models` for details) - -W trace-macros=val -- for every macro invocation, print its name and arguments (default: no) - -W translate-remapped-path-to-local-path=val -- translate remapped paths into local paths when possible (default: yes) - -W trap-unreachable=val -- generate trap instructions for unreachable intrinsics (default: use target setting, usually yes) - -W treat-err-as-bug=val -- treat error number `val` that occurs as bug - -W trim-diagnostic-paths=val -- in diagnostics, use heuristics to shorten paths referring to items - -W ui-testing=val -- emit compiler diagnostics in a form suitable for UI testing (default: no) - -W uninit-const-chunk-threshold=val -- allow generating const initializers with mixed init/uninit chunks, and set the maximum number of chunks for which this is allowed (default: 16) - -W unleash-the-miri-inside-of-you=val -- take the brakes off const evaluation. NOTE: this is unsound (default: no) - -W unpretty=val -- present the input source, unstable (and less-pretty) variants; - `normal`, `identified`, - `expanded`, `expanded,identified`, - `expanded,hygiene` (with internal representations), - `ast-tree` (raw AST before expansion), - `ast-tree,expanded` (raw AST after expansion), - `hir` (the HIR), `hir,identified`, - `hir,typed` (HIR with types for each node), - `hir-tree` (dump the raw HIR), - `mir` (the MIR), or `mir-cfg` (graphviz formatted MIR) - -W unsound-mir-opts=val -- enable unsound and buggy MIR optimizations (default: no) - -W unstable-options=val -- adds unstable command line options to rustc interface (default: no) - -W use-ctors-section=val -- use legacy .ctors section for initializers rather than .init_array - -W validate-mir=val -- validate MIR after each transformation - -W verbose=val -- in general, enable more debug printouts (default: no) - -W verify-llvm-ir=val -- verify LLVM IR (default: no) - -W virtual-function-elimination=val -- enables dead virtual function elimination optimization. Requires `-Clto[=[fat,yes]]` - -W wasi-exec-model=val -- whether to build a wasi command or reactor +Available lint options: + -W <foo> Warn about <foo> + -A <foo> Allow <foo> + -D <foo> Deny <foo> + -F <foo> Forbid <foo> (deny <foo> and all attempts to override) + + +Lint checks provided by rustc: + + $NAMES $LEVELS $MEANINGS + +Lint groups provided by rustc: + + $NAMES $SUB_LINTS + +Lint checks provided by plugins loaded by this crate: + + $NAMES $LEVELS $MEANINGS + +Lint groups provided by plugins loaded by this crate: + + $NAMES $SUB_LINTS + diff --git a/src/test/rustdoc/assoc-consts.rs b/src/test/rustdoc/assoc-consts.rs index 0ac6dc763df..a79e93145ba 100644 --- a/src/test/rustdoc/assoc-consts.rs +++ b/src/test/rustdoc/assoc-consts.rs @@ -27,6 +27,10 @@ impl Bar { // @has assoc_consts/struct.Bar.html '//*[@id="associatedconstant.BAR"]' \ // 'const BAR: usize' pub const BAR: usize = 3; + + // @has - '//*[@id="associatedconstant.BAR_ESCAPED"]' \ + // "const BAR_ESCAPED: &'static str = \"<em>markup</em>\"" + pub const BAR_ESCAPED: &'static str = "<em>markup</em>"; } pub struct Baz<'a, U: 'a, T>(T, &'a [U]); diff --git a/src/test/rustdoc/assoc-types.rs b/src/test/rustdoc/assoc-types.rs index d9e4ffab1c7..a9e5b8d0019 100644 --- a/src/test/rustdoc/assoc-types.rs +++ b/src/test/rustdoc/assoc-types.rs @@ -2,7 +2,7 @@ // @has assoc_types/trait.Index.html pub trait Index<I: ?Sized> { - // @has - '//*[@id="associatedtype.Output"]//h4[@class="code-header"]' 'type Output: ?Sized' + // @has - '//*[@id="associatedtype.Output"]//h4[@class="code-header"]' 'type Output: ?Sized' type Output: ?Sized; // @has - '//*[@id="tymethod.index"]//h4[@class="code-header"]' \ // "fn index<'a>(&'a self, index: I) -> &'a Self::Output" diff --git a/src/test/rustdoc/const-value-display.rs b/src/test/rustdoc/const-value-display.rs index 0ae52592b64..5b2f3c48d57 100644 --- a/src/test/rustdoc/const-value-display.rs +++ b/src/test/rustdoc/const-value-display.rs @@ -1,9 +1,9 @@ #![crate_name = "foo"] // @has 'foo/constant.HOUR_IN_SECONDS.html' -// @has - '//*[@class="docblock item-decl"]//code' 'pub const HOUR_IN_SECONDS: u64 = 60 * 60; // 3_600u64' +// @has - '//*[@class="docblock item-decl"]//code' 'pub const HOUR_IN_SECONDS: u64 = _; // 3_600u64' pub const HOUR_IN_SECONDS: u64 = 60 * 60; // @has 'foo/constant.NEGATIVE.html' -// @has - '//*[@class="docblock item-decl"]//code' 'pub const NEGATIVE: i64 = -60 * 60; // -3_600i64' +// @has - '//*[@class="docblock item-decl"]//code' 'pub const NEGATIVE: i64 = _; // -3_600i64' pub const NEGATIVE: i64 = -60 * 60; diff --git a/src/test/rustdoc/decl-trailing-whitespace.declaration.html b/src/test/rustdoc/decl-trailing-whitespace.declaration.html new file mode 100644 index 00000000000..e60caaeff38 --- /dev/null +++ b/src/test/rustdoc/decl-trailing-whitespace.declaration.html @@ -0,0 +1,7 @@ +<code>pub trait Write { + fn <a href="#tymethod.poll_write" class="fnname">poll_write</a>(<br />        self: <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>>,<br />        cx: &mut <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>>,<br />        buf: &mut [<a class="primitive" href="{{channel}}/std/primitive.usize.html">usize</a>]<br />    ) -> <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="enum" href="{{channel}}/core/result/enum.Result.html" title="enum core::result::Result">Result</a><<a class="primitive" href="{{channel}}/std/primitive.usize.html">usize</a>, <a class="struct" href="struct.Error.html" title="struct foo::Error">Error</a>>>; +<span class="item-spacer" /> fn <a href="#tymethod.poll_flush" class="fnname">poll_flush</a>(<br />        self: <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>>,<br />        cx: &mut <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>><br />    ) -> <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="enum" href="{{channel}}/core/result/enum.Result.html" title="enum core::result::Result">Result</a><<a class="primitive" href="{{channel}}/std/primitive.unit.html">()</a>, <a class="struct" href="struct.Error.html" title="struct foo::Error">Error</a>>>; +<span class="item-spacer" /> fn <a href="#tymethod.poll_close" class="fnname">poll_close</a>(<br />        self: <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>>,<br />        cx: &mut <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>><br />    ) -> <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="enum" href="{{channel}}/core/result/enum.Result.html" title="enum core::result::Result">Result</a><<a class="primitive" href="{{channel}}/std/primitive.unit.html">()</a>, <a class="struct" href="struct.Error.html" title="struct foo::Error">Error</a>>>; + + fn <a href="#method.poll_write_vectored" class="fnname">poll_write_vectored</a>(<br />        self: <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>>,<br />        cx: &mut <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>>,<br />        bufs: &[<a class="primitive" href="{{channel}}/std/primitive.usize.html">usize</a>]<br />    ) -> <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="enum" href="{{channel}}/core/result/enum.Result.html" title="enum core::result::Result">Result</a><<a class="primitive" href="{{channel}}/std/primitive.usize.html">usize</a>, <a class="struct" href="struct.Error.html" title="struct foo::Error">Error</a>>> { ... } +}</code> diff --git a/src/test/rustdoc/decl-trailing-whitespace.rs b/src/test/rustdoc/decl-trailing-whitespace.rs new file mode 100644 index 00000000000..46a2307abef --- /dev/null +++ b/src/test/rustdoc/decl-trailing-whitespace.rs @@ -0,0 +1,30 @@ +// Regression test for <https://github.com/rust-lang/rust/issues/98803>. + +#![crate_name = "foo"] + +pub struct Error; + +// @has 'foo/trait.Write.html' + +pub trait Write { + // @snapshot 'declaration' - '//*[@class="docblock item-decl"]//code' + fn poll_write( + self: Option<String>, + cx: &mut Option<String>, + buf: &mut [usize] + ) -> Option<Result<usize, Error>>; + fn poll_flush( + self: Option<String>, + cx: &mut Option<String> + ) -> Option<Result<(), Error>>; + fn poll_close( + self: Option<String>, + cx: &mut Option<String>, + ) -> Option<Result<(), Error>>; + + fn poll_write_vectored( + self: Option<String>, + cx: &mut Option<String>, + bufs: &[usize] + ) -> Option<Result<usize, Error>> {} +} diff --git a/src/test/rustdoc/hide-complex-unevaluated-const-arguments.rs b/src/test/rustdoc/hide-complex-unevaluated-const-arguments.rs new file mode 100644 index 00000000000..644a6e1cf33 --- /dev/null +++ b/src/test/rustdoc/hide-complex-unevaluated-const-arguments.rs @@ -0,0 +1,82 @@ +// Test that certain unevaluated constant expression arguments that are +// deemed too verbose or complex and that may leak private or +// `doc(hidden)` struct fields are not displayed in the documentation. +// +// Read the documentation of `rustdoc::clean::utils::print_const_expr` +// for further details. +#![feature(const_trait_impl, generic_const_exprs)] +#![allow(incomplete_features)] + +// @has hide_complex_unevaluated_const_arguments/trait.Stage.html +pub trait Stage { + // A helper constant that prevents const expressions containing it + // from getting fully evaluated since it doesn't have a body and + // thus is non-reducible. This allows us to specifically test the + // pretty-printing of *unevaluated* consts. + const ABSTRACT: usize; + + // Currently considered "overly complex" by the `generic_const_exprs` + // feature. If / once this expression kind gets supported, this + // unevaluated const expression could leak the private struct field. + // + // FIXME: Once the line below compiles, make this a test that + // ensures that the private field is not printed. + // + //const ARRAY0: [u8; Struct { private: () } + Self::ABSTRACT]; + + // This assoc. const could leak the private assoc. function `Struct::new`. + // Ensure that this does not happen. + // + // @has - '//*[@id="associatedconstant.ARRAY1"]' \ + // 'const ARRAY1: [u8; { _ }]' + const ARRAY1: [u8; Struct::new(/* ... */) + Self::ABSTRACT * 1_000]; + + // @has - '//*[@id="associatedconstant.VERBOSE"]' \ + // 'const VERBOSE: [u16; { _ }]' + const VERBOSE: [u16; compute("thing", 9 + 9) * Self::ABSTRACT]; + + // Check that we do not leak the private struct field contained within + // the path. The output could definitely be improved upon + // (e.g. printing sth. akin to `<Self as Helper<{ _ }>>::OUT`) but + // right now “safe is safe”. + // + // @has - '//*[@id="associatedconstant.PATH"]' \ + // 'const PATH: usize = _' + const PATH: usize = <Self as Helper<{ Struct { private: () } }>>::OUT; +} + +const fn compute(input: &str, extra: usize) -> usize { + input.len() + extra +} + +pub trait Helper<const S: Struct> { + const OUT: usize; +} + +impl<const S: Struct, St: Stage + ?Sized> Helper<S> for St { + const OUT: usize = St::ABSTRACT; +} + +// Currently in rustdoc, const arguments are not evaluated in this position +// and therefore they fall under the realm of `print_const_expr`. +// If rustdoc gets patched to evaluate const arguments, it is fine to replace +// this test as long as one can ensure that private fields are not leaked! +// +// @has hide_complex_unevaluated_const_arguments/trait.Sub.html \ +// '//*[@class="rust trait"]' \ +// 'pub trait Sub: Sup<{ _ }, { _ }> { }' +pub trait Sub: Sup<{ 90 * 20 * 4 }, { Struct { private: () } }> {} + +pub trait Sup<const N: usize, const S: Struct> {} + +pub struct Struct { private: () } + +impl Struct { + const fn new() -> Self { Self { private: () } } +} + +impl const std::ops::Add<usize> for Struct { + type Output = usize; + + fn add(self, _: usize) -> usize { 0 } +} diff --git a/src/test/rustdoc/hide-complex-unevaluated-consts.rs b/src/test/rustdoc/hide-complex-unevaluated-consts.rs new file mode 100644 index 00000000000..ba623246a01 --- /dev/null +++ b/src/test/rustdoc/hide-complex-unevaluated-consts.rs @@ -0,0 +1,71 @@ +// Regression test for issue #97933. +// +// Test that certain unevaluated constant expressions that are +// deemed too verbose or complex and that may leak private or +// `doc(hidden)` struct fields are not displayed in the documentation. +// +// Read the documentation of `rustdoc::clean::utils::print_const_expr` +// for further details. + +// @has hide_complex_unevaluated_consts/trait.Container.html +pub trait Container { + // A helper constant that prevents const expressions containing it + // from getting fully evaluated since it doesn't have a body and + // thus is non-reducible. This allows us to specifically test the + // pretty-printing of *unevaluated* consts. + const ABSTRACT: i32; + + // Ensure that the private field does not get leaked: + // + // @has - '//*[@id="associatedconstant.STRUCT0"]' \ + // 'const STRUCT0: Struct = _' + const STRUCT0: Struct = Struct { private: () }; + + // @has - '//*[@id="associatedconstant.STRUCT1"]' \ + // 'const STRUCT1: (Struct,) = _' + const STRUCT1: (Struct,) = (Struct{private: /**/()},); + + // Although the struct field is public here, check that it is not + // displayed. In a future version of rustdoc, we definitely want to + // show it. However for the time being, the printing logic is a bit + // conservative. + // + // @has - '//*[@id="associatedconstant.STRUCT2"]' \ + // 'const STRUCT2: Record = _' + const STRUCT2: Record = Record { public: 5 }; + + // Test that we do not show the incredibly verbose match expr: + // + // @has - '//*[@id="associatedconstant.MATCH0"]' \ + // 'const MATCH0: i32 = _' + const MATCH0: i32 = match 234 { + 0 => 1, + _ => Self::ABSTRACT, + }; + + // @has - '//*[@id="associatedconstant.MATCH1"]' \ + // 'const MATCH1: bool = _' + const MATCH1: bool = match Self::ABSTRACT { + _ => true, + }; + + // Check that we hide complex (arithmetic) operations. + // In this case, it is a bit unfortunate since the expression + // is not *that* verbose and it might be quite useful to the reader. + // + // However in general, the expression might be quite large and + // contain match expressions and structs with private fields. + // We would need to recurse over the whole expression and even more + // importantly respect operator precedence when pretty-printing + // the potentially partially censored expression. + // For now, the implementation is quite simple and the choices + // rather conservative. + // + // @has - '//*[@id="associatedconstant.ARITH_OPS"]' \ + // 'const ARITH_OPS: i32 = _' + const ARITH_OPS: i32 = Self::ABSTRACT * 2 + 1; +} + +pub struct Struct { private: () } + +pub struct Record { pub public: i32 } diff --git a/src/test/rustdoc/show-const-contents.rs b/src/test/rustdoc/show-const-contents.rs index f5a356bcae6..48b60885974 100644 --- a/src/test/rustdoc/show-const-contents.rs +++ b/src/test/rustdoc/show-const-contents.rs @@ -21,7 +21,7 @@ pub const CONST_NEG_I32: i32 = -42; // @!has show_const_contents/constant.CONST_EQ_TO_VALUE_I32.html '// 42i32' pub const CONST_EQ_TO_VALUE_I32: i32 = 42i32; -// @has show_const_contents/constant.CONST_CALC_I32.html '= 42 + 1; // 43i32' +// @has show_const_contents/constant.CONST_CALC_I32.html '= _; // 43i32' pub const CONST_CALC_I32: i32 = 42 + 1; // @!has show_const_contents/constant.CONST_REF_I32.html '= &42;' diff --git a/src/test/ui/abi/rustcall-generic.rs b/src/test/ui/abi/rustcall-generic.rs index 2fa41a7e35a..411c98e1031 100644 --- a/src/test/ui/abi/rustcall-generic.rs +++ b/src/test/ui/abi/rustcall-generic.rs @@ -1,4 +1,7 @@ +// revisions: normal opt // check-pass +//[opt] compile-flags: -Zmir-opt-level=3 + #![feature(unboxed_closures)] extern "rust-call" fn foo<T>(_: T) {} diff --git a/src/test/ui/deriving/deriving-all-codegen.rs b/src/test/ui/deriving/deriving-all-codegen.rs index 2f6ef74ac49..028ed9c2305 100644 --- a/src/test/ui/deriving/deriving-all-codegen.rs +++ b/src/test/ui/deriving/deriving-all-codegen.rs @@ -28,12 +28,17 @@ struct Point { y: u32, } -// A long struct. +// A large struct. #[derive(Clone, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)] struct Big { b1: u32, b2: u32, b3: u32, b4: u32, b5: u32, b6: u32, b7: u32, b8:u32, } +// A packed tuple struct. +#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)] +#[repr(packed)] +struct Packed(u32); + // A C-like, fieldless enum. #[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)] enum Fieldless { diff --git a/src/test/ui/deriving/deriving-all-codegen.stdout b/src/test/ui/deriving/deriving-all-codegen.stdout index faa5a3c3ddf..c24ed4237b8 100644 --- a/src/test/ui/deriving/deriving-all-codegen.stdout +++ b/src/test/ui/deriving/deriving-all-codegen.stdout @@ -37,7 +37,7 @@ impl ::core::marker::Copy for Empty { } #[allow(unused_qualifications)] impl ::core::fmt::Debug for Empty { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - match *self { Self => ::core::fmt::Formatter::write_str(f, "Empty"), } + ::core::fmt::Formatter::write_str(f, "Empty") } } #[automatically_derived] @@ -49,18 +49,14 @@ impl ::core::default::Default for Empty { #[automatically_derived] #[allow(unused_qualifications)] impl ::core::hash::Hash for Empty { - fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () { - match *self { Self => {} } - } + fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () { {} } } impl ::core::marker::StructuralPartialEq for Empty {} #[automatically_derived] #[allow(unused_qualifications)] impl ::core::cmp::PartialEq for Empty { #[inline] - fn eq(&self, other: &Empty) -> bool { - match *other { Self => match *self { Self => true, }, } - } + fn eq(&self, other: &Empty) -> bool { true } } impl ::core::marker::StructuralEq for Empty {} #[automatically_derived] @@ -77,13 +73,7 @@ impl ::core::cmp::PartialOrd for Empty { #[inline] fn partial_cmp(&self, other: &Empty) -> ::core::option::Option<::core::cmp::Ordering> { - match *other { - Self => - match *self { - Self => - ::core::option::Option::Some(::core::cmp::Ordering::Equal), - }, - } + ::core::option::Option::Some(::core::cmp::Ordering::Equal) } } #[automatically_derived] @@ -91,9 +81,7 @@ impl ::core::cmp::PartialOrd for Empty { impl ::core::cmp::Ord for Empty { #[inline] fn cmp(&self, other: &Empty) -> ::core::cmp::Ordering { - match *other { - Self => match *self { Self => ::core::cmp::Ordering::Equal, }, - } + ::core::cmp::Ordering::Equal } } @@ -121,11 +109,8 @@ impl ::core::marker::Copy for Point { } #[allow(unused_qualifications)] impl ::core::fmt::Debug for Point { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - match *self { - Self { x: ref __self_0_0, y: ref __self_0_1 } => - ::core::fmt::Formatter::debug_struct_field2_finish(f, "Point", - "x", &&(*__self_0_0), "y", &&(*__self_0_1)), - } + ::core::fmt::Formatter::debug_struct_field2_finish(f, "Point", "x", + &&self.x, "y", &&self.y) } } #[automatically_derived] @@ -143,11 +128,9 @@ impl ::core::default::Default for Point { #[allow(unused_qualifications)] impl ::core::hash::Hash for Point { fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () { - match *self { - Self { x: ref __self_0_0, y: ref __self_0_1 } => { - ::core::hash::Hash::hash(&(*__self_0_0), state); - ::core::hash::Hash::hash(&(*__self_0_1), state) - } + { + ::core::hash::Hash::hash(&self.x, state); + ::core::hash::Hash::hash(&self.y, state) } } } @@ -157,25 +140,11 @@ impl ::core::marker::StructuralPartialEq for Point {} impl ::core::cmp::PartialEq for Point { #[inline] fn eq(&self, other: &Point) -> bool { - match *other { - Self { x: ref __self_1_0, y: ref __self_1_1 } => - match *self { - Self { x: ref __self_0_0, y: ref __self_0_1 } => - (*__self_0_0) == (*__self_1_0) && - (*__self_0_1) == (*__self_1_1), - }, - } + self.x == other.x && self.y == other.y } #[inline] fn ne(&self, other: &Point) -> bool { - match *other { - Self { x: ref __self_1_0, y: ref __self_1_1 } => - match *self { - Self { x: ref __self_0_0, y: ref __self_0_1 } => - (*__self_0_0) != (*__self_1_0) || - (*__self_0_1) != (*__self_1_1), - }, - } + self.x != other.x || self.y != other.y } } impl ::core::marker::StructuralEq for Point {} @@ -198,24 +167,16 @@ impl ::core::cmp::PartialOrd for Point { #[inline] fn partial_cmp(&self, other: &Point) -> ::core::option::Option<::core::cmp::Ordering> { - match *other { - Self { x: ref __self_1_0, y: ref __self_1_1 } => - match *self { - Self { x: ref __self_0_0, y: ref __self_0_1 } => - match ::core::cmp::PartialOrd::partial_cmp(&(*__self_0_0), - &(*__self_1_0)) { - ::core::option::Option::Some(::core::cmp::Ordering::Equal) - => - match ::core::cmp::PartialOrd::partial_cmp(&(*__self_0_1), - &(*__self_1_1)) { - ::core::option::Option::Some(::core::cmp::Ordering::Equal) - => - ::core::option::Option::Some(::core::cmp::Ordering::Equal), - cmp => cmp, - }, - cmp => cmp, - }, + match ::core::cmp::PartialOrd::partial_cmp(&self.x, &other.x) { + ::core::option::Option::Some(::core::cmp::Ordering::Equal) => + match ::core::cmp::PartialOrd::partial_cmp(&self.y, &other.y) + { + ::core::option::Option::Some(::core::cmp::Ordering::Equal) + => + ::core::option::Option::Some(::core::cmp::Ordering::Equal), + cmp => cmp, }, + cmp => cmp, } } } @@ -224,27 +185,19 @@ impl ::core::cmp::PartialOrd for Point { impl ::core::cmp::Ord for Point { #[inline] fn cmp(&self, other: &Point) -> ::core::cmp::Ordering { - match *other { - Self { x: ref __self_1_0, y: ref __self_1_1 } => - match *self { - Self { x: ref __self_0_0, y: ref __self_0_1 } => - match ::core::cmp::Ord::cmp(&(*__self_0_0), &(*__self_1_0)) - { - ::core::cmp::Ordering::Equal => - match ::core::cmp::Ord::cmp(&(*__self_0_1), &(*__self_1_1)) - { - ::core::cmp::Ordering::Equal => - ::core::cmp::Ordering::Equal, - cmp => cmp, - }, - cmp => cmp, - }, + match ::core::cmp::Ord::cmp(&self.x, &other.x) { + ::core::cmp::Ordering::Equal => + match ::core::cmp::Ord::cmp(&self.y, &other.y) { + ::core::cmp::Ordering::Equal => + ::core::cmp::Ordering::Equal, + cmp => cmp, }, + cmp => cmp, } } } -// A long struct. +// A large struct. struct Big { b1: u32, b2: u32, @@ -260,26 +213,15 @@ struct Big { impl ::core::clone::Clone for Big { #[inline] fn clone(&self) -> Big { - match *self { - Self { - b1: ref __self_0_0, - b2: ref __self_0_1, - b3: ref __self_0_2, - b4: ref __self_0_3, - b5: ref __self_0_4, - b6: ref __self_0_5, - b7: ref __self_0_6, - b8: ref __self_0_7 } => - Big { - b1: ::core::clone::Clone::clone(&(*__self_0_0)), - b2: ::core::clone::Clone::clone(&(*__self_0_1)), - b3: ::core::clone::Clone::clone(&(*__self_0_2)), - b4: ::core::clone::Clone::clone(&(*__self_0_3)), - b5: ::core::clone::Clone::clone(&(*__self_0_4)), - b6: ::core::clone::Clone::clone(&(*__self_0_5)), - b7: ::core::clone::Clone::clone(&(*__self_0_6)), - b8: ::core::clone::Clone::clone(&(*__self_0_7)), - }, + Big { + b1: ::core::clone::Clone::clone(&self.b1), + b2: ::core::clone::Clone::clone(&self.b2), + b3: ::core::clone::Clone::clone(&self.b3), + b4: ::core::clone::Clone::clone(&self.b4), + b5: ::core::clone::Clone::clone(&self.b5), + b6: ::core::clone::Clone::clone(&self.b6), + b7: ::core::clone::Clone::clone(&self.b7), + b8: ::core::clone::Clone::clone(&self.b8), } } } @@ -287,25 +229,14 @@ impl ::core::clone::Clone for Big { #[allow(unused_qualifications)] impl ::core::fmt::Debug for Big { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - match *self { - Self { - b1: ref __self_0_0, - b2: ref __self_0_1, - b3: ref __self_0_2, - b4: ref __self_0_3, - b5: ref __self_0_4, - b6: ref __self_0_5, - b7: ref __self_0_6, - b8: ref __self_0_7 } => { - let names: &'static _ = - &["b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8"]; - let values: &[&dyn ::core::fmt::Debug] = - &[&&(*__self_0_0), &&(*__self_0_1), &&(*__self_0_2), - &&(*__self_0_3), &&(*__self_0_4), &&(*__self_0_5), - &&(*__self_0_6), &&(*__self_0_7)]; - ::core::fmt::Formatter::debug_struct_fields_finish(f, "Big", - names, values) - } + { + let names: &'static _ = + &["b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8"]; + let values: &[&dyn ::core::fmt::Debug] = + &[&&self.b1, &&self.b2, &&self.b3, &&self.b4, &&self.b5, + &&self.b6, &&self.b7, &&self.b8]; + ::core::fmt::Formatter::debug_struct_fields_finish(f, "Big", + names, values) } } } @@ -330,25 +261,15 @@ impl ::core::default::Default for Big { #[allow(unused_qualifications)] impl ::core::hash::Hash for Big { fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () { - match *self { - Self { - b1: ref __self_0_0, - b2: ref __self_0_1, - b3: ref __self_0_2, - b4: ref __self_0_3, - b5: ref __self_0_4, - b6: ref __self_0_5, - b7: ref __self_0_6, - b8: ref __self_0_7 } => { - ::core::hash::Hash::hash(&(*__self_0_0), state); - ::core::hash::Hash::hash(&(*__self_0_1), state); - ::core::hash::Hash::hash(&(*__self_0_2), state); - ::core::hash::Hash::hash(&(*__self_0_3), state); - ::core::hash::Hash::hash(&(*__self_0_4), state); - ::core::hash::Hash::hash(&(*__self_0_5), state); - ::core::hash::Hash::hash(&(*__self_0_6), state); - ::core::hash::Hash::hash(&(*__self_0_7), state) - } + { + ::core::hash::Hash::hash(&self.b1, state); + ::core::hash::Hash::hash(&self.b2, state); + ::core::hash::Hash::hash(&self.b3, state); + ::core::hash::Hash::hash(&self.b4, state); + ::core::hash::Hash::hash(&self.b5, state); + ::core::hash::Hash::hash(&self.b6, state); + ::core::hash::Hash::hash(&self.b7, state); + ::core::hash::Hash::hash(&self.b8, state) } } } @@ -358,69 +279,17 @@ impl ::core::marker::StructuralPartialEq for Big {} impl ::core::cmp::PartialEq for Big { #[inline] fn eq(&self, other: &Big) -> bool { - match *other { - Self { - b1: ref __self_1_0, - b2: ref __self_1_1, - b3: ref __self_1_2, - b4: ref __self_1_3, - b5: ref __self_1_4, - b6: ref __self_1_5, - b7: ref __self_1_6, - b8: ref __self_1_7 } => - match *self { - Self { - b1: ref __self_0_0, - b2: ref __self_0_1, - b3: ref __self_0_2, - b4: ref __self_0_3, - b5: ref __self_0_4, - b6: ref __self_0_5, - b7: ref __self_0_6, - b8: ref __self_0_7 } => - (*__self_0_0) == (*__self_1_0) && - (*__self_0_1) == (*__self_1_1) && - (*__self_0_2) == (*__self_1_2) && - (*__self_0_3) == (*__self_1_3) && - (*__self_0_4) == (*__self_1_4) && - (*__self_0_5) == (*__self_1_5) && - (*__self_0_6) == (*__self_1_6) && - (*__self_0_7) == (*__self_1_7), - }, - } + self.b1 == other.b1 && self.b2 == other.b2 && self.b3 == other.b3 && + self.b4 == other.b4 && self.b5 == other.b5 && + self.b6 == other.b6 && self.b7 == other.b7 && + self.b8 == other.b8 } #[inline] fn ne(&self, other: &Big) -> bool { - match *other { - Self { - b1: ref __self_1_0, - b2: ref __self_1_1, - b3: ref __self_1_2, - b4: ref __self_1_3, - b5: ref __self_1_4, - b6: ref __self_1_5, - b7: ref __self_1_6, - b8: ref __self_1_7 } => - match *self { - Self { - b1: ref __self_0_0, - b2: ref __self_0_1, - b3: ref __self_0_2, - b4: ref __self_0_3, - b5: ref __self_0_4, - b6: ref __self_0_5, - b7: ref __self_0_6, - b8: ref __self_0_7 } => - (*__self_0_0) != (*__self_1_0) || - (*__self_0_1) != (*__self_1_1) || - (*__self_0_2) != (*__self_1_2) || - (*__self_0_3) != (*__self_1_3) || - (*__self_0_4) != (*__self_1_4) || - (*__self_0_5) != (*__self_1_5) || - (*__self_0_6) != (*__self_1_6) || - (*__self_0_7) != (*__self_1_7), - }, - } + self.b1 != other.b1 || self.b2 != other.b2 || self.b3 != other.b3 || + self.b4 != other.b4 || self.b5 != other.b5 || + self.b6 != other.b6 || self.b7 != other.b7 || + self.b8 != other.b8 } } impl ::core::marker::StructuralEq for Big {} @@ -449,63 +318,37 @@ impl ::core::cmp::PartialOrd for Big { #[inline] fn partial_cmp(&self, other: &Big) -> ::core::option::Option<::core::cmp::Ordering> { - match *other { - Self { - b1: ref __self_1_0, - b2: ref __self_1_1, - b3: ref __self_1_2, - b4: ref __self_1_3, - b5: ref __self_1_4, - b6: ref __self_1_5, - b7: ref __self_1_6, - b8: ref __self_1_7 } => - match *self { - Self { - b1: ref __self_0_0, - b2: ref __self_0_1, - b3: ref __self_0_2, - b4: ref __self_0_3, - b5: ref __self_0_4, - b6: ref __self_0_5, - b7: ref __self_0_6, - b8: ref __self_0_7 } => - match ::core::cmp::PartialOrd::partial_cmp(&(*__self_0_0), - &(*__self_1_0)) { + match ::core::cmp::PartialOrd::partial_cmp(&self.b1, &other.b1) { + ::core::option::Option::Some(::core::cmp::Ordering::Equal) => + match ::core::cmp::PartialOrd::partial_cmp(&self.b2, + &other.b2) { + ::core::option::Option::Some(::core::cmp::Ordering::Equal) + => + match ::core::cmp::PartialOrd::partial_cmp(&self.b3, + &other.b3) { ::core::option::Option::Some(::core::cmp::Ordering::Equal) => - match ::core::cmp::PartialOrd::partial_cmp(&(*__self_0_1), - &(*__self_1_1)) { + match ::core::cmp::PartialOrd::partial_cmp(&self.b4, + &other.b4) { ::core::option::Option::Some(::core::cmp::Ordering::Equal) => - match ::core::cmp::PartialOrd::partial_cmp(&(*__self_0_2), - &(*__self_1_2)) { + match ::core::cmp::PartialOrd::partial_cmp(&self.b5, + &other.b5) { ::core::option::Option::Some(::core::cmp::Ordering::Equal) => - match ::core::cmp::PartialOrd::partial_cmp(&(*__self_0_3), - &(*__self_1_3)) { + match ::core::cmp::PartialOrd::partial_cmp(&self.b6, + &other.b6) { ::core::option::Option::Some(::core::cmp::Ordering::Equal) => - match ::core::cmp::PartialOrd::partial_cmp(&(*__self_0_4), - &(*__self_1_4)) { + match ::core::cmp::PartialOrd::partial_cmp(&self.b7, + &other.b7) { ::core::option::Option::Some(::core::cmp::Ordering::Equal) => - match ::core::cmp::PartialOrd::partial_cmp(&(*__self_0_5), - &(*__self_1_5)) { + match ::core::cmp::PartialOrd::partial_cmp(&self.b8, + &other.b8) { ::core::option::Option::Some(::core::cmp::Ordering::Equal) => - match ::core::cmp::PartialOrd::partial_cmp(&(*__self_0_6), - &(*__self_1_6)) { - ::core::option::Option::Some(::core::cmp::Ordering::Equal) - => - match ::core::cmp::PartialOrd::partial_cmp(&(*__self_0_7), - &(*__self_1_7)) { - ::core::option::Option::Some(::core::cmp::Ordering::Equal) - => - ::core::option::Option::Some(::core::cmp::Ordering::Equal), - cmp => cmp, - }, - cmp => cmp, - }, + ::core::option::Option::Some(::core::cmp::Ordering::Equal), cmp => cmp, }, cmp => cmp, @@ -518,7 +361,9 @@ impl ::core::cmp::PartialOrd for Big { }, cmp => cmp, }, + cmp => cmp, }, + cmp => cmp, } } } @@ -527,55 +372,23 @@ impl ::core::cmp::PartialOrd for Big { impl ::core::cmp::Ord for Big { #[inline] fn cmp(&self, other: &Big) -> ::core::cmp::Ordering { - match *other { - Self { - b1: ref __self_1_0, - b2: ref __self_1_1, - b3: ref __self_1_2, - b4: ref __self_1_3, - b5: ref __self_1_4, - b6: ref __self_1_5, - b7: ref __self_1_6, - b8: ref __self_1_7 } => - match *self { - Self { - b1: ref __self_0_0, - b2: ref __self_0_1, - b3: ref __self_0_2, - b4: ref __self_0_3, - b5: ref __self_0_4, - b6: ref __self_0_5, - b7: ref __self_0_6, - b8: ref __self_0_7 } => - match ::core::cmp::Ord::cmp(&(*__self_0_0), &(*__self_1_0)) - { + match ::core::cmp::Ord::cmp(&self.b1, &other.b1) { + ::core::cmp::Ordering::Equal => + match ::core::cmp::Ord::cmp(&self.b2, &other.b2) { + ::core::cmp::Ordering::Equal => + match ::core::cmp::Ord::cmp(&self.b3, &other.b3) { ::core::cmp::Ordering::Equal => - match ::core::cmp::Ord::cmp(&(*__self_0_1), &(*__self_1_1)) - { + match ::core::cmp::Ord::cmp(&self.b4, &other.b4) { ::core::cmp::Ordering::Equal => - match ::core::cmp::Ord::cmp(&(*__self_0_2), &(*__self_1_2)) - { + match ::core::cmp::Ord::cmp(&self.b5, &other.b5) { ::core::cmp::Ordering::Equal => - match ::core::cmp::Ord::cmp(&(*__self_0_3), &(*__self_1_3)) - { + match ::core::cmp::Ord::cmp(&self.b6, &other.b6) { ::core::cmp::Ordering::Equal => - match ::core::cmp::Ord::cmp(&(*__self_0_4), &(*__self_1_4)) - { + match ::core::cmp::Ord::cmp(&self.b7, &other.b7) { ::core::cmp::Ordering::Equal => - match ::core::cmp::Ord::cmp(&(*__self_0_5), &(*__self_1_5)) - { + match ::core::cmp::Ord::cmp(&self.b8, &other.b8) { ::core::cmp::Ordering::Equal => - match ::core::cmp::Ord::cmp(&(*__self_0_6), &(*__self_1_6)) - { - ::core::cmp::Ordering::Equal => - match ::core::cmp::Ord::cmp(&(*__self_0_7), &(*__self_1_7)) - { - ::core::cmp::Ordering::Equal => - ::core::cmp::Ordering::Equal, - cmp => cmp, - }, - cmp => cmp, - }, + ::core::cmp::Ordering::Equal, cmp => cmp, }, cmp => cmp, @@ -588,7 +401,116 @@ impl ::core::cmp::Ord for Big { }, cmp => cmp, }, + cmp => cmp, }, + cmp => cmp, + } + } +} + +// A packed tuple struct. +#[repr(packed)] +struct Packed(u32); +#[automatically_derived] +#[allow(unused_qualifications)] +impl ::core::clone::Clone for Packed { + #[inline] + fn clone(&self) -> Packed { + { let _: ::core::clone::AssertParamIsClone<u32>; *self } + } +} +#[automatically_derived] +#[allow(unused_qualifications)] +impl ::core::marker::Copy for Packed { } +#[automatically_derived] +#[allow(unused_qualifications)] +impl ::core::fmt::Debug for Packed { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + { + let Self(__self_0_0) = *self; + ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Packed", + &&__self_0_0) + } + } +} +#[automatically_derived] +#[allow(unused_qualifications)] +impl ::core::default::Default for Packed { + #[inline] + fn default() -> Packed { Packed(::core::default::Default::default()) } +} +#[automatically_derived] +#[allow(unused_qualifications)] +impl ::core::hash::Hash for Packed { + fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () { + { + let Self(__self_0_0) = *self; + { ::core::hash::Hash::hash(&__self_0_0, state) } + } + } +} +impl ::core::marker::StructuralPartialEq for Packed {} +#[automatically_derived] +#[allow(unused_qualifications)] +impl ::core::cmp::PartialEq for Packed { + #[inline] + fn eq(&self, other: &Packed) -> bool { + { + let Self(__self_0_0) = *self; + let Self(__self_1_0) = *other; + __self_0_0 == __self_1_0 + } + } + #[inline] + fn ne(&self, other: &Packed) -> bool { + { + let Self(__self_0_0) = *self; + let Self(__self_1_0) = *other; + __self_0_0 != __self_1_0 + } + } +} +impl ::core::marker::StructuralEq for Packed {} +#[automatically_derived] +#[allow(unused_qualifications)] +impl ::core::cmp::Eq for Packed { + #[inline] + #[doc(hidden)] + #[no_coverage] + fn assert_receiver_is_total_eq(&self) -> () { + { let _: ::core::cmp::AssertParamIsEq<u32>; } + } +} +#[automatically_derived] +#[allow(unused_qualifications)] +impl ::core::cmp::PartialOrd for Packed { + #[inline] + fn partial_cmp(&self, other: &Packed) + -> ::core::option::Option<::core::cmp::Ordering> { + { + let Self(__self_0_0) = *self; + let Self(__self_1_0) = *other; + match ::core::cmp::PartialOrd::partial_cmp(&__self_0_0, + &__self_1_0) { + ::core::option::Option::Some(::core::cmp::Ordering::Equal) => + ::core::option::Option::Some(::core::cmp::Ordering::Equal), + cmp => cmp, + } + } + } +} +#[automatically_derived] +#[allow(unused_qualifications)] +impl ::core::cmp::Ord for Packed { + #[inline] + fn cmp(&self, other: &Packed) -> ::core::cmp::Ordering { + { + let Self(__self_0_0) = *self; + let Self(__self_1_0) = *other; + match ::core::cmp::Ord::cmp(&__self_0_0, &__self_1_0) { + ::core::cmp::Ordering::Equal => ::core::cmp::Ordering::Equal, + cmp => cmp, + } } } } @@ -738,10 +660,10 @@ impl ::core::fmt::Debug for Mixed { (&Mixed::Q,) => ::core::fmt::Formatter::write_str(f, "Q"), (&Mixed::R(ref __self_0),) => ::core::fmt::Formatter::debug_tuple_field1_finish(f, "R", - &&(*__self_0)), + &&*__self_0), (&Mixed::S { d1: ref __self_0, d2: ref __self_1 },) => ::core::fmt::Formatter::debug_struct_field2_finish(f, "S", - "d1", &&(*__self_0), "d2", &&(*__self_1)), + "d1", &&*__self_0, "d2", &&*__self_1), } } } @@ -759,13 +681,13 @@ impl ::core::hash::Hash for Mixed { (&Mixed::R(ref __self_0),) => { ::core::hash::Hash::hash(&::core::intrinsics::discriminant_value(self), state); - ::core::hash::Hash::hash(&(*__self_0), state) + ::core::hash::Hash::hash(&*__self_0, state) } (&Mixed::S { d1: ref __self_0, d2: ref __self_1 },) => { ::core::hash::Hash::hash(&::core::intrinsics::discriminant_value(self), state); - ::core::hash::Hash::hash(&(*__self_0), state); - ::core::hash::Hash::hash(&(*__self_1), state) + ::core::hash::Hash::hash(&*__self_0, state); + ::core::hash::Hash::hash(&*__self_1, state) } _ => { ::core::hash::Hash::hash(&::core::intrinsics::discriminant_value(self), @@ -786,10 +708,10 @@ impl ::core::cmp::PartialEq for Mixed { if __self_vi == __arg_1_vi { match (&*self, &*other) { (&Mixed::R(ref __self_0), &Mixed::R(ref __arg_1_0)) => - (*__self_0) == (*__arg_1_0), + *__self_0 == *__arg_1_0, (&Mixed::S { d1: ref __self_0, d2: ref __self_1 }, &Mixed::S { d1: ref __arg_1_0, d2: ref __arg_1_1 }) => - (*__self_0) == (*__arg_1_0) && (*__self_1) == (*__arg_1_1), + *__self_0 == *__arg_1_0 && *__self_1 == *__arg_1_1, _ => true, } } else { false } @@ -803,10 +725,10 @@ impl ::core::cmp::PartialEq for Mixed { if __self_vi == __arg_1_vi { match (&*self, &*other) { (&Mixed::R(ref __self_0), &Mixed::R(ref __arg_1_0)) => - (*__self_0) != (*__arg_1_0), + *__self_0 != *__arg_1_0, (&Mixed::S { d1: ref __self_0, d2: ref __self_1 }, &Mixed::S { d1: ref __arg_1_0, d2: ref __arg_1_1 }) => - (*__self_0) != (*__arg_1_0) || (*__self_1) != (*__arg_1_1), + *__self_0 != *__arg_1_0 || *__self_1 != *__arg_1_1, _ => false, } } else { true } @@ -840,8 +762,8 @@ impl ::core::cmp::PartialOrd for Mixed { if __self_vi == __arg_1_vi { match (&*self, &*other) { (&Mixed::R(ref __self_0), &Mixed::R(ref __arg_1_0)) => - match ::core::cmp::PartialOrd::partial_cmp(&(*__self_0), - &(*__arg_1_0)) { + match ::core::cmp::PartialOrd::partial_cmp(&*__self_0, + &*__arg_1_0) { ::core::option::Option::Some(::core::cmp::Ordering::Equal) => ::core::option::Option::Some(::core::cmp::Ordering::Equal), @@ -849,12 +771,12 @@ impl ::core::cmp::PartialOrd for Mixed { }, (&Mixed::S { d1: ref __self_0, d2: ref __self_1 }, &Mixed::S { d1: ref __arg_1_0, d2: ref __arg_1_1 }) => - match ::core::cmp::PartialOrd::partial_cmp(&(*__self_0), - &(*__arg_1_0)) { + match ::core::cmp::PartialOrd::partial_cmp(&*__self_0, + &*__arg_1_0) { ::core::option::Option::Some(::core::cmp::Ordering::Equal) => - match ::core::cmp::PartialOrd::partial_cmp(&(*__self_1), - &(*__arg_1_1)) { + match ::core::cmp::PartialOrd::partial_cmp(&*__self_1, + &*__arg_1_1) { ::core::option::Option::Some(::core::cmp::Ordering::Equal) => ::core::option::Option::Some(::core::cmp::Ordering::Equal), @@ -883,16 +805,16 @@ impl ::core::cmp::Ord for Mixed { if __self_vi == __arg_1_vi { match (&*self, &*other) { (&Mixed::R(ref __self_0), &Mixed::R(ref __arg_1_0)) => - match ::core::cmp::Ord::cmp(&(*__self_0), &(*__arg_1_0)) { + match ::core::cmp::Ord::cmp(&*__self_0, &*__arg_1_0) { ::core::cmp::Ordering::Equal => ::core::cmp::Ordering::Equal, cmp => cmp, }, (&Mixed::S { d1: ref __self_0, d2: ref __self_1 }, &Mixed::S { d1: ref __arg_1_0, d2: ref __arg_1_1 }) => - match ::core::cmp::Ord::cmp(&(*__self_0), &(*__arg_1_0)) { + match ::core::cmp::Ord::cmp(&*__self_0, &*__arg_1_0) { ::core::cmp::Ordering::Equal => - match ::core::cmp::Ord::cmp(&(*__self_1), &(*__arg_1_1)) { + match ::core::cmp::Ord::cmp(&*__self_1, &*__arg_1_1) { ::core::cmp::Ordering::Equal => ::core::cmp::Ordering::Equal, cmp => cmp, @@ -916,11 +838,11 @@ impl ::core::clone::Clone for Fielded { fn clone(&self) -> Fielded { match (&*self,) { (&Fielded::X(ref __self_0),) => - Fielded::X(::core::clone::Clone::clone(&(*__self_0))), + Fielded::X(::core::clone::Clone::clone(&*__self_0)), (&Fielded::Y(ref __self_0),) => - Fielded::Y(::core::clone::Clone::clone(&(*__self_0))), + Fielded::Y(::core::clone::Clone::clone(&*__self_0)), (&Fielded::Z(ref __self_0),) => - Fielded::Z(::core::clone::Clone::clone(&(*__self_0))), + Fielded::Z(::core::clone::Clone::clone(&*__self_0)), } } } @@ -931,13 +853,13 @@ impl ::core::fmt::Debug for Fielded { match (&*self,) { (&Fielded::X(ref __self_0),) => ::core::fmt::Formatter::debug_tuple_field1_finish(f, "X", - &&(*__self_0)), + &&*__self_0), (&Fielded::Y(ref __self_0),) => ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Y", - &&(*__self_0)), + &&*__self_0), (&Fielded::Z(ref __self_0),) => ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Z", - &&(*__self_0)), + &&*__self_0), } } } @@ -949,17 +871,17 @@ impl ::core::hash::Hash for Fielded { (&Fielded::X(ref __self_0),) => { ::core::hash::Hash::hash(&::core::intrinsics::discriminant_value(self), state); - ::core::hash::Hash::hash(&(*__self_0), state) + ::core::hash::Hash::hash(&*__self_0, state) } (&Fielded::Y(ref __self_0),) => { ::core::hash::Hash::hash(&::core::intrinsics::discriminant_value(self), state); - ::core::hash::Hash::hash(&(*__self_0), state) + ::core::hash::Hash::hash(&*__self_0, state) } (&Fielded::Z(ref __self_0),) => { ::core::hash::Hash::hash(&::core::intrinsics::discriminant_value(self), state); - ::core::hash::Hash::hash(&(*__self_0), state) + ::core::hash::Hash::hash(&*__self_0, state) } } } @@ -976,11 +898,11 @@ impl ::core::cmp::PartialEq for Fielded { if __self_vi == __arg_1_vi { match (&*self, &*other) { (&Fielded::X(ref __self_0), &Fielded::X(ref __arg_1_0)) => - (*__self_0) == (*__arg_1_0), + *__self_0 == *__arg_1_0, (&Fielded::Y(ref __self_0), &Fielded::Y(ref __arg_1_0)) => - (*__self_0) == (*__arg_1_0), + *__self_0 == *__arg_1_0, (&Fielded::Z(ref __self_0), &Fielded::Z(ref __arg_1_0)) => - (*__self_0) == (*__arg_1_0), + *__self_0 == *__arg_1_0, _ => unsafe { ::core::intrinsics::unreachable() } } } else { false } @@ -994,11 +916,11 @@ impl ::core::cmp::PartialEq for Fielded { if __self_vi == __arg_1_vi { match (&*self, &*other) { (&Fielded::X(ref __self_0), &Fielded::X(ref __arg_1_0)) => - (*__self_0) != (*__arg_1_0), + *__self_0 != *__arg_1_0, (&Fielded::Y(ref __self_0), &Fielded::Y(ref __arg_1_0)) => - (*__self_0) != (*__arg_1_0), + *__self_0 != *__arg_1_0, (&Fielded::Z(ref __self_0), &Fielded::Z(ref __arg_1_0)) => - (*__self_0) != (*__arg_1_0), + *__self_0 != *__arg_1_0, _ => unsafe { ::core::intrinsics::unreachable() } } } else { true } @@ -1032,24 +954,24 @@ impl ::core::cmp::PartialOrd for Fielded { if __self_vi == __arg_1_vi { match (&*self, &*other) { (&Fielded::X(ref __self_0), &Fielded::X(ref __arg_1_0)) => - match ::core::cmp::PartialOrd::partial_cmp(&(*__self_0), - &(*__arg_1_0)) { + match ::core::cmp::PartialOrd::partial_cmp(&*__self_0, + &*__arg_1_0) { ::core::option::Option::Some(::core::cmp::Ordering::Equal) => ::core::option::Option::Some(::core::cmp::Ordering::Equal), cmp => cmp, }, (&Fielded::Y(ref __self_0), &Fielded::Y(ref __arg_1_0)) => - match ::core::cmp::PartialOrd::partial_cmp(&(*__self_0), - &(*__arg_1_0)) { + match ::core::cmp::PartialOrd::partial_cmp(&*__self_0, + &*__arg_1_0) { ::core::option::Option::Some(::core::cmp::Ordering::Equal) => ::core::option::Option::Some(::core::cmp::Ordering::Equal), cmp => cmp, }, (&Fielded::Z(ref __self_0), &Fielded::Z(ref __arg_1_0)) => - match ::core::cmp::PartialOrd::partial_cmp(&(*__self_0), - &(*__arg_1_0)) { + match ::core::cmp::PartialOrd::partial_cmp(&*__self_0, + &*__arg_1_0) { ::core::option::Option::Some(::core::cmp::Ordering::Equal) => ::core::option::Option::Some(::core::cmp::Ordering::Equal), @@ -1075,19 +997,19 @@ impl ::core::cmp::Ord for Fielded { if __self_vi == __arg_1_vi { match (&*self, &*other) { (&Fielded::X(ref __self_0), &Fielded::X(ref __arg_1_0)) => - match ::core::cmp::Ord::cmp(&(*__self_0), &(*__arg_1_0)) { + match ::core::cmp::Ord::cmp(&*__self_0, &*__arg_1_0) { ::core::cmp::Ordering::Equal => ::core::cmp::Ordering::Equal, cmp => cmp, }, (&Fielded::Y(ref __self_0), &Fielded::Y(ref __arg_1_0)) => - match ::core::cmp::Ord::cmp(&(*__self_0), &(*__arg_1_0)) { + match ::core::cmp::Ord::cmp(&*__self_0, &*__arg_1_0) { ::core::cmp::Ordering::Equal => ::core::cmp::Ordering::Equal, cmp => cmp, }, (&Fielded::Z(ref __self_0), &Fielded::Z(ref __arg_1_0)) => - match ::core::cmp::Ord::cmp(&(*__self_0), &(*__arg_1_0)) { + match ::core::cmp::Ord::cmp(&*__self_0, &*__arg_1_0) { ::core::cmp::Ordering::Equal => ::core::cmp::Ordering::Equal, cmp => cmp, diff --git a/src/test/ui/dropck/dropck_no_diverge_on_nonregular_1.rs b/src/test/ui/dropck/dropck_no_diverge_on_nonregular_1.rs index 6ca5f5e3c5f..43c1c775978 100644 --- a/src/test/ui/dropck/dropck_no_diverge_on_nonregular_1.rs +++ b/src/test/ui/dropck/dropck_no_diverge_on_nonregular_1.rs @@ -23,5 +23,4 @@ enum FingerTree<T:'static> { fn main() { let ft = //~ ERROR overflow while adding drop-check rules for FingerTree FingerTree::Single(1); - //~^ ERROR overflow while adding drop-check rules for FingerTree } diff --git a/src/test/ui/dropck/dropck_no_diverge_on_nonregular_1.stderr b/src/test/ui/dropck/dropck_no_diverge_on_nonregular_1.stderr index 5df69e4649d..c447e2f7987 100644 --- a/src/test/ui/dropck/dropck_no_diverge_on_nonregular_1.stderr +++ b/src/test/ui/dropck/dropck_no_diverge_on_nonregular_1.stderr @@ -6,13 +6,5 @@ LL | let ft = | = note: overflowed on FingerTree<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<i32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> -error[E0320]: overflow while adding drop-check rules for FingerTree<i32> - --> $DIR/dropck_no_diverge_on_nonregular_1.rs:25:9 - | -LL | FingerTree::Single(1); - | ^^^^^^^^^^^^^^^^^^^^^ - | - = note: overflowed on FingerTree<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<i32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - -error: aborting due to 2 previous errors +error: aborting due to previous error diff --git a/src/test/ui/dropck/dropck_no_diverge_on_nonregular_2.rs b/src/test/ui/dropck/dropck_no_diverge_on_nonregular_2.rs index d34f7e326d1..edd07652e53 100644 --- a/src/test/ui/dropck/dropck_no_diverge_on_nonregular_2.rs +++ b/src/test/ui/dropck/dropck_no_diverge_on_nonregular_2.rs @@ -22,5 +22,4 @@ enum FingerTree<T:'static> { fn main() { let ft = //~ ERROR overflow while adding drop-check rules for FingerTree FingerTree::Single(1); - //~^ ERROR overflow while adding drop-check rules for FingerTree } diff --git a/src/test/ui/dropck/dropck_no_diverge_on_nonregular_2.stderr b/src/test/ui/dropck/dropck_no_diverge_on_nonregular_2.stderr index d34097d4010..cd4706dd903 100644 --- a/src/test/ui/dropck/dropck_no_diverge_on_nonregular_2.stderr +++ b/src/test/ui/dropck/dropck_no_diverge_on_nonregular_2.stderr @@ -6,13 +6,5 @@ LL | let ft = | = note: overflowed on FingerTree<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<i32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> -error[E0320]: overflow while adding drop-check rules for FingerTree<i32> - --> $DIR/dropck_no_diverge_on_nonregular_2.rs:24:9 - | -LL | FingerTree::Single(1); - | ^^^^^^^^^^^^^^^^^^^^^ - | - = note: overflowed on FingerTree<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<i32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - -error: aborting due to 2 previous errors +error: aborting due to previous error diff --git a/src/test/ui/dropck/dropck_no_diverge_on_nonregular_3.rs b/src/test/ui/dropck/dropck_no_diverge_on_nonregular_3.rs index 558b4342da7..af7402ca4a1 100644 --- a/src/test/ui/dropck/dropck_no_diverge_on_nonregular_3.rs +++ b/src/test/ui/dropck/dropck_no_diverge_on_nonregular_3.rs @@ -31,6 +31,5 @@ enum Wrapper<T:'static> { fn main() { let w = //~ ERROR overflow while adding drop-check rules for Option Some(Wrapper::Simple::<u32>); - //~^ ERROR overflow while adding drop-check rules for Option - //~| ERROR overflow while adding drop-check rules for Wrapper + //~^ ERROR overflow while adding drop-check rules for Wrapper } diff --git a/src/test/ui/dropck/dropck_no_diverge_on_nonregular_3.stderr b/src/test/ui/dropck/dropck_no_diverge_on_nonregular_3.stderr index b24e1d1bf79..18cd1b6cd41 100644 --- a/src/test/ui/dropck/dropck_no_diverge_on_nonregular_3.stderr +++ b/src/test/ui/dropck/dropck_no_diverge_on_nonregular_3.stderr @@ -6,14 +6,6 @@ LL | let w = | = note: overflowed on FingerTree<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<u32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> -error[E0320]: overflow while adding drop-check rules for Option<Wrapper<u32>> - --> $DIR/dropck_no_diverge_on_nonregular_3.rs:33:9 - | -LL | Some(Wrapper::Simple::<u32>); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: overflowed on FingerTree<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<u32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - error[E0320]: overflow while adding drop-check rules for Wrapper<u32> --> $DIR/dropck_no_diverge_on_nonregular_3.rs:33:14 | @@ -22,5 +14,5 @@ LL | Some(Wrapper::Simple::<u32>); | = note: overflowed on FingerTree<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<u32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors diff --git a/src/test/ui/inference/ambiguous_type_parameter.stderr b/src/test/ui/inference/ambiguous_type_parameter.stderr index a08342371b3..9cbe221de13 100644 --- a/src/test/ui/inference/ambiguous_type_parameter.stderr +++ b/src/test/ui/inference/ambiguous_type_parameter.stderr @@ -2,7 +2,12 @@ error[E0282]: type annotations needed --> $DIR/ambiguous_type_parameter.rs:16:19 | LL | InMemoryStore.get_raw(&String::default()); - | ^^^^^^^ cannot infer type for type parameter `K` + | ^^^^^^^ + | +help: try using a fully qualified path to specify the expected types + | +LL | <InMemoryStore as Store<String, HashMap<K, String>>>::get_raw(&InMemoryStore, &String::default()); + | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ~ error: aborting due to previous error diff --git a/src/test/ui/inference/cannot-infer-partial-try-return.rs b/src/test/ui/inference/cannot-infer-partial-try-return.rs index 976827a4478..b555697dc34 100644 --- a/src/test/ui/inference/cannot-infer-partial-try-return.rs +++ b/src/test/ui/inference/cannot-infer-partial-try-return.rs @@ -16,8 +16,8 @@ fn infallible() -> Result<(), std::convert::Infallible> { fn main() { let x = || -> Result<_, QualifiedError<_>> { - //~^ ERROR type annotations needed for `Result<(), QualifiedError<_>>` infallible()?; Ok(()) + //~^ ERROR type annotations needed }; } diff --git a/src/test/ui/inference/cannot-infer-partial-try-return.stderr b/src/test/ui/inference/cannot-infer-partial-try-return.stderr index c1e43f0b721..2a56aaa44fe 100644 --- a/src/test/ui/inference/cannot-infer-partial-try-return.stderr +++ b/src/test/ui/inference/cannot-infer-partial-try-return.stderr @@ -1,16 +1,15 @@ -error[E0282]: type annotations needed for `Result<(), QualifiedError<_>>` - --> $DIR/cannot-infer-partial-try-return.rs:18:13 +error[E0282]: type annotations needed + --> $DIR/cannot-infer-partial-try-return.rs:20:9 | -LL | let x = || -> Result<_, QualifiedError<_>> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | LL | infallible()?; | ------------- type must be known at this point +LL | Ok(()) + | ^^ cannot infer type of the type parameter `E` declared on the enum `Result` | -help: try giving this closure an explicit return type +help: consider specifying the generic arguments | -LL | let x = || -> Result<(), QualifiedError<_>> { - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +LL | Ok::<(), QualifiedError<_>>(()) + | +++++++++++++++++++++++++ error: aborting due to previous error diff --git a/src/test/ui/inference/need_type_info/channel.rs b/src/test/ui/inference/need_type_info/channel.rs new file mode 100644 index 00000000000..e2ba5a94171 --- /dev/null +++ b/src/test/ui/inference/need_type_info/channel.rs @@ -0,0 +1,19 @@ +// Test that we suggest specifying the generic argument of `channel` +// instead of the return type of that function, which is a lot more +// complex. +use std::sync::mpsc::channel; + +fn no_tuple() { + let _data = + channel(); //~ ERROR type annotations needed +} + +fn tuple() { + let (_sender, _receiver) = + channel(); //~ ERROR type annotations needed +} + +fn main() { + no_tuple(); + tuple(); +} diff --git a/src/test/ui/inference/need_type_info/channel.stderr b/src/test/ui/inference/need_type_info/channel.stderr new file mode 100644 index 00000000000..e33ace0338d --- /dev/null +++ b/src/test/ui/inference/need_type_info/channel.stderr @@ -0,0 +1,25 @@ +error[E0282]: type annotations needed + --> $DIR/channel.rs:8:9 + | +LL | channel(); + | ^^^^^^^ cannot infer type of the type parameter `T` declared on the function `channel` + | +help: consider specifying the generic argument + | +LL | channel::<T>(); + | +++++ + +error[E0282]: type annotations needed + --> $DIR/channel.rs:13:9 + | +LL | channel(); + | ^^^^^^^ cannot infer type of the type parameter `T` declared on the function `channel` + | +help: consider specifying the generic argument + | +LL | channel::<T>(); + | +++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/infinite/infinite-struct.rs b/src/test/ui/infinite/infinite-struct.rs index 70a203ea6e8..74185dc597b 100644 --- a/src/test/ui/infinite/infinite-struct.rs +++ b/src/test/ui/infinite/infinite-struct.rs @@ -1,6 +1,5 @@ struct Take(Take); //~^ ERROR has infinite size -//~| ERROR cycle detected // check that we don't hang trying to find the tail of a recursive struct (#79437) fn foo() -> Take { diff --git a/src/test/ui/infinite/infinite-struct.stderr b/src/test/ui/infinite/infinite-struct.stderr index 214be091cce..5a6d13786d1 100644 --- a/src/test/ui/infinite/infinite-struct.stderr +++ b/src/test/ui/infinite/infinite-struct.stderr @@ -11,16 +11,6 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Take` repre LL | struct Take(Box<Take>); | ++++ + -error[E0391]: cycle detected when computing drop-check constraints for `Take` - --> $DIR/infinite-struct.rs:1:1 - | -LL | struct Take(Take); - | ^^^^^^^^^^^ - | - = note: ...which immediately requires computing drop-check constraints for `Take` again - = note: cycle used when computing dropck types for `Canonical { max_universe: U0, variables: [], value: ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: UserFacing, constness: NotConst }, value: Take } }` - -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0072, E0391. -For more information about an error, try `rustc --explain E0072`. +For more information about this error, try `rustc --explain E0072`. diff --git a/src/test/ui/infinite/infinite-tag-type-recursion.rs b/src/test/ui/infinite/infinite-tag-type-recursion.rs index 8578c5545bc..87a9e08dd38 100644 --- a/src/test/ui/infinite/infinite-tag-type-recursion.rs +++ b/src/test/ui/infinite/infinite-tag-type-recursion.rs @@ -1,5 +1,4 @@ enum MList { Cons(isize, MList), Nil } //~^ ERROR recursive type `MList` has infinite size -//~| ERROR cycle detected when computing drop-check constraints for `MList` fn main() { let a = MList::Cons(10, MList::Cons(11, MList::Nil)); } diff --git a/src/test/ui/infinite/infinite-tag-type-recursion.stderr b/src/test/ui/infinite/infinite-tag-type-recursion.stderr index 1802c7599a3..d2dad4b9178 100644 --- a/src/test/ui/infinite/infinite-tag-type-recursion.stderr +++ b/src/test/ui/infinite/infinite-tag-type-recursion.stderr @@ -11,16 +11,6 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `MList` repr LL | enum MList { Cons(isize, Box<MList>), Nil } | ++++ + -error[E0391]: cycle detected when computing drop-check constraints for `MList` - --> $DIR/infinite-tag-type-recursion.rs:1:1 - | -LL | enum MList { Cons(isize, MList), Nil } - | ^^^^^^^^^^ - | - = note: ...which immediately requires computing drop-check constraints for `MList` again - = note: cycle used when computing dropck types for `Canonical { max_universe: U0, variables: [], value: ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: UserFacing, constness: NotConst }, value: MList } }` - -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0072, E0391. -For more information about an error, try `rustc --explain E0072`. +For more information about this error, try `rustc --explain E0072`. diff --git a/src/test/ui/issues/issue-23041.stderr b/src/test/ui/issues/issue-23041.stderr index 401086b2044..7b9a1634a0d 100644 --- a/src/test/ui/issues/issue-23041.stderr +++ b/src/test/ui/issues/issue-23041.stderr @@ -1,8 +1,13 @@ error[E0282]: type annotations needed - --> $DIR/issue-23041.rs:6:22 + --> $DIR/issue-23041.rs:6:7 | LL | b.downcast_ref::<fn(_)->_>(); - | ^^^^^^^^ cannot infer type + | ^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the associated function `downcast_ref` + | +help: consider specifying the generic arguments + | +LL | b.downcast_ref::<fn(_) -> _>(); + | ~~~~~~~~~~~~~~ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-24013.stderr b/src/test/ui/issues/issue-24013.stderr index 4e3cb88297d..863993f4509 100644 --- a/src/test/ui/issues/issue-24013.stderr +++ b/src/test/ui/issues/issue-24013.stderr @@ -1,8 +1,13 @@ error[E0282]: type annotations needed - --> $DIR/issue-24013.rs:5:20 + --> $DIR/issue-24013.rs:5:13 | LL | unsafe {swap::<&mut _>(transmute(&a), transmute(&b))}; - | ^^^^^^ cannot infer type + | ^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `swap` + | +help: consider specifying the generic arguments + | +LL | unsafe {swap::<&mut _>(transmute(&a), transmute(&b))}; + | ~~~~~~~~~~ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-25368.rs b/src/test/ui/issues/issue-25368.rs index b7f0f613e80..4be83457f7a 100644 --- a/src/test/ui/issues/issue-25368.rs +++ b/src/test/ui/issues/issue-25368.rs @@ -5,10 +5,10 @@ use std::marker::PhantomData; struct Foo<T> {foo: PhantomData<T>} fn main() { - let (tx, rx) = //~ ERROR type annotations needed + let (tx, rx) = channel(); - // FIXME(#89862): Suggest adding a generic argument to `channel` instead spawn(move || { tx.send(Foo{ foo: PhantomData }); + //~^ ERROR type annotations needed }); } diff --git a/src/test/ui/issues/issue-25368.stderr b/src/test/ui/issues/issue-25368.stderr index ffcb7384952..e6ed3aac710 100644 --- a/src/test/ui/issues/issue-25368.stderr +++ b/src/test/ui/issues/issue-25368.stderr @@ -1,13 +1,13 @@ -error[E0282]: type annotations needed for `(Sender<Foo<T>>, std::sync::mpsc::Receiver<Foo<T>>)` - --> $DIR/issue-25368.rs:8:9 +error[E0282]: type annotations needed + --> $DIR/issue-25368.rs:11:27 | -LL | let (tx, rx) = - | ^^^^^^^^ +LL | tx.send(Foo{ foo: PhantomData }); + | ^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the struct `PhantomData` | -help: consider giving this pattern a type, where the type for type parameter `T` is specified +help: consider specifying the generic argument | -LL | let (tx, rx): (Sender<Foo<T>>, std::sync::mpsc::Receiver<Foo<T>>) = - | +++++++++++++++++++++++++++++++++++++++++++++++++++++ +LL | tx.send(Foo{ foo: PhantomData::<T> }); + | +++++ error: aborting due to previous error diff --git a/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr b/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr index 66e7ada3ac5..e0f8a5447b0 100644 --- a/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr +++ b/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr @@ -13,7 +13,7 @@ error[E0283]: type annotations needed --> $DIR/method-ambig-one-trait-unknown-int-type.rs:26:7 | LL | x.foo(); - | ^^^ cannot infer type for struct `Vec<_>` + | ^^^ | note: multiple `impl`s satisfying `Vec<_>: Foo` found --> $DIR/method-ambig-one-trait-unknown-int-type.rs:9:1 @@ -23,6 +23,10 @@ LL | impl Foo for Vec<usize> { ... LL | impl Foo for Vec<isize> { | ^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | <Vec<T> as Foo>::foo(&x); + | ++++++++++++++++++++++ ~ error[E0308]: mismatched types --> $DIR/method-ambig-one-trait-unknown-int-type.rs:33:20 diff --git a/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.rs b/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.rs index c857eb459b8..c9e93174e20 100644 --- a/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.rs +++ b/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.rs @@ -1,18 +1,14 @@ -// Dropck shouldn't hit a recursion limit from checking `S<u32>` since it has -// no free regions or type parameters. -// Codegen however, has to error for the infinitely many `drop_in_place` -// functions it has been asked to create. - -// build-fail -// normalize-stderr-test: ".nll/" -> "/" -// compile-flags: -Zmir-opt-level=0 +// `S` is infinitely recursing so it's not possible to generate a finite +// drop impl (ignoring polymorphization). +// +// Dropck should therefore detect that this is the case and eagerly error. struct S<T> { t: T, s: Box<S<fn(u: T)>>, } -fn f(x: S<u32>) {} +fn f(x: S<u32>) {} //~ ERROR overflow while adding drop-check rules for S<u32> fn main() { // Force instantiation. diff --git a/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr b/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr index d749ee00c22..1da29be43db 100644 --- a/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr +++ b/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr @@ -1,15 +1,10 @@ -error: reached the recursion limit while instantiating `std::ptr::drop_in_place::<S<fn(f...)))))))))))))))))))))))))))))>))` - --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL +error[E0320]: overflow while adding drop-check rules for S<u32> + --> $DIR/issue-38591-non-regular-dropck-recursion.rs:11:6 | -LL | pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn f(x: S<u32>) {} + | ^ | -note: `std::ptr::drop_in_place` defined here - --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL - | -LL | pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: the full type name has been written to '$TEST_BUILD_DIR/recursion/issue-38591-non-regular-dropck-recursion/issue-38591-non-regular-dropck-recursion.long-type.txt' + = note: overflowed on S<fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(u32)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))> error: aborting due to previous error diff --git a/src/test/ui/recursion/issue-86784.rs b/src/test/ui/recursion/issue-86784.rs new file mode 100644 index 00000000000..34f4aaedb32 --- /dev/null +++ b/src/test/ui/recursion/issue-86784.rs @@ -0,0 +1,2597 @@ +// build-pass + +fn main() { + let _temp_1 = 0; + let _temp_2 = 0; + let _temp_3 = 0; + let _temp_4 = 0; + let _temp_5 = 0; + let _temp_6 = 0; + let _temp_7 = 0; + let _temp_8 = 0; + let _temp_9 = 0; + let _temp_10 = 0; + let _temp_11 = 0; + let _temp_12 = 0; + let _temp_13 = 0; + let _temp_14 = 0; + let _temp_15 = 0; + let _temp_16 = 0; + let _temp_17 = 0; + let _temp_18 = 0; + let _temp_19 = 0; + let _temp_20 = 0; + let _temp_21 = 0; + let _temp_22 = 0; + let _temp_23 = 0; + let _temp_24 = 0; + let _temp_25 = 0; + let _temp_26 = 0; + let _temp_27 = 0; + let _temp_28 = 0; + let _temp_29 = 0; + let _temp_30 = 0; + let _temp_31 = 0; + let _temp_32 = 0; + let _temp_33 = 0; + let _temp_34 = 0; + let _temp_35 = 0; + let _temp_36 = 0; + let _temp_37 = 0; + let _temp_38 = 0; + let _temp_39 = 0; + let _temp_40 = 0; + let _temp_41 = 0; + let _temp_42 = 0; + let _temp_43 = 0; + let _temp_44 = 0; + let _temp_45 = 0; + let _temp_46 = 0; + let _temp_47 = 0; + let _temp_48 = 0; + let _temp_49 = 0; + let _temp_50 = 0; + let _temp_51 = 0; + let _temp_52 = 0; + let _temp_53 = 0; + let _temp_54 = 0; + let _temp_55 = 0; + let _temp_56 = 0; + let _temp_57 = 0; + let _temp_58 = 0; + let _temp_59 = 0; + let _temp_60 = 0; + let _temp_61 = 0; + let _temp_62 = 0; + let _temp_63 = 0; + let _temp_64 = 0; + let _temp_65 = 0; + let _temp_66 = 0; + let _temp_67 = 0; + let _temp_68 = 0; + let _temp_69 = 0; + let _temp_70 = 0; + let _temp_71 = 0; + let _temp_72 = 0; + let _temp_73 = 0; + let _temp_74 = 0; + let _temp_75 = 0; + let _temp_76 = 0; + let _temp_77 = 0; + let _temp_78 = 0; + let _temp_79 = 0; + let _temp_80 = 0; + let _temp_81 = 0; + let _temp_82 = 0; + let _temp_83 = 0; + let _temp_84 = 0; + let _temp_85 = 0; + let _temp_86 = 0; + let _temp_87 = 0; + let _temp_88 = 0; + let _temp_89 = 0; + let _temp_90 = 0; + let _temp_91 = 0; + let _temp_92 = 0; + let _temp_93 = 0; + let _temp_94 = 0; + let _temp_95 = 0; + let _temp_96 = 0; + let _temp_97 = 0; + let _temp_98 = 0; + let _temp_99 = 0; + let _temp_100 = 0; + let _temp_101 = 0; + let _temp_102 = 0; + let _temp_103 = 0; + let _temp_104 = 0; + let _temp_105 = 0; + let _temp_106 = 0; + let _temp_107 = 0; + let _temp_108 = 0; + let _temp_109 = 0; + let _temp_110 = 0; + let _temp_111 = 0; + let _temp_112 = 0; + let _temp_113 = 0; + let _temp_114 = 0; + let _temp_115 = 0; + let _temp_116 = 0; + let _temp_117 = 0; + let _temp_118 = 0; + let _temp_119 = 0; + let _temp_120 = 0; + let _temp_121 = 0; + let _temp_122 = 0; + let _temp_123 = 0; + let _temp_124 = 0; + let _temp_125 = 0; + let _temp_126 = 0; + let _temp_127 = 0; + let _temp_128 = 0; + let _temp_129 = 0; + let _temp_130 = 0; + let _temp_131 = 0; + let _temp_132 = 0; + let _temp_133 = 0; + let _temp_134 = 0; + let _temp_135 = 0; + let _temp_136 = 0; + let _temp_137 = 0; + let _temp_138 = 0; + let _temp_139 = 0; + let _temp_140 = 0; + let _temp_141 = 0; + let _temp_142 = 0; + let _temp_143 = 0; + let _temp_144 = 0; + let _temp_145 = 0; + let _temp_146 = 0; + let _temp_147 = 0; + let _temp_148 = 0; + let _temp_149 = 0; + let _temp_150 = 0; + let _temp_151 = 0; + let _temp_152 = 0; + let _temp_153 = 0; + let _temp_154 = 0; + let _temp_155 = 0; + let _temp_156 = 0; + let _temp_157 = 0; + let _temp_158 = 0; + let _temp_159 = 0; + let _temp_160 = 0; + let _temp_161 = 0; + let _temp_162 = 0; + let _temp_163 = 0; + let _temp_164 = 0; + let _temp_165 = 0; + let _temp_166 = 0; + let _temp_167 = 0; + let _temp_168 = 0; + let _temp_169 = 0; + let _temp_170 = 0; + let _temp_171 = 0; + let _temp_172 = 0; + let _temp_173 = 0; + let _temp_174 = 0; + let _temp_175 = 0; + let _temp_176 = 0; + let _temp_177 = 0; + let _temp_178 = 0; + let _temp_179 = 0; + let _temp_180 = 0; + let _temp_181 = 0; + let _temp_182 = 0; + let _temp_183 = 0; + let _temp_184 = 0; + let _temp_185 = 0; + let _temp_186 = 0; + let _temp_187 = 0; + let _temp_188 = 0; + let _temp_189 = 0; + let _temp_190 = 0; + let _temp_191 = 0; + let _temp_192 = 0; + let _temp_193 = 0; + let _temp_194 = 0; + let _temp_195 = 0; + let _temp_196 = 0; + let _temp_197 = 0; + let _temp_198 = 0; + let _temp_199 = 0; + let _temp_200 = 0; + let _temp_201 = 0; + let _temp_202 = 0; + let _temp_203 = 0; + let _temp_204 = 0; + let _temp_205 = 0; + let _temp_206 = 0; + let _temp_207 = 0; + let _temp_208 = 0; + let _temp_209 = 0; + let _temp_210 = 0; + let _temp_211 = 0; + let _temp_212 = 0; + let _temp_213 = 0; + let _temp_214 = 0; + let _temp_215 = 0; + let _temp_216 = 0; + let _temp_217 = 0; + let _temp_218 = 0; + let _temp_219 = 0; + let _temp_220 = 0; + let _temp_221 = 0; + let _temp_222 = 0; + let _temp_223 = 0; + let _temp_224 = 0; + let _temp_225 = 0; + let _temp_226 = 0; + let _temp_227 = 0; + let _temp_228 = 0; + let _temp_229 = 0; + let _temp_230 = 0; + let _temp_231 = 0; + let _temp_232 = 0; + let _temp_233 = 0; + let _temp_234 = 0; + let _temp_235 = 0; + let _temp_236 = 0; + let _temp_237 = 0; + let _temp_238 = 0; + let _temp_239 = 0; + let _temp_240 = 0; + let _temp_241 = 0; + let _temp_242 = 0; + let _temp_243 = 0; + let _temp_244 = 0; + let _temp_245 = 0; + let _temp_246 = 0; + let _temp_247 = 0; + let _temp_248 = 0; + let _temp_249 = 0; + let _temp_250 = 0; + let _temp_251 = 0; + let _temp_252 = 0; + let _temp_253 = 0; + let _temp_254 = 0; + let _temp_255 = 0; + let _temp_256 = 0; + let _temp_257 = 0; + let _temp_258 = 0; + let _temp_259 = 0; + let _temp_260 = 0; + let _temp_261 = 0; + let _temp_262 = 0; + let _temp_263 = 0; + let _temp_264 = 0; + let _temp_265 = 0; + let _temp_266 = 0; + let _temp_267 = 0; + let _temp_268 = 0; + let _temp_269 = 0; + let _temp_270 = 0; + let _temp_271 = 0; + let _temp_272 = 0; + let _temp_273 = 0; + let _temp_274 = 0; + let _temp_275 = 0; + let _temp_276 = 0; + let _temp_277 = 0; + let _temp_278 = 0; + let _temp_279 = 0; + let _temp_280 = 0; + let _temp_281 = 0; + let _temp_282 = 0; + let _temp_283 = 0; + let _temp_284 = 0; + let _temp_285 = 0; + let _temp_286 = 0; + let _temp_287 = 0; + let _temp_288 = 0; + let _temp_289 = 0; + let _temp_290 = 0; + let _temp_291 = 0; + let _temp_292 = 0; + let _temp_293 = 0; + let _temp_294 = 0; + let _temp_295 = 0; + let _temp_296 = 0; + let _temp_297 = 0; + let _temp_298 = 0; + let _temp_299 = 0; + let _temp_300 = 0; + let _temp_301 = 0; + let _temp_302 = 0; + let _temp_303 = 0; + let _temp_304 = 0; + let _temp_305 = 0; + let _temp_306 = 0; + let _temp_307 = 0; + let _temp_308 = 0; + let _temp_309 = 0; + let _temp_310 = 0; + let _temp_311 = 0; + let _temp_312 = 0; + let _temp_313 = 0; + let _temp_314 = 0; + let _temp_315 = 0; + let _temp_316 = 0; + let _temp_317 = 0; + let _temp_318 = 0; + let _temp_319 = 0; + let _temp_320 = 0; + let _temp_321 = 0; + let _temp_322 = 0; + let _temp_323 = 0; + let _temp_324 = 0; + let _temp_325 = 0; + let _temp_326 = 0; + let _temp_327 = 0; + let _temp_328 = 0; + let _temp_329 = 0; + let _temp_330 = 0; + let _temp_331 = 0; + let _temp_332 = 0; + let _temp_333 = 0; + let _temp_334 = 0; + let _temp_335 = 0; + let _temp_336 = 0; + let _temp_337 = 0; + let _temp_338 = 0; + let _temp_339 = 0; + let _temp_340 = 0; + let _temp_341 = 0; + let _temp_342 = 0; + let _temp_343 = 0; + let _temp_344 = 0; + let _temp_345 = 0; + let _temp_346 = 0; + let _temp_347 = 0; + let _temp_348 = 0; + let _temp_349 = 0; + let _temp_350 = 0; + let _temp_351 = 0; + let _temp_352 = 0; + let _temp_353 = 0; + let _temp_354 = 0; + let _temp_355 = 0; + let _temp_356 = 0; + let _temp_357 = 0; + let _temp_358 = 0; + let _temp_359 = 0; + let _temp_360 = 0; + let _temp_361 = 0; + let _temp_362 = 0; + let _temp_363 = 0; + let _temp_364 = 0; + let _temp_365 = 0; + let _temp_366 = 0; + let _temp_367 = 0; + let _temp_368 = 0; + let _temp_369 = 0; + let _temp_370 = 0; + let _temp_371 = 0; + let _temp_372 = 0; + let _temp_373 = 0; + let _temp_374 = 0; + let _temp_375 = 0; + let _temp_376 = 0; + let _temp_377 = 0; + let _temp_378 = 0; + let _temp_379 = 0; + let _temp_380 = 0; + let _temp_381 = 0; + let _temp_382 = 0; + let _temp_383 = 0; + let _temp_384 = 0; + let _temp_385 = 0; + let _temp_386 = 0; + let _temp_387 = 0; + let _temp_388 = 0; + let _temp_389 = 0; + let _temp_390 = 0; + let _temp_391 = 0; + let _temp_392 = 0; + let _temp_393 = 0; + let _temp_394 = 0; + let _temp_395 = 0; + let _temp_396 = 0; + let _temp_397 = 0; + let _temp_398 = 0; + let _temp_399 = 0; + let _temp_400 = 0; + let _temp_401 = 0; + let _temp_402 = 0; + let _temp_403 = 0; + let _temp_404 = 0; + let _temp_405 = 0; + let _temp_406 = 0; + let _temp_407 = 0; + let _temp_408 = 0; + let _temp_409 = 0; + let _temp_410 = 0; + let _temp_411 = 0; + let _temp_412 = 0; + let _temp_413 = 0; + let _temp_414 = 0; + let _temp_415 = 0; + let _temp_416 = 0; + let _temp_417 = 0; + let _temp_418 = 0; + let _temp_419 = 0; + let _temp_420 = 0; + let _temp_421 = 0; + let _temp_422 = 0; + let _temp_423 = 0; + let _temp_424 = 0; + let _temp_425 = 0; + let _temp_426 = 0; + let _temp_427 = 0; + let _temp_428 = 0; + let _temp_429 = 0; + let _temp_430 = 0; + let _temp_431 = 0; + let _temp_432 = 0; + let _temp_433 = 0; + let _temp_434 = 0; + let _temp_435 = 0; + let _temp_436 = 0; + let _temp_437 = 0; + let _temp_438 = 0; + let _temp_439 = 0; + let _temp_440 = 0; + let _temp_441 = 0; + let _temp_442 = 0; + let _temp_443 = 0; + let _temp_444 = 0; + let _temp_445 = 0; + let _temp_446 = 0; + let _temp_447 = 0; + let _temp_448 = 0; + let _temp_449 = 0; + let _temp_450 = 0; + let _temp_451 = 0; + let _temp_452 = 0; + let _temp_453 = 0; + let _temp_454 = 0; + let _temp_455 = 0; + let _temp_456 = 0; + let _temp_457 = 0; + let _temp_458 = 0; + let _temp_459 = 0; + let _temp_460 = 0; + let _temp_461 = 0; + let _temp_462 = 0; + let _temp_463 = 0; + let _temp_464 = 0; + let _temp_465 = 0; + let _temp_466 = 0; + let _temp_467 = 0; + let _temp_468 = 0; + let _temp_469 = 0; + let _temp_470 = 0; + let _temp_471 = 0; + let _temp_472 = 0; + let _temp_473 = 0; + let _temp_474 = 0; + let _temp_475 = 0; + let _temp_476 = 0; + let _temp_477 = 0; + let _temp_478 = 0; + let _temp_479 = 0; + let _temp_480 = 0; + let _temp_481 = 0; + let _temp_482 = 0; + let _temp_483 = 0; + let _temp_484 = 0; + let _temp_485 = 0; + let _temp_486 = 0; + let _temp_487 = 0; + let _temp_488 = 0; + let _temp_489 = 0; + let _temp_490 = 0; + let _temp_491 = 0; + let _temp_492 = 0; + let _temp_493 = 0; + let _temp_494 = 0; + let _temp_495 = 0; + let _temp_496 = 0; + let _temp_497 = 0; + let _temp_498 = 0; + let _temp_499 = 0; + let _temp_500 = 0; + let _temp_501 = 0; + let _temp_502 = 0; + let _temp_503 = 0; + let _temp_504 = 0; + let _temp_505 = 0; + let _temp_506 = 0; + let _temp_507 = 0; + let _temp_508 = 0; + let _temp_509 = 0; + let _temp_510 = 0; + let _temp_511 = 0; + let _temp_512 = 0; + let _temp_513 = 0; + let _temp_514 = 0; + let _temp_515 = 0; + let _temp_516 = 0; + let _temp_517 = 0; + let _temp_518 = 0; + let _temp_519 = 0; + let _temp_520 = 0; + let _temp_521 = 0; + let _temp_522 = 0; + let _temp_523 = 0; + let _temp_524 = 0; + let _temp_525 = 0; + let _temp_526 = 0; + let _temp_527 = 0; + let _temp_528 = 0; + let _temp_529 = 0; + let _temp_530 = 0; + let _temp_531 = 0; + let _temp_532 = 0; + let _temp_533 = 0; + let _temp_534 = 0; + let _temp_535 = 0; + let _temp_536 = 0; + let _temp_537 = 0; + let _temp_538 = 0; + let _temp_539 = 0; + let _temp_540 = 0; + let _temp_541 = 0; + let _temp_542 = 0; + let _temp_543 = 0; + let _temp_544 = 0; + let _temp_545 = 0; + let _temp_546 = 0; + let _temp_547 = 0; + let _temp_548 = 0; + let _temp_549 = 0; + let _temp_550 = 0; + let _temp_551 = 0; + let _temp_552 = 0; + let _temp_553 = 0; + let _temp_554 = 0; + let _temp_555 = 0; + let _temp_556 = 0; + let _temp_557 = 0; + let _temp_558 = 0; + let _temp_559 = 0; + let _temp_560 = 0; + let _temp_561 = 0; + let _temp_562 = 0; + let _temp_563 = 0; + let _temp_564 = 0; + let _temp_565 = 0; + let _temp_566 = 0; + let _temp_567 = 0; + let _temp_568 = 0; + let _temp_569 = 0; + let _temp_570 = 0; + let _temp_571 = 0; + let _temp_572 = 0; + let _temp_573 = 0; + let _temp_574 = 0; + let _temp_575 = 0; + let _temp_576 = 0; + let _temp_577 = 0; + let _temp_578 = 0; + let _temp_579 = 0; + let _temp_580 = 0; + let _temp_581 = 0; + let _temp_582 = 0; + let _temp_583 = 0; + let _temp_584 = 0; + let _temp_585 = 0; + let _temp_586 = 0; + let _temp_587 = 0; + let _temp_588 = 0; + let _temp_589 = 0; + let _temp_590 = 0; + let _temp_591 = 0; + let _temp_592 = 0; + let _temp_593 = 0; + let _temp_594 = 0; + let _temp_595 = 0; + let _temp_596 = 0; + let _temp_597 = 0; + let _temp_598 = 0; + let _temp_599 = 0; + let _temp_600 = 0; + let _temp_601 = 0; + let _temp_602 = 0; + let _temp_603 = 0; + let _temp_604 = 0; + let _temp_605 = 0; + let _temp_606 = 0; + let _temp_607 = 0; + let _temp_608 = 0; + let _temp_609 = 0; + let _temp_610 = 0; + let _temp_611 = 0; + let _temp_612 = 0; + let _temp_613 = 0; + let _temp_614 = 0; + let _temp_615 = 0; + let _temp_616 = 0; + let _temp_617 = 0; + let _temp_618 = 0; + let _temp_619 = 0; + let _temp_620 = 0; + let _temp_621 = 0; + let _temp_622 = 0; + let _temp_623 = 0; + let _temp_624 = 0; + let _temp_625 = 0; + let _temp_626 = 0; + let _temp_627 = 0; + let _temp_628 = 0; + let _temp_629 = 0; + let _temp_630 = 0; + let _temp_631 = 0; + let _temp_632 = 0; + let _temp_633 = 0; + let _temp_634 = 0; + let _temp_635 = 0; + let _temp_636 = 0; + let _temp_637 = 0; + let _temp_638 = 0; + let _temp_639 = 0; + let _temp_640 = 0; + let _temp_641 = 0; + let _temp_642 = 0; + let _temp_643 = 0; + let _temp_644 = 0; + let _temp_645 = 0; + let _temp_646 = 0; + let _temp_647 = 0; + let _temp_648 = 0; + let _temp_649 = 0; + let _temp_650 = 0; + let _temp_651 = 0; + let _temp_652 = 0; + let _temp_653 = 0; + let _temp_654 = 0; + let _temp_655 = 0; + let _temp_656 = 0; + let _temp_657 = 0; + let _temp_658 = 0; + let _temp_659 = 0; + let _temp_660 = 0; + let _temp_661 = 0; + let _temp_662 = 0; + let _temp_663 = 0; + let _temp_664 = 0; + let _temp_665 = 0; + let _temp_666 = 0; + let _temp_667 = 0; + let _temp_668 = 0; + let _temp_669 = 0; + let _temp_670 = 0; + let _temp_671 = 0; + let _temp_672 = 0; + let _temp_673 = 0; + let _temp_674 = 0; + let _temp_675 = 0; + let _temp_676 = 0; + let _temp_677 = 0; + let _temp_678 = 0; + let _temp_679 = 0; + let _temp_680 = 0; + let _temp_681 = 0; + let _temp_682 = 0; + let _temp_683 = 0; + let _temp_684 = 0; + let _temp_685 = 0; + let _temp_686 = 0; + let _temp_687 = 0; + let _temp_688 = 0; + let _temp_689 = 0; + let _temp_690 = 0; + let _temp_691 = 0; + let _temp_692 = 0; + let _temp_693 = 0; + let _temp_694 = 0; + let _temp_695 = 0; + let _temp_696 = 0; + let _temp_697 = 0; + let _temp_698 = 0; + let _temp_699 = 0; + let _temp_700 = 0; + let _temp_701 = 0; + let _temp_702 = 0; + let _temp_703 = 0; + let _temp_704 = 0; + let _temp_705 = 0; + let _temp_706 = 0; + let _temp_707 = 0; + let _temp_708 = 0; + let _temp_709 = 0; + let _temp_710 = 0; + let _temp_711 = 0; + let _temp_712 = 0; + let _temp_713 = 0; + let _temp_714 = 0; + let _temp_715 = 0; + let _temp_716 = 0; + let _temp_717 = 0; + let _temp_718 = 0; + let _temp_719 = 0; + let _temp_720 = 0; + let _temp_721 = 0; + let _temp_722 = 0; + let _temp_723 = 0; + let _temp_724 = 0; + let _temp_725 = 0; + let _temp_726 = 0; + let _temp_727 = 0; + let _temp_728 = 0; + let _temp_729 = 0; + let _temp_730 = 0; + let _temp_731 = 0; + let _temp_732 = 0; + let _temp_733 = 0; + let _temp_734 = 0; + let _temp_735 = 0; + let _temp_736 = 0; + let _temp_737 = 0; + let _temp_738 = 0; + let _temp_739 = 0; + let _temp_740 = 0; + let _temp_741 = 0; + let _temp_742 = 0; + let _temp_743 = 0; + let _temp_744 = 0; + let _temp_745 = 0; + let _temp_746 = 0; + let _temp_747 = 0; + let _temp_748 = 0; + let _temp_749 = 0; + let _temp_750 = 0; + let _temp_751 = 0; + let _temp_752 = 0; + let _temp_753 = 0; + let _temp_754 = 0; + let _temp_755 = 0; + let _temp_756 = 0; + let _temp_757 = 0; + let _temp_758 = 0; + let _temp_759 = 0; + let _temp_760 = 0; + let _temp_761 = 0; + let _temp_762 = 0; + let _temp_763 = 0; + let _temp_764 = 0; + let _temp_765 = 0; + let _temp_766 = 0; + let _temp_767 = 0; + let _temp_768 = 0; + let _temp_769 = 0; + let _temp_770 = 0; + let _temp_771 = 0; + let _temp_772 = 0; + let _temp_773 = 0; + let _temp_774 = 0; + let _temp_775 = 0; + let _temp_776 = 0; + let _temp_777 = 0; + let _temp_778 = 0; + let _temp_779 = 0; + let _temp_780 = 0; + let _temp_781 = 0; + let _temp_782 = 0; + let _temp_783 = 0; + let _temp_784 = 0; + let _temp_785 = 0; + let _temp_786 = 0; + let _temp_787 = 0; + let _temp_788 = 0; + let _temp_789 = 0; + let _temp_790 = 0; + let _temp_791 = 0; + let _temp_792 = 0; + let _temp_793 = 0; + let _temp_794 = 0; + let _temp_795 = 0; + let _temp_796 = 0; + let _temp_797 = 0; + let _temp_798 = 0; + let _temp_799 = 0; + let _temp_800 = 0; + let _temp_801 = 0; + let _temp_802 = 0; + let _temp_803 = 0; + let _temp_804 = 0; + let _temp_805 = 0; + let _temp_806 = 0; + let _temp_807 = 0; + let _temp_808 = 0; + let _temp_809 = 0; + let _temp_810 = 0; + let _temp_811 = 0; + let _temp_812 = 0; + let _temp_813 = 0; + let _temp_814 = 0; + let _temp_815 = 0; + let _temp_816 = 0; + let _temp_817 = 0; + let _temp_818 = 0; + let _temp_819 = 0; + let _temp_820 = 0; + let _temp_821 = 0; + let _temp_822 = 0; + let _temp_823 = 0; + let _temp_824 = 0; + let _temp_825 = 0; + let _temp_826 = 0; + let _temp_827 = 0; + let _temp_828 = 0; + let _temp_829 = 0; + let _temp_830 = 0; + let _temp_831 = 0; + let _temp_832 = 0; + let _temp_833 = 0; + let _temp_834 = 0; + let _temp_835 = 0; + let _temp_836 = 0; + let _temp_837 = 0; + let _temp_838 = 0; + let _temp_839 = 0; + let _temp_840 = 0; + let _temp_841 = 0; + let _temp_842 = 0; + let _temp_843 = 0; + let _temp_844 = 0; + let _temp_845 = 0; + let _temp_846 = 0; + let _temp_847 = 0; + let _temp_848 = 0; + let _temp_849 = 0; + let _temp_850 = 0; + let _temp_851 = 0; + let _temp_852 = 0; + let _temp_853 = 0; + let _temp_854 = 0; + let _temp_855 = 0; + let _temp_856 = 0; + let _temp_857 = 0; + let _temp_858 = 0; + let _temp_859 = 0; + let _temp_860 = 0; + let _temp_861 = 0; + let _temp_862 = 0; + let _temp_863 = 0; + let _temp_864 = 0; + let _temp_865 = 0; + let _temp_866 = 0; + let _temp_867 = 0; + let _temp_868 = 0; + let _temp_869 = 0; + let _temp_870 = 0; + let _temp_871 = 0; + let _temp_872 = 0; + let _temp_873 = 0; + let _temp_874 = 0; + let _temp_875 = 0; + let _temp_876 = 0; + let _temp_877 = 0; + let _temp_878 = 0; + let _temp_879 = 0; + let _temp_880 = 0; + let _temp_881 = 0; + let _temp_882 = 0; + let _temp_883 = 0; + let _temp_884 = 0; + let _temp_885 = 0; + let _temp_886 = 0; + let _temp_887 = 0; + let _temp_888 = 0; + let _temp_889 = 0; + let _temp_890 = 0; + let _temp_891 = 0; + let _temp_892 = 0; + let _temp_893 = 0; + let _temp_894 = 0; + let _temp_895 = 0; + let _temp_896 = 0; + let _temp_897 = 0; + let _temp_898 = 0; + let _temp_899 = 0; + let _temp_900 = 0; + let _temp_901 = 0; + let _temp_902 = 0; + let _temp_903 = 0; + let _temp_904 = 0; + let _temp_905 = 0; + let _temp_906 = 0; + let _temp_907 = 0; + let _temp_908 = 0; + let _temp_909 = 0; + let _temp_910 = 0; + let _temp_911 = 0; + let _temp_912 = 0; + let _temp_913 = 0; + let _temp_914 = 0; + let _temp_915 = 0; + let _temp_916 = 0; + let _temp_917 = 0; + let _temp_918 = 0; + let _temp_919 = 0; + let _temp_920 = 0; + let _temp_921 = 0; + let _temp_922 = 0; + let _temp_923 = 0; + let _temp_924 = 0; + let _temp_925 = 0; + let _temp_926 = 0; + let _temp_927 = 0; + let _temp_928 = 0; + let _temp_929 = 0; + let _temp_930 = 0; + let _temp_931 = 0; + let _temp_932 = 0; + let _temp_933 = 0; + let _temp_934 = 0; + let _temp_935 = 0; + let _temp_936 = 0; + let _temp_937 = 0; + let _temp_938 = 0; + let _temp_939 = 0; + let _temp_940 = 0; + let _temp_941 = 0; + let _temp_942 = 0; + let _temp_943 = 0; + let _temp_944 = 0; + let _temp_945 = 0; + let _temp_946 = 0; + let _temp_947 = 0; + let _temp_948 = 0; + let _temp_949 = 0; + let _temp_950 = 0; + let _temp_951 = 0; + let _temp_952 = 0; + let _temp_953 = 0; + let _temp_954 = 0; + let _temp_955 = 0; + let _temp_956 = 0; + let _temp_957 = 0; + let _temp_958 = 0; + let _temp_959 = 0; + let _temp_960 = 0; + let _temp_961 = 0; + let _temp_962 = 0; + let _temp_963 = 0; + let _temp_964 = 0; + let _temp_965 = 0; + let _temp_966 = 0; + let _temp_967 = 0; + let _temp_968 = 0; + let _temp_969 = 0; + let _temp_970 = 0; + let _temp_971 = 0; + let _temp_972 = 0; + let _temp_973 = 0; + let _temp_974 = 0; + let _temp_975 = 0; + let _temp_976 = 0; + let _temp_977 = 0; + let _temp_978 = 0; + let _temp_979 = 0; + let _temp_980 = 0; + let _temp_981 = 0; + let _temp_982 = 0; + let _temp_983 = 0; + let _temp_984 = 0; + let _temp_985 = 0; + let _temp_986 = 0; + let _temp_987 = 0; + let _temp_988 = 0; + let _temp_989 = 0; + let _temp_990 = 0; + let _temp_991 = 0; + let _temp_992 = 0; + let _temp_993 = 0; + let _temp_994 = 0; + let _temp_995 = 0; + let _temp_996 = 0; + let _temp_997 = 0; + let _temp_998 = 0; + let _temp_999 = 0; + let _temp_1000 = 0; + let _temp_1001 = 0; + let _temp_1002 = 0; + let _temp_1003 = 0; + let _temp_1004 = 0; + let _temp_1005 = 0; + let _temp_1006 = 0; + let _temp_1007 = 0; + let _temp_1008 = 0; + let _temp_1009 = 0; + let _temp_1010 = 0; + let _temp_1011 = 0; + let _temp_1012 = 0; + let _temp_1013 = 0; + let _temp_1014 = 0; + let _temp_1015 = 0; + let _temp_1016 = 0; + let _temp_1017 = 0; + let _temp_1018 = 0; + let _temp_1019 = 0; + let _temp_1020 = 0; + let _temp_1021 = 0; + let _temp_1022 = 0; + let _temp_1023 = 0; + let _temp_1024 = 0; + let _temp_1025 = 0; + let _temp_1026 = 0; + let _temp_1027 = 0; + let _temp_1028 = 0; + let _temp_1029 = 0; + let _temp_1030 = 0; + let _temp_1031 = 0; + let _temp_1032 = 0; + let _temp_1033 = 0; + let _temp_1034 = 0; + let _temp_1035 = 0; + let _temp_1036 = 0; + let _temp_1037 = 0; + let _temp_1038 = 0; + let _temp_1039 = 0; + let _temp_1040 = 0; + let _temp_1041 = 0; + let _temp_1042 = 0; + let _temp_1043 = 0; + let _temp_1044 = 0; + let _temp_1045 = 0; + let _temp_1046 = 0; + let _temp_1047 = 0; + let _temp_1048 = 0; + let _temp_1049 = 0; + let _temp_1050 = 0; + let _temp_1051 = 0; + let _temp_1052 = 0; + let _temp_1053 = 0; + let _temp_1054 = 0; + let _temp_1055 = 0; + let _temp_1056 = 0; + let _temp_1057 = 0; + let _temp_1058 = 0; + let _temp_1059 = 0; + let _temp_1060 = 0; + let _temp_1061 = 0; + let _temp_1062 = 0; + let _temp_1063 = 0; + let _temp_1064 = 0; + let _temp_1065 = 0; + let _temp_1066 = 0; + let _temp_1067 = 0; + let _temp_1068 = 0; + let _temp_1069 = 0; + let _temp_1070 = 0; + let _temp_1071 = 0; + let _temp_1072 = 0; + let _temp_1073 = 0; + let _temp_1074 = 0; + let _temp_1075 = 0; + let _temp_1076 = 0; + let _temp_1077 = 0; + let _temp_1078 = 0; + let _temp_1079 = 0; + let _temp_1080 = 0; + let _temp_1081 = 0; + let _temp_1082 = 0; + let _temp_1083 = 0; + let _temp_1084 = 0; + let _temp_1085 = 0; + let _temp_1086 = 0; + let _temp_1087 = 0; + let _temp_1088 = 0; + let _temp_1089 = 0; + let _temp_1090 = 0; + let _temp_1091 = 0; + let _temp_1092 = 0; + let _temp_1093 = 0; + let _temp_1094 = 0; + let _temp_1095 = 0; + let _temp_1096 = 0; + let _temp_1097 = 0; + let _temp_1098 = 0; + let _temp_1099 = 0; + let _temp_1100 = 0; + let _temp_1101 = 0; + let _temp_1102 = 0; + let _temp_1103 = 0; + let _temp_1104 = 0; + let _temp_1105 = 0; + let _temp_1106 = 0; + let _temp_1107 = 0; + let _temp_1108 = 0; + let _temp_1109 = 0; + let _temp_1110 = 0; + let _temp_1111 = 0; + let _temp_1112 = 0; + let _temp_1113 = 0; + let _temp_1114 = 0; + let _temp_1115 = 0; + let _temp_1116 = 0; + let _temp_1117 = 0; + let _temp_1118 = 0; + let _temp_1119 = 0; + let _temp_1120 = 0; + let _temp_1121 = 0; + let _temp_1122 = 0; + let _temp_1123 = 0; + let _temp_1124 = 0; + let _temp_1125 = 0; + let _temp_1126 = 0; + let _temp_1127 = 0; + let _temp_1128 = 0; + let _temp_1129 = 0; + let _temp_1130 = 0; + let _temp_1131 = 0; + let _temp_1132 = 0; + let _temp_1133 = 0; + let _temp_1134 = 0; + let _temp_1135 = 0; + let _temp_1136 = 0; + let _temp_1137 = 0; + let _temp_1138 = 0; + let _temp_1139 = 0; + let _temp_1140 = 0; + let _temp_1141 = 0; + let _temp_1142 = 0; + let _temp_1143 = 0; + let _temp_1144 = 0; + let _temp_1145 = 0; + let _temp_1146 = 0; + let _temp_1147 = 0; + let _temp_1148 = 0; + let _temp_1149 = 0; + let _temp_1150 = 0; + let _temp_1151 = 0; + let _temp_1152 = 0; + let _temp_1153 = 0; + let _temp_1154 = 0; + let _temp_1155 = 0; + let _temp_1156 = 0; + let _temp_1157 = 0; + let _temp_1158 = 0; + let _temp_1159 = 0; + let _temp_1160 = 0; + let _temp_1161 = 0; + let _temp_1162 = 0; + let _temp_1163 = 0; + let _temp_1164 = 0; + let _temp_1165 = 0; + let _temp_1166 = 0; + let _temp_1167 = 0; + let _temp_1168 = 0; + let _temp_1169 = 0; + let _temp_1170 = 0; + let _temp_1171 = 0; + let _temp_1172 = 0; + let _temp_1173 = 0; + let _temp_1174 = 0; + let _temp_1175 = 0; + let _temp_1176 = 0; + let _temp_1177 = 0; + let _temp_1178 = 0; + let _temp_1179 = 0; + let _temp_1180 = 0; + let _temp_1181 = 0; + let _temp_1182 = 0; + let _temp_1183 = 0; + let _temp_1184 = 0; + let _temp_1185 = 0; + let _temp_1186 = 0; + let _temp_1187 = 0; + let _temp_1188 = 0; + let _temp_1189 = 0; + let _temp_1190 = 0; + let _temp_1191 = 0; + let _temp_1192 = 0; + let _temp_1193 = 0; + let _temp_1194 = 0; + let _temp_1195 = 0; + let _temp_1196 = 0; + let _temp_1197 = 0; + let _temp_1198 = 0; + let _temp_1199 = 0; + let _temp_1200 = 0; + let _temp_1201 = 0; + let _temp_1202 = 0; + let _temp_1203 = 0; + let _temp_1204 = 0; + let _temp_1205 = 0; + let _temp_1206 = 0; + let _temp_1207 = 0; + let _temp_1208 = 0; + let _temp_1209 = 0; + let _temp_1210 = 0; + let _temp_1211 = 0; + let _temp_1212 = 0; + let _temp_1213 = 0; + let _temp_1214 = 0; + let _temp_1215 = 0; + let _temp_1216 = 0; + let _temp_1217 = 0; + let _temp_1218 = 0; + let _temp_1219 = 0; + let _temp_1220 = 0; + let _temp_1221 = 0; + let _temp_1222 = 0; + let _temp_1223 = 0; + let _temp_1224 = 0; + let _temp_1225 = 0; + let _temp_1226 = 0; + let _temp_1227 = 0; + let _temp_1228 = 0; + let _temp_1229 = 0; + let _temp_1230 = 0; + let _temp_1231 = 0; + let _temp_1232 = 0; + let _temp_1233 = 0; + let _temp_1234 = 0; + let _temp_1235 = 0; + let _temp_1236 = 0; + let _temp_1237 = 0; + let _temp_1238 = 0; + let _temp_1239 = 0; + let _temp_1240 = 0; + let _temp_1241 = 0; + let _temp_1242 = 0; + let _temp_1243 = 0; + let _temp_1244 = 0; + let _temp_1245 = 0; + let _temp_1246 = 0; + let _temp_1247 = 0; + let _temp_1248 = 0; + let _temp_1249 = 0; + let _temp_1250 = 0; + let _temp_1251 = 0; + let _temp_1252 = 0; + let _temp_1253 = 0; + let _temp_1254 = 0; + let _temp_1255 = 0; + let _temp_1256 = 0; + let _temp_1257 = 0; + let _temp_1258 = 0; + let _temp_1259 = 0; + let _temp_1260 = 0; + let _temp_1261 = 0; + let _temp_1262 = 0; + let _temp_1263 = 0; + let _temp_1264 = 0; + let _temp_1265 = 0; + let _temp_1266 = 0; + let _temp_1267 = 0; + let _temp_1268 = 0; + let _temp_1269 = 0; + let _temp_1270 = 0; + let _temp_1271 = 0; + let _temp_1272 = 0; + let _temp_1273 = 0; + let _temp_1274 = 0; + let _temp_1275 = 0; + let _temp_1276 = 0; + let _temp_1277 = 0; + let _temp_1278 = 0; + let _temp_1279 = 0; + let _temp_1280 = 0; + let _temp_1281 = 0; + let _temp_1282 = 0; + let _temp_1283 = 0; + let _temp_1284 = 0; + let _temp_1285 = 0; + let _temp_1286 = 0; + let _temp_1287 = 0; + let _temp_1288 = 0; + let _temp_1289 = 0; + let _temp_1290 = 0; + let _temp_1291 = 0; + let _temp_1292 = 0; + let _temp_1293 = 0; + let _temp_1294 = 0; + let _temp_1295 = 0; + let _temp_1296 = 0; + let _temp_1297 = 0; + let _temp_1298 = 0; + let _temp_1299 = 0; + let _temp_1300 = 0; + let _temp_1301 = 0; + let _temp_1302 = 0; + let _temp_1303 = 0; + let _temp_1304 = 0; + let _temp_1305 = 0; + let _temp_1306 = 0; + let _temp_1307 = 0; + let _temp_1308 = 0; + let _temp_1309 = 0; + let _temp_1310 = 0; + let _temp_1311 = 0; + let _temp_1312 = 0; + let _temp_1313 = 0; + let _temp_1314 = 0; + let _temp_1315 = 0; + let _temp_1316 = 0; + let _temp_1317 = 0; + let _temp_1318 = 0; + let _temp_1319 = 0; + let _temp_1320 = 0; + let _temp_1321 = 0; + let _temp_1322 = 0; + let _temp_1323 = 0; + let _temp_1324 = 0; + let _temp_1325 = 0; + let _temp_1326 = 0; + let _temp_1327 = 0; + let _temp_1328 = 0; + let _temp_1329 = 0; + let _temp_1330 = 0; + let _temp_1331 = 0; + let _temp_1332 = 0; + let _temp_1333 = 0; + let _temp_1334 = 0; + let _temp_1335 = 0; + let _temp_1336 = 0; + let _temp_1337 = 0; + let _temp_1338 = 0; + let _temp_1339 = 0; + let _temp_1340 = 0; + let _temp_1341 = 0; + let _temp_1342 = 0; + let _temp_1343 = 0; + let _temp_1344 = 0; + let _temp_1345 = 0; + let _temp_1346 = 0; + let _temp_1347 = 0; + let _temp_1348 = 0; + let _temp_1349 = 0; + let _temp_1350 = 0; + let _temp_1351 = 0; + let _temp_1352 = 0; + let _temp_1353 = 0; + let _temp_1354 = 0; + let _temp_1355 = 0; + let _temp_1356 = 0; + let _temp_1357 = 0; + let _temp_1358 = 0; + let _temp_1359 = 0; + let _temp_1360 = 0; + let _temp_1361 = 0; + let _temp_1362 = 0; + let _temp_1363 = 0; + let _temp_1364 = 0; + let _temp_1365 = 0; + let _temp_1366 = 0; + let _temp_1367 = 0; + let _temp_1368 = 0; + let _temp_1369 = 0; + let _temp_1370 = 0; + let _temp_1371 = 0; + let _temp_1372 = 0; + let _temp_1373 = 0; + let _temp_1374 = 0; + let _temp_1375 = 0; + let _temp_1376 = 0; + let _temp_1377 = 0; + let _temp_1378 = 0; + let _temp_1379 = 0; + let _temp_1380 = 0; + let _temp_1381 = 0; + let _temp_1382 = 0; + let _temp_1383 = 0; + let _temp_1384 = 0; + let _temp_1385 = 0; + let _temp_1386 = 0; + let _temp_1387 = 0; + let _temp_1388 = 0; + let _temp_1389 = 0; + let _temp_1390 = 0; + let _temp_1391 = 0; + let _temp_1392 = 0; + let _temp_1393 = 0; + let _temp_1394 = 0; + let _temp_1395 = 0; + let _temp_1396 = 0; + let _temp_1397 = 0; + let _temp_1398 = 0; + let _temp_1399 = 0; + let _temp_1400 = 0; + let _temp_1401 = 0; + let _temp_1402 = 0; + let _temp_1403 = 0; + let _temp_1404 = 0; + let _temp_1405 = 0; + let _temp_1406 = 0; + let _temp_1407 = 0; + let _temp_1408 = 0; + let _temp_1409 = 0; + let _temp_1410 = 0; + let _temp_1411 = 0; + let _temp_1412 = 0; + let _temp_1413 = 0; + let _temp_1414 = 0; + let _temp_1415 = 0; + let _temp_1416 = 0; + let _temp_1417 = 0; + let _temp_1418 = 0; + let _temp_1419 = 0; + let _temp_1420 = 0; + let _temp_1421 = 0; + let _temp_1422 = 0; + let _temp_1423 = 0; + let _temp_1424 = 0; + let _temp_1425 = 0; + let _temp_1426 = 0; + let _temp_1427 = 0; + let _temp_1428 = 0; + let _temp_1429 = 0; + let _temp_1430 = 0; + let _temp_1431 = 0; + let _temp_1432 = 0; + let _temp_1433 = 0; + let _temp_1434 = 0; + let _temp_1435 = 0; + let _temp_1436 = 0; + let _temp_1437 = 0; + let _temp_1438 = 0; + let _temp_1439 = 0; + let _temp_1440 = 0; + let _temp_1441 = 0; + let _temp_1442 = 0; + let _temp_1443 = 0; + let _temp_1444 = 0; + let _temp_1445 = 0; + let _temp_1446 = 0; + let _temp_1447 = 0; + let _temp_1448 = 0; + let _temp_1449 = 0; + let _temp_1450 = 0; + let _temp_1451 = 0; + let _temp_1452 = 0; + let _temp_1453 = 0; + let _temp_1454 = 0; + let _temp_1455 = 0; + let _temp_1456 = 0; + let _temp_1457 = 0; + let _temp_1458 = 0; + let _temp_1459 = 0; + let _temp_1460 = 0; + let _temp_1461 = 0; + let _temp_1462 = 0; + let _temp_1463 = 0; + let _temp_1464 = 0; + let _temp_1465 = 0; + let _temp_1466 = 0; + let _temp_1467 = 0; + let _temp_1468 = 0; + let _temp_1469 = 0; + let _temp_1470 = 0; + let _temp_1471 = 0; + let _temp_1472 = 0; + let _temp_1473 = 0; + let _temp_1474 = 0; + let _temp_1475 = 0; + let _temp_1476 = 0; + let _temp_1477 = 0; + let _temp_1478 = 0; + let _temp_1479 = 0; + let _temp_1480 = 0; + let _temp_1481 = 0; + let _temp_1482 = 0; + let _temp_1483 = 0; + let _temp_1484 = 0; + let _temp_1485 = 0; + let _temp_1486 = 0; + let _temp_1487 = 0; + let _temp_1488 = 0; + let _temp_1489 = 0; + let _temp_1490 = 0; + let _temp_1491 = 0; + let _temp_1492 = 0; + let _temp_1493 = 0; + let _temp_1494 = 0; + let _temp_1495 = 0; + let _temp_1496 = 0; + let _temp_1497 = 0; + let _temp_1498 = 0; + let _temp_1499 = 0; + let _temp_1500 = 0; + let _temp_1501 = 0; + let _temp_1502 = 0; + let _temp_1503 = 0; + let _temp_1504 = 0; + let _temp_1505 = 0; + let _temp_1506 = 0; + let _temp_1507 = 0; + let _temp_1508 = 0; + let _temp_1509 = 0; + let _temp_1510 = 0; + let _temp_1511 = 0; + let _temp_1512 = 0; + let _temp_1513 = 0; + let _temp_1514 = 0; + let _temp_1515 = 0; + let _temp_1516 = 0; + let _temp_1517 = 0; + let _temp_1518 = 0; + let _temp_1519 = 0; + let _temp_1520 = 0; + let _temp_1521 = 0; + let _temp_1522 = 0; + let _temp_1523 = 0; + let _temp_1524 = 0; + let _temp_1525 = 0; + let _temp_1526 = 0; + let _temp_1527 = 0; + let _temp_1528 = 0; + let _temp_1529 = 0; + let _temp_1530 = 0; + let _temp_1531 = 0; + let _temp_1532 = 0; + let _temp_1533 = 0; + let _temp_1534 = 0; + let _temp_1535 = 0; + let _temp_1536 = 0; + let _temp_1537 = 0; + let _temp_1538 = 0; + let _temp_1539 = 0; + let _temp_1540 = 0; + let _temp_1541 = 0; + let _temp_1542 = 0; + let _temp_1543 = 0; + let _temp_1544 = 0; + let _temp_1545 = 0; + let _temp_1546 = 0; + let _temp_1547 = 0; + let _temp_1548 = 0; + let _temp_1549 = 0; + let _temp_1550 = 0; + let _temp_1551 = 0; + let _temp_1552 = 0; + let _temp_1553 = 0; + let _temp_1554 = 0; + let _temp_1555 = 0; + let _temp_1556 = 0; + let _temp_1557 = 0; + let _temp_1558 = 0; + let _temp_1559 = 0; + let _temp_1560 = 0; + let _temp_1561 = 0; + let _temp_1562 = 0; + let _temp_1563 = 0; + let _temp_1564 = 0; + let _temp_1565 = 0; + let _temp_1566 = 0; + let _temp_1567 = 0; + let _temp_1568 = 0; + let _temp_1569 = 0; + let _temp_1570 = 0; + let _temp_1571 = 0; + let _temp_1572 = 0; + let _temp_1573 = 0; + let _temp_1574 = 0; + let _temp_1575 = 0; + let _temp_1576 = 0; + let _temp_1577 = 0; + let _temp_1578 = 0; + let _temp_1579 = 0; + let _temp_1580 = 0; + let _temp_1581 = 0; + let _temp_1582 = 0; + let _temp_1583 = 0; + let _temp_1584 = 0; + let _temp_1585 = 0; + let _temp_1586 = 0; + let _temp_1587 = 0; + let _temp_1588 = 0; + let _temp_1589 = 0; + let _temp_1590 = 0; + let _temp_1591 = 0; + let _temp_1592 = 0; + let _temp_1593 = 0; + let _temp_1594 = 0; + let _temp_1595 = 0; + let _temp_1596 = 0; + let _temp_1597 = 0; + let _temp_1598 = 0; + let _temp_1599 = 0; + let _temp_1600 = 0; + let _temp_1601 = 0; + let _temp_1602 = 0; + let _temp_1603 = 0; + let _temp_1604 = 0; + let _temp_1605 = 0; + let _temp_1606 = 0; + let _temp_1607 = 0; + let _temp_1608 = 0; + let _temp_1609 = 0; + let _temp_1610 = 0; + let _temp_1611 = 0; + let _temp_1612 = 0; + let _temp_1613 = 0; + let _temp_1614 = 0; + let _temp_1615 = 0; + let _temp_1616 = 0; + let _temp_1617 = 0; + let _temp_1618 = 0; + let _temp_1619 = 0; + let _temp_1620 = 0; + let _temp_1621 = 0; + let _temp_1622 = 0; + let _temp_1623 = 0; + let _temp_1624 = 0; + let _temp_1625 = 0; + let _temp_1626 = 0; + let _temp_1627 = 0; + let _temp_1628 = 0; + let _temp_1629 = 0; + let _temp_1630 = 0; + let _temp_1631 = 0; + let _temp_1632 = 0; + let _temp_1633 = 0; + let _temp_1634 = 0; + let _temp_1635 = 0; + let _temp_1636 = 0; + let _temp_1637 = 0; + let _temp_1638 = 0; + let _temp_1639 = 0; + let _temp_1640 = 0; + let _temp_1641 = 0; + let _temp_1642 = 0; + let _temp_1643 = 0; + let _temp_1644 = 0; + let _temp_1645 = 0; + let _temp_1646 = 0; + let _temp_1647 = 0; + let _temp_1648 = 0; + let _temp_1649 = 0; + let _temp_1650 = 0; + let _temp_1651 = 0; + let _temp_1652 = 0; + let _temp_1653 = 0; + let _temp_1654 = 0; + let _temp_1655 = 0; + let _temp_1656 = 0; + let _temp_1657 = 0; + let _temp_1658 = 0; + let _temp_1659 = 0; + let _temp_1660 = 0; + let _temp_1661 = 0; + let _temp_1662 = 0; + let _temp_1663 = 0; + let _temp_1664 = 0; + let _temp_1665 = 0; + let _temp_1666 = 0; + let _temp_1667 = 0; + let _temp_1668 = 0; + let _temp_1669 = 0; + let _temp_1670 = 0; + let _temp_1671 = 0; + let _temp_1672 = 0; + let _temp_1673 = 0; + let _temp_1674 = 0; + let _temp_1675 = 0; + let _temp_1676 = 0; + let _temp_1677 = 0; + let _temp_1678 = 0; + let _temp_1679 = 0; + let _temp_1680 = 0; + let _temp_1681 = 0; + let _temp_1682 = 0; + let _temp_1683 = 0; + let _temp_1684 = 0; + let _temp_1685 = 0; + let _temp_1686 = 0; + let _temp_1687 = 0; + let _temp_1688 = 0; + let _temp_1689 = 0; + let _temp_1690 = 0; + let _temp_1691 = 0; + let _temp_1692 = 0; + let _temp_1693 = 0; + let _temp_1694 = 0; + let _temp_1695 = 0; + let _temp_1696 = 0; + let _temp_1697 = 0; + let _temp_1698 = 0; + let _temp_1699 = 0; + let _temp_1700 = 0; + let _temp_1701 = 0; + let _temp_1702 = 0; + let _temp_1703 = 0; + let _temp_1704 = 0; + let _temp_1705 = 0; + let _temp_1706 = 0; + let _temp_1707 = 0; + let _temp_1708 = 0; + let _temp_1709 = 0; + let _temp_1710 = 0; + let _temp_1711 = 0; + let _temp_1712 = 0; + let _temp_1713 = 0; + let _temp_1714 = 0; + let _temp_1715 = 0; + let _temp_1716 = 0; + let _temp_1717 = 0; + let _temp_1718 = 0; + let _temp_1719 = 0; + let _temp_1720 = 0; + let _temp_1721 = 0; + let _temp_1722 = 0; + let _temp_1723 = 0; + let _temp_1724 = 0; + let _temp_1725 = 0; + let _temp_1726 = 0; + let _temp_1727 = 0; + let _temp_1728 = 0; + let _temp_1729 = 0; + let _temp_1730 = 0; + let _temp_1731 = 0; + let _temp_1732 = 0; + let _temp_1733 = 0; + let _temp_1734 = 0; + let _temp_1735 = 0; + let _temp_1736 = 0; + let _temp_1737 = 0; + let _temp_1738 = 0; + let _temp_1739 = 0; + let _temp_1740 = 0; + let _temp_1741 = 0; + let _temp_1742 = 0; + let _temp_1743 = 0; + let _temp_1744 = 0; + let _temp_1745 = 0; + let _temp_1746 = 0; + let _temp_1747 = 0; + let _temp_1748 = 0; + let _temp_1749 = 0; + let _temp_1750 = 0; + let _temp_1751 = 0; + let _temp_1752 = 0; + let _temp_1753 = 0; + let _temp_1754 = 0; + let _temp_1755 = 0; + let _temp_1756 = 0; + let _temp_1757 = 0; + let _temp_1758 = 0; + let _temp_1759 = 0; + let _temp_1760 = 0; + let _temp_1761 = 0; + let _temp_1762 = 0; + let _temp_1763 = 0; + let _temp_1764 = 0; + let _temp_1765 = 0; + let _temp_1766 = 0; + let _temp_1767 = 0; + let _temp_1768 = 0; + let _temp_1769 = 0; + let _temp_1770 = 0; + let _temp_1771 = 0; + let _temp_1772 = 0; + let _temp_1773 = 0; + let _temp_1774 = 0; + let _temp_1775 = 0; + let _temp_1776 = 0; + let _temp_1777 = 0; + let _temp_1778 = 0; + let _temp_1779 = 0; + let _temp_1780 = 0; + let _temp_1781 = 0; + let _temp_1782 = 0; + let _temp_1783 = 0; + let _temp_1784 = 0; + let _temp_1785 = 0; + let _temp_1786 = 0; + let _temp_1787 = 0; + let _temp_1788 = 0; + let _temp_1789 = 0; + let _temp_1790 = 0; + let _temp_1791 = 0; + let _temp_1792 = 0; + let _temp_1793 = 0; + let _temp_1794 = 0; + let _temp_1795 = 0; + let _temp_1796 = 0; + let _temp_1797 = 0; + let _temp_1798 = 0; + let _temp_1799 = 0; + let _temp_1800 = 0; + let _temp_1801 = 0; + let _temp_1802 = 0; + let _temp_1803 = 0; + let _temp_1804 = 0; + let _temp_1805 = 0; + let _temp_1806 = 0; + let _temp_1807 = 0; + let _temp_1808 = 0; + let _temp_1809 = 0; + let _temp_1810 = 0; + let _temp_1811 = 0; + let _temp_1812 = 0; + let _temp_1813 = 0; + let _temp_1814 = 0; + let _temp_1815 = 0; + let _temp_1816 = 0; + let _temp_1817 = 0; + let _temp_1818 = 0; + let _temp_1819 = 0; + let _temp_1820 = 0; + let _temp_1821 = 0; + let _temp_1822 = 0; + let _temp_1823 = 0; + let _temp_1824 = 0; + let _temp_1825 = 0; + let _temp_1826 = 0; + let _temp_1827 = 0; + let _temp_1828 = 0; + let _temp_1829 = 0; + let _temp_1830 = 0; + let _temp_1831 = 0; + let _temp_1832 = 0; + let _temp_1833 = 0; + let _temp_1834 = 0; + let _temp_1835 = 0; + let _temp_1836 = 0; + let _temp_1837 = 0; + let _temp_1838 = 0; + let _temp_1839 = 0; + let _temp_1840 = 0; + let _temp_1841 = 0; + let _temp_1842 = 0; + let _temp_1843 = 0; + let _temp_1844 = 0; + let _temp_1845 = 0; + let _temp_1846 = 0; + let _temp_1847 = 0; + let _temp_1848 = 0; + let _temp_1849 = 0; + let _temp_1850 = 0; + let _temp_1851 = 0; + let _temp_1852 = 0; + let _temp_1853 = 0; + let _temp_1854 = 0; + let _temp_1855 = 0; + let _temp_1856 = 0; + let _temp_1857 = 0; + let _temp_1858 = 0; + let _temp_1859 = 0; + let _temp_1860 = 0; + let _temp_1861 = 0; + let _temp_1862 = 0; + let _temp_1863 = 0; + let _temp_1864 = 0; + let _temp_1865 = 0; + let _temp_1866 = 0; + let _temp_1867 = 0; + let _temp_1868 = 0; + let _temp_1869 = 0; + let _temp_1870 = 0; + let _temp_1871 = 0; + let _temp_1872 = 0; + let _temp_1873 = 0; + let _temp_1874 = 0; + let _temp_1875 = 0; + let _temp_1876 = 0; + let _temp_1877 = 0; + let _temp_1878 = 0; + let _temp_1879 = 0; + let _temp_1880 = 0; + let _temp_1881 = 0; + let _temp_1882 = 0; + let _temp_1883 = 0; + let _temp_1884 = 0; + let _temp_1885 = 0; + let _temp_1886 = 0; + let _temp_1887 = 0; + let _temp_1888 = 0; + let _temp_1889 = 0; + let _temp_1890 = 0; + let _temp_1891 = 0; + let _temp_1892 = 0; + let _temp_1893 = 0; + let _temp_1894 = 0; + let _temp_1895 = 0; + let _temp_1896 = 0; + let _temp_1897 = 0; + let _temp_1898 = 0; + let _temp_1899 = 0; + let _temp_1900 = 0; + let _temp_1901 = 0; + let _temp_1902 = 0; + let _temp_1903 = 0; + let _temp_1904 = 0; + let _temp_1905 = 0; + let _temp_1906 = 0; + let _temp_1907 = 0; + let _temp_1908 = 0; + let _temp_1909 = 0; + let _temp_1910 = 0; + let _temp_1911 = 0; + let _temp_1912 = 0; + let _temp_1913 = 0; + let _temp_1914 = 0; + let _temp_1915 = 0; + let _temp_1916 = 0; + let _temp_1917 = 0; + let _temp_1918 = 0; + let _temp_1919 = 0; + let _temp_1920 = 0; + let _temp_1921 = 0; + let _temp_1922 = 0; + let _temp_1923 = 0; + let _temp_1924 = 0; + let _temp_1925 = 0; + let _temp_1926 = 0; + let _temp_1927 = 0; + let _temp_1928 = 0; + let _temp_1929 = 0; + let _temp_1930 = 0; + let _temp_1931 = 0; + let _temp_1932 = 0; + let _temp_1933 = 0; + let _temp_1934 = 0; + let _temp_1935 = 0; + let _temp_1936 = 0; + let _temp_1937 = 0; + let _temp_1938 = 0; + let _temp_1939 = 0; + let _temp_1940 = 0; + let _temp_1941 = 0; + let _temp_1942 = 0; + let _temp_1943 = 0; + let _temp_1944 = 0; + let _temp_1945 = 0; + let _temp_1946 = 0; + let _temp_1947 = 0; + let _temp_1948 = 0; + let _temp_1949 = 0; + let _temp_1950 = 0; + let _temp_1951 = 0; + let _temp_1952 = 0; + let _temp_1953 = 0; + let _temp_1954 = 0; + let _temp_1955 = 0; + let _temp_1956 = 0; + let _temp_1957 = 0; + let _temp_1958 = 0; + let _temp_1959 = 0; + let _temp_1960 = 0; + let _temp_1961 = 0; + let _temp_1962 = 0; + let _temp_1963 = 0; + let _temp_1964 = 0; + let _temp_1965 = 0; + let _temp_1966 = 0; + let _temp_1967 = 0; + let _temp_1968 = 0; + let _temp_1969 = 0; + let _temp_1970 = 0; + let _temp_1971 = 0; + let _temp_1972 = 0; + let _temp_1973 = 0; + let _temp_1974 = 0; + let _temp_1975 = 0; + let _temp_1976 = 0; + let _temp_1977 = 0; + let _temp_1978 = 0; + let _temp_1979 = 0; + let _temp_1980 = 0; + let _temp_1981 = 0; + let _temp_1982 = 0; + let _temp_1983 = 0; + let _temp_1984 = 0; + let _temp_1985 = 0; + let _temp_1986 = 0; + let _temp_1987 = 0; + let _temp_1988 = 0; + let _temp_1989 = 0; + let _temp_1990 = 0; + let _temp_1991 = 0; + let _temp_1992 = 0; + let _temp_1993 = 0; + let _temp_1994 = 0; + let _temp_1995 = 0; + let _temp_1996 = 0; + let _temp_1997 = 0; + let _temp_1998 = 0; + let _temp_1999 = 0; + let _temp_2000 = 0; + let _temp_2001 = 0; + let _temp_2002 = 0; + let _temp_2003 = 0; + let _temp_2004 = 0; + let _temp_2005 = 0; + let _temp_2006 = 0; + let _temp_2007 = 0; + let _temp_2008 = 0; + let _temp_2009 = 0; + let _temp_2010 = 0; + let _temp_2011 = 0; + let _temp_2012 = 0; + let _temp_2013 = 0; + let _temp_2014 = 0; + let _temp_2015 = 0; + let _temp_2016 = 0; + let _temp_2017 = 0; + let _temp_2018 = 0; + let _temp_2019 = 0; + let _temp_2020 = 0; + let _temp_2021 = 0; + let _temp_2022 = 0; + let _temp_2023 = 0; + let _temp_2024 = 0; + let _temp_2025 = 0; + let _temp_2026 = 0; + let _temp_2027 = 0; + let _temp_2028 = 0; + let _temp_2029 = 0; + let _temp_2030 = 0; + let _temp_2031 = 0; + let _temp_2032 = 0; + let _temp_2033 = 0; + let _temp_2034 = 0; + let _temp_2035 = 0; + let _temp_2036 = 0; + let _temp_2037 = 0; + let _temp_2038 = 0; + let _temp_2039 = 0; + let _temp_2040 = 0; + let _temp_2041 = 0; + let _temp_2042 = 0; + let _temp_2043 = 0; + let _temp_2044 = 0; + let _temp_2045 = 0; + let _temp_2046 = 0; + let _temp_2047 = 0; + let _temp_2048 = 0; + let _temp_2049 = 0; + let _temp_2050 = 0; + let _temp_2051 = 0; + let _temp_2052 = 0; + let _temp_2053 = 0; + let _temp_2054 = 0; + let _temp_2055 = 0; + let _temp_2056 = 0; + let _temp_2057 = 0; + let _temp_2058 = 0; + let _temp_2059 = 0; + let _temp_2060 = 0; + let _temp_2061 = 0; + let _temp_2062 = 0; + let _temp_2063 = 0; + let _temp_2064 = 0; + let _temp_2065 = 0; + let _temp_2066 = 0; + let _temp_2067 = 0; + let _temp_2068 = 0; + let _temp_2069 = 0; + let _temp_2070 = 0; + let _temp_2071 = 0; + let _temp_2072 = 0; + let _temp_2073 = 0; + let _temp_2074 = 0; + let _temp_2075 = 0; + let _temp_2076 = 0; + let _temp_2077 = 0; + let _temp_2078 = 0; + let _temp_2079 = 0; + let _temp_2080 = 0; + let _temp_2081 = 0; + let _temp_2082 = 0; + let _temp_2083 = 0; + let _temp_2084 = 0; + let _temp_2085 = 0; + let _temp_2086 = 0; + let _temp_2087 = 0; + let _temp_2088 = 0; + let _temp_2089 = 0; + let _temp_2090 = 0; + let _temp_2091 = 0; + let _temp_2092 = 0; + let _temp_2093 = 0; + let _temp_2094 = 0; + let _temp_2095 = 0; + let _temp_2096 = 0; + let _temp_2097 = 0; + let _temp_2098 = 0; + let _temp_2099 = 0; + let _temp_2100 = 0; + let _temp_2101 = 0; + let _temp_2102 = 0; + let _temp_2103 = 0; + let _temp_2104 = 0; + let _temp_2105 = 0; + let _temp_2106 = 0; + let _temp_2107 = 0; + let _temp_2108 = 0; + let _temp_2109 = 0; + let _temp_2110 = 0; + let _temp_2111 = 0; + let _temp_2112 = 0; + let _temp_2113 = 0; + let _temp_2114 = 0; + let _temp_2115 = 0; + let _temp_2116 = 0; + let _temp_2117 = 0; + let _temp_2118 = 0; + let _temp_2119 = 0; + let _temp_2120 = 0; + let _temp_2121 = 0; + let _temp_2122 = 0; + let _temp_2123 = 0; + let _temp_2124 = 0; + let _temp_2125 = 0; + let _temp_2126 = 0; + let _temp_2127 = 0; + let _temp_2128 = 0; + let _temp_2129 = 0; + let _temp_2130 = 0; + let _temp_2131 = 0; + let _temp_2132 = 0; + let _temp_2133 = 0; + let _temp_2134 = 0; + let _temp_2135 = 0; + let _temp_2136 = 0; + let _temp_2137 = 0; + let _temp_2138 = 0; + let _temp_2139 = 0; + let _temp_2140 = 0; + let _temp_2141 = 0; + let _temp_2142 = 0; + let _temp_2143 = 0; + let _temp_2144 = 0; + let _temp_2145 = 0; + let _temp_2146 = 0; + let _temp_2147 = 0; + let _temp_2148 = 0; + let _temp_2149 = 0; + let _temp_2150 = 0; + let _temp_2151 = 0; + let _temp_2152 = 0; + let _temp_2153 = 0; + let _temp_2154 = 0; + let _temp_2155 = 0; + let _temp_2156 = 0; + let _temp_2157 = 0; + let _temp_2158 = 0; + let _temp_2159 = 0; + let _temp_2160 = 0; + let _temp_2161 = 0; + let _temp_2162 = 0; + let _temp_2163 = 0; + let _temp_2164 = 0; + let _temp_2165 = 0; + let _temp_2166 = 0; + let _temp_2167 = 0; + let _temp_2168 = 0; + let _temp_2169 = 0; + let _temp_2170 = 0; + let _temp_2171 = 0; + let _temp_2172 = 0; + let _temp_2173 = 0; + let _temp_2174 = 0; + let _temp_2175 = 0; + let _temp_2176 = 0; + let _temp_2177 = 0; + let _temp_2178 = 0; + let _temp_2179 = 0; + let _temp_2180 = 0; + let _temp_2181 = 0; + let _temp_2182 = 0; + let _temp_2183 = 0; + let _temp_2184 = 0; + let _temp_2185 = 0; + let _temp_2186 = 0; + let _temp_2187 = 0; + let _temp_2188 = 0; + let _temp_2189 = 0; + let _temp_2190 = 0; + let _temp_2191 = 0; + let _temp_2192 = 0; + let _temp_2193 = 0; + let _temp_2194 = 0; + let _temp_2195 = 0; + let _temp_2196 = 0; + let _temp_2197 = 0; + let _temp_2198 = 0; + let _temp_2199 = 0; + let _temp_2200 = 0; + let _temp_2201 = 0; + let _temp_2202 = 0; + let _temp_2203 = 0; + let _temp_2204 = 0; + let _temp_2205 = 0; + let _temp_2206 = 0; + let _temp_2207 = 0; + let _temp_2208 = 0; + let _temp_2209 = 0; + let _temp_2210 = 0; + let _temp_2211 = 0; + let _temp_2212 = 0; + let _temp_2213 = 0; + let _temp_2214 = 0; + let _temp_2215 = 0; + let _temp_2216 = 0; + let _temp_2217 = 0; + let _temp_2218 = 0; + let _temp_2219 = 0; + let _temp_2220 = 0; + let _temp_2221 = 0; + let _temp_2222 = 0; + let _temp_2223 = 0; + let _temp_2224 = 0; + let _temp_2225 = 0; + let _temp_2226 = 0; + let _temp_2227 = 0; + let _temp_2228 = 0; + let _temp_2229 = 0; + let _temp_2230 = 0; + let _temp_2231 = 0; + let _temp_2232 = 0; + let _temp_2233 = 0; + let _temp_2234 = 0; + let _temp_2235 = 0; + let _temp_2236 = 0; + let _temp_2237 = 0; + let _temp_2238 = 0; + let _temp_2239 = 0; + let _temp_2240 = 0; + let _temp_2241 = 0; + let _temp_2242 = 0; + let _temp_2243 = 0; + let _temp_2244 = 0; + let _temp_2245 = 0; + let _temp_2246 = 0; + let _temp_2247 = 0; + let _temp_2248 = 0; + let _temp_2249 = 0; + let _temp_2250 = 0; + let _temp_2251 = 0; + let _temp_2252 = 0; + let _temp_2253 = 0; + let _temp_2254 = 0; + let _temp_2255 = 0; + let _temp_2256 = 0; + let _temp_2257 = 0; + let _temp_2258 = 0; + let _temp_2259 = 0; + let _temp_2260 = 0; + let _temp_2261 = 0; + let _temp_2262 = 0; + let _temp_2263 = 0; + let _temp_2264 = 0; + let _temp_2265 = 0; + let _temp_2266 = 0; + let _temp_2267 = 0; + let _temp_2268 = 0; + let _temp_2269 = 0; + let _temp_2270 = 0; + let _temp_2271 = 0; + let _temp_2272 = 0; + let _temp_2273 = 0; + let _temp_2274 = 0; + let _temp_2275 = 0; + let _temp_2276 = 0; + let _temp_2277 = 0; + let _temp_2278 = 0; + let _temp_2279 = 0; + let _temp_2280 = 0; + let _temp_2281 = 0; + let _temp_2282 = 0; + let _temp_2283 = 0; + let _temp_2284 = 0; + let _temp_2285 = 0; + let _temp_2286 = 0; + let _temp_2287 = 0; + let _temp_2288 = 0; + let _temp_2289 = 0; + let _temp_2290 = 0; + let _temp_2291 = 0; + let _temp_2292 = 0; + let _temp_2293 = 0; + let _temp_2294 = 0; + let _temp_2295 = 0; + let _temp_2296 = 0; + let _temp_2297 = 0; + let _temp_2298 = 0; + let _temp_2299 = 0; + let _temp_2300 = 0; + let _temp_2301 = 0; + let _temp_2302 = 0; + let _temp_2303 = 0; + let _temp_2304 = 0; + let _temp_2305 = 0; + let _temp_2306 = 0; + let _temp_2307 = 0; + let _temp_2308 = 0; + let _temp_2309 = 0; + let _temp_2310 = 0; + let _temp_2311 = 0; + let _temp_2312 = 0; + let _temp_2313 = 0; + let _temp_2314 = 0; + let _temp_2315 = 0; + let _temp_2316 = 0; + let _temp_2317 = 0; + let _temp_2318 = 0; + let _temp_2319 = 0; + let _temp_2320 = 0; + let _temp_2321 = 0; + let _temp_2322 = 0; + let _temp_2323 = 0; + let _temp_2324 = 0; + let _temp_2325 = 0; + let _temp_2326 = 0; + let _temp_2327 = 0; + let _temp_2328 = 0; + let _temp_2329 = 0; + let _temp_2330 = 0; + let _temp_2331 = 0; + let _temp_2332 = 0; + let _temp_2333 = 0; + let _temp_2334 = 0; + let _temp_2335 = 0; + let _temp_2336 = 0; + let _temp_2337 = 0; + let _temp_2338 = 0; + let _temp_2339 = 0; + let _temp_2340 = 0; + let _temp_2341 = 0; + let _temp_2342 = 0; + let _temp_2343 = 0; + let _temp_2344 = 0; + let _temp_2345 = 0; + let _temp_2346 = 0; + let _temp_2347 = 0; + let _temp_2348 = 0; + let _temp_2349 = 0; + let _temp_2350 = 0; + let _temp_2351 = 0; + let _temp_2352 = 0; + let _temp_2353 = 0; + let _temp_2354 = 0; + let _temp_2355 = 0; + let _temp_2356 = 0; + let _temp_2357 = 0; + let _temp_2358 = 0; + let _temp_2359 = 0; + let _temp_2360 = 0; + let _temp_2361 = 0; + let _temp_2362 = 0; + let _temp_2363 = 0; + let _temp_2364 = 0; + let _temp_2365 = 0; + let _temp_2366 = 0; + let _temp_2367 = 0; + let _temp_2368 = 0; + let _temp_2369 = 0; + let _temp_2370 = 0; + let _temp_2371 = 0; + let _temp_2372 = 0; + let _temp_2373 = 0; + let _temp_2374 = 0; + let _temp_2375 = 0; + let _temp_2376 = 0; + let _temp_2377 = 0; + let _temp_2378 = 0; + let _temp_2379 = 0; + let _temp_2380 = 0; + let _temp_2381 = 0; + let _temp_2382 = 0; + let _temp_2383 = 0; + let _temp_2384 = 0; + let _temp_2385 = 0; + let _temp_2386 = 0; + let _temp_2387 = 0; + let _temp_2388 = 0; + let _temp_2389 = 0; + let _temp_2390 = 0; + let _temp_2391 = 0; + let _temp_2392 = 0; + let _temp_2393 = 0; + let _temp_2394 = 0; + let _temp_2395 = 0; + let _temp_2396 = 0; + let _temp_2397 = 0; + let _temp_2398 = 0; + let _temp_2399 = 0; + let _temp_2400 = 0; + let _temp_2401 = 0; + let _temp_2402 = 0; + let _temp_2403 = 0; + let _temp_2404 = 0; + let _temp_2405 = 0; + let _temp_2406 = 0; + let _temp_2407 = 0; + let _temp_2408 = 0; + let _temp_2409 = 0; + let _temp_2410 = 0; + let _temp_2411 = 0; + let _temp_2412 = 0; + let _temp_2413 = 0; + let _temp_2414 = 0; + let _temp_2415 = 0; + let _temp_2416 = 0; + let _temp_2417 = 0; + let _temp_2418 = 0; + let _temp_2419 = 0; + let _temp_2420 = 0; + let _temp_2421 = 0; + let _temp_2422 = 0; + let _temp_2423 = 0; + let _temp_2424 = 0; + let _temp_2425 = 0; + let _temp_2426 = 0; + let _temp_2427 = 0; + let _temp_2428 = 0; + let _temp_2429 = 0; + let _temp_2430 = 0; + let _temp_2431 = 0; + let _temp_2432 = 0; + let _temp_2433 = 0; + let _temp_2434 = 0; + let _temp_2435 = 0; + let _temp_2436 = 0; + let _temp_2437 = 0; + let _temp_2438 = 0; + let _temp_2439 = 0; + let _temp_2440 = 0; + let _temp_2441 = 0; + let _temp_2442 = 0; + let _temp_2443 = 0; + let _temp_2444 = 0; + let _temp_2445 = 0; + let _temp_2446 = 0; + let _temp_2447 = 0; + let _temp_2448 = 0; + let _temp_2449 = 0; + let _temp_2450 = 0; + let _temp_2451 = 0; + let _temp_2452 = 0; + let _temp_2453 = 0; + let _temp_2454 = 0; + let _temp_2455 = 0; + let _temp_2456 = 0; + let _temp_2457 = 0; + let _temp_2458 = 0; + let _temp_2459 = 0; + let _temp_2460 = 0; + let _temp_2461 = 0; + let _temp_2462 = 0; + let _temp_2463 = 0; + let _temp_2464 = 0; + let _temp_2465 = 0; + let _temp_2466 = 0; + let _temp_2467 = 0; + let _temp_2468 = 0; + let _temp_2469 = 0; + let _temp_2470 = 0; + let _temp_2471 = 0; + let _temp_2472 = 0; + let _temp_2473 = 0; + let _temp_2474 = 0; + let _temp_2475 = 0; + let _temp_2476 = 0; + let _temp_2477 = 0; + let _temp_2478 = 0; + let _temp_2479 = 0; + let _temp_2480 = 0; + let _temp_2481 = 0; + let _temp_2482 = 0; + let _temp_2483 = 0; + let _temp_2484 = 0; + let _temp_2485 = 0; + let _temp_2486 = 0; + let _temp_2487 = 0; + let _temp_2488 = 0; + let _temp_2489 = 0; + let _temp_2490 = 0; + let _temp_2491 = 0; + let _temp_2492 = 0; + let _temp_2493 = 0; + let _temp_2494 = 0; + let _temp_2495 = 0; + let _temp_2496 = 0; + let _temp_2497 = 0; + let _temp_2498 = 0; + let _temp_2499 = 0; + let _temp_2500 = 0; + let _temp_2501 = 0; + let _temp_2502 = 0; + let _temp_2503 = 0; + let _temp_2504 = 0; + let _temp_2505 = 0; + let _temp_2506 = 0; + let _temp_2507 = 0; + let _temp_2508 = 0; + let _temp_2509 = 0; + let _temp_2510 = 0; + let _temp_2511 = 0; + let _temp_2512 = 0; + let _temp_2513 = 0; + let _temp_2514 = 0; + let _temp_2515 = 0; + let _temp_2516 = 0; + let _temp_2517 = 0; + let _temp_2518 = 0; + let _temp_2519 = 0; + let _temp_2520 = 0; + let _temp_2521 = 0; + let _temp_2522 = 0; + let _temp_2523 = 0; + let _temp_2524 = 0; + let _temp_2525 = 0; + let _temp_2526 = 0; + let _temp_2527 = 0; + let _temp_2528 = 0; + let _temp_2529 = 0; + let _temp_2530 = 0; + let _temp_2531 = 0; + let _temp_2532 = 0; + let _temp_2533 = 0; + let _temp_2534 = 0; + let _temp_2535 = 0; + let _temp_2536 = 0; + let _temp_2537 = 0; + let _temp_2538 = 0; + let _temp_2539 = 0; + let _temp_2540 = 0; + let _temp_2541 = 0; + let _temp_2542 = 0; + let _temp_2543 = 0; + let _temp_2544 = 0; + let _temp_2545 = 0; + let _temp_2546 = 0; + let _temp_2547 = 0; + let _temp_2548 = 0; + let _temp_2549 = 0; + let _temp_2550 = 0; + let _temp_2551 = 0; + let _temp_2552 = 0; + let _temp_2553 = 0; + let _temp_2554 = 0; + let _temp_2555 = 0; + let _temp_2556 = 0; + let _temp_2557 = 0; + let _temp_2558 = 0; + let _temp_2559 = 0; + let _temp_2560 = 0; + let _temp_2561 = 0; + let _temp_2562 = 0; + let _temp_2563 = 0; + let _temp_2564 = 0; + let _temp_2565 = 0; + let _temp_2566 = 0; + let _temp_2567 = 0; + let _temp_2568 = 0; + let _temp_2569 = 0; + let _temp_2570 = 0; + let _temp_2571 = 0; + let _temp_2572 = 0; + let _temp_2573 = 0; + let _temp_2574 = 0; + let _temp_2575 = 0; + let _temp_2576 = 0; + let _temp_2577 = 0; + let _temp_2578 = 0; + let _temp_2579 = 0; + let _temp_2580 = 0; + let _temp_2581 = 0; + let _temp_2582 = 0; + let _temp_2583 = 0; + let _temp_2584 = 0; + let _temp_2585 = 0; + let _temp_2586 = 0; + let _temp_2587 = 0; + let _temp_2588 = 0; + let _temp_2589 = 0; + let _temp_2590 = 0; + let _temp_2591 = 0; + let _temp_2592 = 0; + let _temp_2593 = 0; +} diff --git a/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr b/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr index 450984aacc7..a751ba79347 100644 --- a/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr +++ b/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr @@ -1,8 +1,8 @@ -error: cannot specialize on `Binder(ProjectionPredicate(ProjectionTy { substs: [V], item_def_id: DefId(0:6 ~ repeated_projection_type[54ea]::Id::This) }, Ty((I,))), [])` - --> $DIR/repeated_projection_type.rs:19:1 +error: cannot specialize on associated type `<V as Id>::This == (I,)` + --> $DIR/repeated_projection_type.rs:19:15 | LL | impl<I, V: Id<This = (I,)>> X for V { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/specialization/min_specialization/spec-marker-supertraits.stderr b/src/test/ui/specialization/min_specialization/spec-marker-supertraits.stderr index b1ab58551e6..ba9d6bbe300 100644 --- a/src/test/ui/specialization/min_specialization/spec-marker-supertraits.stderr +++ b/src/test/ui/specialization/min_specialization/spec-marker-supertraits.stderr @@ -1,8 +1,8 @@ error: cannot specialize on trait `HasMethod` - --> $DIR/spec-marker-supertraits.rs:22:1 + --> $DIR/spec-marker-supertraits.rs:22:9 | LL | impl<T: Marker> Spec for T { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/specialization/min_specialization/specialization_super_trait.stderr b/src/test/ui/specialization/min_specialization/specialization_super_trait.stderr index 1f2ff99d415..e935786624b 100644 --- a/src/test/ui/specialization/min_specialization/specialization_super_trait.stderr +++ b/src/test/ui/specialization/min_specialization/specialization_super_trait.stderr @@ -1,8 +1,8 @@ error: cannot specialize on trait `Default` - --> $DIR/specialization_super_trait.rs:13:1 + --> $DIR/specialization_super_trait.rs:13:9 | LL | impl<T: Default> SpecMarker for T { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/specialization/min_specialization/specialization_trait.stderr b/src/test/ui/specialization/min_specialization/specialization_trait.stderr index ecb07ba908e..bc87ae0f8b8 100644 --- a/src/test/ui/specialization/min_specialization/specialization_trait.stderr +++ b/src/test/ui/specialization/min_specialization/specialization_trait.stderr @@ -11,10 +11,10 @@ LL | impl<T> SpecMarker for (T, T) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: cannot specialize on trait `Clone` - --> $DIR/specialization_trait.rs:21:1 + --> $DIR/specialization_trait.rs:21:9 | LL | impl<T: Clone> SpecMarker for [T] { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/specialization/min_specialization/specialize_on_trait.stderr b/src/test/ui/specialization/min_specialization/specialize_on_trait.stderr index 92daddbd800..7b79c7eb4ad 100644 --- a/src/test/ui/specialization/min_specialization/specialize_on_trait.stderr +++ b/src/test/ui/specialization/min_specialization/specialize_on_trait.stderr @@ -1,8 +1,8 @@ error: cannot specialize on trait `SpecMarker` - --> $DIR/specialize_on_trait.rs:15:1 + --> $DIR/specialize_on_trait.rs:15:9 | LL | impl<T: SpecMarker> X for T { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/suggestions/suggest-on-bare-closure-call.rs b/src/test/ui/suggestions/suggest-on-bare-closure-call.rs index 355708c08ec..496c305bc2a 100644 --- a/src/test/ui/suggestions/suggest-on-bare-closure-call.rs +++ b/src/test/ui/suggestions/suggest-on-bare-closure-call.rs @@ -1,4 +1,11 @@ +// edition:2021 + +#![feature(async_closure)] + fn main() { let _ = ||{}(); //~^ ERROR expected function, found `()` + + let _ = async ||{}(); + //~^ ERROR expected function, found `()` } diff --git a/src/test/ui/suggestions/suggest-on-bare-closure-call.stderr b/src/test/ui/suggestions/suggest-on-bare-closure-call.stderr index 81f2e498fe5..e65a6eb4939 100644 --- a/src/test/ui/suggestions/suggest-on-bare-closure-call.stderr +++ b/src/test/ui/suggestions/suggest-on-bare-closure-call.stderr @@ -1,5 +1,5 @@ error[E0618]: expected function, found `()` - --> $DIR/suggest-on-bare-closure-call.rs:2:15 + --> $DIR/suggest-on-bare-closure-call.rs:6:15 | LL | let _ = ||{}(); | ^^-- @@ -11,6 +11,19 @@ help: if you meant to create this closure and immediately call it, surround the LL | let _ = (||{})(); | + + -error: aborting due to previous error +error[E0618]: expected function, found `()` + --> $DIR/suggest-on-bare-closure-call.rs:9:21 + | +LL | let _ = async ||{}(); + | ^^-- + | | + | call expression requires function + | +help: if you meant to create this closure and immediately call it, surround the closure with parentheses + | +LL | let _ = (async ||{})(); + | + + + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0618`. diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index bdf26d040ad..be81ff881f3 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -269,6 +269,10 @@ pub struct Config { /// Flags to pass to the compiler when building for the target pub target_rustcflags: Option<String>, + /// Whether tests should be optimized by default. Individual test-suites and test files may + /// override this setting. + pub optimize_tests: bool, + /// What panic strategy the target is built with. Unwind supports Abort, but /// not vice versa. pub target_panic: PanicStrategy, diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 31e979a574b..7cf4a88c470 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -244,6 +244,7 @@ impl TestProps { // copy over select properties to the aux build: props.incremental_dir = self.incremental_dir.clone(); + props.ignore_pass = true; props.load_from(testfile, cfg, config); props diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index 4e8e5afd4bb..a8a151ca114 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -102,6 +102,7 @@ pub fn parse_config(args: Vec<String>) -> Config { ) .optmulti("", "host-rustcflags", "flags to pass to rustc for host", "FLAGS") .optmulti("", "target-rustcflags", "flags to pass to rustc for target", "FLAGS") + .optflag("", "optimize-tests", "run tests with optimizations enabled") .optopt("", "target-panic", "what panic strategy the target supports", "unwind | abort") .optflag("", "verbose", "run tests verbosely, showing all output") .optflag( @@ -253,6 +254,7 @@ pub fn parse_config(args: Vec<String>) -> Config { runtool: matches.opt_str("runtool"), host_rustcflags: Some(matches.opt_strs("host-rustcflags").join(" ")), target_rustcflags: Some(matches.opt_strs("target-rustcflags").join(" ")), + optimize_tests: matches.opt_present("optimize-tests"), target_panic: match matches.opt_str("target-panic").as_deref() { Some("unwind") | None => PanicStrategy::Unwind, Some("abort") => PanicStrategy::Abort, diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 160b9785d97..dd9e2a6687e 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1862,6 +1862,31 @@ impl<'test> TestCx<'test> { } } + if self.config.optimize_tests && !is_rustdoc { + match self.config.mode { + Ui => { + // If optimize-tests is true we still only want to optimize tests that actually get + // executed and that don't specify their own optimization levels. + // Note: aux libs don't have a pass-mode, so they won't get optimized + // unless compile-flags are set in the aux file. + if self.config.optimize_tests + && self.props.pass_mode(&self.config) == Some(PassMode::Run) + && !self + .props + .compile_flags + .iter() + .any(|arg| arg == "-O" || arg.contains("opt-level")) + { + rustc.arg("-O"); + } + } + DebugInfo => { /* debuginfo tests must be unoptimized */ } + _ => { + rustc.arg("-O"); + } + } + } + match self.config.mode { Incremental => { // If we are extracting and matching errors in the new @@ -3245,7 +3270,8 @@ impl<'test> TestCx<'test> { if !self.props.error_patterns.is_empty() { // "// error-pattern" comments - self.check_error_patterns(&proc_res.stderr, &proc_res, pm); + let output_to_check = self.get_output(&proc_res); + self.check_error_patterns(&output_to_check, &proc_res, pm); } } @@ -3266,7 +3292,8 @@ impl<'test> TestCx<'test> { if check_patterns { // "// error-pattern" comments - self.check_error_patterns(&proc_res.stderr, &proc_res, pm); + let output_to_check = self.get_output(&proc_res); + self.check_error_patterns(&output_to_check, &proc_res, pm); } if check_annotations { diff --git a/src/tools/tidy/src/bins.rs b/src/tools/tidy/src/bins.rs index 503df537047..9615c4db6b4 100644 --- a/src/tools/tidy/src/bins.rs +++ b/src/tools/tidy/src/bins.rs @@ -96,9 +96,25 @@ mod os_impl { #[cfg(unix)] pub fn check(path: &Path, bad: &mut bool) { + const ALLOWED: &[&str] = &["configure"]; + crate::walk_no_read( path, - &mut |path| crate::filter_dirs(path) || path.ends_with("src/etc"), + &mut |path| { + crate::filter_dirs(path) + || path.ends_with("src/etc") + // This is a list of directories that we almost certainly + // don't need to walk. A future PR will likely want to + // remove these in favor of crate::walk_no_read using git + // ls-files to discover the paths we should check, which + // would naturally ignore all of these directories. It's + // also likely faster than walking the directory tree + // directly (since git is just reading from a couple files + // to produce the results). + || path.ends_with("target") + || path.ends_with("build") + || path.ends_with(".git") + }, &mut |entry| { let file = entry.path(); let filename = file.file_name().unwrap().to_string_lossy(); @@ -110,6 +126,11 @@ mod os_impl { if t!(is_executable(&file), file) { let rel_path = file.strip_prefix(path).unwrap(); let git_friendly_path = rel_path.to_str().unwrap().replace("\\", "/"); + + if ALLOWED.contains(&git_friendly_path.as_str()) { + return; + } + let output = Command::new("git") .arg("ls-files") .arg(&git_friendly_path) diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs index d555f7c8e34..aa8d8b4f64d 100644 --- a/src/tools/tidy/src/main.rs +++ b/src/tools/tidy/src/main.rs @@ -78,13 +78,8 @@ fn main() { check!(unit_tests, &compiler_path); check!(unit_tests, &library_path); - if bins::check_filesystem_support( - &[&src_path, &compiler_path, &library_path], - &output_directory, - ) { - check!(bins, &src_path); - check!(bins, &compiler_path); - check!(bins, &library_path); + if bins::check_filesystem_support(&[&root_path], &output_directory) { + check!(bins, &root_path); } check!(style, &src_path); |
