diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 454fd14ea748..129a30661d6f 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -27,7 +27,7 @@ use rustc_middle::mir::{ }; use rustc_middle::ty::print::PrintTraitRefExt as _; use rustc_middle::ty::{ - self, ClauseKind, PredicateKind, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor, Upcast, + self, PredicateKind, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor, Upcast, suggest_constraining_type_params, }; use rustc_middle::util::CallKind; @@ -649,11 +649,11 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { ) -> Option { let tcx = self.infcx.tcx; let sig = tcx.fn_sig(callee_did).instantiate_identity().skip_binder(); - let clauses = tcx.predicates_of(callee_did).instantiate_identity(self.infcx.tcx).predicates; + let clauses = tcx.predicates_of(callee_did); // First, is there at least one method on one of `param`'s trait bounds? // This keeps us from suggesting borrowing the argument to `mem::drop`, e.g. - if !clauses.iter().any(|clause| { + if !clauses.instantiate_identity(tcx).predicates.iter().any(|clause| { clause.as_trait_clause().is_some_and(|tc| { tc.self_ty().skip_binder().is_param(param.index) && tc.polarity() == ty::PredicatePolarity::Positive @@ -682,8 +682,12 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { // Normalize before comparing to see through type aliases and projections. let old_ty = ty::EarlyBinder::bind(ty).instantiate(tcx, generic_args); let new_ty = ty::EarlyBinder::bind(ty).instantiate(tcx, new_args); - if let Ok(old_ty) = tcx.try_normalize_erasing_regions(self.param_env, old_ty) - && let Ok(new_ty) = tcx.try_normalize_erasing_regions(self.param_env, new_ty) + if let Ok(old_ty) = + tcx.try_normalize_erasing_regions(self.infcx.typing_env(self.param_env), old_ty) + && let Ok(new_ty) = tcx.try_normalize_erasing_regions( + self.infcx.typing_env(self.param_env), + new_ty, + ) { old_ty == new_ty } else { @@ -700,23 +704,19 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { return false; } - // Test the callee's predicates, substituting a reference in for the self ty - // in bounds on `param`. - clauses.iter().all(|&clause| { - let clause_for_ref = clause.kind().map_bound(|kind| match kind { - ClauseKind::Trait(c) if c.self_ty().is_param(param.index) => { - ClauseKind::Trait(c.with_self_ty(tcx, ref_ty)) - } - ClauseKind::Projection(c) if c.self_ty().is_param(param.index) => { - ClauseKind::Projection(c.with_self_ty(tcx, ref_ty)) - } - _ => kind, - }); + // Test the callee's predicates, substituting in `ref_ty` for the moved argument type. + clauses.instantiate(tcx, new_args).predicates.iter().all(|&(mut clause)| { + // Normalize before testing to see through type aliases and projections. + if let Ok(normalized) = + tcx.try_normalize_erasing_regions(self.infcx.typing_env(self.param_env), clause) + { + clause = normalized; + } self.infcx.predicate_must_hold_modulo_regions(&Obligation::new( tcx, ObligationCause::dummy(), self.param_env, - ty::EarlyBinder::bind(clause_for_ref).instantiate(tcx, generic_args), + clause, )) }) }) { @@ -3837,11 +3837,16 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { if tcx.is_diagnostic_item(sym::deref_method, method_did) { let deref_target = tcx.get_diagnostic_item(sym::deref_target).and_then(|deref_target| { - Instance::try_resolve(tcx, self.param_env, deref_target, method_args) - .transpose() + Instance::try_resolve( + tcx, + self.infcx.typing_env(self.param_env), + deref_target, + method_args, + ) + .transpose() }); if let Some(Ok(instance)) = deref_target { - let deref_target_ty = instance.ty(tcx, self.param_env); + let deref_target_ty = instance.ty(tcx, self.infcx.typing_env(self.param_env)); err.note(format!("borrow occurs due to deref coercion to `{deref_target_ty}`")); err.span_note(tcx.def_span(instance.def_id()), "deref defined here"); } diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 0797bb49bf9b..6c63da819c78 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -864,7 +864,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { let kind = call_kind( self.infcx.tcx, - self.param_env, + self.infcx.typing_env(self.param_env), method_did, method_args, *fn_span, diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 807b5576976f..d4660d8af43b 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -952,7 +952,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { if let Ok(Some(instance)) = ty::Instance::try_resolve( tcx, - self.param_env, + self.infcx.typing_env(self.param_env), *fn_did, self.infcx.resolve_vars_if_possible(args), ) { diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 0fe6a4b5fce9..ac0219684d8d 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1527,7 +1527,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // The signature in this call can reference region variables, // so erase them before calling a query. let output_ty = self.tcx().erase_regions(sig.output()); - if !output_ty.is_privately_uninhabited(self.tcx(), self.param_env) { + if !output_ty + .is_privately_uninhabited(self.tcx(), self.infcx.typing_env(self.param_env)) + { span_mirbug!(self, term, "call to converging function {:?} w/o dest", sig); } } diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs index f647ee36c482..7dd2139cf90c 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs @@ -376,7 +376,7 @@ pub(crate) fn codegen_terminator_call<'tcx>( let instance = if let ty::FnDef(def_id, fn_args) = *func.layout().ty.kind() { let instance = ty::Instance::expect_resolve( fx.tcx, - ty::ParamEnv::reveal_all(), + ty::TypingEnv::fully_monomorphized(), def_id, fn_args, source_info.span, diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index da3818ca25e9..1b91d251bfdd 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -666,7 +666,7 @@ fn codegen_stmt<'tcx>( let func_ref = fx.get_function_ref( Instance::resolve_for_fn_ptr( fx.tcx, - ParamEnv::reveal_all(), + ty::TypingEnv::fully_monomorphized(), def_id, args, ) @@ -841,14 +841,18 @@ fn codegen_stmt<'tcx>( lval.write_cvalue(fx, CValue::by_val(operand, box_layout)); } Rvalue::NullaryOp(ref null_op, ty) => { - assert!(lval.layout().ty.is_sized(fx.tcx, ParamEnv::reveal_all())); + assert!(lval.layout().ty.is_sized(fx.tcx, ty::ParamEnv::reveal_all())); let layout = fx.layout_of(fx.monomorphize(ty)); let val = match null_op { NullOp::SizeOf => layout.size.bytes(), NullOp::AlignOf => layout.align.abi.bytes(), NullOp::OffsetOf(fields) => fx .tcx - .offset_of_subfield(ParamEnv::reveal_all(), layout, fields.iter()) + .offset_of_subfield( + ty::TypingEnv::fully_monomorphized(), + layout, + fields.iter(), + ) .bytes(), NullOp::UbChecks => { let val = fx.tcx.sess.ub_checks(); diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs index 27e71b925618..add081bc795b 100644 --- a/compiler/rustc_codegen_cranelift/src/common.rs +++ b/compiler/rustc_codegen_cranelift/src/common.rs @@ -103,11 +103,11 @@ fn clif_pair_type_from_ty<'tcx>( /// Is a pointer to this type a wide ptr? pub(crate) fn has_ptr_meta<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool { - if ty.is_sized(tcx, ParamEnv::reveal_all()) { + if ty.is_sized(tcx, ty::ParamEnv::reveal_all()) { return false; } - let tail = tcx.struct_tail_for_codegen(ty, ParamEnv::reveal_all()); + let tail = tcx.struct_tail_for_codegen(ty, ty::TypingEnv::fully_monomorphized()); match tail.kind() { ty::Foreign(..) => false, ty::Str | ty::Slice(..) | ty::Dynamic(..) => true, @@ -339,9 +339,9 @@ impl<'tcx> rustc_abi::HasDataLayout for FunctionCx<'_, '_, 'tcx> { } } -impl<'tcx> layout::HasParamEnv<'tcx> for FunctionCx<'_, '_, 'tcx> { - fn param_env(&self) -> ParamEnv<'tcx> { - ParamEnv::reveal_all() +impl<'tcx> layout::HasTypingEnv<'tcx> for FunctionCx<'_, '_, 'tcx> { + fn typing_env(&self) -> ty::TypingEnv<'tcx> { + ty::TypingEnv::fully_monomorphized() } } @@ -358,7 +358,7 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> { { self.instance.instantiate_mir_and_normalize_erasing_regions( self.tcx, - ty::ParamEnv::reveal_all(), + ty::TypingEnv::fully_monomorphized(), ty::EarlyBinder::bind(value), ) } @@ -497,9 +497,9 @@ impl<'tcx> rustc_abi::HasDataLayout for RevealAllLayoutCx<'tcx> { } } -impl<'tcx> layout::HasParamEnv<'tcx> for RevealAllLayoutCx<'tcx> { - fn param_env(&self) -> ParamEnv<'tcx> { - ParamEnv::reveal_all() +impl<'tcx> layout::HasTypingEnv<'tcx> for RevealAllLayoutCx<'tcx> { + fn typing_env(&self) -> ty::TypingEnv<'tcx> { + ty::TypingEnv::fully_monomorphized() } } diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index ab78584332a0..5311547309c5 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -78,7 +78,7 @@ pub(crate) fn eval_mir_constant<'tcx>( let cv = fx.monomorphize(constant.const_); // This cannot fail because we checked all required_consts in advance. let val = cv - .eval(fx.tcx, ty::ParamEnv::reveal_all(), constant.span) + .eval(fx.tcx, ty::TypingEnv::fully_monomorphized(), constant.span) .expect("erroneous constant missed by mono item collection"); (val, cv.ty()) } @@ -265,8 +265,13 @@ fn data_id_for_static( assert!(!definition); assert!(!tcx.is_mutable_static(def_id)); - let ty = instance.ty(tcx, ParamEnv::reveal_all()); - let align = tcx.layout_of(ParamEnv::reveal_all().and(ty)).unwrap().align.pref.bytes(); + let ty = instance.ty(tcx, ty::TypingEnv::fully_monomorphized()); + let align = tcx + .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)) + .unwrap() + .align + .pref + .bytes(); let linkage = if import_linkage == rustc_middle::mir::mono::Linkage::ExternalWeak || import_linkage == rustc_middle::mir::mono::Linkage::WeakAny diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs index 9025ea97b81d..f3a8623e2161 100644 --- a/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs @@ -210,7 +210,7 @@ impl DebugContext { type_names::push_generic_params( tcx, - tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), args), + tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), args), &mut name, ); @@ -275,8 +275,10 @@ impl DebugContext { let span = tcx.def_span(def_id); let (file_id, line, _column) = self.get_span_loc(tcx, span, span); - let static_type = Instance::mono(tcx, def_id).ty(tcx, ty::ParamEnv::reveal_all()); - let static_layout = tcx.layout_of(ty::ParamEnv::reveal_all().and(static_type)).unwrap(); + let static_type = Instance::mono(tcx, def_id).ty(tcx, ty::TypingEnv::fully_monomorphized()); + let static_layout = tcx + .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(static_type)) + .unwrap(); // FIXME use the actual type layout let type_id = self.debug_type(tcx, type_dbg, static_type); diff --git a/compiler/rustc_codegen_cranelift/src/inline_asm.rs b/compiler/rustc_codegen_cranelift/src/inline_asm.rs index a3f816f70a94..0df1a30fc0a4 100644 --- a/compiler/rustc_codegen_cranelift/src/inline_asm.rs +++ b/compiler/rustc_codegen_cranelift/src/inline_asm.rs @@ -92,7 +92,7 @@ pub(crate) fn codegen_inline_asm_terminator<'tcx>( if let ty::FnDef(def_id, args) = *const_.ty().kind() { let instance = ty::Instance::resolve_for_fn_ptr( fx.tcx, - ty::ParamEnv::reveal_all(), + ty::TypingEnv::fully_monomorphized(), def_id, args, ) @@ -227,11 +227,11 @@ pub(crate) fn codegen_naked_asm<'tcx>( InlineAsmOperand::Const { ref value } => { let cv = instance.instantiate_mir_and_normalize_erasing_regions( tcx, - ty::ParamEnv::reveal_all(), + ty::TypingEnv::fully_monomorphized(), ty::EarlyBinder::bind(value.const_), ); let const_value = cv - .eval(tcx, ty::ParamEnv::reveal_all(), value.span) + .eval(tcx, ty::TypingEnv::fully_monomorphized(), value.span) .expect("erroneous constant missed by mono item collection"); let value = rustc_codegen_ssa::common::asm_const_to_str( @@ -250,13 +250,13 @@ pub(crate) fn codegen_naked_asm<'tcx>( let const_ = instance.instantiate_mir_and_normalize_erasing_regions( tcx, - ty::ParamEnv::reveal_all(), + ty::TypingEnv::fully_monomorphized(), ty::EarlyBinder::bind(value.const_), ); if let ty::FnDef(def_id, args) = *const_.ty().kind() { let instance = ty::Instance::resolve_for_fn_ptr( tcx, - ty::ParamEnv::reveal_all(), + ty::TypingEnv::fully_monomorphized(), def_id, args, ) diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs index b92885cc1a79..c663f6fc2d32 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs @@ -20,7 +20,7 @@ mod simd; use cranelift_codegen::ir::AtomicRmwOp; use rustc_middle::ty; use rustc_middle::ty::GenericArgsRef; -use rustc_middle::ty::layout::{HasParamEnv, ValidityRequirement}; +use rustc_middle::ty::layout::ValidityRequirement; use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths}; use rustc_span::source_map::Spanned; use rustc_span::symbol::{Symbol, sym}; @@ -682,7 +682,10 @@ fn codegen_regular_intrinsic_call<'tcx>( if let Some(requirement) = requirement { let do_panic = !fx .tcx - .check_validity_requirement((requirement, fx.param_env().and(ty))) + .check_validity_requirement(( + requirement, + ty::TypingEnv::fully_monomorphized().as_query_input(ty), + )) .expect("expect to have layout during codegen"); if do_panic { @@ -741,7 +744,7 @@ fn codegen_regular_intrinsic_call<'tcx>( let const_val = fx .tcx - .const_eval_instance(ParamEnv::reveal_all(), instance, source_info.span) + .const_eval_instance(ty::ParamEnv::reveal_all(), instance, source_info.span) .unwrap(); let val = crate::constant::codegen_const_value(fx, const_val, ret.layout().ty); ret.write_cvalue(fx, val); @@ -1264,6 +1267,7 @@ fn codegen_regular_intrinsic_call<'tcx>( sym::cold_path => { // This is a no-op. The intrinsic is just a hint to the optimizer. + // We still have an impl here to avoid it being turned into a call. } // Unimplemented intrinsics must have a fallback body. The fallback body is obtained diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index b506b1f57315..e6f6ae305816 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -98,7 +98,7 @@ mod prelude { pub(crate) use rustc_middle::mir::{self, *}; pub(crate) use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; pub(crate) use rustc_middle::ty::{ - self, FloatTy, Instance, InstanceKind, IntTy, ParamEnv, Ty, TyCtxt, UintTy, + self, FloatTy, Instance, InstanceKind, IntTy, Ty, TyCtxt, UintTy, }; pub(crate) use rustc_span::Span; diff --git a/compiler/rustc_codegen_cranelift/src/main_shim.rs b/compiler/rustc_codegen_cranelift/src/main_shim.rs index df92bc58bf53..2ee4ff5cec72 100644 --- a/compiler/rustc_codegen_cranelift/src/main_shim.rs +++ b/compiler/rustc_codegen_cranelift/src/main_shim.rs @@ -49,7 +49,7 @@ pub(crate) fn maybe_create_entry_wrapper( // regions must appear in the argument // listing. let main_ret_ty = tcx.normalize_erasing_regions( - ty::ParamEnv::reveal_all(), + ty::TypingEnv::fully_monomorphized(), main_ret_ty.no_bound_vars().unwrap(), ); @@ -113,7 +113,7 @@ pub(crate) fn maybe_create_entry_wrapper( .unwrap(); let report = Instance::expect_resolve( tcx, - ParamEnv::reveal_all(), + ty::TypingEnv::fully_monomorphized(), report.def_id, tcx.mk_args(&[GenericArg::from(main_ret_ty)]), DUMMY_SP, @@ -139,7 +139,7 @@ pub(crate) fn maybe_create_entry_wrapper( let start_def_id = tcx.require_lang_item(LangItem::Start, None); let start_instance = Instance::expect_resolve( tcx, - ParamEnv::reveal_all(), + ty::TypingEnv::fully_monomorphized(), start_def_id, tcx.mk_args(&[main_ret_ty.into()]), DUMMY_SP, diff --git a/compiler/rustc_codegen_cranelift/src/unsize.rs b/compiler/rustc_codegen_cranelift/src/unsize.rs index 336934354e11..2843e5bbdfb2 100644 --- a/compiler/rustc_codegen_cranelift/src/unsize.rs +++ b/compiler/rustc_codegen_cranelift/src/unsize.rs @@ -3,6 +3,7 @@ //! [`PointerCoercion::Unsize`]: `rustc_middle::ty::adjustment::PointerCoercion::Unsize` use rustc_codegen_ssa::base::validate_trivial_unsize; +use rustc_middle::ty::layout::HasTypingEnv; use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths}; use crate::base::codegen_panic_nounwind; @@ -23,7 +24,7 @@ pub(crate) fn unsized_info<'tcx>( old_info: Option, ) -> Value { let (source, target) = - fx.tcx.struct_lockstep_tails_for_codegen(source, target, ParamEnv::reveal_all()); + fx.tcx.struct_lockstep_tails_for_codegen(source, target, fx.typing_env()); match (&source.kind(), &target.kind()) { (&ty::Array(_, len), &ty::Slice(_)) => fx.bcx.ins().iconst( fx.pointer_type, diff --git a/compiler/rustc_codegen_cranelift/src/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs index 900d7e69714e..6676e684ca02 100644 --- a/compiler/rustc_codegen_cranelift/src/value_and_place.rs +++ b/compiler/rustc_codegen_cranelift/src/value_and_place.rs @@ -4,6 +4,7 @@ use cranelift_codegen::entity::EntityRef; use cranelift_codegen::ir::immediates::Offset32; use cranelift_frontend::Variable; use rustc_middle::ty::FnSig; +use rustc_middle::ty::layout::HasTypingEnv; use crate::prelude::*; @@ -884,19 +885,17 @@ pub(crate) fn assert_assignable<'tcx>( assert_assignable(fx, *a, *b, limit - 1); } (ty::FnPtr(..), ty::FnPtr(..)) => { - let from_sig = fx.tcx.normalize_erasing_late_bound_regions( - ParamEnv::reveal_all(), - from_ty.fn_sig(fx.tcx), - ); + let from_sig = fx + .tcx + .normalize_erasing_late_bound_regions(fx.typing_env(), from_ty.fn_sig(fx.tcx)); let FnSig { inputs_and_output: types_from, c_variadic: c_variadic_from, safety: unsafety_from, abi: abi_from, } = from_sig; - let to_sig = fx - .tcx - .normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), to_ty.fn_sig(fx.tcx)); + let to_sig = + fx.tcx.normalize_erasing_late_bound_regions(fx.typing_env(), to_ty.fn_sig(fx.tcx)); let FnSig { inputs_and_output: types_to, c_variadic: c_variadic_to, @@ -932,9 +931,8 @@ pub(crate) fn assert_assignable<'tcx>( (&ty::Dynamic(from_traits, _, _from_kind), &ty::Dynamic(to_traits, _, _to_kind)) => { // FIXME(dyn-star): Do the right thing with DynKinds for (from, to) in from_traits.iter().zip(to_traits) { - let from = - fx.tcx.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), from); - let to = fx.tcx.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), to); + let from = fx.tcx.normalize_erasing_late_bound_regions(fx.typing_env(), from); + let to = fx.tcx.normalize_erasing_late_bound_regions(fx.typing_env(), to); assert_eq!( from, to, "Can't write trait object of incompatible traits {:?} to place with traits {:?}\n\n{:#?}", diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs index e6ae7cf174d0..9a142326ad19 100644 --- a/compiler/rustc_codegen_gcc/src/builder.rs +++ b/compiler/rustc_codegen_gcc/src/builder.rs @@ -24,9 +24,9 @@ use rustc_data_structures::fx::FxHashSet; use rustc_middle::bug; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; use rustc_middle::ty::layout::{ - FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, HasTyCtxt, LayoutError, LayoutOfHelpers, + FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasTyCtxt, HasTypingEnv, LayoutError, LayoutOfHelpers, }; -use rustc_middle::ty::{Instance, ParamEnv, Ty, TyCtxt}; +use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; use rustc_span::Span; use rustc_span::def_id::DefId; use rustc_target::abi::call::FnAbi; @@ -2319,9 +2319,9 @@ impl<'a, 'gcc, 'tcx> StaticBuilderMethods for Builder<'a, 'gcc, 'tcx> { } } -impl<'tcx> HasParamEnv<'tcx> for Builder<'_, '_, 'tcx> { - fn param_env(&self) -> ParamEnv<'tcx> { - self.cx.param_env() +impl<'tcx> HasTypingEnv<'tcx> for Builder<'_, '_, 'tcx> { + fn typing_env(&self) -> ty::TypingEnv<'tcx> { + self.cx.typing_env() } } diff --git a/compiler/rustc_codegen_gcc/src/consts.rs b/compiler/rustc_codegen_gcc/src/consts.rs index 07c7a54de1ce..6dc2f4ed6688 100644 --- a/compiler/rustc_codegen_gcc/src/consts.rs +++ b/compiler/rustc_codegen_gcc/src/consts.rs @@ -215,7 +215,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { let gcc_type = if nested { self.type_i8() } else { - let ty = instance.ty(self.tcx, ty::ParamEnv::reveal_all()); + let ty = instance.ty(self.tcx, ty::TypingEnv::fully_monomorphized()); self.layout_of(ty).gcc_type(self) }; diff --git a/compiler/rustc_codegen_gcc/src/context.rs b/compiler/rustc_codegen_gcc/src/context.rs index 707b35967a6d..3846d0255377 100644 --- a/compiler/rustc_codegen_gcc/src/context.rs +++ b/compiler/rustc_codegen_gcc/src/context.rs @@ -11,10 +11,10 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_middle::mir::mono::CodegenUnit; use rustc_middle::span_bug; use rustc_middle::ty::layout::{ - FnAbiError, FnAbiOf, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, HasTyCtxt, LayoutError, + FnAbiError, FnAbiOf, FnAbiOfHelpers, FnAbiRequest, HasTyCtxt, HasTypingEnv, LayoutError, LayoutOfHelpers, }; -use rustc_middle::ty::{self, Instance, ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt}; +use rustc_middle::ty::{self, Instance, PolyExistentialTraitRef, Ty, TyCtxt}; use rustc_session::Session; use rustc_span::source_map::respan; use rustc_span::{DUMMY_SP, Span}; @@ -144,7 +144,9 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { supports_f128_type: bool, ) -> Self { let create_type = |ctype, rust_type| { - let layout = tcx.layout_of(ParamEnv::reveal_all().and(rust_type)).unwrap(); + let layout = tcx + .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(rust_type)) + .unwrap(); let align = layout.align.abi.bytes(); #[cfg(feature = "master")] { @@ -459,7 +461,7 @@ impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { Some(def_id) if !wants_msvc_seh(self.sess()) => { let instance = ty::Instance::expect_resolve( tcx, - ty::ParamEnv::reveal_all(), + self.typing_env(), def_id, ty::List::empty(), DUMMY_SP, @@ -583,9 +585,9 @@ impl<'gcc, 'tcx> FnAbiOfHelpers<'tcx> for CodegenCx<'gcc, 'tcx> { } } -impl<'tcx, 'gcc> HasParamEnv<'tcx> for CodegenCx<'gcc, 'tcx> { - fn param_env(&self) -> ParamEnv<'tcx> { - ParamEnv::reveal_all() +impl<'tcx, 'gcc> HasTypingEnv<'tcx> for CodegenCx<'gcc, 'tcx> { + fn typing_env(&self) -> ty::TypingEnv<'tcx> { + ty::TypingEnv::fully_monomorphized() } } diff --git a/compiler/rustc_codegen_gcc/src/debuginfo.rs b/compiler/rustc_codegen_gcc/src/debuginfo.rs index 5d8c5c199b12..6aeb656c1ab4 100644 --- a/compiler/rustc_codegen_gcc/src/debuginfo.rs +++ b/compiler/rustc_codegen_gcc/src/debuginfo.rs @@ -113,15 +113,15 @@ fn make_mir_scope<'gcc, 'tcx>( let scope_data = &mir.source_scopes[scope]; let parent_scope = if let Some(parent) = scope_data.parent_scope { make_mir_scope(cx, _instance, mir, variables, debug_context, instantiated, parent); - debug_context.scopes[parent] + debug_context.scopes[parent].unwrap() } else { // The root is the function itself. let file = cx.sess().source_map().lookup_source_file(mir.span.lo()); - debug_context.scopes[scope] = DebugScope { + debug_context.scopes[scope] = Some(DebugScope { file_start_pos: file.start_pos, file_end_pos: file.end_position(), - ..debug_context.scopes[scope] - }; + ..debug_context.scopes[scope].unwrap() + }); instantiated.insert(scope); return; }; @@ -130,7 +130,7 @@ fn make_mir_scope<'gcc, 'tcx>( if !vars.contains(scope) && scope_data.inlined.is_none() { // Do not create a DIScope if there are no variables defined in this // MIR `SourceScope`, and it's not `inlined`, to avoid debuginfo bloat. - debug_context.scopes[scope] = parent_scope; + debug_context.scopes[scope] = Some(parent_scope); instantiated.insert(scope); return; } @@ -157,12 +157,12 @@ fn make_mir_scope<'gcc, 'tcx>( // TODO(tempdragon): dbg_scope: Add support for scope extension here. inlined_at.or(p_inlined_at); - debug_context.scopes[scope] = DebugScope { + debug_context.scopes[scope] = Some(DebugScope { dbg_scope, inlined_at, file_start_pos: loc.file.start_pos, file_end_pos: loc.file.end_position(), - }; + }); instantiated.insert(scope); } @@ -232,12 +232,12 @@ impl<'gcc, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { } // Initialize fn debug context (including scopes). - let empty_scope = DebugScope { + let empty_scope = Some(DebugScope { dbg_scope: self.dbg_scope_fn(instance, fn_abi, Some(llfn)), inlined_at: None, file_start_pos: BytePos(0), file_end_pos: BytePos(0), - }; + }); let mut fn_debug_context = FunctionDebugContext { scopes: IndexVec::from_elem(empty_scope, mir.source_scopes.as_slice()), inlined_function_scopes: Default::default(), diff --git a/compiler/rustc_codegen_gcc/src/int.rs b/compiler/rustc_codegen_gcc/src/int.rs index 5ca440f4c9b1..02b760dc7334 100644 --- a/compiler/rustc_codegen_gcc/src/int.rs +++ b/compiler/rustc_codegen_gcc/src/int.rs @@ -5,7 +5,7 @@ use gccjit::{BinaryOp, ComparisonOp, FunctionType, Location, RValue, ToRValue, Type, UnaryOp}; use rustc_codegen_ssa::common::{IntPredicate, TypeKind}; use rustc_codegen_ssa::traits::{BackendTypes, BaseTypeCodegenMethods, BuilderMethods, OverflowOp}; -use rustc_middle::ty::{ParamEnv, Ty}; +use rustc_middle::ty::{self, Ty}; use rustc_target::abi::Endian; use rustc_target::abi::call::{ArgAbi, ArgAttributes, Conv, FnAbi, PassMode}; use rustc_target::spec; @@ -380,7 +380,10 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let overflow_field = self.context.new_field(self.location, self.bool_type, "overflow"); let ret_ty = Ty::new_tup(self.tcx, &[self.tcx.types.i128, self.tcx.types.bool]); - let layout = self.tcx.layout_of(ParamEnv::reveal_all().and(ret_ty)).unwrap(); + let layout = self + .tcx + .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ret_ty)) + .unwrap(); let arg_abi = ArgAbi { layout, mode: PassMode::Direct(ArgAttributes::new()) }; let mut fn_abi = FnAbi { diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs index 225f294e1e46..69326f409bb3 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs @@ -21,7 +21,7 @@ use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, MiscCodegenMethods}; use rustc_middle::bug; use rustc_middle::ty::layout::LayoutOf; #[cfg(feature = "master")] -use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt}; +use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, HasTypingEnv}; use rustc_middle::ty::{self, Instance, Ty}; use rustc_span::{Span, Symbol, sym}; use rustc_target::abi::HasDataLayout; @@ -107,7 +107,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc span: Span, ) -> Result<(), Instance<'tcx>> { let tcx = self.tcx; - let callee_ty = instance.ty(tcx, ty::ParamEnv::reveal_all()); + let callee_ty = instance.ty(tcx, self.typing_env()); let (def_id, fn_args) = match *callee_ty.kind() { ty::FnDef(def_id, fn_args) => (def_id, fn_args), @@ -115,7 +115,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc }; let sig = callee_ty.fn_sig(tcx); - let sig = tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), sig); + let sig = tcx.normalize_erasing_late_bound_regions(self.typing_env(), sig); let arg_tys = sig.inputs(); let ret_ty = sig.output(); let name = tcx.item_name(def_id); diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs index 43dbfafa8718..604678a9af4c 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs @@ -55,8 +55,10 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( } let tcx = bx.tcx(); - let sig = - tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), callee_ty.fn_sig(tcx)); + let sig = tcx.normalize_erasing_late_bound_regions( + ty::TypingEnv::fully_monomorphized(), + callee_ty.fn_sig(tcx), + ); let arg_tys = sig.inputs(); if name == sym::simd_select_bitmask { @@ -478,7 +480,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( match *in_elem.kind() { ty::RawPtr(p_ty, _) => { let metadata = p_ty.ptr_metadata_ty(bx.tcx, |ty| { - bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty) + bx.tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), ty) }); require!(metadata.is_unit(), InvalidMonomorphization::CastWidePointer { span, @@ -493,7 +495,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( match *out_elem.kind() { ty::RawPtr(p_ty, _) => { let metadata = p_ty.ptr_metadata_ty(bx.tcx, |ty| { - bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty) + bx.tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), ty) }); require!(metadata.is_unit(), InvalidMonomorphization::CastWidePointer { span, diff --git a/compiler/rustc_codegen_gcc/src/mono_item.rs b/compiler/rustc_codegen_gcc/src/mono_item.rs index b7b282bf2a65..239902df7f04 100644 --- a/compiler/rustc_codegen_gcc/src/mono_item.rs +++ b/compiler/rustc_codegen_gcc/src/mono_item.rs @@ -6,7 +6,7 @@ use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_middle::bug; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::mono::{Linkage, Visibility}; -use rustc_middle::ty::layout::{FnAbiOf, LayoutOf}; +use rustc_middle::ty::layout::{FnAbiOf, HasTypingEnv, LayoutOf}; use rustc_middle::ty::{self, Instance, TypeVisitableExt}; use crate::context::CodegenCx; @@ -27,11 +27,8 @@ impl<'gcc, 'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { let DefKind::Static { nested, .. } = self.tcx.def_kind(def_id) else { bug!() }; // Nested statics do not have a type, so pick a dummy type and let `codegen_static` figure out // the gcc type from the actual evaluated initializer. - let ty = if nested { - self.tcx.types.unit - } else { - instance.ty(self.tcx, ty::ParamEnv::reveal_all()) - }; + let ty = + if nested { self.tcx.types.unit } else { instance.ty(self.tcx, self.typing_env()) }; let gcc_type = self.layout_of(ty).gcc_type(self); let is_tls = attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL); diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index ac76b781218a..b5bb7630ca6c 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -14,7 +14,7 @@ use rustc_data_structures::small_c_str::SmallCStr; use rustc_hir::def_id::DefId; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; use rustc_middle::ty::layout::{ - FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, LayoutError, LayoutOfHelpers, + FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasTypingEnv, LayoutError, LayoutOfHelpers, TyAndLayout, }; use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; @@ -81,9 +81,9 @@ impl<'tcx> ty::layout::HasTyCtxt<'tcx> for Builder<'_, '_, 'tcx> { } } -impl<'tcx> ty::layout::HasParamEnv<'tcx> for Builder<'_, '_, 'tcx> { - fn param_env(&self) -> ty::ParamEnv<'tcx> { - self.cx.param_env() +impl<'tcx> ty::layout::HasTypingEnv<'tcx> for Builder<'_, '_, 'tcx> { + fn typing_env(&self) -> ty::TypingEnv<'tcx> { + self.cx.typing_env() } } @@ -472,7 +472,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { #[instrument(level = "trace", skip(self))] fn load_operand(&mut self, place: PlaceRef<'tcx, &'ll Value>) -> OperandRef<'tcx, &'ll Value> { if place.layout.is_unsized() { - let tail = self.tcx.struct_tail_for_codegen(place.layout.ty, self.param_env()); + let tail = self.tcx.struct_tail_for_codegen(place.layout.ty, self.typing_env()); if matches!(tail.kind(), ty::Foreign(..)) { // Unsized locals and, at least conceptually, even unsized arguments must be copied // around, which requires dynamically determining their size. Therefore, we cannot diff --git a/compiler/rustc_codegen_llvm/src/callee.rs b/compiler/rustc_codegen_llvm/src/callee.rs index dcea9d3b3915..e0a2de3366c0 100644 --- a/compiler/rustc_codegen_llvm/src/callee.rs +++ b/compiler/rustc_codegen_llvm/src/callee.rs @@ -5,7 +5,7 @@ //! closure. use rustc_codegen_ssa::common; -use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt}; +use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, HasTypingEnv}; use rustc_middle::ty::{self, Instance, TypeVisitableExt}; use tracing::debug; @@ -28,12 +28,7 @@ pub(crate) fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'t } let sym = tcx.symbol_name(instance).name; - debug!( - "get_fn({:?}: {:?}) => {}", - instance, - instance.ty(cx.tcx(), ty::ParamEnv::reveal_all()), - sym - ); + debug!("get_fn({:?}: {:?}) => {}", instance, instance.ty(cx.tcx(), cx.typing_env()), sym); let fn_abi = cx.fn_abi_of_instance(instance, ty::List::empty()); diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index 7ab4f45cd733..6f5ffbb4b345 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -13,8 +13,8 @@ use rustc_middle::mir::interpret::{ read_target_uint, }; use rustc_middle::mir::mono::MonoItem; -use rustc_middle::ty::layout::LayoutOf; -use rustc_middle::ty::{self, Instance}; +use rustc_middle::ty::Instance; +use rustc_middle::ty::layout::{HasTypingEnv, LayoutOf}; use rustc_middle::{bug, span_bug}; use rustc_session::config::Lto; use tracing::{debug, instrument, trace}; @@ -244,7 +244,7 @@ impl<'ll> CodegenCx<'ll, '_> { let llty = if nested { self.type_i8() } else { - let ty = instance.ty(self.tcx, ty::ParamEnv::reveal_all()); + let ty = instance.ty(self.tcx, self.typing_env()); trace!(?ty); self.layout_of(ty).llvm_type(self) }; diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 3a7c7efe03b9..841c110b3c8e 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -15,7 +15,7 @@ use rustc_hir::def_id::DefId; use rustc_middle::middle::codegen_fn_attrs::PatchableFunctionEntry; use rustc_middle::mir::mono::CodegenUnit; use rustc_middle::ty::layout::{ - FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, LayoutError, LayoutOfHelpers, + FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasTypingEnv, LayoutError, LayoutOfHelpers, }; use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; use rustc_middle::{bug, span_bug}; @@ -658,7 +658,7 @@ impl<'ll, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> { let llfn = match tcx.lang_items().eh_personality() { Some(def_id) if name.is_none() => self.get_fn_addr(ty::Instance::expect_resolve( tcx, - ty::ParamEnv::reveal_all(), + self.typing_env(), def_id, ty::List::empty(), DUMMY_SP, @@ -1162,9 +1162,9 @@ impl<'tcx> ty::layout::HasTyCtxt<'tcx> for CodegenCx<'_, 'tcx> { } } -impl<'tcx, 'll> HasParamEnv<'tcx> for CodegenCx<'ll, 'tcx> { - fn param_env(&self) -> ty::ParamEnv<'tcx> { - ty::ParamEnv::reveal_all() +impl<'tcx, 'll> HasTypingEnv<'tcx> for CodegenCx<'ll, 'tcx> { + fn typing_env(&self) -> ty::TypingEnv<'tcx> { + ty::TypingEnv::fully_monomorphized() } } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs index 0f1909486ec7..07bd0f4d1c17 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs @@ -6,10 +6,10 @@ use rustc_data_structures::fx::FxHashMap; use rustc_index::Idx; use rustc_index::bit_set::BitSet; use rustc_middle::mir::{Body, SourceScope}; -use rustc_middle::ty::layout::FnAbiOf; +use rustc_middle::ty::layout::{FnAbiOf, HasTypingEnv}; use rustc_middle::ty::{self, Instance}; use rustc_session::config::DebugInfo; -use rustc_span::BytePos; +use rustc_span::{BytePos, hygiene}; use super::metadata::file_metadata; use super::utils::DIB; @@ -85,15 +85,23 @@ fn make_mir_scope<'ll, 'tcx>( discriminators, parent, ); - debug_context.scopes[parent] + if let Some(parent_scope) = debug_context.scopes[parent] { + parent_scope + } else { + // If the parent scope could not be represented then no children + // can be either. + debug_context.scopes[scope] = None; + instantiated.insert(scope); + return; + } } else { // The root is the function itself. let file = cx.sess().source_map().lookup_source_file(mir.span.lo()); - debug_context.scopes[scope] = DebugScope { + debug_context.scopes[scope] = Some(DebugScope { file_start_pos: file.start_pos, file_end_pos: file.end_position(), - ..debug_context.scopes[scope] - }; + ..debug_context.scopes[scope].unwrap() + }); instantiated.insert(scope); return; }; @@ -104,7 +112,7 @@ fn make_mir_scope<'ll, 'tcx>( { // Do not create a DIScope if there are no variables defined in this // MIR `SourceScope`, and it's not `inlined`, to avoid debuginfo bloat. - debug_context.scopes[scope] = parent_scope; + debug_context.scopes[scope] = Some(parent_scope); instantiated.insert(scope); return; } @@ -118,7 +126,7 @@ fn make_mir_scope<'ll, 'tcx>( // if this is moved to `rustc_codegen_ssa::mir::debuginfo`. let callee = cx.tcx.instantiate_and_normalize_erasing_regions( instance.args, - ty::ParamEnv::reveal_all(), + cx.typing_env(), ty::EarlyBinder::bind(callee), ); debug_context.inlined_function_scopes.entry(callee).or_insert_with(|| { @@ -137,14 +145,20 @@ fn make_mir_scope<'ll, 'tcx>( }, }; - let inlined_at = scope_data.inlined.map(|(_, callsite_span)| { - // FIXME(eddyb) this doesn't account for the macro-related - // `Span` fixups that `rustc_codegen_ssa::mir::debuginfo` does. + let mut debug_scope = Some(DebugScope { + dbg_scope, + inlined_at: parent_scope.inlined_at, + file_start_pos: loc.file.start_pos, + file_end_pos: loc.file.end_position(), + }); + + if let Some((_, callsite_span)) = scope_data.inlined { + let callsite_span = hygiene::walk_chain_collapsed(callsite_span, mir.span); let callsite_scope = parent_scope.adjust_dbg_scope_for_span(cx, callsite_span); let loc = cx.dbg_loc(callsite_scope, parent_scope.inlined_at, callsite_span); // NB: In order to produce proper debug info for variables (particularly - // arguments) in multiply-inline functions, LLVM expects to see a single + // arguments) in multiply-inlined functions, LLVM expects to see a single // DILocalVariable with multiple different DILocations in the IR. While // the source information for each DILocation would be identical, their // inlinedAt attributes will be unique to the particular callsite. @@ -152,7 +166,7 @@ fn make_mir_scope<'ll, 'tcx>( // We generate DILocations here based on the callsite's location in the // source code. A single location in the source code usually can't // produce multiple distinct calls so this mostly works, until - // proc-macros get involved. A proc-macro can generate multiple calls + // macros get involved. A macro can generate multiple calls // at the same span, which breaks the assumption that we're going to // produce a unique DILocation for every scope we process here. We // have to explicitly add discriminators if we see inlines into the @@ -161,24 +175,29 @@ fn make_mir_scope<'ll, 'tcx>( // Note further that we can't key this hashtable on the span itself, // because these spans could have distinct SyntaxContexts. We have // to key on exactly what we're giving to LLVM. - match discriminators.entry(callsite_span.lo()) { + let inlined_at = match discriminators.entry(callsite_span.lo()) { Entry::Occupied(mut o) => { *o.get_mut() += 1; unsafe { llvm::LLVMRustDILocationCloneWithBaseDiscriminator(loc, *o.get()) } - .expect("Failed to encode discriminator in DILocation") } Entry::Vacant(v) => { v.insert(0); - loc + Some(loc) + } + }; + match inlined_at { + Some(inlined_at) => { + debug_scope.as_mut().unwrap().inlined_at = Some(inlined_at); + } + None => { + // LLVM has a maximum discriminator that it can encode (currently + // it uses 12 bits for 4096 possible values). If we exceed that + // there is little we can do but drop the debug info. + debug_scope = None; } } - }); + } - debug_context.scopes[scope] = DebugScope { - dbg_scope, - inlined_at: inlined_at.or(parent_scope.inlined_at), - file_start_pos: loc.file.start_pos, - file_end_pos: loc.file.end_position(), - }; + debug_context.scopes[scope] = debug_scope; instantiated.insert(scope); } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 151923a3bd28..ef16e5bb4593 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -11,10 +11,9 @@ use rustc_codegen_ssa::traits::*; use rustc_hir::def::{CtorKind, DefKind}; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_middle::bug; -use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; +use rustc_middle::ty::layout::{HasTypingEnv, LayoutOf, TyAndLayout}; use rustc_middle::ty::{ - self, AdtKind, CoroutineArgsExt, Instance, ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt, - Visibility, + self, AdtKind, CoroutineArgsExt, Instance, PolyExistentialTraitRef, Ty, TyCtxt, Visibility, }; use rustc_session::config::{self, DebugInfo, Lto}; use rustc_span::symbol::Symbol; @@ -301,9 +300,8 @@ fn build_subroutine_type_di_node<'ll, 'tcx>( .insert(unique_type_id, recursion_marker_type_di_node(cx)); let fn_ty = unique_type_id.expect_ty(); - let signature = cx - .tcx - .normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), fn_ty.fn_sig(cx.tcx)); + let signature = + cx.tcx.normalize_erasing_late_bound_regions(cx.typing_env(), fn_ty.fn_sig(cx.tcx)); let signature_di_nodes: SmallVec<_> = iter::once( // return type @@ -1109,9 +1107,7 @@ fn build_upvar_field_di_nodes<'ll, 'tcx>( } }; - assert!( - up_var_tys.iter().all(|t| t == cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), t)) - ); + assert!(up_var_tys.iter().all(|t| t == cx.tcx.normalize_erasing_regions(cx.typing_env(), t))); let capture_names = cx.tcx.closure_saved_names_of_captured_variables(def_id); let layout = cx.layout_of(closure_or_coroutine_ty); @@ -1272,8 +1268,7 @@ fn build_generic_type_param_di_nodes<'ll, 'tcx>( let template_params: SmallVec<_> = iter::zip(args, names) .filter_map(|(kind, name)| { kind.as_type().map(|ty| { - let actual_type = - cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty); + let actual_type = cx.tcx.normalize_erasing_regions(cx.typing_env(), ty); let actual_type_di_node = type_di_node(cx, actual_type); let name = name.as_str(); unsafe { @@ -1341,7 +1336,7 @@ pub(crate) fn build_global_var_di_node<'ll>( if nested { return; } - let variable_type = Instance::mono(cx.tcx, def_id).ty(cx.tcx, ty::ParamEnv::reveal_all()); + let variable_type = Instance::mono(cx.tcx, def_id).ty(cx.tcx, cx.typing_env()); let type_di_node = type_di_node(cx, variable_type); let var_name = tcx.item_name(def_id); let var_name = var_name.as_str(); diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs index 5120b63d173b..4e461476040b 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs @@ -6,7 +6,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_macros::HashStable; use rustc_middle::bug; -use rustc_middle::ty::{ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt}; +use rustc_middle::ty::{self, PolyExistentialTraitRef, Ty, TyCtxt}; use super::{SmallVec, UNKNOWN_LINE_NUMBER, unknown_file_metadata}; use crate::common::{AsCCharPtr, CodegenCx}; @@ -49,12 +49,15 @@ pub(super) enum UniqueTypeId<'tcx> { impl<'tcx> UniqueTypeId<'tcx> { pub(crate) fn for_ty(tcx: TyCtxt<'tcx>, t: Ty<'tcx>) -> Self { - assert_eq!(t, tcx.normalize_erasing_regions(ParamEnv::reveal_all(), t)); + assert_eq!(t, tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), t)); UniqueTypeId::Ty(t, private::HiddenZst) } pub(crate) fn for_enum_variant_part(tcx: TyCtxt<'tcx>, enum_ty: Ty<'tcx>) -> Self { - assert_eq!(enum_ty, tcx.normalize_erasing_regions(ParamEnv::reveal_all(), enum_ty)); + assert_eq!( + enum_ty, + tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), enum_ty) + ); UniqueTypeId::VariantPart(enum_ty, private::HiddenZst) } @@ -63,7 +66,10 @@ impl<'tcx> UniqueTypeId<'tcx> { enum_ty: Ty<'tcx>, variant_idx: VariantIdx, ) -> Self { - assert_eq!(enum_ty, tcx.normalize_erasing_regions(ParamEnv::reveal_all(), enum_ty)); + assert_eq!( + enum_ty, + tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), enum_ty) + ); UniqueTypeId::VariantStructType(enum_ty, variant_idx, private::HiddenZst) } @@ -72,7 +78,10 @@ impl<'tcx> UniqueTypeId<'tcx> { enum_ty: Ty<'tcx>, variant_idx: VariantIdx, ) -> Self { - assert_eq!(enum_ty, tcx.normalize_erasing_regions(ParamEnv::reveal_all(), enum_ty)); + assert_eq!( + enum_ty, + tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), enum_ty) + ); UniqueTypeId::VariantStructTypeCppLikeWrapper(enum_ty, variant_idx, private::HiddenZst) } @@ -81,10 +90,13 @@ impl<'tcx> UniqueTypeId<'tcx> { self_type: Ty<'tcx>, implemented_trait: Option>, ) -> Self { - assert_eq!(self_type, tcx.normalize_erasing_regions(ParamEnv::reveal_all(), self_type)); + assert_eq!( + self_type, + tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), self_type) + ); assert_eq!( implemented_trait, - tcx.normalize_erasing_regions(ParamEnv::reveal_all(), implemented_trait) + tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), implemented_trait) ); UniqueTypeId::VTableTy(self_type, implemented_trait, private::HiddenZst) } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index 89492e4b9fe5..a8fdfbed5924 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -15,8 +15,8 @@ use rustc_data_structures::unord::UnordMap; use rustc_hir::def_id::{DefId, DefIdMap}; use rustc_index::IndexVec; use rustc_middle::mir; -use rustc_middle::ty::layout::LayoutOf; -use rustc_middle::ty::{self, GenericArgsRef, Instance, ParamEnv, Ty, TypeVisitableExt}; +use rustc_middle::ty::layout::{HasTypingEnv, LayoutOf}; +use rustc_middle::ty::{self, GenericArgsRef, Instance, Ty, TypeVisitableExt}; use rustc_session::Session; use rustc_session::config::{self, DebugInfo}; use rustc_span::symbol::Symbol; @@ -294,12 +294,12 @@ impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> { } // Initialize fn debug context (including scopes). - let empty_scope = DebugScope { + let empty_scope = Some(DebugScope { dbg_scope: self.dbg_scope_fn(instance, fn_abi, Some(llfn)), inlined_at: None, file_start_pos: BytePos(0), file_end_pos: BytePos(0), - }; + }); let mut fn_debug_context = FunctionDebugContext { scopes: IndexVec::from_elem(empty_scope, &mir.source_scopes), inlined_function_scopes: Default::default(), @@ -344,7 +344,7 @@ impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> { type_names::push_generic_params( tcx, - tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), args), + tcx.normalize_erasing_regions(self.typing_env(), args), &mut name, ); @@ -481,8 +481,7 @@ impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> { iter::zip(args, names) .filter_map(|(kind, name)| { kind.as_type().map(|ty| { - let actual_type = - cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty); + let actual_type = cx.tcx.normalize_erasing_regions(cx.typing_env(), ty); let actual_type_metadata = type_di_node(cx, actual_type); let name = name.as_str(); unsafe { @@ -526,7 +525,7 @@ impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> { if cx.tcx.trait_id_of_impl(impl_def_id).is_none() { let impl_self_ty = cx.tcx.instantiate_and_normalize_erasing_regions( instance.args, - ty::ParamEnv::reveal_all(), + cx.typing_env(), cx.tcx.type_of(impl_def_id), ); diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs b/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs index 960487ada16a..6e8412934778 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs @@ -1,7 +1,7 @@ // Utility Functions. use rustc_hir::def_id::DefId; -use rustc_middle::ty::layout::{HasParamEnv, LayoutOf}; +use rustc_middle::ty::layout::{HasTypingEnv, LayoutOf}; use rustc_middle::ty::{self, Ty}; use tracing::trace; @@ -62,7 +62,7 @@ pub(crate) fn wide_pointer_kind<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, pointee_ty: Ty<'tcx>, ) -> Option { - let pointee_tail_ty = cx.tcx.struct_tail_for_codegen(pointee_ty, cx.param_env()); + let pointee_tail_ty = cx.tcx.struct_tail_for_codegen(pointee_ty, cx.typing_env()); let layout = cx.layout_of(pointee_tail_ty); trace!( "wide_pointer_kind: {:?} has layout {:?} (is_unsized? {})", diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index b56f464975df..da7f94e8cf71 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -10,7 +10,7 @@ use rustc_codegen_ssa::mir::place::{PlaceRef, PlaceValue}; use rustc_codegen_ssa::traits::*; use rustc_hir as hir; use rustc_middle::mir::BinOp; -use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, LayoutOf}; +use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, HasTypingEnv, LayoutOf}; use rustc_middle::ty::{self, GenericArgsRef, Ty}; use rustc_middle::{bug, span_bug}; use rustc_span::{Span, Symbol, sym}; @@ -163,14 +163,14 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { span: Span, ) -> Result<(), ty::Instance<'tcx>> { let tcx = self.tcx; - let callee_ty = instance.ty(tcx, ty::ParamEnv::reveal_all()); + let callee_ty = instance.ty(tcx, self.typing_env()); let ty::FnDef(def_id, fn_args) = *callee_ty.kind() else { bug!("expected fn item type, found {}", callee_ty); }; let sig = callee_ty.fn_sig(tcx); - let sig = tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), sig); + let sig = tcx.normalize_erasing_late_bound_regions(self.typing_env(), sig); let arg_tys = sig.inputs(); let ret_ty = sig.output(); let name = tcx.item_name(def_id); @@ -1152,8 +1152,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>( } let tcx = bx.tcx(); - let sig = - tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), callee_ty.fn_sig(tcx)); + let sig = tcx.normalize_erasing_late_bound_regions(bx.typing_env(), callee_ty.fn_sig(tcx)); let arg_tys = sig.inputs(); // Sanity-check: all vector arguments must be immediates. @@ -2187,7 +2186,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>( match in_elem.kind() { ty::RawPtr(p_ty, _) => { let metadata = p_ty.ptr_metadata_ty(bx.tcx, |ty| { - bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty) + bx.tcx.normalize_erasing_regions(bx.typing_env(), ty) }); require!(metadata.is_unit(), InvalidMonomorphization::CastWidePointer { span, @@ -2202,7 +2201,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>( match out_elem.kind() { ty::RawPtr(p_ty, _) => { let metadata = p_ty.ptr_metadata_ty(bx.tcx, |ty| { - bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty) + bx.tcx.normalize_erasing_regions(bx.typing_env(), ty) }); require!(metadata.is_unit(), InvalidMonomorphization::CastWidePointer { span, diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs index ea8857b4739c..33789c6261f1 100644 --- a/compiler/rustc_codegen_llvm/src/mono_item.rs +++ b/compiler/rustc_codegen_llvm/src/mono_item.rs @@ -3,7 +3,7 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_middle::bug; use rustc_middle::mir::mono::{Linkage, Visibility}; -use rustc_middle::ty::layout::{FnAbiOf, LayoutOf}; +use rustc_middle::ty::layout::{FnAbiOf, HasTypingEnv, LayoutOf}; use rustc_middle::ty::{self, Instance, TypeVisitableExt}; use rustc_session::config::CrateType; use rustc_target::spec::RelocModel; @@ -26,11 +26,8 @@ impl<'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> { let DefKind::Static { nested, .. } = self.tcx.def_kind(def_id) else { bug!() }; // Nested statics do not have a type, so pick a dummy type and let `codegen_static` figure // out the llvm type from the actual evaluated initializer. - let ty = if nested { - self.tcx.types.unit - } else { - instance.ty(self.tcx, ty::ParamEnv::reveal_all()) - }; + let ty = + if nested { self.tcx.types.unit } else { instance.ty(self.tcx, self.typing_env()) }; let llty = self.layout_of(ty).llvm_type(self); let g = self.define_global(symbol_name, llty).unwrap_or_else(|| { diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index 850d36872dd5..d9152c5d0807 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -595,8 +595,10 @@ pub(crate) fn linking_symbol_name_for_instance_in_crate<'tcx>( let (conv, args) = instance .map(|i| { - tcx.fn_abi_of_instance(ty::ParamEnv::reveal_all().and((i, ty::List::empty()))) - .unwrap_or_else(|_| bug!("fn_abi_of_instance({i:?}) failed")) + tcx.fn_abi_of_instance( + ty::TypingEnv::fully_monomorphized().as_query_input((i, ty::List::empty())), + ) + .unwrap_or_else(|_| bug!("fn_abi_of_instance({i:?}) failed")) }) .map(|fnabi| (fnabi.conv, &fnabi.args[..])) .unwrap_or((Conv::Rust, &[])); diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index ef95ab94062e..c8b3b30218ad 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -21,7 +21,7 @@ use rustc_middle::middle::{exported_symbols, lang_items}; use rustc_middle::mir::BinOp; use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem}; use rustc_middle::query::Providers; -use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout}; +use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutOf, TyAndLayout}; use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypingMode}; use rustc_session::Session; use rustc_session::config::{self, CrateType, EntryFnType, OptLevel, OutputType}; @@ -165,7 +165,7 @@ fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( ) -> Bx::Value { let cx = bx.cx(); let (source, target) = - cx.tcx().struct_lockstep_tails_for_codegen(source, target, bx.param_env()); + cx.tcx().struct_lockstep_tails_for_codegen(source, target, bx.typing_env()); match (source.kind(), target.kind()) { (&ty::Array(_, len), &ty::Slice(_)) => cx.const_usize( len.try_to_target_usize(cx.tcx()).expect("expected monomorphic const in codegen"), @@ -466,10 +466,9 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // late-bound regions, since late-bound // regions must appear in the argument // listing. - let main_ret_ty = cx.tcx().normalize_erasing_regions( - ty::ParamEnv::reveal_all(), - main_ret_ty.no_bound_vars().unwrap(), - ); + let main_ret_ty = cx + .tcx() + .normalize_erasing_regions(cx.typing_env(), main_ret_ty.no_bound_vars().unwrap()); let Some(llfn) = cx.declare_c_main(llfty) else { // FIXME: We should be smart and show a better diagnostic here. @@ -495,7 +494,7 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let start_def_id = cx.tcx().require_lang_item(LangItem::Start, None); let start_instance = ty::Instance::expect_resolve( cx.tcx(), - ty::ParamEnv::reveal_all(), + cx.typing_env(), start_def_id, cx.tcx().mk_args(&[main_ret_ty.into()]), DUMMY_SP, diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index 27bc58516c08..6c4f6d37972d 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -21,9 +21,7 @@ use rustc_hir::definitions::{DefPathData, DefPathDataName, DisambiguatedDefPathD use rustc_hir::{CoroutineDesugaring, CoroutineKind, CoroutineSource, Mutability}; use rustc_middle::bug; use rustc_middle::ty::layout::{IntegerExt, TyAndLayout}; -use rustc_middle::ty::{ - self, ExistentialProjection, GenericArgKind, GenericArgsRef, ParamEnv, Ty, TyCtxt, -}; +use rustc_middle::ty::{self, ExistentialProjection, GenericArgKind, GenericArgsRef, Ty, TyCtxt}; use smallvec::SmallVec; use crate::debuginfo::wants_c_like_enum_debuginfo; @@ -82,7 +80,7 @@ fn push_debuginfo_type_name<'tcx>( ty::Adt(def, args) => { // `layout_for_cpp_like_fallback` will be `Some` if we want to use the fallback encoding. let layout_for_cpp_like_fallback = if cpp_like_debuginfo && def.is_enum() { - match tcx.layout_of(ParamEnv::reveal_all().and(t)) { + match tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(t)) { Ok(layout) => { if !wants_c_like_enum_debuginfo(tcx, layout) { Some(layout) @@ -248,8 +246,10 @@ fn push_debuginfo_type_name<'tcx>( }; if let Some(principal) = trait_data.principal() { - let principal = - tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), principal); + let principal = tcx.normalize_erasing_late_bound_regions( + ty::TypingEnv::fully_monomorphized(), + principal, + ); push_item_name(tcx, principal.def_id, qualified, output); let principal_has_generic_params = push_generic_params_internal(tcx, principal.args, output, visited); @@ -350,8 +350,10 @@ fn push_debuginfo_type_name<'tcx>( return; } - let sig = - tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), t.fn_sig(tcx)); + let sig = tcx.normalize_erasing_late_bound_regions( + ty::TypingEnv::fully_monomorphized(), + t.fn_sig(tcx), + ); if cpp_like_debuginfo { // Format as a C++ function pointer: return_type (*)(params...) @@ -415,7 +417,8 @@ fn push_debuginfo_type_name<'tcx>( // In the case of cpp-like debuginfo, the name additionally gets wrapped inside of // an artificial `enum2$<>` type, as defined in msvc_enum_fallback(). if cpp_like_debuginfo && t.is_coroutine() { - let ty_and_layout = tcx.layout_of(ParamEnv::reveal_all().and(t)).unwrap(); + let ty_and_layout = + tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(t)).unwrap(); msvc_enum_fallback( tcx, ty_and_layout, @@ -529,8 +532,8 @@ pub fn compute_debuginfo_vtable_name<'tcx>( } if let Some(trait_ref) = trait_ref { - let trait_ref = - tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), trait_ref); + let trait_ref = tcx + .normalize_erasing_late_bound_regions(ty::TypingEnv::fully_monomorphized(), trait_ref); push_item_name(tcx, trait_ref.def_id, true, &mut vtable_name); visited.clear(); push_generic_params_internal(tcx, trait_ref.args, &mut vtable_name, &mut visited); @@ -639,7 +642,7 @@ fn push_generic_params_internal<'tcx>( output: &mut String, visited: &mut FxHashSet>, ) -> bool { - assert_eq!(args, tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), args)); + assert_eq!(args, tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), args)); let mut args = args.non_erasable_generics().peekable(); if args.peek().is_none() { return false; @@ -678,14 +681,14 @@ fn push_const_param<'tcx>(tcx: TyCtxt<'tcx>, ct: ty::Const<'tcx>, output: &mut S // FIXME: directly extract the bits from a valtree instead of evaluating an // already evaluated `Const` in order to get the bits. let bits = ct - .try_to_bits(tcx, ty::ParamEnv::reveal_all()) + .try_to_bits(tcx, ty::TypingEnv::fully_monomorphized()) .expect("expected monomorphic const in codegen"); let val = Integer::from_int_ty(&tcx, *ity).size().sign_extend(bits) as i128; write!(output, "{val}") } ty::Uint(_) => { let val = ct - .try_to_bits(tcx, ty::ParamEnv::reveal_all()) + .try_to_bits(tcx, ty::TypingEnv::fully_monomorphized()) .expect("expected monomorphic const in codegen"); write!(output, "{val}") } diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 097d37bb70c4..e3ed12b5ce61 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -777,7 +777,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let do_panic = !bx .tcx() - .check_validity_requirement((requirement, bx.param_env().and(ty))) + .check_validity_requirement((requirement, bx.typing_env().as_query_input(ty))) .expect("expect to have layout during codegen"); let layout = bx.layout_of(ty); @@ -848,14 +848,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let (instance, mut llfn) = match *callee.layout.ty.kind() { ty::FnDef(def_id, args) => ( Some( - ty::Instance::expect_resolve( - bx.tcx(), - ty::ParamEnv::reveal_all(), - def_id, - args, - fn_span, - ) - .polymorphize(bx.tcx()), + ty::Instance::expect_resolve(bx.tcx(), bx.typing_env(), def_id, args, fn_span) + .polymorphize(bx.tcx()), ), None, ), @@ -1191,7 +1185,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { if let ty::FnDef(def_id, args) = *const_.ty().kind() { let instance = ty::Instance::resolve_for_fn_ptr( bx.tcx(), - ty::ParamEnv::reveal_all(), + bx.typing_env(), def_id, args, ) diff --git a/compiler/rustc_codegen_ssa/src/mir/constant.rs b/compiler/rustc_codegen_ssa/src/mir/constant.rs index 54b9c9cc89f5..7676e1e171aa 100644 --- a/compiler/rustc_codegen_ssa/src/mir/constant.rs +++ b/compiler/rustc_codegen_ssa/src/mir/constant.rs @@ -1,6 +1,6 @@ use rustc_abi::BackendRepr; use rustc_middle::mir::interpret::ErrorHandled; -use rustc_middle::ty::layout::HasTyCtxt; +use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv}; use rustc_middle::ty::{self, Ty}; use rustc_middle::{bug, mir, span_bug}; @@ -24,7 +24,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // `MirUsedCollector` visited all required_consts before codegen began, so if we got here // there can be no more constants that fail to evaluate. self.monomorphize(constant.const_) - .eval(self.cx.tcx(), ty::ParamEnv::reveal_all(), constant.span) + .eval(self.cx.tcx(), self.cx.typing_env(), constant.span) .expect("erroneous constant missed by mono item collection") } @@ -57,7 +57,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { other => span_bug!(constant.span, "{other:#?}"), }; let uv = self.monomorphize(uv); - self.cx.tcx().const_eval_resolve_for_typeck(ty::ParamEnv::reveal_all(), uv, constant.span) + self.cx.tcx().const_eval_resolve_for_typeck(self.cx.typing_env(), uv, constant.span) } /// process constant containing SIMD shuffle indices & constant vectors diff --git a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs index 21d20475408b..d4d7f16db55d 100644 --- a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs +++ b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs @@ -20,7 +20,9 @@ use crate::traits::*; pub struct FunctionDebugContext<'tcx, S, L> { /// Maps from source code to the corresponding debug info scope. - pub scopes: IndexVec>, + /// May be None if the backend is not capable of representing the scope for + /// some reason. + pub scopes: IndexVec>>, /// Maps from an inlined function to its debug info declaration. pub inlined_function_scopes: FxHashMap, S>, @@ -231,7 +233,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { &self, source_info: mir::SourceInfo, ) -> Option<(Bx::DIScope, Option, Span)> { - let scope = &self.debug_context.as_ref()?.scopes[source_info.scope]; + let scope = &self.debug_context.as_ref()?.scopes[source_info.scope]?; let span = hygiene::walk_chain_collapsed(source_info.span, self.mir.span); Some((scope.adjust_dbg_scope_for_span(self.cx, span), scope.inlined_at, span)) } diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs index 2a1b9e28c1e0..c35d0b90706e 100644 --- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs +++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs @@ -59,14 +59,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { llresult: Bx::Value, span: Span, ) -> Result<(), ty::Instance<'tcx>> { - let callee_ty = instance.ty(bx.tcx(), ty::ParamEnv::reveal_all()); + let callee_ty = instance.ty(bx.tcx(), bx.typing_env()); let ty::FnDef(def_id, fn_args) = *callee_ty.kind() else { bug!("expected fn item type, found {}", callee_ty); }; let sig = callee_ty.fn_sig(bx.tcx()); - let sig = bx.tcx().normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), sig); + let sig = bx.tcx().normalize_erasing_late_bound_regions(bx.typing_env(), sig); let arg_tys = sig.inputs(); let ret_ty = sig.output(); let name = bx.tcx().item_name(def_id); diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index f19e3b721419..0cbc5c45736e 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -4,7 +4,7 @@ use rustc_index::IndexVec; use rustc_index::bit_set::BitSet; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::{UnwindTerminateReason, traversal}; -use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, TyAndLayout}; +use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, HasTypingEnv, TyAndLayout}; use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeFoldable, TypeVisitableExt}; use rustc_middle::{bug, mir, span_bug}; use rustc_target::callconv::{FnAbi, PassMode}; @@ -128,7 +128,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { debug!("monomorphize: self.instance={:?}", self.instance); self.instance.instantiate_mir_and_normalize_erasing_regions( self.cx.tcx(), - ty::ParamEnv::reveal_all(), + self.cx.typing_env(), ty::EarlyBinder::bind(value), ) } diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 0e1cd662f918..f63b2d139c5f 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -474,7 +474,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { ty::FnDef(def_id, args) => { let instance = ty::Instance::resolve_for_fn_ptr( bx.tcx(), - ty::ParamEnv::reveal_all(), + bx.typing_env(), def_id, args, ) @@ -709,7 +709,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mir::NullOp::OffsetOf(fields) => { let val = bx .tcx() - .offset_of_subfield(bx.param_env(), layout, fields.iter()) + .offset_of_subfield(bx.typing_env(), layout, fields.iter()) .bytes(); bx.cx().const_usize(val) } @@ -727,7 +727,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mir::Rvalue::ThreadLocalRef(def_id) => { assert!(bx.cx().tcx().is_static(def_id)); - let layout = bx.layout_of(bx.cx().tcx().static_ptr_ty(def_id)); + let layout = bx.layout_of(bx.cx().tcx().static_ptr_ty(def_id, bx.typing_env())); let static_ = if !def_id.is_local() && bx.cx().tcx().needs_thread_local_shim(def_id) { let instance = ty::Instance { diff --git a/compiler/rustc_codegen_ssa/src/traits/type_.rs b/compiler/rustc_codegen_ssa/src/traits/type_.rs index 44ba22621494..3810c609fd4f 100644 --- a/compiler/rustc_codegen_ssa/src/traits/type_.rs +++ b/compiler/rustc_codegen_ssa/src/traits/type_.rs @@ -1,6 +1,6 @@ use rustc_abi::{AddressSpace, Float, Integer}; use rustc_middle::bug; -use rustc_middle::ty::layout::{HasTyCtxt, TyAndLayout}; +use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, TyAndLayout}; use rustc_middle::ty::{self, Ty}; use rustc_target::callconv::{ArgAbi, CastTarget, FnAbi, Reg}; @@ -41,7 +41,7 @@ pub trait BaseTypeCodegenMethods<'tcx>: BackendTypes { } pub trait DerivedTypeCodegenMethods<'tcx>: - BaseTypeCodegenMethods<'tcx> + MiscCodegenMethods<'tcx> + HasTyCtxt<'tcx> + BaseTypeCodegenMethods<'tcx> + MiscCodegenMethods<'tcx> + HasTyCtxt<'tcx> + HasTypingEnv<'tcx> { fn type_int(&self) -> Self::Type { match &self.sess().target.c_int_width[..] { @@ -74,7 +74,7 @@ pub trait DerivedTypeCodegenMethods<'tcx>: } fn type_needs_drop(&self, ty: Ty<'tcx>) -> bool { - ty.needs_drop(self.tcx(), ty::ParamEnv::reveal_all()) + ty.needs_drop(self.tcx(), self.typing_env()) } fn type_is_sized(&self, ty: Ty<'tcx>) -> bool { @@ -86,12 +86,11 @@ pub trait DerivedTypeCodegenMethods<'tcx>: } fn type_has_metadata(&self, ty: Ty<'tcx>) -> bool { - let param_env = ty::ParamEnv::reveal_all(); - if ty.is_sized(self.tcx(), param_env) { + if ty.is_sized(self.tcx(), self.param_env()) { return false; } - let tail = self.tcx().struct_tail_for_codegen(ty, param_env); + let tail = self.tcx().struct_tail_for_codegen(ty, self.typing_env()); match tail.kind() { ty::Foreign(..) => false, ty::Str | ty::Slice(..) | ty::Dynamic(..) => true, @@ -101,7 +100,10 @@ pub trait DerivedTypeCodegenMethods<'tcx>: } impl<'tcx, T> DerivedTypeCodegenMethods<'tcx> for T where - Self: BaseTypeCodegenMethods<'tcx> + MiscCodegenMethods<'tcx> + HasTyCtxt<'tcx> + Self: BaseTypeCodegenMethods<'tcx> + + MiscCodegenMethods<'tcx> + + HasTyCtxt<'tcx> + + HasTypingEnv<'tcx> { } diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl index 15027ae0c187..f93f4d36e454 100644 --- a/compiler/rustc_const_eval/messages.ftl +++ b/compiler/rustc_const_eval/messages.ftl @@ -403,7 +403,7 @@ const_eval_uninhabited_enum_variant_written = const_eval_unmarked_const_fn_exposed = `{$def_path}` cannot be (indirectly) exposed to stable .help = either mark the callee as `#[rustc_const_stable_indirect]`, or the caller as `#[rustc_const_unstable]` const_eval_unmarked_intrinsic_exposed = intrinsic `{$def_path}` cannot be (indirectly) exposed to stable - .help = mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_intrinsic]` (but this requires team approval) + .help = mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_intrinsic_const_stable_indirect]` (but this requires team approval) const_eval_unreachable = entering unreachable code const_eval_unreachable_unwind = diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs index ffe32acb3165..8e96d365bebe 100644 --- a/compiler/rustc_const_eval/src/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/check_consts/check.rs @@ -388,7 +388,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> { return false; } - let infcx = tcx.infer_ctxt().build(self.body.typing_mode(tcx)); + let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(self.body.typing_env(tcx)); let ocx = ObligationCtxt::new_with_diagnostics(&infcx); let body_id = self.body.source.def_id().expect_local(); @@ -398,11 +398,8 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> { ty::BoundConstness::Const } }; - let const_conditions = ocx.normalize( - &ObligationCause::misc(call_span, body_id), - self.param_env, - const_conditions, - ); + let const_conditions = + ocx.normalize(&ObligationCause::misc(call_span, body_id), param_env, const_conditions); ocx.register_obligations(const_conditions.into_iter().map(|(trait_ref, span)| { Obligation::new( tcx, @@ -411,7 +408,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> { body_id, ObligationCauseCode::WhereClause(callee, span), ), - self.param_env, + param_env, trait_ref.to_host_effect_clause(tcx, host_polarity), ) })); @@ -760,7 +757,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { Some(ConstStability { level: StabilityLevel::Stable { .. }, .. }) => { // All good. Note that a `#[rustc_const_stable]` intrinsic (meaning it // can be *directly* invoked from stable const code) does not always - // have the `#[rustc_const_stable_intrinsic]` attribute (which controls + // have the `#[rustc_intrinsic_const_stable_indirect]` attribute (which controls // exposing an intrinsic indirectly); we accept this call anyway. } } diff --git a/compiler/rustc_const_eval/src/check_consts/mod.rs b/compiler/rustc_const_eval/src/check_consts/mod.rs index ebdd55a4f70c..80d3c6448aab 100644 --- a/compiler/rustc_const_eval/src/check_consts/mod.rs +++ b/compiler/rustc_const_eval/src/check_consts/mod.rs @@ -24,17 +24,15 @@ mod resolver; pub struct ConstCx<'mir, 'tcx> { pub body: &'mir mir::Body<'tcx>, pub tcx: TyCtxt<'tcx>, - pub param_env: ty::ParamEnv<'tcx>, + pub typing_env: ty::TypingEnv<'tcx>, pub const_kind: Option, } impl<'mir, 'tcx> ConstCx<'mir, 'tcx> { pub fn new(tcx: TyCtxt<'tcx>, body: &'mir mir::Body<'tcx>) -> Self { - let def_id = body.source.def_id().expect_local(); - let param_env = tcx.param_env(def_id); - + let typing_env = body.typing_env(tcx); let const_kind = tcx.hir().body_const_context(body.source.def_id().expect_local()); - ConstCx { body, tcx, param_env, const_kind } + ConstCx { body, tcx, typing_env, const_kind } } pub(crate) fn dcx(&self) -> DiagCtxtHandle<'tcx> { diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs index ca95e42dd2ba..8ba6b89aad4d 100644 --- a/compiler/rustc_const_eval/src/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/check_consts/ops.rs @@ -120,7 +120,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { #[allow(rustc::untranslatable_diagnostic)] fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, _: Span) -> Diag<'tcx> { let FnCallNonConst { callee, args, span, call_source } = *self; - let ConstCx { tcx, param_env, .. } = *ccx; + let ConstCx { tcx, typing_env, .. } = *ccx; let caller = ccx.def_id(); let diag_trait = |err, self_ty: Ty<'_>, trait_id| { @@ -146,13 +146,11 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { } } ty::Adt(..) => { + let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env); let obligation = Obligation::new(tcx, ObligationCause::dummy(), param_env, trait_ref); - - let infcx = tcx.infer_ctxt().build(ccx.body.typing_mode(tcx)); let mut selcx = SelectionContext::new(&infcx); let implsrc = selcx.select(&obligation); - if let Ok(Some(ImplSource::UserDefined(data))) = implsrc { // FIXME(const_trait_impl) revisit this if !tcx.is_const_trait_impl(data.impl_def_id) { @@ -166,7 +164,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { }; let call_kind = - call_kind(tcx, ccx.param_env, callee, args, span, call_source.from_hir_call(), None); + call_kind(tcx, ccx.typing_env, callee, args, span, call_source.from_hir_call(), None); debug!(?call_kind); diff --git a/compiler/rustc_const_eval/src/check_consts/post_drop_elaboration.rs b/compiler/rustc_const_eval/src/check_consts/post_drop_elaboration.rs index 0173a528c22a..f6eb130fbd38 100644 --- a/compiler/rustc_const_eval/src/check_consts/post_drop_elaboration.rs +++ b/compiler/rustc_const_eval/src/check_consts/post_drop_elaboration.rs @@ -32,17 +32,15 @@ pub fn checking_enabled(ccx: &ConstCx<'_, '_>) -> bool { /// This is separate from the rest of the const checking logic because it must run after drop /// elaboration. pub fn check_live_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mir::Body<'tcx>) { - let def_id = body.source.def_id().expect_local(); - let const_kind = tcx.hir().body_const_context(def_id); - if const_kind.is_none() { + let ccx = ConstCx::new(tcx, body); + if ccx.const_kind.is_none() { return; } - if tcx.has_attr(def_id, sym::rustc_do_not_const_check) { + if tcx.has_attr(body.source.def_id(), sym::rustc_do_not_const_check) { return; } - let ccx = ConstCx { body, tcx, const_kind, param_env: tcx.param_env(def_id) }; if !checking_enabled(&ccx) { return; } diff --git a/compiler/rustc_const_eval/src/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/check_consts/qualifs.rs index 29a08579175e..bc416acc58d7 100644 --- a/compiler/rustc_const_eval/src/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/check_consts/qualifs.rs @@ -106,20 +106,24 @@ impl Qualif for HasMutInterior { // Instead we invoke an obligation context manually, and provide the opaque type inference settings // that allow the trait solver to just error out instead of cycling. let freeze_def_id = cx.tcx.require_lang_item(LangItem::Freeze, Some(cx.body.span)); - + // FIXME(#132279): Once we've got a typing mode which reveals opaque types using the HIR + // typeck results without causing query cycles, we should use this here instead of defining + // opaque types. + let typing_env = ty::TypingEnv { + typing_mode: ty::TypingMode::analysis_in_body( + cx.tcx, + cx.body.source.def_id().expect_local(), + ), + param_env: cx.typing_env.param_env, + }; + let (infcx, param_env) = cx.tcx.infer_ctxt().build_with_typing_env(typing_env); + let ocx = ObligationCtxt::new(&infcx); let obligation = Obligation::new( cx.tcx, ObligationCause::dummy_with_span(cx.body.span), - cx.param_env, + param_env, ty::TraitRef::new(cx.tcx, freeze_def_id, [ty::GenericArg::from(ty)]), ); - - // FIXME(#132279): This should eventually use the already defined hidden types. - let infcx = cx.tcx.infer_ctxt().build(ty::TypingMode::analysis_in_body( - cx.tcx, - cx.body.source.def_id().expect_local(), - )); - let ocx = ObligationCtxt::new(&infcx); ocx.register_obligation(obligation); let errors = ocx.select_all_or_error(); !errors.is_empty() @@ -156,7 +160,7 @@ impl Qualif for NeedsDrop { } fn in_any_value_of_ty<'tcx>(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool { - ty.needs_drop(cx.tcx, cx.param_env) + ty.needs_drop(cx.tcx, cx.typing_env) } fn in_adt_inherently<'tcx>( diff --git a/compiler/rustc_const_eval/src/check_consts/resolver.rs b/compiler/rustc_const_eval/src/check_consts/resolver.rs index 74eb6b37fbba..03624a2ce50b 100644 --- a/compiler/rustc_const_eval/src/check_consts/resolver.rs +++ b/compiler/rustc_const_eval/src/check_consts/resolver.rs @@ -120,7 +120,10 @@ where /// /// [rust-lang/unsafe-code-guidelines#134]: https://github.com/rust-lang/unsafe-code-guidelines/issues/134 fn shared_borrow_allows_mutation(&self, place: mir::Place<'tcx>) -> bool { - !place.ty(self.ccx.body, self.ccx.tcx).ty.is_freeze(self.ccx.tcx, self.ccx.param_env) + !place + .ty(self.ccx.body, self.ccx.tcx) + .ty + .is_freeze(self.ccx.tcx, self.ccx.typing_env.param_env) } } diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index a430d9dc797f..ca3ee6773a0e 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -221,7 +221,7 @@ pub(super) fn op_to_const<'tcx>( let pointee_ty = imm.layout.ty.builtin_deref(false).unwrap(); // `false` = no raw ptrs debug_assert!( matches!( - ecx.tcx.struct_tail_for_codegen(pointee_ty, ecx.param_env).kind(), + ecx.tcx.struct_tail_for_codegen(pointee_ty, ecx.typing_env()).kind(), ty::Str | ty::Slice(..), ), "`ConstValue::Slice` is for slice-tailed types only, but got {}", @@ -280,11 +280,13 @@ pub fn eval_to_const_value_raw_provider<'tcx>( // opaque types. This is needed for trivial things like `size_of`, but also for using associated // types that are not specified in the opaque type. assert_eq!(key.param_env.reveal(), Reveal::All); + let typing_env = + ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env: key.param_env }; // We call `const_eval` for zero arg intrinsics, too, in order to cache their value. // Catch such calls and evaluate them instead of trying to load a constant's MIR. if let ty::InstanceKind::Intrinsic(def_id) = key.value.instance.def { - let ty = key.value.instance.ty(tcx, key.param_env); + let ty = key.value.instance.ty(tcx, typing_env); let ty::FnDef(_, args) = ty.kind() else { bug!("intrinsic with type {:?}", ty); }; diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index f12320cb8517..19c3195aaa4a 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -249,9 +249,10 @@ impl<'tcx> CompileTimeInterpCx<'tcx> { } else if self.tcx.is_lang_item(def_id, LangItem::PanicFmt) { // For panic_fmt, call const_panic_fmt instead. let const_def_id = self.tcx.require_lang_item(LangItem::ConstPanicFmt, None); + // FIXME(@lcnr): why does this use an empty env if we've got a `param_env` right here. let new_instance = ty::Instance::expect_resolve( *self.tcx, - ty::ParamEnv::reveal_all(), + ty::TypingEnv::fully_monomorphized(), const_def_id, instance.args, self.cur_span(), diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs index ea88b2ed22e2..64bedea3b3f1 100644 --- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs +++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs @@ -2,6 +2,7 @@ use rustc_abi::{BackendRepr, VariantIdx}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId}; use rustc_middle::ty::layout::{LayoutCx, LayoutOf, TyAndLayout}; +use rustc_middle::ty::solve::Reveal; use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt}; use rustc_middle::{bug, mir}; use rustc_span::DUMMY_SP; @@ -281,8 +282,9 @@ pub fn valtree_to_const_value<'tcx>( // the `ValTree` and using `place_projection` and `place_field` to // create inner `MPlace`s which are filled recursively. // FIXME Does this need an example? - let (param_env, ty) = param_env_ty.into_parts(); + debug_assert_eq!(param_env.reveal(), Reveal::All); + let typing_env = ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env }; match *ty.kind() { ty::FnDef(..) => { @@ -302,11 +304,12 @@ pub fn valtree_to_const_value<'tcx>( let mut ecx = mk_eval_cx_to_read_const_val(tcx, DUMMY_SP, param_env, CanAccessMutGlobal::No); let imm = valtree_to_ref(&mut ecx, valtree, inner_ty); - let imm = ImmTy::from_immediate(imm, tcx.layout_of(param_env_ty).unwrap()); + let imm = + ImmTy::from_immediate(imm, tcx.layout_of(typing_env.as_query_input(ty)).unwrap()); op_to_const(&ecx, &imm.into(), /* for diagnostics */ false) } ty::Tuple(_) | ty::Array(_, _) | ty::Adt(..) => { - let layout = tcx.layout_of(param_env_ty).unwrap(); + let layout = tcx.layout_of(typing_env.as_query_input(ty)).unwrap(); if layout.is_zst() { // Fast path to avoid some allocations. return mir::ConstValue::ZeroSized; @@ -319,7 +322,7 @@ pub fn valtree_to_const_value<'tcx>( let branches = valtree.unwrap_branch(); // Find the non-ZST field. (There can be aligned ZST!) for (i, &inner_valtree) in branches.iter().enumerate() { - let field = layout.field(&LayoutCx::new(tcx, param_env), i); + let field = layout.field(&LayoutCx::new(tcx, typing_env), i); if !field.is_zst() { return valtree_to_const_value(tcx, param_env.and(field.ty), inner_valtree); } diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs index ef0902e42261..6cfe4b21907d 100644 --- a/compiler/rustc_const_eval/src/interpret/call.rs +++ b/compiler/rustc_const_eval/src/interpret/call.rs @@ -215,7 +215,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // Even if `ty` is normalized, the search for the unsized tail will project // to fields, which can yield non-normalized types. So we need to provide a // normalization function. - let normalize = |ty| self.tcx.normalize_erasing_regions(self.param_env, ty); + let normalize = |ty| self.tcx.normalize_erasing_regions(self.typing_env(), ty); ty.ptr_metadata_ty(*self.tcx, normalize) }; return interp_ok(meta_ty(caller) == meta_ty(callee)); @@ -652,35 +652,35 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { }; // Obtain the underlying trait we are working on, and the adjusted receiver argument. - let (trait_, dyn_ty, adjusted_recv) = if let ty::Dynamic(data, _, ty::DynStar) = - receiver_place.layout.ty.kind() - { - let recv = self.unpack_dyn_star(&receiver_place, data)?; + let (trait_, dyn_ty, adjusted_recv) = + if let ty::Dynamic(data, _, ty::DynStar) = receiver_place.layout.ty.kind() { + let recv = self.unpack_dyn_star(&receiver_place, data)?; - (data.principal(), recv.layout.ty, recv.ptr()) - } else { - // Doesn't have to be a `dyn Trait`, but the unsized tail must be `dyn Trait`. - // (For that reason we also cannot use `unpack_dyn_trait`.) - let receiver_tail = - self.tcx.struct_tail_for_codegen(receiver_place.layout.ty, self.param_env); - let ty::Dynamic(receiver_trait, _, ty::Dyn) = receiver_tail.kind() else { - span_bug!( - self.cur_span(), - "dynamic call on non-`dyn` type {}", - receiver_tail - ) + (data.principal(), recv.layout.ty, recv.ptr()) + } else { + // Doesn't have to be a `dyn Trait`, but the unsized tail must be `dyn Trait`. + // (For that reason we also cannot use `unpack_dyn_trait`.) + let receiver_tail = self + .tcx + .struct_tail_for_codegen(receiver_place.layout.ty, self.typing_env()); + let ty::Dynamic(receiver_trait, _, ty::Dyn) = receiver_tail.kind() else { + span_bug!( + self.cur_span(), + "dynamic call on non-`dyn` type {}", + receiver_tail + ) + }; + assert!(receiver_place.layout.is_unsized()); + + // Get the required information from the vtable. + let vptr = receiver_place.meta().unwrap_meta().to_pointer(self)?; + let dyn_ty = self.get_ptr_vtable_ty(vptr, Some(receiver_trait))?; + + // It might be surprising that we use a pointer as the receiver even if this + // is a by-val case; this works because by-val passing of an unsized `dyn + // Trait` to a function is actually desugared to a pointer. + (receiver_trait.principal(), dyn_ty, receiver_place.ptr()) }; - assert!(receiver_place.layout.is_unsized()); - - // Get the required information from the vtable. - let vptr = receiver_place.meta().unwrap_meta().to_pointer(self)?; - let dyn_ty = self.get_ptr_vtable_ty(vptr, Some(receiver_trait))?; - - // It might be surprising that we use a pointer as the receiver even if this - // is a by-val case; this works because by-val passing of an unsized `dyn - // Trait` to a function is actually desugared to a pointer. - (receiver_trait.principal(), dyn_ty, receiver_place.ptr()) - }; // Now determine the actual method to call. Usually we use the easy way of just // looking up the method at index `idx`. @@ -704,7 +704,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let concrete_method = Instance::expect_resolve_for_vtable( tcx, - self.param_env, + self.typing_env(), def_id, instance.args.rebase_onto(tcx, trait_def_id, concrete_trait_ref.args), self.cur_span(), diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index 49559059265f..2d1bb5c95517 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -83,7 +83,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { ty::FnDef(def_id, args) => { let instance = ty::Instance::resolve_for_fn_ptr( *self.tcx, - self.param_env, + self.typing_env(), def_id, args, ) @@ -384,7 +384,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { ) -> InterpResult<'tcx> { // A -> A conversion let (src_pointee_ty, dest_pointee_ty) = - self.tcx.struct_lockstep_tails_for_codegen(source_ty, cast_ty, self.param_env); + self.tcx.struct_lockstep_tails_for_codegen(source_ty, cast_ty, self.typing_env()); match (src_pointee_ty.kind(), dest_pointee_ty.kind()) { (&ty::Array(_, length), &ty::Slice(_)) => { diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index eb574bd5f771..4f413c84615c 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -10,9 +10,7 @@ use rustc_middle::query::TyCtxtAt; use rustc_middle::ty::layout::{ self, FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers, TyAndLayout, }; -use rustc_middle::ty::{ - self, GenericArgsRef, ParamEnv, Ty, TyCtxt, TypeFoldable, TypingMode, Variance, -}; +use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, TypeFoldable, TypingEnv, Variance}; use rustc_middle::{mir, span_bug}; use rustc_session::Limit; use rustc_span::Span; @@ -65,12 +63,12 @@ where } } -impl<'tcx, M> layout::HasParamEnv<'tcx> for InterpCx<'tcx, M> +impl<'tcx, M> layout::HasTypingEnv<'tcx> for InterpCx<'tcx, M> where M: Machine<'tcx>, { - fn param_env(&self) -> ty::ParamEnv<'tcx> { - self.param_env + fn typing_env(&self) -> ty::TypingEnv<'tcx> { + self.typing_env() } } @@ -116,8 +114,7 @@ impl<'tcx, M: Machine<'tcx>> FnAbiOfHelpers<'tcx> for InterpCx<'tcx, M> { /// This test should be symmetric, as it is primarily about layout compatibility. pub(super) fn mir_assign_valid_types<'tcx>( tcx: TyCtxt<'tcx>, - typing_mode: TypingMode<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: TypingEnv<'tcx>, src: TyAndLayout<'tcx>, dest: TyAndLayout<'tcx>, ) -> bool { @@ -125,7 +122,7 @@ pub(super) fn mir_assign_valid_types<'tcx>( // all normal lifetimes are erased, higher-ranked types with their // late-bound lifetimes are still around and can lead to type // differences. - if util::relate_types(tcx, typing_mode, param_env, Variance::Covariant, src.ty, dest.ty) { + if util::relate_types(tcx, typing_env, Variance::Covariant, src.ty, dest.ty) { // Make sure the layout is equal, too -- just to be safe. Miri really // needs layout equality. For performance reason we skip this check when // the types are equal. Equal types *can* have different layouts when @@ -145,8 +142,7 @@ pub(super) fn mir_assign_valid_types<'tcx>( #[cfg_attr(not(debug_assertions), inline(always))] pub(super) fn from_known_layout<'tcx>( tcx: TyCtxtAt<'tcx>, - typing_mode: TypingMode<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: TypingEnv<'tcx>, known_layout: Option>, compute: impl FnOnce() -> InterpResult<'tcx, TyAndLayout<'tcx>>, ) -> InterpResult<'tcx, TyAndLayout<'tcx>> { @@ -155,13 +151,7 @@ pub(super) fn from_known_layout<'tcx>( Some(known_layout) => { if cfg!(debug_assertions) { let check_layout = compute()?; - if !mir_assign_valid_types( - tcx.tcx, - typing_mode, - param_env, - check_layout, - known_layout, - ) { + if !mir_assign_valid_types(tcx.tcx, typing_env, check_layout, known_layout) { span_bug!( tcx.span, "expected type differs from actual type.\nexpected: {}\nactual: {}", @@ -211,9 +201,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } } - pub fn typing_mode(&self) -> TypingMode<'tcx> { + /// During CTFE we're always in `PostAnalysis` mode. + #[inline(always)] + pub fn typing_env(&self) -> ty::TypingEnv<'tcx> { debug_assert_eq!(self.param_env.reveal(), Reveal::All); - TypingMode::PostAnalysis + ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env: self.param_env } } /// Returns the span of the currently executed statement/terminator. @@ -304,13 +296,13 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { .instance .try_instantiate_mir_and_normalize_erasing_regions( *self.tcx, - self.param_env, + self.typing_env(), ty::EarlyBinder::bind(value), ) .map_err(|_| ErrorHandled::TooGeneric(self.cur_span())) } - /// The `args` are assumed to already be in our interpreter "universe" (param_env). + /// The `args` are assumed to already be in our interpreter "universe". pub(super) fn resolve( &self, def: DefId, @@ -319,7 +311,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { trace!("resolve: {:?}, {:#?}", def, args); trace!("param_env: {:#?}", self.param_env); trace!("args: {:#?}", args); - match ty::Instance::try_resolve(*self.tcx, self.param_env, def, args) { + match ty::Instance::try_resolve(*self.tcx, self.typing_env(), def, args) { Ok(Some(instance)) => interp_ok(instance), Ok(None) => throw_inval!(TooGeneric), @@ -328,7 +320,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } } - /// Check if the two things are equal in the current param_env, using an infctx to get proper + /// Check if the two things are equal in the current param_env, using an infcx to get proper /// equality checks. #[instrument(level = "trace", skip(self), ret)] pub(super) fn eq_in_param_env(&self, a: T, b: T) -> bool @@ -340,14 +332,14 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { return true; } // Slow path: spin up an inference context to check if these traits are sufficiently equal. - let infcx = self.tcx.infer_ctxt().build(self.typing_mode()); + let (infcx, param_env) = self.tcx.infer_ctxt().build_with_typing_env(self.typing_env()); let ocx = ObligationCtxt::new(&infcx); let cause = ObligationCause::dummy_with_span(self.cur_span()); // equate the two trait refs after normalization - let a = ocx.normalize(&cause, self.param_env, a); - let b = ocx.normalize(&cause, self.param_env, b); + let a = ocx.normalize(&cause, param_env, a); + let b = ocx.normalize(&cause, param_env, b); - if let Err(terr) = ocx.eq(&cause, self.param_env, a, b) { + if let Err(terr) = ocx.eq(&cause, param_env, a, b) { trace!(?terr); return false; } @@ -572,7 +564,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let val = if self.tcx.is_static(gid.instance.def_id()) { let alloc_id = self.tcx.reserve_and_set_static_alloc(gid.instance.def_id()); - let ty = instance.ty(self.tcx.tcx, self.param_env); + let ty = instance.ty(self.tcx.tcx, self.typing_env()); mir::ConstAlloc { alloc_id, ty } } else { self.ctfe_query(|tcx| tcx.eval_to_allocation_raw(self.param_env.and(gid)))? @@ -587,7 +579,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { layout: Option>, ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> { M::eval_mir_constant(self, *val, span, layout, |ecx, val, span, layout| { - let const_val = val.eval(*ecx.tcx, ecx.param_env, span).map_err(|err| { + let const_val = val.eval(*ecx.tcx, ecx.typing_env(), span).map_err(|err| { if M::ALL_CONSTS_ARE_PRECHECKED { match err { ErrorHandled::TooGeneric(..) => {}, diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index d89d73824aa3..c8859ab3e880 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -40,6 +40,7 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>( ) -> InterpResult<'tcx, ConstValue<'tcx>> { let tp_ty = args.type_at(0); let name = tcx.item_name(def_id); + let typing_env = ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env }; interp_ok(match name { sym::type_name => { ensure_monomorphic_enough(tcx, tp_ty)?; @@ -48,11 +49,13 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>( } sym::needs_drop => { ensure_monomorphic_enough(tcx, tp_ty)?; - ConstValue::from_bool(tp_ty.needs_drop(tcx, param_env)) + ConstValue::from_bool(tp_ty.needs_drop(tcx, typing_env)) } sym::pref_align_of => { // Correctly handles non-monomorphic calls, so there is no need for ensure_monomorphic_enough. - let layout = tcx.layout_of(param_env.and(tp_ty)).map_err(|e| err_inval!(Layout(*e)))?; + let layout = tcx + .layout_of(typing_env.as_query_input(tp_ty)) + .map_err(|e| err_inval!(Layout(*e)))?; ConstValue::from_target_usize(layout.align.pref.bytes(), &tcx) } sym::type_id => { @@ -355,7 +358,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let should_panic = !self .tcx - .check_validity_requirement((requirement, self.param_env.and(ty))) + .check_validity_requirement((requirement, self.typing_env().as_query_input(ty))) .map_err(|_| err_inval!(TooGeneric))?; if should_panic { @@ -417,9 +420,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // These just return their argument self.copy_op(&args[0], dest)?; } - sym::cold_path => { - // This is a no-op. The intrinsic is just a hint to the optimizer. - } sym::raw_eq => { let result = self.raw_eq_intrinsic(&args[0], &args[1])?; self.write_scalar(result, dest)?; diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 09635c96e57c..07566e9fda27 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -859,7 +859,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // # Global allocations if let Some(global_alloc) = self.tcx.try_get_global_alloc(id) { - let (size, align) = global_alloc.size_and_align(*self.tcx, self.param_env); + let (size, align) = global_alloc.size_and_align(*self.tcx, self.typing_env()); let mutbl = global_alloc.mutability(*self.tcx, self.param_env); let kind = match global_alloc { GlobalAlloc::Static { .. } | GlobalAlloc::Memory { .. } => AllocKind::LiveData, diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index a130ae89bcb6..0157e6c2125e 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -8,7 +8,7 @@ use rustc_abi as abi; use rustc_abi::{BackendRepr, HasDataLayout, Size}; use rustc_hir::def::Namespace; use rustc_middle::mir::interpret::ScalarSizeMismatch; -use rustc_middle::ty::layout::{HasParamEnv, HasTyCtxt, LayoutOf, TyAndLayout}; +use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutOf, TyAndLayout}; use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter}; use rustc_middle::ty::{ConstInt, ScalarInt, Ty, TyCtxt}; use rustc_middle::{bug, mir, span_bug, ty}; @@ -297,21 +297,25 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> { #[inline] pub fn from_bool(b: bool, tcx: TyCtxt<'tcx>) -> Self { - let layout = tcx.layout_of(ty::ParamEnv::reveal_all().and(tcx.types.bool)).unwrap(); + let layout = tcx + .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(tcx.types.bool)) + .unwrap(); Self::from_scalar(Scalar::from_bool(b), layout) } #[inline] pub fn from_ordering(c: std::cmp::Ordering, tcx: TyCtxt<'tcx>) -> Self { let ty = tcx.ty_ordering_enum(None); - let layout = tcx.layout_of(ty::ParamEnv::reveal_all().and(ty)).unwrap(); + let layout = + tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)).unwrap(); Self::from_scalar(Scalar::from_i8(c as i8), layout) } pub fn from_pair(a: Self, b: Self, tcx: TyCtxt<'tcx>) -> Self { let layout = tcx .layout_of( - ty::ParamEnv::reveal_all().and(Ty::new_tup(tcx, &[a.layout.ty, b.layout.ty])), + ty::TypingEnv::fully_monomorphized() + .as_query_input(Ty::new_tup(tcx, &[a.layout.ty, b.layout.ty])), ) .unwrap(); Self::from_scalar_pair(a.to_scalar(), b.to_scalar(), layout) @@ -341,7 +345,7 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> { #[inline] #[cfg_attr(debug_assertions, track_caller)] // only in debug builds due to perf (see #98980) - pub fn to_pair(self, cx: &(impl HasTyCtxt<'tcx> + HasParamEnv<'tcx>)) -> (Self, Self) { + pub fn to_pair(self, cx: &(impl HasTyCtxt<'tcx> + HasTypingEnv<'tcx>)) -> (Self, Self) { let layout = self.layout; let (val0, val1) = self.to_scalar_pair(); ( @@ -773,8 +777,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { )?; if !mir_assign_valid_types( *self.tcx, - self.typing_mode(), - self.param_env, + self.typing_env(), self.layout_of(normalized_place_ty)?, op.layout, ) { @@ -833,9 +836,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { }) }; let layout = - from_known_layout(self.tcx, self.typing_mode(), self.param_env, layout, || { - self.layout_of(ty).into() - })?; + from_known_layout(self.tcx, self.typing_env(), layout, || self.layout_of(ty).into())?; let imm = match val_val { mir::ConstValue::Indirect { alloc_id, offset } => { // This is const data, no mutation allowed. diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs index fbc85d379538..201f1b5dc622 100644 --- a/compiler/rustc_const_eval/src/interpret/operator.rs +++ b/compiler/rustc_const_eval/src/interpret/operator.rs @@ -533,7 +533,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } OffsetOf(fields) => { let val = - self.tcx.offset_of_subfield(self.param_env, layout, fields.iter()).bytes(); + self.tcx.offset_of_subfield(self.typing_env(), layout, fields.iter()).bytes(); ImmTy::from_uint(val, usize_layout()) } UbChecks => ImmTy::from_bool(M::ub_checks(self)?, *self.tcx), diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index cc8d1db6cfb8..13fcccca76b0 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -540,8 +540,7 @@ where )?; if !mir_assign_valid_types( *self.tcx, - self.typing_mode(), - self.param_env, + self.typing_env(), self.layout_of(normalized_place_ty)?, place.layout, ) { @@ -871,13 +870,8 @@ where ) -> InterpResult<'tcx> { // We do NOT compare the types for equality, because well-typed code can // actually "transmute" `&mut T` to `&T` in an assignment without a cast. - let layout_compat = mir_assign_valid_types( - *self.tcx, - self.typing_mode(), - self.param_env, - src.layout(), - dest.layout(), - ); + let layout_compat = + mir_assign_valid_types(*self.tcx, self.typing_env(), src.layout(), dest.layout()); if !allow_transmute && !layout_compat { span_bug!( self.cur_span(), diff --git a/compiler/rustc_const_eval/src/interpret/stack.rs b/compiler/rustc_const_eval/src/interpret/stack.rs index 50c0446b3cd8..037c1a233eeb 100644 --- a/compiler/rustc_const_eval/src/interpret/stack.rs +++ b/compiler/rustc_const_eval/src/interpret/stack.rs @@ -379,7 +379,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { for &const_ in body.required_consts() { let c = self.instantiate_from_current_frame_and_normalize_erasing_regions(const_.const_)?; - c.eval(*self.tcx, self.param_env, const_.span).map_err(|err| { + c.eval(*self.tcx, self.typing_env(), const_.span).map_err(|err| { err.emit_note(*self.tcx); err })?; @@ -596,13 +596,12 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { return interp_ok(layout); } - let layout = - from_known_layout(self.tcx, self.typing_mode(), self.param_env, layout, || { - let local_ty = frame.body.local_decls[local].ty; - let local_ty = - self.instantiate_from_frame_and_normalize_erasing_regions(frame, local_ty)?; - self.layout_of(local_ty).into() - })?; + let layout = from_known_layout(self.tcx, self.typing_env(), layout, || { + let local_ty = frame.body.local_decls[local].ty; + let local_ty = + self.instantiate_from_frame_and_normalize_erasing_regions(frame, local_ty)?; + self.layout_of(local_ty).into() + })?; // Layouts of locals are requested a lot, so we cache them. state.layout.set(Some(layout)); diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index 18cff2c5e0f3..d4525243642e 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -418,7 +418,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { .collect::>>()?; let fn_sig_binder = func.layout.ty.fn_sig(*self.tcx); - let fn_sig = self.tcx.normalize_erasing_late_bound_regions(self.param_env, fn_sig_binder); + let fn_sig = + self.tcx.normalize_erasing_late_bound_regions(self.typing_env(), fn_sig_binder); let extra_args = &args[fn_sig.inputs().len()..]; let extra_args = self.tcx.mk_type_list_from_iter(extra_args.iter().map(|arg| arg.layout().ty)); diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 3a68db9f7f74..005b430bc8aa 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -448,7 +448,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { meta: MemPlaceMeta, pointee: TyAndLayout<'tcx>, ) -> InterpResult<'tcx> { - let tail = self.ecx.tcx.struct_tail_for_codegen(pointee.ty, self.ecx.param_env); + let tail = self.ecx.tcx.struct_tail_for_codegen(pointee.ty, self.ecx.typing_env()); match tail.kind() { ty::Dynamic(data, _, ty::Dyn) => { let vtable = meta.unwrap_meta().to_pointer(self.ecx)?; @@ -568,7 +568,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { throw_validation_failure!(self.path, DanglingPtrUseAfterFree { ptr_kind }); }; let (size, _align) = - global_alloc.size_and_align(*self.ecx.tcx, self.ecx.param_env); + global_alloc.size_and_align(*self.ecx.tcx, self.ecx.typing_env()); if let GlobalAlloc::Static(did) = global_alloc { let DefKind::Static { nested, .. } = self.ecx.tcx.def_kind(did) else { @@ -955,7 +955,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { ) -> Cow<'e, RangeSet> { assert!(layout.ty.is_union()); assert!(layout.is_sized(), "there are no unsized unions"); - let layout_cx = LayoutCx::new(*ecx.tcx, ecx.param_env); + let layout_cx = LayoutCx::new(*ecx.tcx, ecx.typing_env()); return M::cached_union_data_range(ecx, layout.ty, || { let mut out = RangeSet(Vec::new()); union_data_range_uncached(&layout_cx, layout, Size::ZERO, &mut out); diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index 0490195caf4f..527236b2c22e 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -47,7 +47,7 @@ pub fn provide(providers: &mut Providers) { providers.hooks.try_destructure_mir_constant_for_user_output = const_eval::try_destructure_mir_constant_for_user_output; providers.valtree_to_const_val = |tcx, (ty, valtree)| { - const_eval::valtree_to_const_value(tcx, ty::ParamEnv::empty().and(ty), valtree) + const_eval::valtree_to_const_value(tcx, ty::ParamEnv::reveal_all().and(ty), valtree) }; providers.check_validity_requirement = |tcx, (init_kind, param_env_and_ty)| { util::check_validity_requirement(tcx, init_kind, param_env_and_ty) diff --git a/compiler/rustc_const_eval/src/util/alignment.rs b/compiler/rustc_const_eval/src/util/alignment.rs index 6fa7d3692296..9507b24f603e 100644 --- a/compiler/rustc_const_eval/src/util/alignment.rs +++ b/compiler/rustc_const_eval/src/util/alignment.rs @@ -9,7 +9,7 @@ use tracing::debug; pub fn is_disaligned<'tcx, L>( tcx: TyCtxt<'tcx>, local_decls: &L, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, place: Place<'tcx>, ) -> bool where @@ -22,8 +22,8 @@ where }; let ty = place.ty(local_decls, tcx).ty; - let unsized_tail = || tcx.struct_tail_for_codegen(ty, param_env); - match tcx.layout_of(param_env.and(ty)) { + let unsized_tail = || tcx.struct_tail_for_codegen(ty, typing_env); + match tcx.layout_of(typing_env.as_query_input(ty)) { Ok(layout) if layout.align.abi <= pack && (layout.is_sized() diff --git a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs index f743525f3599..1afc910ce8fe 100644 --- a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs +++ b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs @@ -3,7 +3,7 @@ use rustc_middle::bug; use rustc_middle::ty::layout::{ HasTyCtxt, LayoutCx, LayoutError, LayoutOf, TyAndLayout, ValidityRequirement, }; -use rustc_middle::ty::{ParamEnvAnd, Ty, TyCtxt}; +use rustc_middle::ty::{PseudoCanonicalInput, Ty, TyCtxt}; use crate::const_eval::{CanAccessMutGlobal, CheckAlignment, CompileTimeMachine}; use crate::interpret::{InterpCx, MemoryKind}; @@ -23,16 +23,16 @@ use crate::interpret::{InterpCx, MemoryKind}; pub fn check_validity_requirement<'tcx>( tcx: TyCtxt<'tcx>, kind: ValidityRequirement, - param_env_and_ty: ParamEnvAnd<'tcx, Ty<'tcx>>, + input: PseudoCanonicalInput<'tcx, Ty<'tcx>>, ) -> Result> { - let layout = tcx.layout_of(param_env_and_ty)?; + let layout = tcx.layout_of(input)?; // There is nothing strict or lax about inhabitedness. if kind == ValidityRequirement::Inhabited { return Ok(!layout.is_uninhabited()); } - let layout_cx = LayoutCx::new(tcx, param_env_and_ty.param_env); + let layout_cx = LayoutCx::new(tcx, input.typing_env); if kind == ValidityRequirement::Uninit || tcx.sess.opts.unstable_opts.strict_init_checks { check_validity_requirement_strict(layout, &layout_cx, kind) } else { @@ -49,7 +49,7 @@ fn check_validity_requirement_strict<'tcx>( ) -> Result> { let machine = CompileTimeMachine::new(CanAccessMutGlobal::No, CheckAlignment::Error); - let mut cx = InterpCx::new(cx.tcx(), rustc_span::DUMMY_SP, cx.param_env, machine); + let mut cx = InterpCx::new(cx.tcx(), rustc_span::DUMMY_SP, cx.typing_env.param_env, machine); let allocated = cx .allocate(ty, MemoryKind::Machine(crate::const_eval::MemoryKind::Heap)) diff --git a/compiler/rustc_const_eval/src/util/compare_types.rs b/compiler/rustc_const_eval/src/util/compare_types.rs index 0cf27d30c368..9eed1a20f152 100644 --- a/compiler/rustc_const_eval/src/util/compare_types.rs +++ b/compiler/rustc_const_eval/src/util/compare_types.rs @@ -5,18 +5,17 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::traits::ObligationCause; -use rustc_middle::ty::{ParamEnv, Ty, TyCtxt, TypingMode, Variance}; +use rustc_middle::ty::{Ty, TyCtxt, TypingEnv, Variance}; use rustc_trait_selection::traits::ObligationCtxt; /// Returns whether `src` is a subtype of `dest`, i.e. `src <: dest`. pub fn sub_types<'tcx>( tcx: TyCtxt<'tcx>, - typing_mode: TypingMode<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: TypingEnv<'tcx>, src: Ty<'tcx>, dest: Ty<'tcx>, ) -> bool { - relate_types(tcx, typing_mode, param_env, Variance::Covariant, src, dest) + relate_types(tcx, typing_env, Variance::Covariant, src, dest) } /// Returns whether `src` is a subtype of `dest`, i.e. `src <: dest`. @@ -26,8 +25,7 @@ pub fn sub_types<'tcx>( /// because we want to check for type equality. pub fn relate_types<'tcx>( tcx: TyCtxt<'tcx>, - typing_mode: TypingMode<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: TypingEnv<'tcx>, variance: Variance, src: Ty<'tcx>, dest: Ty<'tcx>, @@ -36,8 +34,7 @@ pub fn relate_types<'tcx>( return true; } - let mut builder = tcx.infer_ctxt().ignoring_regions(); - let infcx = builder.build(typing_mode); + let (infcx, param_env) = tcx.infer_ctxt().ignoring_regions().build_with_typing_env(typing_env); let ocx = ObligationCtxt::new(&infcx); let cause = ObligationCause::dummy(); let src = ocx.normalize(&cause, param_env, src); diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index a4820ba8b72c..ce2b47ed1eaf 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -838,7 +838,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ template!(Word), WarnFollowing, EncodeCrossCrate::No, IMPL_DETAIL, ), rustc_attr!( - rustc_const_stable_intrinsic, Normal, + rustc_intrinsic_const_stable_indirect, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No, IMPL_DETAIL, ), gated!( diff --git a/compiler/rustc_feature/src/lib.rs b/compiler/rustc_feature/src/lib.rs index 9f42d3ec45cd..5d27b8f542cb 100644 --- a/compiler/rustc_feature/src/lib.rs +++ b/compiler/rustc_feature/src/lib.rs @@ -74,14 +74,19 @@ impl UnstableFeatures { // Returns whether `krate` should be counted as unstable let is_unstable_crate = |var: &str| krate.is_some_and(|name| var.split(',').any(|new_krate| new_krate == name)); - // `true` if we should enable unstable features for bootstrapping. - let bootstrap = - std::env::var("RUSTC_BOOTSTRAP").is_ok_and(|var| var == "1" || is_unstable_crate(&var)); - match (disable_unstable_features, bootstrap) { - (_, true) => UnstableFeatures::Cheat, - (true, _) => UnstableFeatures::Disallow, - (false, _) => UnstableFeatures::Allow, + + let bootstrap = std::env::var("RUSTC_BOOTSTRAP").ok(); + if let Some(val) = bootstrap.as_deref() { + match val { + val if val == "1" || is_unstable_crate(val) => return UnstableFeatures::Cheat, + // Hypnotize ourselves so that we think we are a stable compiler and thus don't + // allow any unstable features. + "-1" => return UnstableFeatures::Disallow, + _ => {} + } } + + if disable_unstable_features { UnstableFeatures::Disallow } else { UnstableFeatures::Allow } } pub fn is_nightly_build(&self) -> bool { diff --git a/compiler/rustc_feature/src/tests.rs b/compiler/rustc_feature/src/tests.rs index 50433e44b135..cc0e1f312096 100644 --- a/compiler/rustc_feature/src/tests.rs +++ b/compiler/rustc_feature/src/tests.rs @@ -18,6 +18,16 @@ fn rustc_bootstrap_parsing() { assert!(!is_bootstrap("x,y,z", Some("a"))); assert!(!is_bootstrap("x,y,z", None)); - // this is technically a breaking change, but there are no stability guarantees for RUSTC_BOOTSTRAP + // `RUSTC_BOOTSTRAP=0` is not recognized. assert!(!is_bootstrap("0", None)); + + // `RUSTC_BOOTSTRAP=-1` is force-stable, no unstable features allowed. + let is_force_stable = |krate| { + std::env::set_var("RUSTC_BOOTSTRAP", "-1"); + matches!(UnstableFeatures::from_environment(krate), UnstableFeatures::Disallow) + }; + assert!(is_force_stable(None)); + // Does not support specifying any crate. + assert!(is_force_stable(Some("x"))); + assert!(is_force_stable(Some("x,y,z"))); } diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 8326d0031ea6..a67a5776449d 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -54,7 +54,7 @@ pub struct EnabledLangFeature { pub stable_since: Option, } -/// Information abhout an enabled library feature. +/// Information about an enabled library feature. #[derive(Debug, Copy, Clone)] pub struct EnabledLibFeature { pub gate_name: Symbol, diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 6e8ba51612ec..64a30e633cf9 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -448,6 +448,11 @@ hir_analysis_rpitit_refined = impl trait in impl method signature does not match .note = add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate .feedback_note = we are soliciting feedback, see issue #121718 for more information +hir_analysis_rpitit_refined_lifetimes = impl trait in impl method captures fewer lifetimes than in trait + .suggestion = modify the `use<..>` bound to capture the same lifetimes that the trait does + .note = add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate + .feedback_note = we are soliciting feedback, see issue #121718 for more information + hir_analysis_self_in_impl_self = `Self` is not valid in the self type of an impl block .note = replace `Self` with a different type diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 3080d8b35108..cf8c81c0b089 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -21,8 +21,7 @@ use rustc_middle::ty::fold::BottomUpFolder; use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES}; use rustc_middle::ty::util::{Discr, InspectCoroutineFields, IntTypeExt}; use rustc_middle::ty::{ - AdtDef, GenericArgKind, ParamEnv, RegionKind, TypeSuperVisitable, TypeVisitable, - TypeVisitableExt, + AdtDef, GenericArgKind, RegionKind, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, }; use rustc_session::lint::builtin::UNINHABITED_STATIC; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; @@ -114,15 +113,15 @@ fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> b } } - let param_env = tcx.param_env(item_def_id); + let typing_env = ty::TypingEnv::non_body_analysis(tcx, item_def_id); for field in &def.non_enum_variant().fields { - let Ok(field_ty) = tcx.try_normalize_erasing_regions(param_env, field.ty(tcx, args)) + let Ok(field_ty) = tcx.try_normalize_erasing_regions(typing_env, field.ty(tcx, args)) else { tcx.dcx().span_delayed_bug(span, "could not normalize field type"); continue; }; - if !allowed_union_field(field_ty, tcx, param_env) { + if !allowed_union_field(field_ty, tcx, typing_env.param_env) { let (field_span, ty_span) = match tcx.hir().get_if_local(field.did) { // We are currently checking the type this field came from, so it must be local. Some(Node::Field(field)) => (field.span, field.ty.span), @@ -137,7 +136,7 @@ fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> b note: (), }); return false; - } else if field_ty.needs_drop(tcx, param_env) { + } else if field_ty.needs_drop(tcx, typing_env) { // This should never happen. But we can get here e.g. in case of name resolution errors. tcx.dcx() .span_delayed_bug(span, "we should never accept maybe-dropping union fields"); @@ -158,7 +157,7 @@ fn check_static_inhabited(tcx: TyCtxt<'_>, def_id: LocalDefId) { // reason to allow any statics to be uninhabited. let ty = tcx.type_of(def_id).instantiate_identity(); let span = tcx.def_span(def_id); - let layout = match tcx.layout_of(ParamEnv::reveal_all().and(ty)) { + let layout = match tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)) { Ok(l) => l, // Foreign statics that overflow their allowed size should emit an error Err(LayoutError::SizeOverflow(_)) @@ -237,7 +236,10 @@ pub(super) fn check_opaque_for_cycles<'tcx>( // And also look for cycle errors in the layout of coroutines. if let Err(&LayoutError::Cycle(guar)) = - tcx.layout_of(tcx.param_env(def_id).and(Ty::new_opaque(tcx, def_id.to_def_id(), args))) + tcx.layout_of( + ty::TypingEnv::post_analysis(tcx, def_id.to_def_id()) + .as_query_input(Ty::new_opaque(tcx, def_id.to_def_id(), args)), + ) { return Err(guar); } @@ -1307,8 +1309,8 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>) // "known" respecting #[non_exhaustive] attributes. let field_infos = adt.all_fields().map(|field| { let ty = field.ty(tcx, GenericArgs::identity_for_item(tcx, field.did)); - let param_env = tcx.param_env(field.did); - let layout = tcx.layout_of(param_env.and(ty)); + let typing_env = ty::TypingEnv::non_body_analysis(tcx, field.did); + let layout = tcx.layout_of(typing_env.as_query_input(ty)); // We are currently checking the type this field came from, so it must be local let span = tcx.hir().span_if_local(field.did).unwrap(); let trivial = layout.is_ok_and(|layout| layout.is_1zst()); diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs index 646c104f1f55..25ba52b4d7bf 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs @@ -1,6 +1,7 @@ +use itertools::Itertools as _; use rustc_data_structures::fx::FxIndexSet; use rustc_hir as hir; -use rustc_hir::def_id::DefId; +use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_lint_defs::builtin::{REFINING_IMPL_TRAIT_INTERNAL, REFINING_IMPL_TRAIT_REACHABLE}; @@ -75,6 +76,8 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>( let mut trait_bounds = vec![]; // Bounds that we find on the RPITITs in the impl signature. let mut impl_bounds = vec![]; + // Pairs of trait and impl opaques. + let mut pairs = vec![]; for trait_projection in collector.types.into_iter().rev() { let impl_opaque_args = trait_projection.args.rebase_onto(tcx, trait_m.def_id, impl_m_args); @@ -121,6 +124,8 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>( tcx.explicit_item_bounds(impl_opaque.def_id) .iter_instantiated_copied(tcx, impl_opaque.args), )); + + pairs.push((trait_projection, impl_opaque)); } let hybrid_preds = tcx @@ -212,6 +217,39 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>( return; } } + + // Make sure that the RPITIT doesn't capture fewer regions than + // the trait definition. We hard-error if it captures *more*, since that + // is literally unrepresentable in the type system; however, we may be + // promising stronger outlives guarantees if we capture *fewer* regions. + for (trait_projection, impl_opaque) in pairs { + let impl_variances = tcx.variances_of(impl_opaque.def_id); + let impl_captures: FxIndexSet<_> = impl_opaque + .args + .iter() + .zip_eq(impl_variances) + .filter(|(_, v)| **v == ty::Invariant) + .map(|(arg, _)| arg) + .collect(); + + let trait_variances = tcx.variances_of(trait_projection.def_id); + let mut trait_captures = FxIndexSet::default(); + for (arg, variance) in trait_projection.args.iter().zip_eq(trait_variances) { + if *variance != ty::Invariant { + continue; + } + arg.visit_with(&mut CollectParams { params: &mut trait_captures }); + } + + if !trait_captures.iter().all(|arg| impl_captures.contains(arg)) { + report_mismatched_rpitit_captures( + tcx, + impl_opaque.def_id.expect_local(), + trait_captures, + is_internal, + ); + } + } } struct ImplTraitInTraitCollector<'tcx> { @@ -342,3 +380,65 @@ impl<'tcx> TypeFolder> for Anonymize<'tcx> { self.tcx.anonymize_bound_vars(t) } } + +struct CollectParams<'a, 'tcx> { + params: &'a mut FxIndexSet>, +} +impl<'tcx> TypeVisitor> for CollectParams<'_, 'tcx> { + fn visit_ty(&mut self, ty: Ty<'tcx>) { + if let ty::Param(_) = ty.kind() { + self.params.insert(ty.into()); + } else { + ty.super_visit_with(self); + } + } + fn visit_region(&mut self, r: ty::Region<'tcx>) { + match r.kind() { + ty::ReEarlyParam(_) | ty::ReLateParam(_) => { + self.params.insert(r.into()); + } + _ => {} + } + } + fn visit_const(&mut self, ct: ty::Const<'tcx>) { + if let ty::ConstKind::Param(_) = ct.kind() { + self.params.insert(ct.into()); + } else { + ct.super_visit_with(self); + } + } +} + +fn report_mismatched_rpitit_captures<'tcx>( + tcx: TyCtxt<'tcx>, + impl_opaque_def_id: LocalDefId, + mut trait_captured_args: FxIndexSet>, + is_internal: bool, +) { + let Some(use_bound_span) = + tcx.hir_node_by_def_id(impl_opaque_def_id).expect_opaque_ty().bounds.iter().find_map( + |bound| match *bound { + rustc_hir::GenericBound::Use(_, span) => Some(span), + hir::GenericBound::Trait(_) | hir::GenericBound::Outlives(_) => None, + }, + ) + else { + // I have no idea when you would ever undercapture without a `use<..>`. + tcx.dcx().delayed_bug("expected use<..> to undercapture in an impl opaque"); + return; + }; + + trait_captured_args + .sort_by_cached_key(|arg| !matches!(arg.unpack(), ty::GenericArgKind::Lifetime(_))); + let suggestion = format!("use<{}>", trait_captured_args.iter().join(", ")); + + tcx.emit_node_span_lint( + if is_internal { REFINING_IMPL_TRAIT_INTERNAL } else { REFINING_IMPL_TRAIT_REACHABLE }, + tcx.local_def_id_to_hir_id(impl_opaque_def_id), + use_bound_span, + crate::errors::ReturnPositionImplTraitInTraitRefinedLifetimes { + suggestion_span: use_bound_span, + suggestion, + }, + ); +} diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 1802f00bc1f1..20bc34b8c793 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1126,7 +1126,7 @@ fn check_type_defn<'tcx>( let ty = tcx.type_of(variant.tail().did).instantiate_identity(); let ty = tcx.erase_regions(ty); assert!(!ty.has_infer()); - ty.needs_drop(tcx, tcx.param_env(item.owner_id)) + ty.needs_drop(tcx, wfcx.infcx.typing_env(wfcx.param_env)) } }; // All fields (except for possibly the last) should be sized. @@ -1281,7 +1281,8 @@ fn check_item_type( UnsizedHandling::Forbid => true, UnsizedHandling::Allow => false, UnsizedHandling::AllowIfForeignTail => { - let tail = tcx.struct_tail_for_codegen(item_ty, wfcx.param_env); + let tail = + tcx.struct_tail_for_codegen(item_ty, wfcx.infcx.typing_env(wfcx.param_env)); !matches!(tail.kind(), ty::Foreign(_)) } }; diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index 5ff52376837e..c2ad61820a7f 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -259,7 +259,9 @@ fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<() let ty_a = field.ty(tcx, args_a); let ty_b = field.ty(tcx, args_b); - if let Ok(layout) = tcx.layout_of(param_env.and(ty_a)) { + if let Ok(layout) = + tcx.layout_of(infcx.typing_env(param_env).as_query_input(ty_a)) + { if layout.is_1zst() { // ignore 1-ZST fields return false; diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index a92a5e4278c5..07d3273b09c7 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -1153,6 +1153,16 @@ pub(crate) struct ReturnPositionImplTraitInTraitRefined<'tcx> { pub return_ty: Ty<'tcx>, } +#[derive(LintDiagnostic)] +#[diag(hir_analysis_rpitit_refined_lifetimes)] +#[note] +#[note(hir_analysis_feedback_note)] +pub(crate) struct ReturnPositionImplTraitInTraitRefinedLifetimes { + #[suggestion(applicability = "maybe-incorrect", code = "{suggestion}")] + pub suggestion_span: Span, + pub suggestion: String, +} + #[derive(Diagnostic)] #[diag(hir_analysis_inherent_ty_outside, code = E0390)] #[help] diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs index 92f38a7dde05..394719314612 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs @@ -3,7 +3,7 @@ use rustc_errors::{DiagCtxtHandle, E0781, struct_span_code_err}; use rustc_hir::{self as hir, HirId}; use rustc_middle::bug; use rustc_middle::ty::layout::LayoutError; -use rustc_middle::ty::{self, ParamEnv, TyCtxt}; +use rustc_middle::ty::{self, TyCtxt}; use crate::errors; @@ -130,7 +130,7 @@ fn is_valid_cmse_inputs<'tcx>( let fn_sig = tcx.instantiate_bound_regions_with_erased(fn_sig); for (index, ty) in fn_sig.inputs().iter().enumerate() { - let layout = tcx.layout_of(ParamEnv::reveal_all().and(*ty))?; + let layout = tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(*ty))?; let align = layout.layout.align().abi.bytes(); let size = layout.layout.size().bytes(); @@ -158,8 +158,10 @@ fn is_valid_cmse_output<'tcx>( // this type is only used for layout computation, which does not rely on regions let fn_sig = tcx.instantiate_bound_regions_with_erased(fn_sig); + let typing_env = ty::TypingEnv::fully_monomorphized(); + let mut ret_ty = fn_sig.output(); - let layout = tcx.layout_of(ParamEnv::reveal_all().and(ret_ty))?; + let layout = tcx.layout_of(typing_env.as_query_input(ret_ty))?; let size = layout.layout.size().bytes(); if size <= 4 { @@ -182,7 +184,7 @@ fn is_valid_cmse_output<'tcx>( for variant_def in adt_def.variants() { for field_def in variant_def.fields.iter() { let ty = field_def.ty(tcx, args); - let layout = tcx.layout_of(ParamEnv::reveal_all().and(ty))?; + let layout = tcx.layout_of(typing_env.as_query_input(ty))?; if !layout.layout.is_1zst() { ret_ty = ty; diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 354993513dac..1610848958e5 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -2357,8 +2357,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Only assoc fns that return `Self` let fn_sig = self.tcx.fn_sig(item.def_id).skip_binder(); let ret_ty = fn_sig.output(); - let ret_ty = - self.tcx.normalize_erasing_late_bound_regions(self.param_env, ret_ty); + let ret_ty = self.tcx.normalize_erasing_late_bound_regions( + self.typing_env(self.param_env), + ret_ty, + ); if !self.can_eq(self.param_env, ret_ty, adt_ty) { return None; } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 919e83724d70..c4c4c2f200ba 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -2648,15 +2648,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } let make_sugg = |expr: &Expr<'_>, span: Span, sugg: &str| { - let needs_parens = match expr.kind { - // parenthesize if needed (Issue #46756) - hir::ExprKind::Cast(_, _) | hir::ExprKind::Binary(_, _, _) => true, - // parenthesize borrows of range literals (Issue #54505) - _ if is_range_literal(expr) => true, - _ => false, - }; - - if needs_parens { + if self.needs_parentheses(expr) { ( vec![ (span.shrink_to_lo(), format!("{prefix}{sugg}(")), @@ -2869,6 +2861,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return None; } + if self.needs_parentheses(expr) { + return Some(( + vec![ + (span, format!("{suggestion}(")), + (expr.span.shrink_to_hi(), ")".to_string()), + ], + message, + Applicability::MachineApplicable, + true, + false, + )); + } + return Some(( vec![(span, suggestion)], message, @@ -2897,6 +2902,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { false } + fn needs_parentheses(&self, expr: &hir::Expr<'_>) -> bool { + match expr.kind { + // parenthesize if needed (Issue #46756) + hir::ExprKind::Cast(_, _) | hir::ExprKind::Binary(_, _, _) => true, + // parenthesize borrows of range literals (Issue #54505) + _ if is_range_literal(expr) => true, + _ => false, + } + } + pub(crate) fn suggest_cast( &self, err: &mut Diag<'_>, diff --git a/compiler/rustc_hir_typeck/src/intrinsicck.rs b/compiler/rustc_hir_typeck/src/intrinsicck.rs index a754f7fddc91..789530d35dd8 100644 --- a/compiler/rustc_hir_typeck/src/intrinsicck.rs +++ b/compiler/rustc_hir_typeck/src/intrinsicck.rs @@ -46,7 +46,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let span = tcx.hir().span(hir_id); let normalize = |ty| { let ty = self.resolve_vars_if_possible(ty); - self.tcx.normalize_erasing_regions(self.param_env, ty) + self.tcx.normalize_erasing_regions(self.typing_env(self.param_env), ty) }; let from = normalize(from); let to = normalize(to); @@ -62,7 +62,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return; } - let skel = |ty| SizeSkeleton::compute(ty, tcx, self.param_env); + let skel = |ty| SizeSkeleton::compute(ty, tcx, self.typing_env(self.param_env)); let sk_from = skel(from); let sk_to = skel(to); trace!(?sk_from, ?sk_to); diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index 175fca327f36..d50eff0deb0b 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -1257,7 +1257,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> Option> { let ty = self.resolve_vars_if_possible(self.node_ty(var_hir_id)); - if !ty.has_significant_drop(self.tcx, self.tcx.param_env(closure_def_id)) { + // FIXME(#132279): Using `non_body_analysis` here feels wrong. + if !ty.has_significant_drop( + self.tcx, + ty::TypingEnv::non_body_analysis(self.tcx, closure_def_id), + ) { debug!("does not have significant drop"); return None; } @@ -1535,8 +1539,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { base_path_ty: Ty<'tcx>, captured_by_move_projs: Vec<&[Projection<'tcx>]>, ) -> bool { - let needs_drop = - |ty: Ty<'tcx>| ty.has_significant_drop(self.tcx, self.tcx.param_env(closure_def_id)); + // FIXME(#132279): Using `non_body_analysis` here feels wrong. + let needs_drop = |ty: Ty<'tcx>| { + ty.has_significant_drop( + self.tcx, + ty::TypingEnv::non_body_analysis(self.tcx, closure_def_id), + ) + }; let is_drop_defined_for_ty = |ty: Ty<'tcx>| { let drop_trait = self.tcx.require_lang_item(hir::LangItem::Drop, Some(closure_span)); diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index 391e640f8bcb..8694800ac43a 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -881,6 +881,8 @@ impl<'tcx> TypeFolder> for EagerlyNormalizeConsts<'tcx> { } fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { - self.tcx.try_normalize_erasing_regions(self.param_env, ct).unwrap_or(ct) + self.tcx + .try_normalize_erasing_regions(ty::TypingEnv::from_param_env(self.param_env), ct) + .unwrap_or(ct) } } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 12df4a10e636..b29dc7f909dd 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -38,7 +38,8 @@ use rustc_middle::ty::fold::{ use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::{ self, ConstVid, FloatVid, GenericArg, GenericArgKind, GenericArgs, GenericArgsRef, - GenericParamDefKind, InferConst, IntVid, Ty, TyCtxt, TyVid, TypingMode, + GenericParamDefKind, InferConst, IntVid, PseudoCanonicalInput, Ty, TyCtxt, TyVid, + TypeVisitable, TypingEnv, TypingMode, }; use rustc_span::Span; use rustc_span::symbol::Symbol; @@ -565,6 +566,13 @@ impl<'tcx> InferCtxtBuilder<'tcx> { (infcx, value, args) } + pub fn build_with_typing_env( + mut self, + TypingEnv { typing_mode, param_env }: TypingEnv<'tcx>, + ) -> (InferCtxt<'tcx>, ty::ParamEnv<'tcx>) { + (self.build(typing_mode), param_env) + } + pub fn build(&mut self, typing_mode: TypingMode<'tcx>) -> InferCtxt<'tcx> { let InferCtxtBuilder { tcx, considering_regions, skip_leak_check, next_trait_solver } = *self; @@ -1278,6 +1286,42 @@ impl<'tcx> InferCtxt<'tcx> { u } + /// Extract [`ty::TypingMode`] of this inference context to get a `TypingEnv` + /// which contains the necessary information to use the trait system without + /// using canonicalization or carrying this inference context around. + pub fn typing_env(&self, param_env: ty::ParamEnv<'tcx>) -> ty::TypingEnv<'tcx> { + let typing_mode = match self.typing_mode(param_env) { + ty::TypingMode::Coherence => ty::TypingMode::Coherence, + // FIXME(#132279): This erases the `defining_opaque_types` as it isn't possible + // to handle them without proper canonicalization. This means we may cause cycle + // errors and fail to reveal opaques while inside of bodies. We should rename this + // function and require explicit comments on all use-sites in the future. + ty::TypingMode::Analysis { defining_opaque_types: _ } => { + TypingMode::non_body_analysis() + } + ty::TypingMode::PostAnalysis => ty::TypingMode::PostAnalysis, + }; + ty::TypingEnv { typing_mode, param_env } + } + + /// Similar to [`Self::canonicalize_query`], except that it returns + /// a [`PseudoCanonicalInput`] and requires both the `value` and the + /// `param_env` to not contain any inference variables or placeholders. + pub fn pseudo_canonicalize_query( + &self, + param_env: ty::ParamEnv<'tcx>, + value: V, + ) -> PseudoCanonicalInput<'tcx, V> + where + V: TypeVisitable>, + { + debug_assert!(!value.has_infer()); + debug_assert!(!value.has_placeholders()); + debug_assert!(!param_env.has_infer()); + debug_assert!(!param_env.has_placeholders()); + self.typing_env(param_env).as_query_input(value) + } + /// The returned function is used in a fast path. If it returns `true` the variable is /// unchanged, `false` indicates that the status is unknown. #[inline] diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 130f3cb7c2a7..f6366ec3b801 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -2485,7 +2485,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue { }); // Check if this ADT has a constrained layout (like `NonNull` and friends). - if let Ok(layout) = cx.tcx.layout_of(cx.param_env.and(ty)) { + if let Ok(layout) = cx.tcx.layout_of(cx.typing_env().as_query_input(ty)) { if let BackendRepr::Scalar(scalar) | BackendRepr::ScalarPair(scalar, _) = &layout.backend_repr { @@ -2521,7 +2521,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue { ty: Ty<'tcx>, init: InitKind, ) -> Option { - let ty = cx.tcx.try_normalize_erasing_regions(cx.param_env, ty).unwrap_or(ty); + let ty = cx.tcx.try_normalize_erasing_regions(cx.typing_env(), ty).unwrap_or(ty); use rustc_type_ir::TyKind::*; match ty.kind() { @@ -2568,7 +2568,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue { let definitely_inhabited = match variant .inhabited_predicate(cx.tcx, *adt_def) .instantiate(cx.tcx, args) - .apply_any_module(cx.tcx, cx.param_env) + .apply_any_module(cx.tcx, cx.typing_env()) { // Entirely skip uninhabited variants. Some(false) => return None, diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index aa7ec2659d08..6eec32beab00 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -19,7 +19,7 @@ use rustc_middle::bug; use rustc_middle::middle::privacy::EffectiveVisibilities; use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout}; use rustc_middle::ty::print::{PrintError, PrintTraitRefExt as _, Printer, with_no_trimmed_paths}; -use rustc_middle::ty::{self, GenericArg, RegisteredTools, Ty, TyCtxt, TypingMode}; +use rustc_middle::ty::{self, GenericArg, RegisteredTools, Ty, TyCtxt, TypingEnv, TypingMode}; use rustc_session::lint::{ BuiltinLintDiag, FutureIncompatibleInfo, Level, Lint, LintBuffer, LintExpectationId, LintId, }; @@ -708,6 +708,10 @@ impl<'tcx> LateContext<'tcx> { TypingMode::non_body_analysis() } + pub fn typing_env(&self) -> TypingEnv<'tcx> { + TypingEnv { typing_mode: self.typing_mode(), param_env: self.param_env } + } + /// Gets the type-checking results for the current body, /// or `None` if outside a body. pub fn maybe_typeck_results(&self) -> Option<&'tcx ty::TypeckResults<'tcx>> { @@ -906,7 +910,7 @@ impl<'tcx> LateContext<'tcx> { .find_by_name_and_kind(tcx, Ident::from_str(name), ty::AssocKind::Type, trait_id) .and_then(|assoc| { let proj = Ty::new_projection(tcx, assoc.def_id, [self_ty]); - tcx.try_normalize_erasing_regions(self.param_env, proj).ok() + tcx.try_normalize_erasing_regions(self.typing_env(), proj).ok() }) } @@ -1010,10 +1014,10 @@ impl<'tcx> ty::layout::HasTyCtxt<'tcx> for LateContext<'tcx> { } } -impl<'tcx> ty::layout::HasParamEnv<'tcx> for LateContext<'tcx> { +impl<'tcx> ty::layout::HasTypingEnv<'tcx> for LateContext<'tcx> { #[inline] - fn param_env(&self) -> ty::ParamEnv<'tcx> { - self.param_env + fn typing_env(&self) -> ty::TypingEnv<'tcx> { + self.typing_env() } } diff --git a/compiler/rustc_lint/src/for_loops_over_fallibles.rs b/compiler/rustc_lint/src/for_loops_over_fallibles.rs index cf68e41243ff..dbc920ea5aee 100644 --- a/compiler/rustc_lint/src/for_loops_over_fallibles.rs +++ b/compiler/rustc_lint/src/for_loops_over_fallibles.rs @@ -166,7 +166,7 @@ fn suggest_question_mark<'tcx>( } let ty = args.type_at(0); - let infcx = cx.tcx.infer_ctxt().build(cx.typing_mode()); + let (infcx, param_env) = cx.tcx.infer_ctxt().build_with_typing_env(cx.typing_env()); let ocx = ObligationCtxt::new(&infcx); let body_def_id = cx.tcx.hir().body_owner_def_id(body_id); @@ -175,7 +175,7 @@ fn suggest_question_mark<'tcx>( ocx.register_bound( cause, - cx.param_env, + param_env, // Erase any region vids from the type, which may not be resolved infcx.tcx.erase_regions(ty), into_iterator_did, diff --git a/compiler/rustc_lint/src/foreign_modules.rs b/compiler/rustc_lint/src/foreign_modules.rs index 394ea798d3e5..45b188205d22 100644 --- a/compiler/rustc_lint/src/foreign_modules.rs +++ b/compiler/rustc_lint/src/foreign_modules.rs @@ -131,7 +131,7 @@ impl ClashingExternDeclarations { // Check that the declarations match. if !structurally_same_type( tcx, - tcx.param_env(this_fi.owner_id), + ty::TypingEnv::non_body_analysis(tcx, this_fi.owner_id), existing_decl_ty, this_decl_ty, types::CItemKind::Declaration, @@ -205,18 +205,18 @@ fn get_relevant_span(tcx: TyCtxt<'_>, fi: hir::OwnerId) -> Span { /// with the same members (as the declarations shouldn't clash). fn structurally_same_type<'tcx>( tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>, ckind: types::CItemKind, ) -> bool { let mut seen_types = UnordSet::default(); - let result = structurally_same_type_impl(&mut seen_types, tcx, param_env, a, b, ckind); + let result = structurally_same_type_impl(&mut seen_types, tcx, typing_env, a, b, ckind); if cfg!(debug_assertions) && result { // Sanity-check: must have same ABI, size and alignment. // `extern` blocks cannot be generic, so we'll always get a layout here. - let a_layout = tcx.layout_of(param_env.and(a)).unwrap(); - let b_layout = tcx.layout_of(param_env.and(b)).unwrap(); + let a_layout = tcx.layout_of(typing_env.as_query_input(a)).unwrap(); + let b_layout = tcx.layout_of(typing_env.as_query_input(b)).unwrap(); assert_eq!(a_layout.backend_repr, b_layout.backend_repr); assert_eq!(a_layout.size, b_layout.size); assert_eq!(a_layout.align, b_layout.align); @@ -227,7 +227,7 @@ fn structurally_same_type<'tcx>( fn structurally_same_type_impl<'tcx>( seen_types: &mut UnordSet<(Ty<'tcx>, Ty<'tcx>)>, tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>, ckind: types::CItemKind, @@ -303,7 +303,7 @@ fn structurally_same_type_impl<'tcx>( structurally_same_type_impl( seen_types, tcx, - param_env, + typing_env, tcx.type_of(a_did).instantiate(tcx, a_gen_args), tcx.type_of(b_did).instantiate(tcx, b_gen_args), ckind, @@ -315,23 +315,23 @@ fn structurally_same_type_impl<'tcx>( // For arrays, we also check the length. a_len == b_len && structurally_same_type_impl( - seen_types, tcx, param_env, *a_ty, *b_ty, ckind, + seen_types, tcx, typing_env, *a_ty, *b_ty, ckind, ) } (Slice(a_ty), Slice(b_ty)) => { - structurally_same_type_impl(seen_types, tcx, param_env, *a_ty, *b_ty, ckind) + structurally_same_type_impl(seen_types, tcx, typing_env, *a_ty, *b_ty, ckind) } (RawPtr(a_ty, a_mutbl), RawPtr(b_ty, b_mutbl)) => { a_mutbl == b_mutbl && structurally_same_type_impl( - seen_types, tcx, param_env, *a_ty, *b_ty, ckind, + seen_types, tcx, typing_env, *a_ty, *b_ty, ckind, ) } (Ref(_a_region, a_ty, a_mut), Ref(_b_region, b_ty, b_mut)) => { // For structural sameness, we don't need the region to be same. a_mut == b_mut && structurally_same_type_impl( - seen_types, tcx, param_env, *a_ty, *b_ty, ckind, + seen_types, tcx, typing_env, *a_ty, *b_ty, ckind, ) } (FnDef(..), FnDef(..)) => { @@ -346,12 +346,12 @@ fn structurally_same_type_impl<'tcx>( (a_sig.abi, a_sig.safety, a_sig.c_variadic) == (b_sig.abi, b_sig.safety, b_sig.c_variadic) && a_sig.inputs().iter().eq_by(b_sig.inputs().iter(), |a, b| { - structurally_same_type_impl(seen_types, tcx, param_env, *a, *b, ckind) + structurally_same_type_impl(seen_types, tcx, typing_env, *a, *b, ckind) }) && structurally_same_type_impl( seen_types, tcx, - param_env, + typing_env, a_sig.output(), b_sig.output(), ckind, @@ -379,14 +379,14 @@ fn structurally_same_type_impl<'tcx>( // An Adt and a primitive or pointer type. This can be FFI-safe if non-null // enum layout optimisation is being applied. (Adt(..), _) if is_primitive_or_pointer(b) => { - if let Some(a_inner) = types::repr_nullable_ptr(tcx, param_env, a, ckind) { + if let Some(a_inner) = types::repr_nullable_ptr(tcx, typing_env, a, ckind) { a_inner == b } else { false } } (_, Adt(..)) if is_primitive_or_pointer(a) => { - if let Some(b_inner) = types::repr_nullable_ptr(tcx, param_env, b, ckind) { + if let Some(b_inner) = types::repr_nullable_ptr(tcx, typing_env, b, ckind) { b_inner == a } else { false diff --git a/compiler/rustc_lint/src/if_let_rescope.rs b/compiler/rustc_lint/src/if_let_rescope.rs index afcfbebc14b3..0e874669043f 100644 --- a/compiler/rustc_lint/src/if_let_rescope.rs +++ b/compiler/rustc_lint/src/if_let_rescope.rs @@ -368,7 +368,7 @@ impl<'tcx, 'a> Visitor<'tcx> for FindSignificantDropper<'tcx, 'a> { .cx .typeck_results() .expr_ty(expr) - .has_significant_drop(self.cx.tcx, self.cx.param_env) + .has_significant_drop(self.cx.tcx, self.cx.typing_env()) { return ControlFlow::Break(expr.span); } diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index 2f338f42f191..38c38b59bc58 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -103,7 +103,8 @@ declare_lint_pass!(QueryStability => [POTENTIAL_QUERY_INSTABILITY, UNTRACKED_QUE impl LateLintPass<'_> for QueryStability { fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { let Some((span, def_id, args)) = typeck_results_of_method_fn(cx, expr) else { return }; - if let Ok(Some(instance)) = ty::Instance::try_resolve(cx.tcx, cx.param_env, def_id, args) { + if let Ok(Some(instance)) = ty::Instance::try_resolve(cx.tcx, cx.typing_env(), def_id, args) + { let def_id = instance.def_id(); if cx.tcx.has_attr(def_id, sym::rustc_lint_query_instability) { cx.emit_span_lint(POTENTIAL_QUERY_INSTABILITY, span, QueryInstability { @@ -544,7 +545,7 @@ impl Diagnostics { ) { // Is the callee marked with `#[rustc_lint_diagnostics]`? let Some(inst) = - ty::Instance::try_resolve(cx.tcx, cx.param_env, def_id, fn_gen_args).ok().flatten() + ty::Instance::try_resolve(cx.tcx, cx.typing_env(), def_id, fn_gen_args).ok().flatten() else { return; }; diff --git a/compiler/rustc_lint/src/let_underscore.rs b/compiler/rustc_lint/src/let_underscore.rs index abee9ee78699..9e4e83331646 100644 --- a/compiler/rustc_lint/src/let_underscore.rs +++ b/compiler/rustc_lint/src/let_underscore.rs @@ -128,7 +128,7 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore { // If the type has a trivial Drop implementation, then it doesn't // matter that we drop the value immediately. - if !ty.needs_drop(cx.tcx, cx.param_env) { + if !ty.needs_drop(cx.tcx, cx.typing_env()) { return; } // Lint for patterns like `mutex.lock()`, which returns `Result` as well. diff --git a/compiler/rustc_lint/src/non_fmt_panic.rs b/compiler/rustc_lint/src/non_fmt_panic.rs index cf25ec99e671..36b1ff59c674 100644 --- a/compiler/rustc_lint/src/non_fmt_panic.rs +++ b/compiler/rustc_lint/src/non_fmt_panic.rs @@ -157,15 +157,17 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc Some(ty_def) if cx.tcx.is_lang_item(ty_def.did(), LangItem::String), ); - let infcx = cx.tcx.infer_ctxt().build(cx.typing_mode()); + let (infcx, param_env) = cx.tcx.infer_ctxt().build_with_typing_env(cx.typing_env()); let suggest_display = is_str - || cx.tcx.get_diagnostic_item(sym::Display).is_some_and(|t| { - infcx.type_implements_trait(t, [ty], cx.param_env).may_apply() - }); + || cx + .tcx + .get_diagnostic_item(sym::Display) + .is_some_and(|t| infcx.type_implements_trait(t, [ty], param_env).may_apply()); let suggest_debug = !suggest_display - && cx.tcx.get_diagnostic_item(sym::Debug).is_some_and(|t| { - infcx.type_implements_trait(t, [ty], cx.param_env).may_apply() - }); + && cx + .tcx + .get_diagnostic_item(sym::Debug) + .is_some_and(|t| infcx.type_implements_trait(t, [ty], param_env).may_apply()); let suggest_panic_any = !is_str && panic == sym::std_panic_macro; diff --git a/compiler/rustc_lint/src/noop_method_call.rs b/compiler/rustc_lint/src/noop_method_call.rs index 4890a93fa76a..76dc96ae00f4 100644 --- a/compiler/rustc_lint/src/noop_method_call.rs +++ b/compiler/rustc_lint/src/noop_method_call.rs @@ -94,9 +94,9 @@ impl<'tcx> LateLintPass<'tcx> for NoopMethodCall { let args = cx .tcx - .normalize_erasing_regions(cx.param_env, cx.typeck_results().node_args(expr.hir_id)); + .normalize_erasing_regions(cx.typing_env(), cx.typeck_results().node_args(expr.hir_id)); // Resolve the trait method instance. - let Ok(Some(i)) = ty::Instance::try_resolve(cx.tcx, cx.param_env, did, args) else { + let Ok(Some(i)) = ty::Instance::try_resolve(cx.tcx, cx.typing_env(), did, args) else { return; }; // (Re)check that it implements the noop diagnostic. diff --git a/compiler/rustc_lint/src/tail_expr_drop_order.rs b/compiler/rustc_lint/src/tail_expr_drop_order.rs index 89763059877c..19763ce1ec59 100644 --- a/compiler/rustc_lint/src/tail_expr_drop_order.rs +++ b/compiler/rustc_lint/src/tail_expr_drop_order.rs @@ -103,7 +103,7 @@ impl TailExprDropOrder { if matches!(fn_kind, hir::intravisit::FnKind::Closure) { for &capture in cx.tcx.closure_captures(def_id) { if matches!(capture.info.capture_kind, ty::UpvarCapture::ByValue) - && capture.place.ty().has_significant_drop(cx.tcx, cx.param_env) + && capture.place.ty().has_significant_drop(cx.tcx, cx.typing_env()) { locals.push(capture.var_ident.span); } @@ -113,7 +113,7 @@ impl TailExprDropOrder { if cx .typeck_results() .node_type(param.hir_id) - .has_significant_drop(cx.tcx, cx.param_env) + .has_significant_drop(cx.tcx, cx.typing_env()) { locals.push(param.span); } @@ -158,7 +158,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LocalCollector<'a, 'tcx> { fn visit_pat(&mut self, pat: &'tcx Pat<'tcx>) { if let PatKind::Binding(_binding_mode, id, ident, pat) = pat.kind { let ty = self.cx.typeck_results().node_type(id); - if ty.has_significant_drop(self.cx.tcx, self.cx.param_env) { + if ty.has_significant_drop(self.cx.tcx, self.cx.typing_env()) { self.locals.push(ident.span); } if let Some(pat) = pat { @@ -234,7 +234,10 @@ impl<'a, 'tcx> LintTailExpr<'a, 'tcx> { if Self::expr_eventually_point_into_local(expr) { return false; } - self.cx.typeck_results().expr_ty(expr).has_significant_drop(self.cx.tcx, self.cx.param_env) + self.cx + .typeck_results() + .expr_ty(expr) + .has_significant_drop(self.cx.tcx, self.cx.typing_env()) } } diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index be70149b664d..2e6cb9938424 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -613,10 +613,11 @@ pub(crate) fn transparent_newtype_field<'a, 'tcx>( tcx: TyCtxt<'tcx>, variant: &'a ty::VariantDef, ) -> Option<&'a ty::FieldDef> { - let param_env = tcx.param_env(variant.def_id); + let typing_env = ty::TypingEnv::non_body_analysis(tcx, variant.def_id); variant.fields.iter().find(|field| { let field_ty = tcx.type_of(field.did).instantiate_identity(); - let is_1zst = tcx.layout_of(param_env.and(field_ty)).is_ok_and(|layout| layout.is_1zst()); + let is_1zst = + tcx.layout_of(typing_env.as_query_input(field_ty)).is_ok_and(|layout| layout.is_1zst()); !is_1zst }) } @@ -624,11 +625,11 @@ pub(crate) fn transparent_newtype_field<'a, 'tcx>( /// Is type known to be non-null? fn ty_is_known_nonnull<'tcx>( tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ty: Ty<'tcx>, mode: CItemKind, ) -> bool { - let ty = tcx.try_normalize_erasing_regions(param_env, ty).unwrap_or(ty); + let ty = tcx.try_normalize_erasing_regions(typing_env, ty).unwrap_or(ty); match ty.kind() { ty::FnPtr(..) => true, @@ -649,7 +650,7 @@ fn ty_is_known_nonnull<'tcx>( def.variants() .iter() .filter_map(|variant| transparent_newtype_field(tcx, variant)) - .any(|field| ty_is_known_nonnull(tcx, param_env, field.ty(tcx, args), mode)) + .any(|field| ty_is_known_nonnull(tcx, typing_env, field.ty(tcx, args), mode)) } _ => false, } @@ -659,10 +660,10 @@ fn ty_is_known_nonnull<'tcx>( /// If the type passed in was not scalar, returns None. fn get_nullable_type<'tcx>( tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ty: Ty<'tcx>, ) -> Option> { - let ty = tcx.try_normalize_erasing_regions(param_env, ty).unwrap_or(ty); + let ty = tcx.try_normalize_erasing_regions(typing_env, ty).unwrap_or(ty); Some(match *ty.kind() { ty::Adt(field_def, field_args) => { @@ -679,7 +680,7 @@ fn get_nullable_type<'tcx>( .expect("No non-zst fields in transparent type.") .ty(tcx, field_args) }; - return get_nullable_type(tcx, param_env, inner_field_ty); + return get_nullable_type(tcx, typing_env, inner_field_ty); } ty::Int(ty) => Ty::new_int(tcx, ty), ty::Uint(ty) => Ty::new_uint(tcx, ty), @@ -708,10 +709,10 @@ fn get_nullable_type<'tcx>( /// - Does not have the `#[non_exhaustive]` attribute. fn is_niche_optimization_candidate<'tcx>( tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ty: Ty<'tcx>, ) -> bool { - if tcx.layout_of(param_env.and(ty)).is_ok_and(|layout| !layout.is_1zst()) { + if tcx.layout_of(typing_env.as_query_input(ty)).is_ok_and(|layout| !layout.is_1zst()) { return false; } @@ -734,7 +735,7 @@ fn is_niche_optimization_candidate<'tcx>( /// `core::ptr::NonNull`, and `#[repr(transparent)]` newtypes. pub(crate) fn repr_nullable_ptr<'tcx>( tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ty: Ty<'tcx>, ckind: CItemKind, ) -> Option> { @@ -747,9 +748,9 @@ pub(crate) fn repr_nullable_ptr<'tcx>( let ty1 = field1.ty(tcx, args); let ty2 = field2.ty(tcx, args); - if is_niche_optimization_candidate(tcx, param_env, ty1) { + if is_niche_optimization_candidate(tcx, typing_env, ty1) { ty2 - } else if is_niche_optimization_candidate(tcx, param_env, ty2) { + } else if is_niche_optimization_candidate(tcx, typing_env, ty2) { ty1 } else { return None; @@ -760,20 +761,20 @@ pub(crate) fn repr_nullable_ptr<'tcx>( _ => return None, }; - if !ty_is_known_nonnull(tcx, param_env, field_ty, ckind) { + if !ty_is_known_nonnull(tcx, typing_env, field_ty, ckind) { return None; } // At this point, the field's type is known to be nonnull and the parent enum is Option-like. // If the computed size for the field and the enum are different, the nonnull optimization isn't // being applied (and we've got a problem somewhere). - let compute_size_skeleton = |t| SizeSkeleton::compute(t, tcx, param_env).ok(); + let compute_size_skeleton = |t| SizeSkeleton::compute(t, tcx, typing_env).ok(); if !compute_size_skeleton(ty)?.same_size(compute_size_skeleton(field_ty)?) { bug!("improper_ctypes: Option nonnull optimization not applied?"); } // Return the nullable type this Option-like enum can be safely represented with. - let field_ty_layout = tcx.layout_of(param_env.and(field_ty)); + let field_ty_layout = tcx.layout_of(typing_env.as_query_input(field_ty)); if field_ty_layout.is_err() && !field_ty.has_non_region_param() { bug!("should be able to compute the layout of non-polymorphic type"); } @@ -784,10 +785,10 @@ pub(crate) fn repr_nullable_ptr<'tcx>( WrappingRange { start: 0, end } if end == field_ty_scalar.size(&tcx).unsigned_int_max() - 1 => { - return Some(get_nullable_type(tcx, param_env, field_ty).unwrap()); + return Some(get_nullable_type(tcx, typing_env, field_ty).unwrap()); } WrappingRange { start: 1, .. } => { - return Some(get_nullable_type(tcx, param_env, field_ty).unwrap()); + return Some(get_nullable_type(tcx, typing_env, field_ty).unwrap()); } WrappingRange { start, end } => { unreachable!("Unhandled start and end range: ({}, {})", start, end) @@ -825,7 +826,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { let field_ty = self .cx .tcx - .try_normalize_erasing_regions(self.cx.param_env, field_ty) + .try_normalize_erasing_regions(self.cx.typing_env(), field_ty) .unwrap_or(field_ty); self.check_type_for_ffi(acc, field_ty) } @@ -988,7 +989,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { { // Special-case types like `Option` and `Result` if let Some(ty) = - repr_nullable_ptr(self.cx.tcx, self.cx.param_env, ty, self.mode) + repr_nullable_ptr(self.cx.tcx, self.cx.typing_env(), ty, self.mode) { return self.check_type_for_ffi(acc, ty); } @@ -1196,7 +1197,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { if let Some(ty) = self .cx .tcx - .try_normalize_erasing_regions(self.cx.param_env, ty) + .try_normalize_erasing_regions(self.cx.typing_env(), ty) .unwrap_or(ty) .visit_with(&mut ProhibitOpaqueTypes) .break_value() @@ -1220,7 +1221,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { return; } - let ty = self.cx.tcx.try_normalize_erasing_regions(self.cx.param_env, ty).unwrap_or(ty); + let ty = self.cx.tcx.try_normalize_erasing_regions(self.cx.typing_env(), ty).unwrap_or(ty); // C doesn't really support passing arrays by value - the only way to pass an array by value // is through a struct. So, first test that the top level isn't an array, and then diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 6c13127b04ea..5ec920d39f49 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -272,7 +272,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { || !ty.is_inhabited_from( cx.tcx, cx.tcx.parent_module(expr.hir_id).to_def_id(), - cx.param_env, + cx.typing_env(), ) { return Some(MustUsePath::Suppressed); @@ -556,7 +556,7 @@ impl<'tcx> LateLintPass<'tcx> for PathStatements { if let hir::StmtKind::Semi(expr) = s.kind { if let hir::ExprKind::Path(_) = expr.kind { let ty = cx.typeck_results().expr_ty(expr); - if ty.needs_drop(cx.tcx, cx.param_env) { + if ty.needs_drop(cx.tcx, cx.typing_env()) { let sub = if let Ok(snippet) = cx.sess().source_map().span_to_snippet(expr.span) { PathStatementDropSub::Suggestion { span: s.span, snippet } diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index 493db498b7c2..ace46891f83d 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -6,7 +6,7 @@ use rustc_ast::CRATE_NODE_ID; use rustc_attr as attr; use rustc_data_structures::fx::FxHashSet; use rustc_middle::query::LocalCrate; -use rustc_middle::ty::{List, ParamEnv, ParamEnvAnd, Ty, TyCtxt}; +use rustc_middle::ty::{self, List, Ty, TyCtxt}; use rustc_session::Session; use rustc_session::config::CrateType; use rustc_session::cstore::{ @@ -613,7 +613,7 @@ impl<'tcx> Collector<'tcx> { .map(|ty| { let layout = self .tcx - .layout_of(ParamEnvAnd { param_env: ParamEnv::empty(), value: ty }) + .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)) .expect("layout") .layout; // In both stdcall and fastcall, we always round up the argument size to the diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs index e6b36299d7fa..94d13021612b 100644 --- a/compiler/rustc_middle/src/middle/stability.rs +++ b/compiler/rustc_middle/src/middle/stability.rs @@ -10,7 +10,6 @@ use rustc_attr::{ use rustc_data_structures::unord::UnordMap; use rustc_errors::{Applicability, Diag, EmissionGuarantee}; use rustc_feature::GateIssue; -use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdMap}; use rustc_hir::{self as hir, HirId}; use rustc_macros::{Decodable, Encodable, HashStable, Subdiagnostic}; @@ -24,7 +23,7 @@ use rustc_span::symbol::{Symbol, sym}; use tracing::debug; pub use self::StabilityLevel::*; -use crate::ty::{self, TyCtxt}; +use crate::ty::TyCtxt; #[derive(PartialEq, Clone, Copy, Debug)] pub enum StabilityLevel { @@ -273,22 +272,6 @@ pub enum EvalResult { Unmarked, } -// See issue #38412. -fn skip_stability_check_due_to_privacy(tcx: TyCtxt<'_>, def_id: DefId) -> bool { - if tcx.def_kind(def_id) == DefKind::TyParam { - // Have no visibility, considered public for the purpose of this check. - return false; - } - match tcx.visibility(def_id) { - // Must check stability for `pub` items. - ty::Visibility::Public => false, - - // These are not visible outside crate; therefore - // stability markers are irrelevant, if even present. - ty::Visibility::Restricted(..) => true, - } -} - // See issue #83250. fn suggestion_for_allocator_api( tcx: TyCtxt<'_>, @@ -407,11 +390,6 @@ impl<'tcx> TyCtxt<'tcx> { def_id, span, stability ); - // Issue #38412: private items lack stability markers. - if skip_stability_check_due_to_privacy(self, def_id) { - return EvalResult::Allow; - } - match stability { Some(Stability { level: attr::Unstable { reason, issue, is_soft, implied_by }, @@ -495,11 +473,6 @@ impl<'tcx> TyCtxt<'tcx> { "body stability: inspecting def_id={def_id:?} span={span:?} of stability={stability:?}" ); - // Issue #38412: private items lack stability markers. - if skip_stability_check_due_to_privacy(self, def_id) { - return EvalResult::Allow; - } - match stability { Some(DefaultBodyStability { level: attr::Unstable { reason, issue, is_soft, .. }, diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs index f95635370dc3..a51370369b8b 100644 --- a/compiler/rustc_middle/src/mir/consts.rs +++ b/compiler/rustc_middle/src/mir/consts.rs @@ -102,10 +102,11 @@ impl<'tcx> ConstValue<'tcx> { pub fn try_to_bits_for_ty( &self, tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ty: Ty<'tcx>, ) -> Option { - let size = tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size; + let size = + tcx.layout_of(typing_env.with_reveal_all_normalized(tcx).as_query_input(ty)).ok()?.size; self.try_to_bits(size) } @@ -314,7 +315,7 @@ impl<'tcx> Const<'tcx> { pub fn eval( self, tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, span: Span, ) -> Result, ErrorHandled> { match self { @@ -333,7 +334,7 @@ impl<'tcx> Const<'tcx> { } Const::Unevaluated(uneval, _) => { // FIXME: We might want to have a `try_eval`-like function on `Unevaluated` - tcx.const_eval_resolve(param_env, uneval, span) + tcx.const_eval_resolve(typing_env, uneval, span) } Const::Val(val, _) => Ok(val), } @@ -343,7 +344,7 @@ impl<'tcx> Const<'tcx> { pub fn try_eval_scalar( self, tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ) -> Option { if let Const::Ty(_, c) = self && let ty::ConstKind::Value(ty, val) = c.kind() @@ -354,7 +355,7 @@ impl<'tcx> Const<'tcx> { // pointer here, which valtrees don't represent.) Some(val.unwrap_leaf().into()) } else { - self.eval(tcx, param_env, DUMMY_SP).ok()?.try_to_scalar() + self.eval(tcx, typing_env, DUMMY_SP).ok()?.try_to_scalar() } } @@ -362,23 +363,29 @@ impl<'tcx> Const<'tcx> { pub fn try_eval_scalar_int( self, tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ) -> Option { - self.try_eval_scalar(tcx, param_env)?.try_to_scalar_int().ok() + self.try_eval_scalar(tcx, typing_env)?.try_to_scalar_int().ok() } #[inline] - pub fn try_eval_bits(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Option { - let int = self.try_eval_scalar_int(tcx, param_env)?; - let size = - tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(self.ty())).ok()?.size; + pub fn try_eval_bits( + &self, + tcx: TyCtxt<'tcx>, + typing_env: ty::TypingEnv<'tcx>, + ) -> Option { + let int = self.try_eval_scalar_int(tcx, typing_env)?; + let size = tcx + .layout_of(typing_env.with_reveal_all_normalized(tcx).as_query_input(self.ty())) + .ok()? + .size; Some(int.to_bits(size)) } /// Panics if the value cannot be evaluated or doesn't contain a valid integer of the given type. #[inline] - pub fn eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> u128 { - self.try_eval_bits(tcx, param_env) + pub fn eval_bits(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> u128 { + self.try_eval_bits(tcx, typing_env) .unwrap_or_else(|| bug!("expected bits of {:#?}, got {:#?}", self.ty(), self)) } @@ -386,21 +393,21 @@ impl<'tcx> Const<'tcx> { pub fn try_eval_target_usize( self, tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ) -> Option { - Some(self.try_eval_scalar_int(tcx, param_env)?.to_target_usize(tcx)) + Some(self.try_eval_scalar_int(tcx, typing_env)?.to_target_usize(tcx)) } #[inline] /// Panics if the value cannot be evaluated or doesn't contain a valid `usize`. - pub fn eval_target_usize(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> u64 { - self.try_eval_target_usize(tcx, param_env) + pub fn eval_target_usize(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> u64 { + self.try_eval_target_usize(tcx, typing_env) .unwrap_or_else(|| bug!("expected usize, got {:#?}", self)) } #[inline] - pub fn try_eval_bool(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Option { - self.try_eval_scalar_int(tcx, param_env)?.try_into().ok() + pub fn try_eval_bool(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> Option { + self.try_eval_scalar_int(tcx, typing_env)?.try_into().ok() } #[inline] @@ -411,17 +418,16 @@ impl<'tcx> Const<'tcx> { pub fn from_bits( tcx: TyCtxt<'tcx>, bits: u128, - param_env_ty: ty::ParamEnvAnd<'tcx, Ty<'tcx>>, + typing_env: ty::TypingEnv<'tcx>, + ty: Ty<'tcx>, ) -> Self { let size = tcx - .layout_of(param_env_ty) - .unwrap_or_else(|e| { - bug!("could not compute layout for {:?}: {:?}", param_env_ty.value, e) - }) + .layout_of(typing_env.as_query_input(ty)) + .unwrap_or_else(|e| bug!("could not compute layout for {ty:?}: {e:?}")) .size; let cv = ConstValue::Scalar(Scalar::from_uint(bits, size)); - Self::Val(cv, param_env_ty.value) + Self::Val(cv, ty) } #[inline] @@ -438,7 +444,8 @@ impl<'tcx> Const<'tcx> { pub fn from_usize(tcx: TyCtxt<'tcx>, n: u64) -> Self { let ty = tcx.types.usize; - Self::from_bits(tcx, n as u128, ty::ParamEnv::empty().and(ty)) + let typing_env = ty::TypingEnv::fully_monomorphized(); + Self::from_bits(tcx, n as u128, typing_env, ty) } #[inline] diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index f225ad94aa70..c4b0e6e39cc4 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -351,7 +351,11 @@ impl<'tcx> GlobalAlloc<'tcx> { } } - pub fn size_and_align(&self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> (Size, Align) { + pub fn size_and_align( + &self, + tcx: TyCtxt<'tcx>, + typing_env: ty::TypingEnv<'tcx>, + ) -> (Size, Align) { match self { GlobalAlloc::Static(def_id) => { let DefKind::Static { nested, .. } = tcx.def_kind(def_id) else { @@ -374,7 +378,7 @@ impl<'tcx> GlobalAlloc<'tcx> { .type_of(def_id) .no_bound_vars() .expect("statics should not have generic parameters"); - let layout = tcx.layout_of(param_env.and(ty)).unwrap(); + let layout = tcx.layout_of(typing_env.as_query_input(ty)).unwrap(); assert!(layout.is_sized()); (layout.size, layout.align.abi) } diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs index 2ecf1d0bcf85..7092f87a7d19 100644 --- a/compiler/rustc_middle/src/mir/interpret/queries.rs +++ b/compiler/rustc_middle/src/mir/interpret/queries.rs @@ -58,7 +58,7 @@ impl<'tcx> TyCtxt<'tcx> { #[instrument(level = "debug", skip(self))] pub fn const_eval_resolve( self, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ct: mir::UnevaluatedConst<'tcx>, span: Span, ) -> EvalToConstValueResult<'tcx> { @@ -72,14 +72,11 @@ impl<'tcx> TyCtxt<'tcx> { bug!("did not expect inference variables here"); } - match ty::Instance::try_resolve( - self, param_env, - // FIXME: maybe have a separate version for resolving mir::UnevaluatedConst? - ct.def, ct.args, - ) { + // FIXME: maybe have a separate version for resolving mir::UnevaluatedConst? + match ty::Instance::try_resolve(self, typing_env, ct.def, ct.args) { Ok(Some(instance)) => { let cid = GlobalId { instance, promoted: ct.promoted }; - self.const_eval_global_id(param_env, cid, span) + self.const_eval_global_id(typing_env.param_env, cid, span) } // For errors during resolution, we deliberately do not point at the usage site of the constant, // since for these errors the place the constant is used shouldn't matter. @@ -91,7 +88,7 @@ impl<'tcx> TyCtxt<'tcx> { #[instrument(level = "debug", skip(self))] pub fn const_eval_resolve_for_typeck( self, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ct: ty::UnevaluatedConst<'tcx>, span: Span, ) -> EvalToValTreeResult<'tcx> { @@ -105,10 +102,10 @@ impl<'tcx> TyCtxt<'tcx> { bug!("did not expect inference variables here"); } - match ty::Instance::try_resolve(self, param_env, ct.def, ct.args) { + match ty::Instance::try_resolve(self, typing_env, ct.def, ct.args) { Ok(Some(instance)) => { let cid = GlobalId { instance, promoted: None }; - self.const_eval_global_id_for_typeck(param_env, cid, span).inspect(|_| { + self.const_eval_global_id_for_typeck(typing_env.param_env, cid, span).inspect(|_| { // We are emitting the lint here instead of in `is_const_evaluatable` // as we normalize obligations before checking them, and normalization // uses this function to evaluate this constant. diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 260c6543f984..425cb059e576 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -39,7 +39,7 @@ use crate::ty::fold::{FallibleTypeFolder, TypeFoldable}; use crate::ty::print::{FmtPrinter, Printer, pretty_print_const, with_no_trimmed_paths}; use crate::ty::visit::TypeVisitableExt; use crate::ty::{ - self, AdtDef, GenericArg, GenericArgsRef, Instance, InstanceKind, List, Ty, TyCtxt, TypingMode, + self, AdtDef, GenericArg, GenericArgsRef, Instance, InstanceKind, List, Ty, TyCtxt, TypingEnv, UserTypeAnnotationIndex, }; @@ -452,12 +452,17 @@ impl<'tcx> Body<'tcx> { self.basic_blocks.as_mut() } - pub fn typing_mode(&self, _tcx: TyCtxt<'tcx>) -> TypingMode<'tcx> { + pub fn typing_env(&self, tcx: TyCtxt<'tcx>) -> TypingEnv<'tcx> { match self.phase { - // FIXME(#132279): the MIR is quite clearly inside of a body, so we - // should instead reveal opaques defined by that body here. - MirPhase::Built | MirPhase::Analysis(_) => TypingMode::non_body_analysis(), - MirPhase::Runtime(_) => TypingMode::PostAnalysis, + // FIXME(#132279): we should reveal the opaques defined in the body during analysis. + MirPhase::Built | MirPhase::Analysis(_) => TypingEnv { + typing_mode: ty::TypingMode::non_body_analysis(), + param_env: tcx.param_env(self.source.def_id()), + }, + MirPhase::Runtime(_) => TypingEnv { + typing_mode: ty::TypingMode::PostAnalysis, + param_env: tcx.param_env_reveal_all_normalized(self.source.def_id()), + }, } } @@ -618,7 +623,7 @@ impl<'tcx> Body<'tcx> { } /// If this basic block ends with a [`TerminatorKind::SwitchInt`] for which we can evaluate the - /// dimscriminant in monomorphization, we return the discriminant bits and the + /// discriminant in monomorphization, we return the discriminant bits and the /// [`SwitchTargets`], just so the caller doesn't also have to match on the terminator. fn try_const_mono_switchint<'a>( tcx: TyCtxt<'tcx>, @@ -627,13 +632,15 @@ impl<'tcx> Body<'tcx> { ) -> Option<(u128, &'a SwitchTargets)> { // There are two places here we need to evaluate a constant. let eval_mono_const = |constant: &ConstOperand<'tcx>| { - let env = ty::ParamEnv::reveal_all(); + // FIXME(#132279): what is this, why are we using an empty environment with + // `RevealAll` here. + let typing_env = ty::TypingEnv::fully_monomorphized(); let mono_literal = instance.instantiate_mir_and_normalize_erasing_regions( tcx, - env, + typing_env, crate::ty::EarlyBinder::bind(constant.const_), ); - mono_literal.try_eval_bits(tcx, env) + mono_literal.try_eval_bits(tcx, typing_env) }; let TerminatorKind::SwitchInt { discr, targets } = &block.terminator().kind else { diff --git a/compiler/rustc_middle/src/mir/statement.rs b/compiler/rustc_middle/src/mir/statement.rs index 88ed90c31146..1ce735cec631 100644 --- a/compiler/rustc_middle/src/mir/statement.rs +++ b/compiler/rustc_middle/src/mir/statement.rs @@ -332,9 +332,9 @@ impl<'tcx> Operand<'tcx> { span: Span, ) -> Operand<'tcx> { debug_assert!({ - let param_env_and_ty = ty::ParamEnv::empty().and(ty); + let typing_env = ty::TypingEnv::fully_monomorphized(); let type_size = tcx - .layout_of(param_env_and_ty) + .layout_of(typing_env.as_query_input(ty)) .unwrap_or_else(|e| panic!("could not compute layout for {ty:?}: {e:?}")) .size; let scalar_size = match val { diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index f01ac305d3f5..2083279e1286 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -20,7 +20,7 @@ use smallvec::SmallVec; use super::{BasicBlock, Const, Local, UserTypeProjection}; use crate::mir::coverage::CoverageKind; use crate::ty::adjustment::PointerCoercion; -use crate::ty::{self, GenericArgsRef, List, Region, Ty, TyCtxt, UserTypeAnnotationIndex}; +use crate::ty::{self, GenericArgsRef, List, Region, Ty, UserTypeAnnotationIndex}; /// Represents the "flavors" of MIR. /// @@ -100,13 +100,6 @@ impl MirPhase { MirPhase::Runtime(RuntimePhase::Optimized) => "runtime-optimized", } } - - pub fn param_env<'tcx>(&self, tcx: TyCtxt<'tcx>, body_def_id: DefId) -> ty::ParamEnv<'tcx> { - match self { - MirPhase::Built | MirPhase::Analysis(_) => tcx.param_env(body_def_id), - MirPhase::Runtime(_) => tcx.param_env_reveal_all_normalized(body_def_id), - } - } } /// See [`MirPhase::Analysis`]. diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs index c5def5fc65be..9cb11cdd3b73 100644 --- a/compiler/rustc_middle/src/query/keys.rs +++ b/compiler/rustc_middle/src/query/keys.rs @@ -467,6 +467,18 @@ impl<'tcx, T: Key> Key for ty::ParamEnvAnd<'tcx, T> { } } +impl<'tcx, T: Key> Key for ty::PseudoCanonicalInput<'tcx, T> { + type Cache = DefaultCache; + + fn default_span(&self, tcx: TyCtxt<'_>) -> Span { + self.value.default_span(tcx) + } + + fn ty_def_id(&self) -> Option { + self.value.ty_def_id() + } +} + impl Key for Symbol { type Cache = DefaultCache; @@ -575,7 +587,7 @@ impl Key for (LocalDefId, HirId) { } } -impl<'tcx> Key for (ValidityRequirement, ty::ParamEnvAnd<'tcx, Ty<'tcx>>) { +impl<'tcx> Key for (ValidityRequirement, ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) { type Cache = DefaultCache; // Just forward to `Ty<'tcx>` diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 4068d06f6dfd..684d5b6c2a77 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -81,8 +81,8 @@ use crate::ty::layout::ValidityRequirement; use crate::ty::print::{PrintTraitRefExt, describe_as_module}; use crate::ty::util::AlwaysRequiresDrop; use crate::ty::{ - self, CrateInherentImpls, GenericArg, GenericArgsRef, ParamEnvAnd, Ty, TyCtxt, TyCtxtFeed, - UnusedGenericParams, + self, CrateInherentImpls, GenericArg, GenericArgsRef, PseudoCanonicalInput, Ty, TyCtxt, + TyCtxtFeed, UnusedGenericParams, }; use crate::{dep_graph, mir, thir}; @@ -1341,10 +1341,10 @@ rustc_queries! { } query codegen_select_candidate( - key: (ty::ParamEnv<'tcx>, ty::TraitRef<'tcx>) + key: PseudoCanonicalInput<'tcx, ty::TraitRef<'tcx>> ) -> Result<&'tcx ImplSource<'tcx, ()>, CodegenObligationError> { cache_on_disk_if { true } - desc { |tcx| "computing candidate for `{}`", key.1 } + desc { |tcx| "computing candidate for `{}`", key.value } } /// Return all `impl` blocks in the current crate. @@ -1406,15 +1406,15 @@ rustc_queries! { desc { "computing whether `{}` is `Unpin`", env.value } } /// Query backing `Ty::needs_drop`. - query needs_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { + query needs_drop_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { desc { "computing whether `{}` needs drop", env.value } } /// Query backing `Ty::needs_async_drop`. - query needs_async_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { + query needs_async_drop_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { desc { "computing whether `{}` needs async drop", env.value } } /// Query backing `Ty::has_significant_drop_raw`. - query has_significant_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { + query has_significant_drop_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { desc { "computing whether `{}` has a significant drop", env.value } } @@ -1451,7 +1451,7 @@ rustc_queries! { /// Computes the layout of a type. Note that this implicitly /// executes in "reveal all" mode, and will normalize the input type. query layout_of( - key: ty::ParamEnvAnd<'tcx, Ty<'tcx>> + key: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>> ) -> Result, &'tcx ty::layout::LayoutError<'tcx>> { depth_limit desc { "computing layout of `{}`", key.value } @@ -1464,7 +1464,7 @@ rustc_queries! { /// NB: this doesn't handle virtual calls - those should use `fn_abi_of_instance` /// instead, where the instance is an `InstanceKind::Virtual`. query fn_abi_of_fn_ptr( - key: ty::ParamEnvAnd<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List>)> + key: ty::PseudoCanonicalInput<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List>)> ) -> Result<&'tcx rustc_target::callconv::FnAbi<'tcx, Ty<'tcx>>, &'tcx ty::layout::FnAbiError<'tcx>> { desc { "computing call ABI of `{}` function pointers", key.value.0 } } @@ -1475,7 +1475,7 @@ rustc_queries! { /// NB: that includes virtual calls, which are represented by "direct calls" /// to an `InstanceKind::Virtual` instance (of `::fn`). query fn_abi_of_instance( - key: ty::ParamEnvAnd<'tcx, (ty::Instance<'tcx>, &'tcx ty::List>)> + key: ty::PseudoCanonicalInput<'tcx, (ty::Instance<'tcx>, &'tcx ty::List>)> ) -> Result<&'tcx rustc_target::callconv::FnAbi<'tcx, Ty<'tcx>>, &'tcx ty::layout::FnAbiError<'tcx>> { desc { "computing call ABI of `{}`", key.value.0 } } @@ -2088,7 +2088,7 @@ rustc_queries! { /// Do not call this query directly: invoke `try_normalize_erasing_regions` instead. query try_normalize_generic_arg_after_erasing_regions( - goal: ParamEnvAnd<'tcx, GenericArg<'tcx>> + goal: PseudoCanonicalInput<'tcx, GenericArg<'tcx>> ) -> Result, NoSolution> { desc { "normalizing `{}`", goal.value } } @@ -2245,7 +2245,7 @@ rustc_queries! { /// from `Ok(None)` to avoid misleading diagnostics when an error /// has already been/will be emitted, for the original cause. query resolve_instance_raw( - key: ty::ParamEnvAnd<'tcx, (DefId, GenericArgsRef<'tcx>)> + key: ty::PseudoCanonicalInput<'tcx, (DefId, GenericArgsRef<'tcx>)> ) -> Result>, ErrorGuaranteed> { desc { "resolving instance `{}`", ty::Instance::new(key.value.0, key.value.1) } } @@ -2283,7 +2283,7 @@ rustc_queries! { desc { "computing the backend features for CLI flags" } } - query check_validity_requirement(key: (ValidityRequirement, ty::ParamEnvAnd<'tcx, Ty<'tcx>>)) -> Result> { + query check_validity_requirement(key: (ValidityRequirement, ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>)) -> Result> { desc { "checking validity requirement for `{}`: {}", key.1.value, key.0 } } diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 70df23790161..0e5b56d34911 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -910,7 +910,7 @@ impl<'tcx> PatRange<'tcx> { &self, value: mir::Const<'tcx>, tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ) -> Option { use Ordering::*; debug_assert_eq!(self.ty, value.ty()); @@ -918,10 +918,10 @@ impl<'tcx> PatRange<'tcx> { let value = PatRangeBoundary::Finite(value); // For performance, it's important to only do the second comparison if necessary. Some( - match self.lo.compare_with(value, ty, tcx, param_env)? { + match self.lo.compare_with(value, ty, tcx, typing_env)? { Less | Equal => true, Greater => false, - } && match value.compare_with(self.hi, ty, tcx, param_env)? { + } && match value.compare_with(self.hi, ty, tcx, typing_env)? { Less => true, Equal => self.end == RangeEnd::Included, Greater => false, @@ -934,17 +934,17 @@ impl<'tcx> PatRange<'tcx> { &self, other: &Self, tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ) -> Option { use Ordering::*; debug_assert_eq!(self.ty, other.ty); // For performance, it's important to only do the second comparison if necessary. Some( - match other.lo.compare_with(self.hi, self.ty, tcx, param_env)? { + match other.lo.compare_with(self.hi, self.ty, tcx, typing_env)? { Less => true, Equal => self.end == RangeEnd::Included, Greater => false, - } && match self.lo.compare_with(other.hi, self.ty, tcx, param_env)? { + } && match self.lo.compare_with(other.hi, self.ty, tcx, typing_env)? { Less => true, Equal => other.end == RangeEnd::Included, Greater => false, @@ -990,9 +990,14 @@ impl<'tcx> PatRangeBoundary<'tcx> { Self::NegInfinity | Self::PosInfinity => None, } } - pub fn eval_bits(self, ty: Ty<'tcx>, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> u128 { + pub fn eval_bits( + self, + ty: Ty<'tcx>, + tcx: TyCtxt<'tcx>, + typing_env: ty::TypingEnv<'tcx>, + ) -> u128 { match self { - Self::Finite(value) => value.eval_bits(tcx, param_env), + Self::Finite(value) => value.eval_bits(tcx, typing_env), Self::NegInfinity => { // Unwrap is ok because the type is known to be numeric. ty.numeric_min_and_max_as_bits(tcx).unwrap().0 @@ -1004,13 +1009,13 @@ impl<'tcx> PatRangeBoundary<'tcx> { } } - #[instrument(skip(tcx, param_env), level = "debug", ret)] + #[instrument(skip(tcx, typing_env), level = "debug", ret)] pub fn compare_with( self, other: Self, ty: Ty<'tcx>, tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ) -> Option { use PatRangeBoundary::*; match (self, other) { @@ -1039,8 +1044,8 @@ impl<'tcx> PatRangeBoundary<'tcx> { _ => {} } - let a = self.eval_bits(ty, tcx, param_env); - let b = other.eval_bits(ty, tcx, param_env); + let a = self.eval_bits(ty, tcx, typing_env); + let b = other.eval_bits(ty, tcx, typing_env); match ty.kind() { ty::Float(ty::FloatTy::F16) => { diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs index 0773eb7a3bef..79d56702be25 100644 --- a/compiler/rustc_middle/src/ty/adt.rs +++ b/compiler/rustc_middle/src/ty/adt.rs @@ -498,12 +498,13 @@ impl<'tcx> AdtDef<'tcx> { expr_did: DefId, ) -> Result, ErrorGuaranteed> { assert!(self.is_enum()); - let param_env = tcx.param_env(expr_did); + let repr_type = self.repr().discr_type(); match tcx.const_eval_poly(expr_did) { Ok(val) => { + let typing_env = ty::TypingEnv::post_analysis(tcx, expr_did); let ty = repr_type.to_ty(tcx); - if let Some(b) = val.try_to_bits_for_ty(tcx, param_env, ty) { + if let Some(b) = val.try_to_bits_for_ty(tcx, typing_env, ty) { trace!("discriminants: {} ({:?})", b, repr_type); Ok(Discr { val: b, ty }) } else { diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 5689f3d42654..3bd09fc91c64 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -9,7 +9,7 @@ use tracing::{debug, instrument}; use crate::middle::resolve_bound_vars as rbv; use crate::mir::interpret::{LitToConstInput, Scalar}; -use crate::ty::{self, GenericArgs, ParamEnv, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt}; +use crate::ty::{self, GenericArgs, Ty, TyCtxt, TypeVisitableExt}; mod int; mod kind; @@ -330,17 +330,22 @@ impl<'tcx> Const<'tcx> { None } - #[inline] /// Creates a constant with the given integer value and interns it. - pub fn from_bits(tcx: TyCtxt<'tcx>, bits: u128, ty: ParamEnvAnd<'tcx, Ty<'tcx>>) -> Self { + #[inline] + pub fn from_bits( + tcx: TyCtxt<'tcx>, + bits: u128, + typing_env: ty::TypingEnv<'tcx>, + ty: Ty<'tcx>, + ) -> Self { let size = tcx - .layout_of(ty) + .layout_of(typing_env.as_query_input(ty)) .unwrap_or_else(|e| panic!("could not compute layout for {ty:?}: {e:?}")) .size; ty::Const::new_value( tcx, ty::ValTree::from_scalar_int(ScalarInt::try_from_uint(bits, size).unwrap()), - ty.value, + ty, ) } @@ -353,13 +358,13 @@ impl<'tcx> Const<'tcx> { #[inline] /// Creates an interned bool constant. pub fn from_bool(tcx: TyCtxt<'tcx>, v: bool) -> Self { - Self::from_bits(tcx, v as u128, ParamEnv::empty().and(tcx.types.bool)) + Self::from_bits(tcx, v as u128, ty::TypingEnv::fully_monomorphized(), tcx.types.bool) } #[inline] /// Creates an interned usize constant. pub fn from_target_usize(tcx: TyCtxt<'tcx>, n: u64) -> Self { - Self::from_bits(tcx, n as u128, ParamEnv::empty().and(tcx.types.usize)) + Self::from_bits(tcx, n as u128, ty::TypingEnv::fully_monomorphized(), tcx.types.usize) } /// Panics if self.kind != ty::ConstKind::Value @@ -393,15 +398,15 @@ impl<'tcx> Const<'tcx> { self.try_to_valtree()?.0.try_to_target_usize(tcx) } - #[inline] /// Attempts to evaluate the given constant to bits. Can fail to evaluate in the presence of /// generics (or erroneous code) or if the value can't be represented as bits (e.g. because it /// contains const generic parameters or pointers). - pub fn try_to_bits(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option { + #[inline] + pub fn try_to_bits(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> Option { let (scalar, ty) = self.try_to_scalar()?; let scalar = scalar.try_to_scalar_int().ok()?; - let size = tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size; - // if `ty` does not depend on generic parameters, use an empty param_env + let input = typing_env.with_reveal_all_normalized(tcx).as_query_input(ty); + let size = tcx.layout_of(input).ok()?.size; Some(scalar.to_bits(size)) } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 84ac281c258e..2ba1bf2822fb 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -596,8 +596,16 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.coroutine_is_async_gen(coroutine_def_id) } - fn layout_is_pointer_like(self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool { - self.layout_of(self.erase_regions(param_env.and(ty))) + // We don't use `TypingEnv` here as it's only defined in `rustc_middle` and + // `rustc_next_trait_solver` shouldn't have to know about it. + fn layout_is_pointer_like( + self, + typing_mode: ty::TypingMode<'tcx>, + param_env: ty::ParamEnv<'tcx>, + ty: Ty<'tcx>, + ) -> bool { + let typing_env = ty::TypingEnv { typing_mode, param_env }; + self.layout_of(self.erase_regions(typing_env).as_query_input(self.erase_regions(ty))) .is_ok_and(|layout| layout.layout.is_pointer_like(&self.data_layout)) } diff --git a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs index bf741f63a3d4..505c7278176f 100644 --- a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs +++ b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs @@ -3,7 +3,7 @@ use smallvec::SmallVec; use tracing::instrument; use crate::ty::context::TyCtxt; -use crate::ty::{self, DefId, OpaqueTypeKey, ParamEnv, Ty}; +use crate::ty::{self, DefId, OpaqueTypeKey, Ty, TypingEnv}; /// Represents whether some type is inhabited in a given context. /// Examples of uninhabited types are `!`, `enum Void {}`, or a struct @@ -35,8 +35,13 @@ pub enum InhabitedPredicate<'tcx> { impl<'tcx> InhabitedPredicate<'tcx> { /// Returns true if the corresponding type is inhabited in the given `ParamEnv` and module. - pub fn apply(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, module_def_id: DefId) -> bool { - self.apply_revealing_opaque(tcx, param_env, module_def_id, &|_| None) + pub fn apply( + self, + tcx: TyCtxt<'tcx>, + typing_env: TypingEnv<'tcx>, + module_def_id: DefId, + ) -> bool { + self.apply_revealing_opaque(tcx, typing_env, module_def_id, &|_| None) } /// Returns true if the corresponding type is inhabited in the given `ParamEnv` and module, @@ -44,13 +49,13 @@ impl<'tcx> InhabitedPredicate<'tcx> { pub fn apply_revealing_opaque( self, tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: TypingEnv<'tcx>, module_def_id: DefId, reveal_opaque: &impl Fn(OpaqueTypeKey<'tcx>) -> Option>, ) -> bool { let Ok(result) = self.apply_inner::( tcx, - param_env, + typing_env, &mut Default::default(), &|id| Ok(tcx.is_descendant_of(module_def_id, id)), reveal_opaque, @@ -59,25 +64,25 @@ impl<'tcx> InhabitedPredicate<'tcx> { } /// Same as `apply`, but returns `None` if self contains a module predicate - pub fn apply_any_module(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option { - self.apply_inner(tcx, param_env, &mut Default::default(), &|_| Err(()), &|_| None).ok() + pub fn apply_any_module(self, tcx: TyCtxt<'tcx>, typing_env: TypingEnv<'tcx>) -> Option { + self.apply_inner(tcx, typing_env, &mut Default::default(), &|_| Err(()), &|_| None).ok() } /// Same as `apply`, but `NotInModule(_)` predicates yield `false`. That is, /// privately uninhabited types are considered always uninhabited. - pub fn apply_ignore_module(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> bool { + pub fn apply_ignore_module(self, tcx: TyCtxt<'tcx>, typing_env: TypingEnv<'tcx>) -> bool { let Ok(result) = - self.apply_inner::(tcx, param_env, &mut Default::default(), &|_| Ok(true), &|_| { + self.apply_inner::(tcx, typing_env, &mut Default::default(), &|_| Ok(true), &|_| { None }); result } - #[instrument(level = "debug", skip(tcx, param_env, in_module, reveal_opaque), ret)] + #[instrument(level = "debug", skip(tcx, typing_env, in_module, reveal_opaque), ret)] fn apply_inner( self, tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: TypingEnv<'tcx>, eval_stack: &mut SmallVec<[Ty<'tcx>; 1]>, // for cycle detection in_module: &impl Fn(DefId) -> Result, reveal_opaque: &impl Fn(OpaqueTypeKey<'tcx>) -> Option>, @@ -94,7 +99,7 @@ impl<'tcx> InhabitedPredicate<'tcx> { // we have a param_env available, we can do better. Self::GenericType(t) => { let normalized_pred = tcx - .try_normalize_erasing_regions(param_env, t) + .try_normalize_erasing_regions(typing_env, t) .map_or(self, |t| t.inhabited_predicate(tcx)); match normalized_pred { // We don't have more information than we started with, so consider inhabited. @@ -107,7 +112,7 @@ impl<'tcx> InhabitedPredicate<'tcx> { } eval_stack.push(t); let ret = - pred.apply_inner(tcx, param_env, eval_stack, in_module, reveal_opaque); + pred.apply_inner(tcx, typing_env, eval_stack, in_module, reveal_opaque); eval_stack.pop(); ret } @@ -126,7 +131,7 @@ impl<'tcx> InhabitedPredicate<'tcx> { eval_stack.push(t); let ret = t.inhabited_predicate(tcx).apply_inner( tcx, - param_env, + typing_env, eval_stack, in_module, reveal_opaque, @@ -136,10 +141,10 @@ impl<'tcx> InhabitedPredicate<'tcx> { } }, Self::And([a, b]) => try_and(a, b, |x| { - x.apply_inner(tcx, param_env, eval_stack, in_module, reveal_opaque) + x.apply_inner(tcx, typing_env, eval_stack, in_module, reveal_opaque) }), Self::Or([a, b]) => try_or(a, b, |x| { - x.apply_inner(tcx, param_env, eval_stack, in_module, reveal_opaque) + x.apply_inner(tcx, typing_env, eval_stack, in_module, reveal_opaque) }), } } diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs index dd00db8635f4..4a5f6d80f24c 100644 --- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs +++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs @@ -181,18 +181,18 @@ impl<'tcx> Ty<'tcx> { self, tcx: TyCtxt<'tcx>, module: DefId, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ) -> bool { - self.inhabited_predicate(tcx).apply(tcx, param_env, module) + self.inhabited_predicate(tcx).apply(tcx, typing_env, module) } /// Returns true if the type is uninhabited without regard to visibility pub fn is_privately_uninhabited( self, tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ) -> bool { - !self.inhabited_predicate(tcx).apply_ignore_module(tcx, param_env) + !self.inhabited_predicate(tcx).apply_ignore_module(tcx, typing_env) } } diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 0d1c56f0d380..d42b6be4787d 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -178,9 +178,9 @@ pub enum InstanceKind<'tcx> { impl<'tcx> Instance<'tcx> { /// Returns the `Ty` corresponding to this `Instance`, with generic instantiations applied and /// lifetimes erased, allowing a `ParamEnv` to be specified for use during normalization. - pub fn ty(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Ty<'tcx> { + pub fn ty(&self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> Ty<'tcx> { let ty = tcx.type_of(self.def.def_id()); - tcx.instantiate_and_normalize_erasing_regions(self.args, param_env, ty) + tcx.instantiate_and_normalize_erasing_regions(self.args, typing_env, ty) } /// Finds a crate that contains a monomorphization of this instance that @@ -519,7 +519,7 @@ impl<'tcx> Instance<'tcx> { #[instrument(level = "debug", skip(tcx), ret)] pub fn try_resolve( tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, def_id: DefId, args: GenericArgsRef<'tcx>, ) -> Result>, ErrorGuaranteed> { @@ -537,17 +537,14 @@ impl<'tcx> Instance<'tcx> { // All regions in the result of this query are erased, so it's // fine to erase all of the input regions. - - // HACK(eddyb) erase regions in `args` first, so that `param_env.and(...)` - // below is more likely to ignore the bounds in scope (e.g. if the only - // generic parameters mentioned by `args` were lifetime ones). + let typing_env = tcx.erase_regions(typing_env); let args = tcx.erase_regions(args); - tcx.resolve_instance_raw(tcx.erase_regions(param_env.and((def_id, args)))) + tcx.resolve_instance_raw(typing_env.as_query_input((def_id, args))) } pub fn expect_resolve( tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, def_id: DefId, args: GenericArgsRef<'tcx>, span: Span, @@ -558,7 +555,7 @@ impl<'tcx> Instance<'tcx> { let span_or_local_def_span = || if span.is_dummy() && def_id.is_local() { tcx.def_span(def_id) } else { span }; - match ty::Instance::try_resolve(tcx, param_env, def_id, args) { + match ty::Instance::try_resolve(tcx, typing_env, def_id, args) { Ok(Some(instance)) => instance, Ok(None) => { let type_length = type_length(args); @@ -600,7 +597,7 @@ impl<'tcx> Instance<'tcx> { pub fn resolve_for_fn_ptr( tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, def_id: DefId, args: GenericArgsRef<'tcx>, ) -> Option> { @@ -608,7 +605,7 @@ impl<'tcx> Instance<'tcx> { // Use either `resolve_closure` or `resolve_for_vtable` assert!(!tcx.is_closure_like(def_id), "Called `resolve_for_fn_ptr` on closure: {def_id:?}"); let reason = tcx.sess.is_sanitizer_kcfi_enabled().then_some(ReifyReason::FnPtr); - Instance::try_resolve(tcx, param_env, def_id, args).ok().flatten().map(|mut resolved| { + Instance::try_resolve(tcx, typing_env, def_id, args).ok().flatten().map(|mut resolved| { match resolved.def { InstanceKind::Item(def) if resolved.def.requires_caller_location(tcx) => { debug!(" => fn pointer created for function with #[track_caller]"); @@ -648,7 +645,7 @@ impl<'tcx> Instance<'tcx> { pub fn expect_resolve_for_vtable( tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, def_id: DefId, args: GenericArgsRef<'tcx>, span: Span, @@ -664,7 +661,7 @@ impl<'tcx> Instance<'tcx> { return Instance { def: InstanceKind::VTableShim(def_id), args }; } - let mut resolved = Instance::expect_resolve(tcx, param_env, def_id, args, span); + let mut resolved = Instance::expect_resolve(tcx, typing_env, def_id, args, span); let reason = tcx.sess.is_sanitizer_kcfi_enabled().then_some(ReifyReason::Vtable); match resolved.def { @@ -743,7 +740,7 @@ impl<'tcx> Instance<'tcx> { let args = tcx.mk_args(&[ty.into()]); Instance::expect_resolve( tcx, - ty::ParamEnv::reveal_all(), + ty::TypingEnv::fully_monomorphized(), def_id, args, ty.ty_adt_def().and_then(|adt| tcx.hir().span_if_local(adt.did())).unwrap_or(DUMMY_SP), @@ -755,7 +752,7 @@ impl<'tcx> Instance<'tcx> { let args = tcx.mk_args(&[ty.into()]); Instance::expect_resolve( tcx, - ty::ParamEnv::reveal_all(), + ty::TypingEnv::fully_monomorphized(), def_id, args, ty.ty_adt_def().and_then(|adt| tcx.hir().span_if_local(adt.did())).unwrap_or(DUMMY_SP), @@ -883,16 +880,16 @@ impl<'tcx> Instance<'tcx> { pub fn instantiate_mir_and_normalize_erasing_regions( &self, tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, v: EarlyBinder<'tcx, T>, ) -> T where T: TypeFoldable>, { if let Some(args) = self.args_for_mir_body() { - tcx.instantiate_and_normalize_erasing_regions(args, param_env, v) + tcx.instantiate_and_normalize_erasing_regions(args, typing_env, v) } else { - tcx.normalize_erasing_regions(param_env, v.instantiate_identity()) + tcx.normalize_erasing_regions(typing_env, v.instantiate_identity()) } } @@ -901,21 +898,21 @@ impl<'tcx> Instance<'tcx> { pub fn try_instantiate_mir_and_normalize_erasing_regions( &self, tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, v: EarlyBinder<'tcx, T>, ) -> Result> where T: TypeFoldable>, { if let Some(args) = self.args_for_mir_body() { - tcx.try_instantiate_and_normalize_erasing_regions(args, param_env, v) + tcx.try_instantiate_and_normalize_erasing_regions(args, typing_env, v) } else { // We're using `instantiate_identity` as e.g. // `FnPtrShim` is separately generated for every // instantiation of the `FnDef`, so the MIR body // is already instantiated. Any generic parameters it // contains are generic parameters from the caller. - tcx.try_normalize_erasing_regions(param_env, v.instantiate_identity()) + tcx.try_normalize_erasing_regions(typing_env, v.instantiate_identity()) } } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index a0eb90293196..8625a8dcb2a3 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -297,12 +297,12 @@ impl<'tcx> IntoDiagArg for LayoutError<'tcx> { #[derive(Clone, Copy)] pub struct LayoutCx<'tcx> { pub calc: abi::LayoutCalculator>, - pub param_env: ty::ParamEnv<'tcx>, + pub typing_env: ty::TypingEnv<'tcx>, } impl<'tcx> LayoutCx<'tcx> { - pub fn new(tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Self { - Self { calc: abi::LayoutCalculator::new(tcx), param_env } + pub fn new(tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> Self { + Self { calc: abi::LayoutCalculator::new(tcx), typing_env } } } @@ -337,12 +337,12 @@ impl<'tcx> SizeSkeleton<'tcx> { pub fn compute( ty: Ty<'tcx>, tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ) -> Result, &'tcx LayoutError<'tcx>> { debug_assert!(!ty.has_non_region_infer()); // First try computing a static layout. - let err = match tcx.layout_of(param_env.and(ty)) { + let err = match tcx.layout_of(typing_env.as_query_input(ty)) { Ok(layout) => { if layout.is_sized() { return Ok(SizeSkeleton::Known(layout.size, Some(layout.align.abi))); @@ -367,7 +367,7 @@ impl<'tcx> SizeSkeleton<'tcx> { let tail = tcx.struct_tail_raw( pointee, - |ty| match tcx.try_normalize_erasing_regions(param_env, ty) { + |ty| match tcx.try_normalize_erasing_regions(typing_env, ty) { Ok(ty) => ty, Err(e) => Ty::new_error_with_message( tcx, @@ -402,7 +402,7 @@ impl<'tcx> SizeSkeleton<'tcx> { return Ok(SizeSkeleton::Known(Size::from_bytes(0), None)); } - match SizeSkeleton::compute(inner, tcx, param_env)? { + match SizeSkeleton::compute(inner, tcx, typing_env)? { // This may succeed because the multiplication of two types may overflow // but a single size of a nested array will not. SizeSkeleton::Known(s, a) => { @@ -432,7 +432,7 @@ impl<'tcx> SizeSkeleton<'tcx> { let i = VariantIdx::from_usize(i); let fields = def.variant(i).fields.iter().map(|field| { - SizeSkeleton::compute(field.ty(tcx, args), tcx, param_env) + SizeSkeleton::compute(field.ty(tcx, args), tcx, typing_env) }); let mut ptr = None; for field in fields { @@ -491,11 +491,11 @@ impl<'tcx> SizeSkeleton<'tcx> { } ty::Alias(..) => { - let normalized = tcx.normalize_erasing_regions(param_env, ty); + let normalized = tcx.normalize_erasing_regions(typing_env, ty); if ty == normalized { Err(err) } else { - SizeSkeleton::compute(normalized, tcx, param_env) + SizeSkeleton::compute(normalized, tcx, typing_env) } } @@ -521,8 +521,14 @@ pub trait HasTyCtxt<'tcx>: HasDataLayout { fn tcx(&self) -> TyCtxt<'tcx>; } -pub trait HasParamEnv<'tcx> { - fn param_env(&self) -> ty::ParamEnv<'tcx>; +pub trait HasTypingEnv<'tcx> { + fn typing_env(&self) -> ty::TypingEnv<'tcx>; + + /// FIXME(#132279): This method should not be used as in the future + /// everything should take a `TypingEnv` instead. Remove it as that point. + fn param_env(&self) -> ty::ParamEnv<'tcx> { + self.typing_env().param_env + } } impl<'tcx> HasDataLayout for TyCtxt<'tcx> { @@ -577,9 +583,9 @@ impl<'tcx> HasTyCtxt<'tcx> for TyCtxtAt<'tcx> { } } -impl<'tcx> HasParamEnv<'tcx> for LayoutCx<'tcx> { - fn param_env(&self) -> ty::ParamEnv<'tcx> { - self.param_env +impl<'tcx> HasTypingEnv<'tcx> for LayoutCx<'tcx> { + fn typing_env(&self) -> ty::TypingEnv<'tcx> { + self.typing_env } } @@ -646,7 +652,7 @@ pub type TyAndLayout<'tcx> = rustc_abi::TyAndLayout<'tcx, Ty<'tcx>>; /// Trait for contexts that want to be able to compute layouts of types. /// This automatically gives access to `LayoutOf`, through a blanket `impl`. -pub trait LayoutOfHelpers<'tcx>: HasDataLayout + HasTyCtxt<'tcx> + HasParamEnv<'tcx> { +pub trait LayoutOfHelpers<'tcx>: HasDataLayout + HasTyCtxt<'tcx> + HasTypingEnv<'tcx> { /// The `TyAndLayout`-wrapping type (or `TyAndLayout` itself), which will be /// returned from `layout_of` (see also `handle_layout_err`). type LayoutOfResult: MaybeResult> = TyAndLayout<'tcx>; @@ -692,7 +698,7 @@ pub trait LayoutOf<'tcx>: LayoutOfHelpers<'tcx> { let tcx = self.tcx().at(span); MaybeResult::from( - tcx.layout_of(self.param_env().and(ty)) + tcx.layout_of(self.typing_env().as_query_input(ty)) .map_err(|err| self.handle_layout_err(*err, span, ty)), ) } @@ -716,7 +722,7 @@ impl<'tcx> LayoutOfHelpers<'tcx> for LayoutCx<'tcx> { impl<'tcx, C> TyAbiInterface<'tcx, C> for Ty<'tcx> where - C: HasTyCtxt<'tcx> + HasParamEnv<'tcx>, + C: HasTyCtxt<'tcx> + HasTypingEnv<'tcx>, { fn ty_and_layout_for_variant( this: TyAndLayout<'tcx>, @@ -736,10 +742,10 @@ where Variants::Single { index } => { let tcx = cx.tcx(); - let param_env = cx.param_env(); + let typing_env = cx.typing_env(); // Deny calling for_variant more than once for non-Single enums. - if let Ok(original_layout) = tcx.layout_of(param_env.and(this.ty)) { + if let Ok(original_layout) = tcx.layout_of(typing_env.as_query_input(this.ty)) { assert_eq!(original_layout.variants, Variants::Single { index }); } @@ -780,7 +786,7 @@ where fn field_ty_or_layout<'tcx>( this: TyAndLayout<'tcx>, - cx: &(impl HasTyCtxt<'tcx> + HasParamEnv<'tcx>), + cx: &(impl HasTyCtxt<'tcx> + HasTypingEnv<'tcx>), i: usize, ) -> TyMaybeWithLayout<'tcx> { let tcx = cx.tcx(); @@ -823,12 +829,13 @@ where Ty::new_mut_ref(tcx, tcx.lifetimes.re_static, nil) }; - // NOTE(eddyb) using an empty `ParamEnv`, and `unwrap`-ing - // the `Result` should always work because the type is - // always either `*mut ()` or `&'static mut ()`. + // NOTE: using an fully monomorphized typing env and `unwrap`-ing + // the `Result` should always work because the type is always either + // `*mut ()` or `&'static mut ()`. + let typing_env = ty::TypingEnv::fully_monomorphized(); return TyMaybeWithLayout::TyAndLayout(TyAndLayout { ty: this.ty, - ..tcx.layout_of(ty::ParamEnv::reveal_all().and(unit_ptr_ty)).unwrap() + ..tcx.layout_of(typing_env.as_query_input(unit_ptr_ty)).unwrap() }); } @@ -848,7 +855,7 @@ where && !pointee.references_error() { let metadata = tcx.normalize_erasing_regions( - cx.param_env(), + cx.typing_env(), Ty::new_projection(tcx, metadata_def_id, [pointee]), ); @@ -865,7 +872,7 @@ where metadata } } else { - match tcx.struct_tail_for_codegen(pointee, cx.param_env()).kind() { + match tcx.struct_tail_for_codegen(pointee, cx.typing_env()).kind() { ty::Slice(_) | ty::Str => tcx.types.usize, ty::Dynamic(data, _, ty::Dyn) => mk_dyn_vtable(data.principal()), _ => bug!("TyAndLayout::field({:?}): not applicable", this), @@ -953,7 +960,7 @@ where match field_ty_or_layout(this, cx, i) { TyMaybeWithLayout::Ty(field_ty) => { - cx.tcx().layout_of(cx.param_env().and(field_ty)).unwrap_or_else(|e| { + cx.tcx().layout_of(cx.typing_env().as_query_input(field_ty)).unwrap_or_else(|e| { bug!( "failed to get layout for `{field_ty}`: {e:?},\n\ despite it being a field (#{i}) of an existing layout: {this:#?}", @@ -972,18 +979,18 @@ where offset: Size, ) -> Option { let tcx = cx.tcx(); - let param_env = cx.param_env(); + let typing_env = cx.typing_env(); let pointee_info = match *this.ty.kind() { ty::RawPtr(p_ty, _) if offset.bytes() == 0 => { - tcx.layout_of(param_env.and(p_ty)).ok().map(|layout| PointeeInfo { + tcx.layout_of(typing_env.as_query_input(p_ty)).ok().map(|layout| PointeeInfo { size: layout.size, align: layout.align.abi, safe: None, }) } ty::FnPtr(..) if offset.bytes() == 0 => { - tcx.layout_of(param_env.and(this.ty)).ok().map(|layout| PointeeInfo { + tcx.layout_of(typing_env.as_query_input(this.ty)).ok().map(|layout| PointeeInfo { size: layout.size, align: layout.align.abi, safe: None, @@ -996,14 +1003,14 @@ where let optimize = tcx.sess.opts.optimize != OptLevel::No; let kind = match mt { hir::Mutability::Not => PointerKind::SharedRef { - frozen: optimize && ty.is_freeze(tcx, cx.param_env()), + frozen: optimize && ty.is_freeze(tcx, typing_env.param_env), }, hir::Mutability::Mut => PointerKind::MutableRef { - unpin: optimize && ty.is_unpin(tcx, cx.param_env()), + unpin: optimize && ty.is_unpin(tcx, typing_env.param_env), }, }; - tcx.layout_of(param_env.and(ty)).ok().map(|layout| PointeeInfo { + tcx.layout_of(typing_env.as_query_input(ty)).ok().map(|layout| PointeeInfo { size: layout.size, align: layout.align.abi, safe: Some(kind), @@ -1093,7 +1100,7 @@ where debug_assert!(pointee.safe.is_none()); let optimize = tcx.sess.opts.optimize != OptLevel::No; pointee.safe = Some(PointerKind::Box { - unpin: optimize && boxed_ty.is_unpin(tcx, cx.param_env()), + unpin: optimize && boxed_ty.is_unpin(tcx, typing_env.param_env), global: this.ty.is_box_global(tcx), }); } @@ -1304,9 +1311,11 @@ pub trait FnAbiOf<'tcx>: FnAbiOfHelpers<'tcx> { let span = self.layout_tcx_at_span(); let tcx = self.tcx().at(span); - MaybeResult::from(tcx.fn_abi_of_fn_ptr(self.param_env().and((sig, extra_args))).map_err( - |err| self.handle_fn_abi_err(*err, span, FnAbiRequest::OfFnPtr { sig, extra_args }), - )) + MaybeResult::from( + tcx.fn_abi_of_fn_ptr(self.typing_env().as_query_input((sig, extra_args))).map_err( + |err| self.handle_fn_abi_err(*err, span, FnAbiRequest::OfFnPtr { sig, extra_args }), + ), + ) } /// Compute a `FnAbi` suitable for declaring/defining an `fn` instance, and for @@ -1326,17 +1335,19 @@ pub trait FnAbiOf<'tcx>: FnAbiOfHelpers<'tcx> { let tcx = self.tcx().at(span); MaybeResult::from( - tcx.fn_abi_of_instance(self.param_env().and((instance, extra_args))).map_err(|err| { - // HACK(eddyb) at least for definitions of/calls to `Instance`s, - // we can get some kind of span even if one wasn't provided. - // However, we don't do this early in order to avoid calling - // `def_span` unconditionally (which may have a perf penalty). - let span = if !span.is_dummy() { span } else { tcx.def_span(instance.def_id()) }; - self.handle_fn_abi_err(*err, span, FnAbiRequest::OfInstance { - instance, - extra_args, - }) - }), + tcx.fn_abi_of_instance(self.typing_env().as_query_input((instance, extra_args))) + .map_err(|err| { + // HACK(eddyb) at least for definitions of/calls to `Instance`s, + // we can get some kind of span even if one wasn't provided. + // However, we don't do this early in order to avoid calling + // `def_span` unconditionally (which may have a perf penalty). + let span = + if !span.is_dummy() { span } else { tcx.def_span(instance.def_id()) }; + self.handle_fn_abi_err(*err, span, FnAbiRequest::OfInstance { + instance, + extra_args, + }) + }), ) } } @@ -1346,14 +1357,14 @@ impl<'tcx, C: FnAbiOfHelpers<'tcx>> FnAbiOf<'tcx> for C {} impl<'tcx> TyCtxt<'tcx> { pub fn offset_of_subfield( self, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, mut layout: TyAndLayout<'tcx>, indices: I, ) -> Size where I: Iterator, { - let cx = LayoutCx::new(self, param_env); + let cx = LayoutCx::new(self, typing_env); let mut offset = Size::ZERO; for (variant, field) in indices { @@ -1363,7 +1374,7 @@ impl<'tcx> TyCtxt<'tcx> { layout = layout.field(&cx, index); if !layout.is_sized() { // If it is not sized, then the tail must still have at least a known static alignment. - let tail = self.struct_tail_for_codegen(layout.ty, param_env); + let tail = self.struct_tail_for_codegen(layout.ty, typing_env); if !matches!(tail.kind(), ty::Slice(..)) { bug!( "offset of not-statically-aligned field (type {:?}) cannot be computed statically", diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 7fda0662a34e..cddd6110c23c 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -103,7 +103,7 @@ use crate::error::{OpaqueHiddenTypeMismatch, TypeMismatchReason}; use crate::metadata::ModChild; use crate::middle::privacy::EffectiveVisibilities; use crate::mir::{Body, CoroutineLayout}; -use crate::query::Providers; +use crate::query::{IntoQueryParam, Providers}; use crate::traits::{self, Reveal}; use crate::ty; pub use crate::ty::diagnostics::*; @@ -1122,6 +1122,105 @@ impl<'tcx, T> ParamEnvAnd<'tcx, T> { } } +/// The environment in which to do trait solving. +/// +/// Most of the time you only need to care about the `ParamEnv` +/// as the `TypingMode` is simply stored in the `InferCtxt`. +/// +/// However, there are some places which rely on trait solving +/// without using an `InferCtxt` themselves. For these to be +/// able to use the trait system they have to be able to initialize +/// such an `InferCtxt` with the right `typing_mode`, so they need +/// to track both. +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)] +#[derive(TypeVisitable, TypeFoldable)] +pub struct TypingEnv<'tcx> { + pub typing_mode: TypingMode<'tcx>, + pub param_env: ParamEnv<'tcx>, +} + +impl<'tcx> TypingEnv<'tcx> { + // FIXME(#132279): This method should be removed but simplifies the + // transition. + pub fn from_param_env(param_env: ParamEnv<'tcx>) -> TypingEnv<'tcx> { + TypingEnv { typing_mode: TypingMode::from_param_env(param_env), param_env } + } + + /// Create a typing environment with no where-clauses in scope + /// where all opaque types and default associated items are revealed. + /// + /// This is only suitable for monomorphized, post-typeck environments. + /// Do not use this for MIR optimizations, as even though they also + /// use `TypingMode::PostAnalysis`, they may still have where-clauses + /// in scope. + pub fn fully_monomorphized() -> TypingEnv<'tcx> { + TypingEnv { typing_mode: TypingMode::PostAnalysis, param_env: ParamEnv::reveal_all() } + } + + /// Create a typing environment for use during analysis outside of a body. + /// + /// Using a typing environment inside of bodies is not supported as the body + /// may define opaque types. In this case the used functions have to be + /// converted to use proper canonical inputs instead. + pub fn non_body_analysis( + tcx: TyCtxt<'tcx>, + def_id: impl IntoQueryParam, + ) -> TypingEnv<'tcx> { + TypingEnv { typing_mode: TypingMode::non_body_analysis(), param_env: tcx.param_env(def_id) } + } + + pub fn post_analysis(tcx: TyCtxt<'tcx>, def_id: impl IntoQueryParam) -> TypingEnv<'tcx> { + TypingEnv { + typing_mode: TypingMode::PostAnalysis, + param_env: tcx.param_env_reveal_all_normalized(def_id), + } + } + + /// Modify the `typing_mode` to `PostAnalysis` and eagerly reveal all + /// opaque types in the `param_env`. + pub fn with_reveal_all_normalized(self, tcx: TyCtxt<'tcx>) -> TypingEnv<'tcx> { + let TypingEnv { typing_mode: _, param_env } = self; + let param_env = param_env.with_reveal_all_normalized(tcx); + TypingEnv { typing_mode: TypingMode::PostAnalysis, param_env } + } + + /// Combine this typing environment with the given `value` to be used by + /// not (yet) canonicalized queries. This only works if the value does not + /// contain anything local to some `InferCtxt`, i.e. inference variables or + /// placeholders. + pub fn as_query_input(self, value: T) -> PseudoCanonicalInput<'tcx, T> + where + T: TypeVisitable>, + { + debug_assert!(!value.has_infer()); + // FIXME(#132279): We should assert that the value does not contain any placeholders + // as these placeholders are also local to the current inference context. However, we + // currently use pseudo-canonical queries in the trait solver which replaces params with + // placeholders. We should also simply not use pseudo-canonical queries in the trait + // solver, at which point we can readd this assert. As of writing this comment, this is + // only used by `fn layout_is_pointer_like` when calling `layout_of`. + // + // debug_assert!(!value.has_placeholders()); + PseudoCanonicalInput { typing_env: self, value } + } +} + +/// Similar to `CanonicalInput`, this carries the `typing_mode` and the environment +/// necessary to do any kind of trait solving inside of nested queries. +/// +/// Unlike proper canonicalization, this requires the `param_env` and the `value` to not +/// contain anything local to the `infcx` of the caller, so we don't actually canonicalize +/// anything. +/// +/// This should be created by using `infcx.pseudo_canonicalize_query(param_env, value)` +/// or by using `typing_env.as_query_input(value)`. +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +#[derive(HashStable)] +pub struct PseudoCanonicalInput<'tcx, T> { + pub typing_env: TypingEnv<'tcx>, + pub value: T, +} + #[derive(Copy, Clone, Debug, HashStable, Encodable, Decodable)] pub struct Destructor { /// The `DefId` of the destructor method diff --git a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs index e51d22019227..f611b69905c9 100644 --- a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs +++ b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs @@ -35,16 +35,16 @@ impl<'tcx> TyCtxt<'tcx> { /// /// This should only be used outside of type inference. For example, /// it assumes that normalization will succeed. - #[tracing::instrument(level = "debug", skip(self, param_env), ret)] - pub fn normalize_erasing_regions(self, param_env: ty::ParamEnv<'tcx>, value: T) -> T + #[tracing::instrument(level = "debug", skip(self, typing_env), ret)] + pub fn normalize_erasing_regions(self, typing_env: ty::TypingEnv<'tcx>, value: T) -> T where T: TypeFoldable>, { debug!( - "normalize_erasing_regions::<{}>(value={:?}, param_env={:?})", + "normalize_erasing_regions::<{}>(value={:?}, typing_env={:?})", std::any::type_name::(), value, - param_env, + typing_env, ); // Erase first before we do the real query -- this keeps the @@ -55,7 +55,7 @@ impl<'tcx> TyCtxt<'tcx> { if !value.has_aliases() { value } else { - value.fold_with(&mut NormalizeAfterErasingRegionsFolder { tcx: self, param_env }) + value.fold_with(&mut NormalizeAfterErasingRegionsFolder { tcx: self, typing_env }) } } @@ -66,17 +66,17 @@ impl<'tcx> TyCtxt<'tcx> { /// succeeds. pub fn try_normalize_erasing_regions( self, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, value: T, ) -> Result> where T: TypeFoldable>, { debug!( - "try_normalize_erasing_regions::<{}>(value={:?}, param_env={:?})", + "try_normalize_erasing_regions::<{}>(value={:?}, typing_env={:?})", std::any::type_name::(), value, - param_env, + typing_env, ); // Erase first before we do the real query -- this keeps the @@ -87,7 +87,7 @@ impl<'tcx> TyCtxt<'tcx> { if !value.has_aliases() { Ok(value) } else { - let mut folder = TryNormalizeAfterErasingRegionsFolder::new(self, param_env); + let mut folder = TryNormalizeAfterErasingRegionsFolder::new(self, typing_env); value.try_fold_with(&mut folder) } } @@ -103,17 +103,17 @@ impl<'tcx> TyCtxt<'tcx> { // FIXME(@lcnr): This method should not be necessary, we now normalize // inside of binders. We should be able to only use // `tcx.instantiate_bound_regions_with_erased`. - #[tracing::instrument(level = "debug", skip(self, param_env))] + #[tracing::instrument(level = "debug", skip(self, typing_env))] pub fn normalize_erasing_late_bound_regions( self, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, value: ty::Binder<'tcx, T>, ) -> T where T: TypeFoldable>, { let value = self.instantiate_bound_regions_with_erased(value); - self.normalize_erasing_regions(param_env, value) + self.normalize_erasing_regions(typing_env, value) } /// Monomorphizes a type from the AST by first applying the @@ -125,14 +125,14 @@ impl<'tcx> TyCtxt<'tcx> { pub fn instantiate_and_normalize_erasing_regions( self, param_args: GenericArgsRef<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, value: EarlyBinder<'tcx, T>, ) -> T where T: TypeFoldable>, { let instantiated = value.instantiate(self, param_args); - self.normalize_erasing_regions(param_env, instantiated) + self.normalize_erasing_regions(typing_env, instantiated) } /// Monomorphizes a type from the AST by first applying the @@ -143,20 +143,20 @@ impl<'tcx> TyCtxt<'tcx> { pub fn try_instantiate_and_normalize_erasing_regions( self, param_args: GenericArgsRef<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, value: EarlyBinder<'tcx, T>, ) -> Result> where T: TypeFoldable>, { let instantiated = value.instantiate(self, param_args); - self.try_normalize_erasing_regions(param_env, instantiated) + self.try_normalize_erasing_regions(typing_env, instantiated) } } struct NormalizeAfterErasingRegionsFolder<'tcx> { tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, } impl<'tcx> NormalizeAfterErasingRegionsFolder<'tcx> { @@ -164,8 +164,7 @@ impl<'tcx> NormalizeAfterErasingRegionsFolder<'tcx> { &self, arg: ty::GenericArg<'tcx>, ) -> ty::GenericArg<'tcx> { - let arg = self.param_env.and(arg); - + let arg = self.typing_env.as_query_input(arg); self.tcx.try_normalize_generic_arg_after_erasing_regions(arg).unwrap_or_else(|_| bug!( "Failed to normalize {:?}, maybe try to call `try_normalize_erasing_regions` instead", arg.value @@ -189,12 +188,12 @@ impl<'tcx> TypeFolder> for NormalizeAfterErasingRegionsFolder<'tcx> struct TryNormalizeAfterErasingRegionsFolder<'tcx> { tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, } impl<'tcx> TryNormalizeAfterErasingRegionsFolder<'tcx> { - fn new(tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Self { - TryNormalizeAfterErasingRegionsFolder { tcx, param_env } + fn new(tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> Self { + TryNormalizeAfterErasingRegionsFolder { tcx, typing_env } } #[instrument(skip(self), level = "debug")] @@ -202,10 +201,8 @@ impl<'tcx> TryNormalizeAfterErasingRegionsFolder<'tcx> { &self, arg: ty::GenericArg<'tcx>, ) -> Result, NoSolution> { - let arg = self.param_env.and(arg); - debug!(?arg); - - self.tcx.try_normalize_generic_arg_after_erasing_regions(arg) + let input = self.typing_env.as_query_input(arg); + self.tcx.try_normalize_generic_arg_after_erasing_regions(input) } } diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 3c6e34160f44..703a7826b7a8 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -18,6 +18,7 @@ use rustc_span::sym; use smallvec::{SmallVec, smallvec}; use tracing::{debug, instrument}; +use super::TypingEnv; use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; use crate::query::Providers; use crate::ty::layout::{FloatExt, IntegerExt}; @@ -177,9 +178,13 @@ impl<'tcx> TyCtxt<'tcx> { /// Should only be called if `ty` has no inference variables and does not /// need its lifetimes preserved (e.g. as part of codegen); otherwise /// normalization attempt may cause compiler bugs. - pub fn struct_tail_for_codegen(self, ty: Ty<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Ty<'tcx> { + pub fn struct_tail_for_codegen( + self, + ty: Ty<'tcx>, + typing_env: ty::TypingEnv<'tcx>, + ) -> Ty<'tcx> { let tcx = self; - tcx.struct_tail_raw(ty, |ty| tcx.normalize_erasing_regions(param_env, ty), || {}) + tcx.struct_tail_raw(ty, |ty| tcx.normalize_erasing_regions(typing_env, ty), || {}) } /// Returns the deeply last field of nested structures, or the same type if @@ -271,11 +276,11 @@ impl<'tcx> TyCtxt<'tcx> { self, source: Ty<'tcx>, target: Ty<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ) -> (Ty<'tcx>, Ty<'tcx>) { let tcx = self; tcx.struct_lockstep_tails_raw(source, target, |ty| { - tcx.normalize_erasing_regions(param_env, ty) + tcx.normalize_erasing_regions(typing_env, ty) }) } @@ -420,10 +425,10 @@ impl<'tcx> TyCtxt<'tcx> { // Async drop glue morphology is an internal detail, so reveal_all probably // should be fine - let param_env = ty::ParamEnv::reveal_all(); - if ty.needs_async_drop(self, param_env) { + let typing_env = ty::TypingEnv::fully_monomorphized(); + if ty.needs_async_drop(self, typing_env) { AsyncDropGlueMorphology::Custom - } else if ty.needs_drop(self, param_env) { + } else if ty.needs_drop(self, typing_env) { AsyncDropGlueMorphology::DeferredDropInPlace } else { AsyncDropGlueMorphology::Noop @@ -683,12 +688,10 @@ impl<'tcx> TyCtxt<'tcx> { } /// Get the type of the pointer to the static that we use in MIR. - pub fn static_ptr_ty(self, def_id: DefId) -> Ty<'tcx> { + pub fn static_ptr_ty(self, def_id: DefId, typing_env: ty::TypingEnv<'tcx>) -> Ty<'tcx> { // Make sure that any constants in the static's type are evaluated. - let static_ty = self.normalize_erasing_regions( - ty::ParamEnv::empty(), - self.type_of(def_id).instantiate_identity(), - ); + let static_ty = + self.normalize_erasing_regions(typing_env, self.type_of(def_id).instantiate_identity()); // Make sure that accesses to unsafe statics end up using raw pointers. // For thread-locals, this needs to be kept in sync with `Rvalue::ty`. @@ -1157,15 +1160,17 @@ impl<'tcx> Ty<'tcx> { /// Returns the maximum value for the given numeric type (including `char`s) /// or returns `None` if the type is not numeric. pub fn numeric_max_val(self, tcx: TyCtxt<'tcx>) -> Option> { + let typing_env = TypingEnv::fully_monomorphized(); self.numeric_min_and_max_as_bits(tcx) - .map(|(_, max)| ty::Const::from_bits(tcx, max, ty::ParamEnv::empty().and(self))) + .map(|(_, max)| ty::Const::from_bits(tcx, max, typing_env, self)) } /// Returns the minimum value for the given numeric type (including `char`s) /// or returns `None` if the type is not numeric. pub fn numeric_min_val(self, tcx: TyCtxt<'tcx>) -> Option> { + let typing_env = TypingEnv::fully_monomorphized(); self.numeric_min_and_max_as_bits(tcx) - .map(|(min, _)| ty::Const::from_bits(tcx, min, ty::ParamEnv::empty().and(self))) + .map(|(min, _)| ty::Const::from_bits(tcx, min, typing_env, self)) } /// Checks whether values of this type `T` are *moved* or *copied* @@ -1345,7 +1350,7 @@ impl<'tcx> Ty<'tcx> { /// /// Note that this method is used to check eligible types in unions. #[inline] - pub fn needs_drop(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { + pub fn needs_drop(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> bool { // Avoid querying in simple cases. match needs_drop_components(tcx, self) { Err(AlwaysRequiresDrop) => true, @@ -1359,14 +1364,13 @@ impl<'tcx> Ty<'tcx> { }; // This doesn't depend on regions, so try to minimize distinct - // query keys used. - // If normalization fails, we just use `query_ty`. - debug_assert!(!param_env.has_infer()); + // query keys used. If normalization fails, we just use `query_ty`. + debug_assert!(!typing_env.param_env.has_infer()); let query_ty = tcx - .try_normalize_erasing_regions(param_env, query_ty) + .try_normalize_erasing_regions(typing_env, query_ty) .unwrap_or_else(|_| tcx.erase_regions(query_ty)); - tcx.needs_drop_raw(param_env.and(query_ty)) + tcx.needs_drop_raw(typing_env.as_query_input(query_ty)) } } } @@ -1385,7 +1389,7 @@ impl<'tcx> Ty<'tcx> { // FIXME(zetanumbers): Note that this method is used to check eligible types // in unions. #[inline] - pub fn needs_async_drop(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { + pub fn needs_async_drop(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> bool { // Avoid querying in simple cases. match needs_drop_components(tcx, self) { Err(AlwaysRequiresDrop) => true, @@ -1401,12 +1405,12 @@ impl<'tcx> Ty<'tcx> { // This doesn't depend on regions, so try to minimize distinct // query keys used. // If normalization fails, we just use `query_ty`. - debug_assert!(!param_env.has_infer()); + debug_assert!(!typing_env.has_infer()); let query_ty = tcx - .try_normalize_erasing_regions(param_env, query_ty) + .try_normalize_erasing_regions(typing_env, query_ty) .unwrap_or_else(|_| tcx.erase_regions(query_ty)); - tcx.needs_async_drop_raw(param_env.and(query_ty)) + tcx.needs_async_drop_raw(typing_env.as_query_input(query_ty)) } } } @@ -1420,7 +1424,7 @@ impl<'tcx> Ty<'tcx> { /// Note that this method is used to check for change in drop order for /// 2229 drop reorder migration analysis. #[inline] - pub fn has_significant_drop(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { + pub fn has_significant_drop(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> bool { // Avoid querying in simple cases. match needs_drop_components(tcx, self) { Err(AlwaysRequiresDrop) => true, @@ -1443,8 +1447,8 @@ impl<'tcx> Ty<'tcx> { // This doesn't depend on regions, so try to minimize distinct // query keys used. - let erased = tcx.normalize_erasing_regions(param_env, query_ty); - tcx.has_significant_drop_raw(param_env.and(erased)) + let erased = tcx.normalize_erasing_regions(typing_env, query_ty); + tcx.has_significant_drop_raw(typing_env.as_query_input(erased)) } } } @@ -1793,7 +1797,7 @@ pub fn intrinsic_raw(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option( assert!(vtable_entries.len() >= vtable_min_entries(tcx, poly_trait_ref)); let layout = tcx - .layout_of(ty::ParamEnv::reveal_all().and(ty)) + .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)) .expect("failed to build vtable representation"); assert!(layout.is_sized(), "can't create a vtable for an unsized type"); let size = layout.size.bytes(); @@ -117,7 +117,7 @@ pub(super) fn vtable_allocation_provider<'tcx>( let idx: u64 = u64::try_from(idx).unwrap(); let scalar = match entry { VtblEntry::MetadataDropInPlace => { - if ty.needs_drop(tcx, ty::ParamEnv::reveal_all()) { + if ty.needs_drop(tcx, ty::TypingEnv::fully_monomorphized()) { let instance = ty::Instance::resolve_drop_in_place(tcx, ty); let fn_alloc_id = tcx.reserve_and_set_fn_alloc(instance, CTFE_ALLOC_SALT); let fn_ptr = Pointer::from(fn_alloc_id); diff --git a/compiler/rustc_middle/src/util/call_kind.rs b/compiler/rustc_middle/src/util/call_kind.rs index ed27a880562d..acfb78b3f6ef 100644 --- a/compiler/rustc_middle/src/util/call_kind.rs +++ b/compiler/rustc_middle/src/util/call_kind.rs @@ -8,7 +8,7 @@ use rustc_span::symbol::Ident; use rustc_span::{DesugaringKind, Span, sym}; use tracing::debug; -use crate::ty::{AssocItemContainer, GenericArgsRef, Instance, ParamEnv, Ty, TyCtxt}; +use crate::ty::{AssocItemContainer, GenericArgsRef, Instance, Ty, TyCtxt, TypingEnv}; #[derive(Clone, Copy, PartialEq, Eq, Debug)] pub enum CallDesugaringKind { @@ -62,7 +62,7 @@ pub enum CallKind<'tcx> { pub fn call_kind<'tcx>( tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: TypingEnv<'tcx>, method_did: DefId, method_args: GenericArgsRef<'tcx>, fn_call_span: Span, @@ -98,10 +98,10 @@ pub fn call_kind<'tcx>( Some(CallKind::Operator { self_arg, trait_id, self_ty: method_args.type_at(0) }) } else if is_deref { let deref_target = tcx.get_diagnostic_item(sym::deref_target).and_then(|deref_target| { - Instance::try_resolve(tcx, param_env, deref_target, method_args).transpose() + Instance::try_resolve(tcx, typing_env, deref_target, method_args).transpose() }); if let Some(Ok(instance)) = deref_target { - let deref_target_ty = instance.ty(tcx, param_env); + let deref_target_ty = instance.ty(tcx, typing_env); Some(CallKind::DerefCoercion { deref_target: tcx.def_span(instance.def_id()), deref_target_ty, diff --git a/compiler/rustc_mir_build/src/build/custom/mod.rs b/compiler/rustc_mir_build/src/build/custom/mod.rs index 4815db47b16c..e809c9a23f30 100644 --- a/compiler/rustc_mir_build/src/build/custom/mod.rs +++ b/compiler/rustc_mir_build/src/build/custom/mod.rs @@ -25,7 +25,7 @@ use rustc_index::{IndexSlice, IndexVec}; use rustc_middle::mir::*; use rustc_middle::span_bug; use rustc_middle::thir::*; -use rustc_middle::ty::{ParamEnv, Ty, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::Span; mod parse; @@ -77,7 +77,7 @@ pub(super) fn build_custom_mir<'tcx>( let mut pctxt = ParseCtxt { tcx, - param_env: tcx.param_env(did), + typing_env: body.typing_env(tcx), thir, source_scope: OUTERMOST_SOURCE_SCOPE, body: &mut body, @@ -136,7 +136,7 @@ fn parse_attribute(attr: &Attribute) -> MirPhase { struct ParseCtxt<'a, 'tcx> { tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, thir: &'a Thir<'tcx>, source_scope: SourceScope, body: &'a mut Body<'tcx>, diff --git a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs index 62d173987fce..c3e9bd302deb 100644 --- a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs +++ b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs @@ -159,7 +159,7 @@ impl<'a, 'tcx> ParseCtxt<'a, 'tcx> { }); } }; - values.push(value.eval_bits(self.tcx, self.param_env)); + values.push(value.eval_bits(self.tcx, self.typing_env)); targets.push(self.parse_block(arm.body)?); } @@ -393,7 +393,7 @@ impl<'a, 'tcx> ParseCtxt<'a, 'tcx> { | ExprKind::NonHirLiteral { .. } | ExprKind::ConstBlock { .. } => Ok({ let value = as_constant_inner(expr, |_| None, self.tcx); - value.const_.eval_bits(self.tcx, self.param_env) + value.const_.eval_bits(self.tcx, self.typing_env) }), ) } diff --git a/compiler/rustc_mir_build/src/build/expr/as_constant.rs b/compiler/rustc_mir_build/src/build/expr/as_constant.rs index 3f2e3b956fc6..640408cb9c80 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs @@ -114,8 +114,7 @@ fn lit_to_mir_constant<'tcx>( ) -> Result, LitToConstError> { let LitToConstInput { lit, ty, neg } = lit_input; let trunc = |n| { - let param_ty = ty::ParamEnv::reveal_all().and(ty); - let width = match tcx.layout_of(param_ty) { + let width = match tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)) { Ok(layout) => layout.size, Err(_) => { tcx.dcx().bug(format!("couldn't compute width of literal: {:?}", lit_input.lit)) diff --git a/compiler/rustc_mir_build/src/build/expr/as_operand.rs b/compiler/rustc_mir_build/src/build/expr/as_operand.rs index 112eac32264f..aad7d54833bf 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_operand.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_operand.rs @@ -123,7 +123,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { match category { Category::Constant if matches!(needs_temporary, NeedsTemporary::No) - || !expr.ty.needs_drop(this.tcx, this.param_env) => + || !expr.ty.needs_drop(this.tcx, this.typing_env()) => { let constant = this.as_constant(expr); block.and(Operand::Constant(Box::new(constant))) diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs index 1985dd3fca0f..a3fee38908b4 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs @@ -197,7 +197,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { { let discr_ty = adt_def.repr().discr_type().to_ty(this.tcx); let temp = unpack!(block = this.as_temp(block, scope, source, Mutability::Not)); - let layout = this.tcx.layout_of(this.param_env.and(source_expr.ty)); + let layout = + this.tcx.layout_of(this.typing_env().as_query_input(source_expr.ty)); let discr = this.temp(discr_ty, source_expr.span); this.cfg.push_assign( block, @@ -226,10 +227,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { if range.start <= range.end { BinOp::BitAnd } else { BinOp::BitOr }; let mut comparer = |range: u128, bin_op: BinOp| -> Place<'tcx> { + // We can use `ty::TypingEnv::fully_monomorphized()`` here + // as we only need it to compute the layout of a primitive. let range_val = Const::from_bits( this.tcx, range, - ty::ParamEnv::empty().and(unsigned_ty), + ty::TypingEnv::fully_monomorphized(), + unsigned_ty, ); let lit_op = this.literal_operand(expr.span, range_val); let is_bin_op = this.temp(bool_ty, expr_span); @@ -812,9 +816,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Helper to get a `-1` value of the appropriate type fn neg_1_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> { - let param_ty = ty::ParamEnv::empty().and(ty); - let size = self.tcx.layout_of(param_ty).unwrap().size; - let literal = Const::from_bits(self.tcx, size.unsigned_int_max(), param_ty); + let typing_env = ty::TypingEnv::fully_monomorphized(); + let size = self.tcx.layout_of(typing_env.as_query_input(ty)).unwrap().size; + let literal = Const::from_bits(self.tcx, size.unsigned_int_max(), typing_env, ty); self.literal_operand(span, literal) } @@ -822,10 +826,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Helper to get the minimum value of the appropriate type fn minval_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> { assert!(ty.is_signed()); - let param_ty = ty::ParamEnv::empty().and(ty); - let bits = self.tcx.layout_of(param_ty).unwrap().size.bits(); + let typing_env = ty::TypingEnv::fully_monomorphized(); + let bits = self.tcx.layout_of(typing_env.as_query_input(ty)).unwrap().size.bits(); let n = 1 << (bits - 1); - let literal = Const::from_bits(self.tcx, n, param_ty); + let literal = Const::from_bits(self.tcx, n, typing_env, ty); self.literal_operand(span, literal) } diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index dc317feb20c4..0dec56d21ae1 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -266,7 +266,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // that makes the call. target: expr .ty - .is_inhabited_from(this.tcx, this.parent_module, this.param_env) + .is_inhabited_from( + this.tcx, + this.parent_module, + this.infcx.typing_env(this.param_env), + ) .then_some(success), call_source: if from_hir_call { CallSource::Normal diff --git a/compiler/rustc_mir_build/src/build/expr/stmt.rs b/compiler/rustc_mir_build/src/build/expr/stmt.rs index 76034c03b4bf..02ca12028d30 100644 --- a/compiler/rustc_mir_build/src/build/expr/stmt.rs +++ b/compiler/rustc_mir_build/src/build/expr/stmt.rs @@ -42,7 +42,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Generate better code for things that don't need to be // dropped. - if lhs_expr.ty.needs_drop(this.tcx, this.param_env) { + if lhs_expr.ty.needs_drop(this.tcx, this.typing_env()) { let rhs = unpack!(block = this.as_local_rvalue(block, rhs)); let lhs = unpack!(block = this.as_place(block, lhs)); block = diff --git a/compiler/rustc_mir_build/src/build/matches/match_pair.rs b/compiler/rustc_mir_build/src/build/matches/match_pair.rs index 6beabb5ccdb3..2815b3903751 100644 --- a/compiler/rustc_mir_build/src/build/matches/match_pair.rs +++ b/compiler/rustc_mir_build/src/build/matches/match_pair.rs @@ -218,7 +218,7 @@ impl<'pat, 'tcx> MatchPairTree<'pat, 'tcx> { || !v .inhabited_predicate(cx.tcx, adt_def) .instantiate(cx.tcx, args) - .apply_ignore_module(cx.tcx, cx.param_env) + .apply_ignore_module(cx.tcx, cx.infcx.typing_env(cx.param_env)) }) && (adt_def.did().is_local() || !adt_def.is_variant_list_non_exhaustive()); if irrefutable { diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs index 37cedd8cf5cd..4f7bbc4ce3e6 100644 --- a/compiler/rustc_mir_build/src/build/matches/test.rs +++ b/compiler/rustc_mir_build/src/build/matches/test.rs @@ -567,7 +567,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // not to add such values here. let is_covering_range = |test_case: &TestCase<'_, 'tcx>| { test_case.as_range().is_some_and(|range| { - matches!(range.contains(value, self.tcx, self.param_env), None | Some(true)) + matches!( + range.contains(value, self.tcx, self.typing_env()), + None | Some(true) + ) }) }; let is_conflicting_candidate = |candidate: &&mut Candidate<'_, 'tcx>| { @@ -584,7 +587,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { None } else { fully_matched = true; - let bits = value.eval_bits(self.tcx, self.param_env); + let bits = value.eval_bits(self.tcx, self.typing_env()); Some(TestBranch::Constant(value, bits)) } } @@ -596,7 +599,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { fully_matched = false; let not_contained = sorted_candidates.keys().filter_map(|br| br.as_constant()).copied().all( - |val| matches!(range.contains(val, self.tcx, self.param_env), Some(false)), + |val| { + matches!(range.contains(val, self.tcx, self.typing_env()), Some(false)) + }, ); not_contained.then(|| { @@ -608,7 +613,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { (TestKind::If, TestCase::Constant { value }) => { fully_matched = true; - let value = value.try_eval_bool(self.tcx, self.param_env).unwrap_or_else(|| { + let value = value.try_eval_bool(self.tcx, self.typing_env()).unwrap_or_else(|| { span_bug!(test.span, "expected boolean value but got {value:?}") }); Some(if value { TestBranch::Success } else { TestBranch::Failure }) @@ -688,7 +693,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { fully_matched = false; // If the testing range does not overlap with pattern range, // the pattern can be matched only if this test fails. - if !test.overlaps(pat, self.tcx, self.param_env)? { + if !test.overlaps(pat, self.tcx, self.typing_env())? { Some(TestBranch::Failure) } else { None @@ -697,7 +702,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } (TestKind::Range(range), &TestCase::Constant { value }) => { fully_matched = false; - if !range.contains(value, self.tcx, self.param_env)? { + if !range.contains(value, self.tcx, self.typing_env())? { // `value` is not contained in the testing range, // so `value` can be matched only if this test fails. Some(TestBranch::Failure) diff --git a/compiler/rustc_mir_build/src/build/misc.rs b/compiler/rustc_mir_build/src/build/misc.rs index 53cb99d44e8f..a14dcad6573c 100644 --- a/compiler/rustc_mir_build/src/build/misc.rs +++ b/compiler/rustc_mir_build/src/build/misc.rs @@ -32,7 +32,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// Returns a zero literal operand for the appropriate type, works for /// bool, char and integers. pub(crate) fn zero_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> { - let literal = Const::from_bits(self.tcx, 0, ty::ParamEnv::empty().and(ty)); + let literal = Const::from_bits(self.tcx, 0, ty::TypingEnv::fully_monomorphized(), ty); self.literal_operand(span, literal) } diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 46be2aee6374..cf8dc597b7bb 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -230,6 +230,10 @@ struct Capture<'tcx> { } impl<'a, 'tcx> Builder<'a, 'tcx> { + fn typing_env(&self) -> ty::TypingEnv<'tcx> { + self.infcx.typing_env(self.param_env) + } + fn is_bound_var_in_guard(&self, id: LocalVarId) -> bool { self.guard_context.iter().any(|frame| frame.locals.iter().any(|local| local.id == id)) } diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs index a7e56b8f589b..e63fbeeac662 100644 --- a/compiler/rustc_mir_build/src/build/scope.rs +++ b/compiler/rustc_mir_build/src/build/scope.rs @@ -1010,7 +1010,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ) { let needs_drop = match drop_kind { DropKind::Value => { - if !self.local_decls[local].ty.needs_drop(self.tcx, self.param_env) { + if !self.local_decls[local].ty.needs_drop(self.tcx, self.typing_env()) { return; } true diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 52e5f2950a50..a042da0eb4a5 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -570,7 +570,9 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { && adt_def.is_union() { if let Some(assigned_ty) = self.assignment_info { - if assigned_ty.needs_drop(self.tcx, self.param_env) { + if assigned_ty + .needs_drop(self.tcx, ty::TypingEnv::from_param_env(self.param_env)) + { // This would be unsafe, but should be outright impossible since we // reject such unions. assert!( diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 4443d9aebc60..676f7c98b8f8 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -528,7 +528,7 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for NonExhaustivePatternsTypeNo } if let ty::Ref(_, sub_ty, _) = self.ty.kind() { - if !sub_ty.is_inhabited_from(self.cx.tcx, self.cx.module, self.cx.param_env) { + if !sub_ty.is_inhabited_from(self.cx.tcx, self.cx.module, self.cx.typing_env()) { diag.note(fluent::mir_build_reference_note); } } diff --git a/compiler/rustc_mir_build/src/lints.rs b/compiler/rustc_mir_build/src/lints.rs index cb9a4e2604e2..a1b75c22c4d8 100644 --- a/compiler/rustc_mir_build/src/lints.rs +++ b/compiler/rustc_mir_build/src/lints.rs @@ -136,12 +136,17 @@ impl<'tcx> TerminatorClassifier<'tcx> for CallRecursion<'tcx> { let func_ty = func.ty(body, tcx); if let ty::FnDef(callee, args) = *func_ty.kind() { - let Ok(normalized_args) = tcx.try_normalize_erasing_regions(param_env, args) else { + let Ok(normalized_args) = + tcx.try_normalize_erasing_regions(ty::TypingEnv::from_param_env(param_env), args) + else { return false; }; - let (callee, call_args) = if let Ok(Some(instance)) = - Instance::try_resolve(tcx, param_env, callee, normalized_args) - { + let (callee, call_args) = if let Ok(Some(instance)) = Instance::try_resolve( + tcx, + ty::TypingEnv::from_param_env(param_env), + callee, + normalized_args, + ) { (instance.def_id(), instance.args) } else { (callee, normalized_args) diff --git a/compiler/rustc_mir_build/src/thir/constant.rs b/compiler/rustc_mir_build/src/thir/constant.rs index b8877a64e47e..3fa0e4def82e 100644 --- a/compiler/rustc_mir_build/src/thir/constant.rs +++ b/compiler/rustc_mir_build/src/thir/constant.rs @@ -2,7 +2,7 @@ use rustc_ast as ast; use rustc_hir::LangItem; use rustc_middle::bug; use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput}; -use rustc_middle::ty::{self, ParamEnv, ScalarInt, TyCtxt}; +use rustc_middle::ty::{self, ScalarInt, TyCtxt}; use tracing::trace; use crate::build::parse_float_into_scalar; @@ -14,8 +14,7 @@ pub(crate) fn lit_to_const<'tcx>( let LitToConstInput { lit, ty, neg } = lit_input; let trunc = |n| { - let param_ty = ParamEnv::reveal_all().and(ty); - let width = match tcx.layout_of(param_ty) { + let width = match tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)) { Ok(layout) => layout.size, Err(_) => { tcx.dcx().bug(format!("couldn't compute width of literal: {:?}", lit_input.lit)) diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 644570319973..198fa4ffb7a6 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -284,10 +284,9 @@ impl<'tcx> Cx<'tcx> { let ty = adt_def.repr().discr_type(); let discr_ty = ty.to_ty(tcx); - let param_env_ty = self.param_env.and(discr_ty); let size = tcx - .layout_of(param_env_ty) - .unwrap_or_else(|e| panic!("could not compute layout for {param_env_ty:?}: {e:?}")) + .layout_of(self.typing_env().as_query_input(discr_ty)) + .unwrap_or_else(|e| panic!("could not compute layout for {discr_ty:?}: {e:?}")) .size; let (lit, overflowing) = ScalarInt::truncate_from_uint(discr_offset as u128, size); @@ -1025,7 +1024,7 @@ impl<'tcx> Cx<'tcx> { // but distinguish between &STATIC and &THREAD_LOCAL as they have different semantics Res::Def(DefKind::Static { .. }, id) => { // this is &raw for extern static or static mut, and & for other statics - let ty = self.tcx.static_ptr_ty(id); + let ty = self.tcx.static_ptr_ty(id, self.typing_env()); let temp_lifetime = self .rvalue_scopes .temporary_scope(self.region_scope_tree, expr.hir_id.local_id); diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs index 377931e3be73..dfc180f52618 100644 --- a/compiler/rustc_mir_build/src/thir/cx/mod.rs +++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs @@ -12,6 +12,7 @@ use rustc_hir::lang_items::LangItem; use rustc_middle::bug; use rustc_middle::middle::region; use rustc_middle::thir::*; +use rustc_middle::ty::solve::Reveal; use rustc_middle::ty::{self, RvalueScopes, TyCtxt}; use tracing::instrument; @@ -109,6 +110,17 @@ impl<'tcx> Cx<'tcx> { } } + fn typing_mode(&self) -> ty::TypingMode<'tcx> { + debug_assert_eq!(self.param_env.reveal(), Reveal::UserFacing); + // FIXME(#132279): In case we're in a body, we should use a typing + // mode which reveals the opaque types defined by that body. + ty::TypingMode::non_body_analysis() + } + + fn typing_env(&self) -> ty::TypingEnv<'tcx> { + ty::TypingEnv { typing_mode: self.typing_mode(), param_env: self.param_env } + } + #[instrument(level = "debug", skip(self))] fn pattern_from_hir(&mut self, p: &'tcx hir::Pat<'tcx>) -> Box> { pat_from_hir(self.tcx, self.param_env, self.typeck_results(), p) diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 4b872d9b7f77..c7dacbc6789f 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -735,8 +735,8 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { .variant(*variant_index) .inhabited_predicate(self.tcx, *adt) .instantiate(self.tcx, args); - variant_inhabited.apply(self.tcx, cx.param_env, cx.module) - && !variant_inhabited.apply_ignore_module(self.tcx, cx.param_env) + variant_inhabited.apply(self.tcx, cx.typing_env(), cx.module) + && !variant_inhabited.apply_ignore_module(self.tcx, cx.typing_env()) } else { false }; @@ -1139,7 +1139,7 @@ fn report_non_exhaustive_match<'p, 'tcx>( } if let ty::Ref(_, sub_ty, _) = scrut_ty.kind() { - if !sub_ty.is_inhabited_from(cx.tcx, cx.module, cx.param_env) { + if !sub_ty.is_inhabited_from(cx.tcx, cx.module, cx.typing_env()) { err.note("references are always considered inhabited"); } } diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index 82632350af59..6b462198db69 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -50,10 +50,10 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { struct ConstToPat<'tcx> { span: Span, - param_env: ty::ParamEnv<'tcx>, // inference context used for checking `T: Structural` bounds. infcx: InferCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, treat_byte_string_as_slice: bool, } @@ -81,6 +81,10 @@ impl<'tcx> ConstToPat<'tcx> { self.infcx.tcx } + fn typing_env(&self) -> ty::TypingEnv<'tcx> { + self.infcx.typing_env(self.param_env) + } + fn type_marked_structural(&self, ty: Ty<'tcx>) -> bool { ty.is_structural_eq_shallow(self.infcx.tcx) } @@ -100,13 +104,14 @@ impl<'tcx> ConstToPat<'tcx> { // // FIXME: `const_eval_resolve_for_typeck` should probably just set the env to `Reveal::All` // instead of having this logic here - let param_env = - self.tcx().erase_regions(self.param_env).with_reveal_all_normalized(self.tcx()); + let typing_env = + self.tcx().erase_regions(self.typing_env()).with_reveal_all_normalized(self.tcx()); let uv = self.tcx().erase_regions(uv); // try to resolve e.g. associated constants to their definition on an impl, and then // evaluate the const. - let valtree = match self.infcx.tcx.const_eval_resolve_for_typeck(param_env, uv, self.span) { + let valtree = match self.infcx.tcx.const_eval_resolve_for_typeck(typing_env, uv, self.span) + { Ok(Ok(c)) => c, Err(ErrorHandled::Reported(_, _)) => { // Let's tell the use where this failing const occurs. @@ -187,7 +192,7 @@ impl<'tcx> ConstToPat<'tcx> { .map(|(idx, (val, ty))| { let field = FieldIdx::new(idx); // Patterns can only use monomorphic types. - let ty = self.tcx().normalize_erasing_regions(self.param_env, ty); + let ty = self.tcx().normalize_erasing_regions(self.typing_env(), ty); FieldPat { field, pattern: self.valtree_to_pat(val, ty) } }) .collect() diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 9b63d7881943..2719070e28d0 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -251,7 +251,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { let lo = lo.unwrap_or(PatRangeBoundary::NegInfinity); let hi = hi.unwrap_or(PatRangeBoundary::PosInfinity); - let cmp = lo.compare_with(hi, ty, self.tcx, self.param_env); + let cmp = lo.compare_with(hi, ty, self.tcx, ty::TypingEnv::from_param_env(self.param_env)); let mut kind = PatKind::Range(Box::new(PatRange { lo, hi, end, ty })); match (end, cmp) { // `x..y` where `x < y`. diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs index 9a1f000d39d8..494b7d54d8a1 100644 --- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs +++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs @@ -6,7 +6,6 @@ use rustc_index::Idx; use rustc_middle::mir::patch::MirPatch; use rustc_middle::mir::*; use rustc_middle::span_bug; -use rustc_middle::traits::Reveal; use rustc_middle::ty::util::IntTypeExt; use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt}; use rustc_span::DUMMY_SP; @@ -111,7 +110,7 @@ pub trait DropElaborator<'a, 'tcx>: fmt::Debug { fn patch(&mut self) -> &mut MirPatch<'tcx>; fn body(&self) -> &'a Body<'tcx>; fn tcx(&self) -> TyCtxt<'tcx>; - fn param_env(&self) -> ty::ParamEnv<'tcx>; + fn typing_env(&self) -> ty::TypingEnv<'tcx>; // Drop logic @@ -273,9 +272,9 @@ where let subpath = self.elaborator.field_subpath(variant_path, field); let tcx = self.tcx(); - assert_eq!(self.elaborator.param_env().reveal(), Reveal::All); + assert_eq!(self.elaborator.typing_env().typing_mode, ty::TypingMode::PostAnalysis); let field_ty = - tcx.normalize_erasing_regions(self.elaborator.param_env(), f.ty(tcx, args)); + tcx.normalize_erasing_regions(self.elaborator.typing_env(), f.ty(tcx, args)); (tcx.mk_place_field(base_place, field, field_ty), subpath) }) @@ -372,7 +371,7 @@ where let mut fields = fields; fields.retain(|&(place, _)| { - self.place_ty(place).needs_drop(self.tcx(), self.elaborator.param_env()) + self.place_ty(place).needs_drop(self.tcx(), self.elaborator.typing_env()) }); debug!("drop_ladder - fields needing drop: {:?}", fields); @@ -544,11 +543,11 @@ where } else { have_otherwise = true; - let param_env = self.elaborator.param_env(); + let typing_env = self.elaborator.typing_env(); let have_field_with_drop_glue = variant .fields .iter() - .any(|field| field.ty(tcx, args).needs_drop(tcx, param_env)); + .any(|field| field.ty(tcx, args).needs_drop(tcx, typing_env)); if have_field_with_drop_glue { have_otherwise_with_drop_glue = true; } diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index af2d514fc76e..ed8678de1eb1 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -462,7 +462,7 @@ impl<'tcx> Map<'tcx> { drop(assignments); // Create values for places whose type have scalar layout. - let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); + let typing_env = body.typing_env(tcx); for place_info in self.places.iter_mut() { // The user requires a bound on the number of created values. if let Some(value_limit) = value_limit @@ -471,13 +471,13 @@ impl<'tcx> Map<'tcx> { break; } - if let Ok(ty) = tcx.try_normalize_erasing_regions(param_env, place_info.ty) { + if let Ok(ty) = tcx.try_normalize_erasing_regions(typing_env, place_info.ty) { place_info.ty = ty; } // Allocate a value slot if it doesn't have one, and the user requested one. assert!(place_info.value_index.is_none()); - if let Ok(layout) = tcx.layout_of(param_env.and(place_info.ty)) + if let Ok(layout) = tcx.layout_of(typing_env.as_query_input(place_info.ty)) && layout.backend_repr.is_scalar() { place_info.value_index = Some(self.value_count.into()); @@ -874,7 +874,7 @@ impl TryFrom> for TrackElem { pub fn iter_fields<'tcx>( ty: Ty<'tcx>, tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, mut f: impl FnMut(Option, FieldIdx, Ty<'tcx>), ) { match ty.kind() { @@ -892,20 +892,20 @@ pub fn iter_fields<'tcx>( for (f_index, f_def) in v_def.fields.iter().enumerate() { let field_ty = f_def.ty(tcx, args); let field_ty = tcx - .try_normalize_erasing_regions(param_env, field_ty) + .try_normalize_erasing_regions(typing_env, field_ty) .unwrap_or_else(|_| tcx.erase_regions(field_ty)); f(variant, f_index.into(), field_ty); } } } ty::Closure(_, args) => { - iter_fields(args.as_closure().tupled_upvars_ty(), tcx, param_env, f); + iter_fields(args.as_closure().tupled_upvars_ty(), tcx, typing_env, f); } ty::Coroutine(_, args) => { - iter_fields(args.as_coroutine().tupled_upvars_ty(), tcx, param_env, f); + iter_fields(args.as_coroutine().tupled_upvars_ty(), tcx, typing_env, f); } ty::CoroutineClosure(_, args) => { - iter_fields(args.as_coroutine_closure().tupled_upvars_ty(), tcx, param_env, f); + iter_fields(args.as_coroutine_closure().tupled_upvars_ty(), tcx, typing_env, f); } _ => (), } diff --git a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs index 559df222a504..12a2fe23b149 100644 --- a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs +++ b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs @@ -1,6 +1,6 @@ use rustc_middle::mir::patch::MirPatch; use rustc_middle::mir::*; -use rustc_middle::ty::TyCtxt; +use rustc_middle::ty::{self, TyCtxt}; use tracing::debug; use crate::util; @@ -40,10 +40,10 @@ pub(super) struct AddMovesForPackedDrops; impl<'tcx> crate::MirPass<'tcx> for AddMovesForPackedDrops { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { debug!("add_moves_for_packed_drops({:?} @ {:?})", body.source, body.span); - - let def_id = body.source.def_id(); let mut patch = MirPatch::new(body); - let param_env = tcx.param_env(def_id); + // FIXME(#132279): This is used during the phase transition from analysis + // to runtime, so we have to manually specify the correct typing mode. + let typing_env = ty::TypingEnv::post_analysis(tcx, body.source.def_id()); for (bb, data) in body.basic_blocks.iter_enumerated() { let loc = Location { block: bb, statement_index: data.statements.len() }; @@ -51,7 +51,7 @@ impl<'tcx> crate::MirPass<'tcx> for AddMovesForPackedDrops { match terminator.kind { TerminatorKind::Drop { place, .. } - if util::is_disaligned(tcx, body, param_env, place) => + if util::is_disaligned(tcx, body, typing_env, place) => { add_move_for_packed_drop( tcx, diff --git a/compiler/rustc_mir_transform/src/check_packed_ref.rs b/compiler/rustc_mir_transform/src/check_packed_ref.rs index 1922d4fef25d..e9b85ba6e9db 100644 --- a/compiler/rustc_mir_transform/src/check_packed_ref.rs +++ b/compiler/rustc_mir_transform/src/check_packed_ref.rs @@ -9,9 +9,9 @@ pub(super) struct CheckPackedRef; impl<'tcx> crate::MirLint<'tcx> for CheckPackedRef { fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { - let param_env = tcx.param_env(body.source.def_id()); + let typing_env = body.typing_env(tcx); let source_info = SourceInfo::outermost(body.span); - let mut checker = PackedRefChecker { body, tcx, param_env, source_info }; + let mut checker = PackedRefChecker { body, tcx, typing_env, source_info }; checker.visit_body(body); } } @@ -19,7 +19,7 @@ impl<'tcx> crate::MirLint<'tcx> for CheckPackedRef { struct PackedRefChecker<'a, 'tcx> { body: &'a Body<'tcx>, tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, source_info: SourceInfo, } @@ -37,7 +37,8 @@ impl<'tcx> Visitor<'tcx> for PackedRefChecker<'_, 'tcx> { } fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location: Location) { - if context.is_borrow() && util::is_disaligned(self.tcx, self.body, self.param_env, *place) { + if context.is_borrow() && util::is_disaligned(self.tcx, self.body, self.typing_env, *place) + { let def_id = self.body.source.instance.def_id(); if let Some(impl_def_id) = self.tcx.impl_of_method(def_id) && self.tcx.is_builtin_derived(impl_def_id) diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index c2666caa1e87..d38a1dd11dc2 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -1069,11 +1069,9 @@ fn elaborate_coroutine_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // Note that `elaborate_drops` only drops the upvars of a coroutine, and // this is ok because `open_drop` can only be reached within that own // coroutine's resume function. + let typing_env = body.typing_env(tcx); - let def_id = body.source.def_id(); - let param_env = tcx.param_env(def_id); - - let mut elaborator = DropShimElaborator { body, patch: MirPatch::new(body), tcx, param_env }; + let mut elaborator = DropShimElaborator { body, patch: MirPatch::new(body), tcx, typing_env }; for (block, block_data) in body.basic_blocks.iter_enumerated() { let (target, unwind, source_info) = match block_data.terminator() { @@ -1204,9 +1202,9 @@ fn insert_panic_block<'tcx>( insert_term_block(body, kind) } -fn can_return<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { +fn can_return<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> bool { // Returning from a function with an uninhabited return type is undefined behavior. - if body.return_ty().is_privately_uninhabited(tcx, param_env) { + if body.return_ty().is_privately_uninhabited(tcx, typing_env) { return false; } @@ -1627,7 +1625,7 @@ impl<'tcx> crate::MirPass<'tcx> for StateTransform { // `storage_liveness` tells us which locals have live storage at suspension points let (remap, layout, storage_liveness) = compute_layout(liveness_info, body); - let can_return = can_return(tcx, body, tcx.param_env(body.source.def_id())); + let can_return = can_return(tcx, body, body.typing_env(tcx)); // Run the transformation which converts Places from Local to coroutine struct // accesses for locals in `remap`. diff --git a/compiler/rustc_mir_transform/src/cost_checker.rs b/compiler/rustc_mir_transform/src/cost_checker.rs index 59b403538a33..b23d8b9e7372 100644 --- a/compiler/rustc_mir_transform/src/cost_checker.rs +++ b/compiler/rustc_mir_transform/src/cost_checker.rs @@ -1,7 +1,7 @@ use rustc_middle::bug; use rustc_middle::mir::visit::*; use rustc_middle::mir::*; -use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt}; const INSTR_COST: usize = 5; const CALL_PENALTY: usize = 25; @@ -14,7 +14,7 @@ const CONST_SWITCH_BONUS: usize = 10; #[derive(Clone)] pub(super) struct CostChecker<'b, 'tcx> { tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, penalty: usize, bonus: usize, callee_body: &'b Body<'tcx>, @@ -24,11 +24,11 @@ pub(super) struct CostChecker<'b, 'tcx> { impl<'b, 'tcx> CostChecker<'b, 'tcx> { pub(super) fn new( tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, instance: Option>, callee_body: &'b Body<'tcx>, ) -> CostChecker<'b, 'tcx> { - CostChecker { tcx, param_env, callee_body, instance, penalty: 0, bonus: 0 } + CostChecker { tcx, typing_env, callee_body, instance, penalty: 0, bonus: 0 } } /// Add function-level costs not well-represented by the block-level costs. @@ -119,7 +119,7 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> { TerminatorKind::Drop { place, unwind, .. } => { // If the place doesn't actually need dropping, treat it like a regular goto. let ty = self.instantiate_ty(place.ty(self.callee_body, self.tcx).ty); - if ty.needs_drop(self.tcx, self.param_env) { + if ty.needs_drop(self.tcx, self.typing_env) { self.penalty += CALL_PENALTY; if let UnwindAction::Cleanup(_) = unwind { self.penalty += LANDINGPAD_PENALTY; diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index ab6460c490b8..500515bc3cc5 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -16,7 +16,7 @@ use rustc_middle::bug; use rustc_middle::mir::interpret::{InterpResult, Scalar}; use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor}; use rustc_middle::mir::*; -use rustc_middle::ty::layout::{HasParamEnv, LayoutOf}; +use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_mir_dataflow::fmt::DebugWithContext; use rustc_mir_dataflow::lattice::{FlatSet, HasBottom}; @@ -82,7 +82,7 @@ struct ConstAnalysis<'a, 'tcx> { tcx: TyCtxt<'tcx>, local_decls: &'a LocalDecls<'tcx>, ecx: InterpCx<'tcx, DummyMachine>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, } impl<'tcx> Analysis<'tcx> for ConstAnalysis<'_, 'tcx> { @@ -144,13 +144,13 @@ impl<'tcx> Analysis<'tcx> for ConstAnalysis<'_, 'tcx> { impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, map: Map<'tcx>) -> Self { - let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); + let typing_env = body.typing_env(tcx); Self { map, tcx, local_decls: &body.local_decls, - ecx: InterpCx::new(tcx, DUMMY_SP, param_env, DummyMachine), - param_env, + ecx: InterpCx::new(tcx, DUMMY_SP, typing_env.param_env, DummyMachine), + typing_env, } } @@ -389,7 +389,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { && let Some(operand_ty) = operand_ty.builtin_deref(true) && let ty::Array(_, len) = operand_ty.kind() && let Some(len) = Const::Ty(self.tcx.types.usize, *len) - .try_eval_scalar_int(self.tcx, self.param_env) + .try_eval_scalar_int(self.tcx, self.typing_env) { state.insert_value_idx(target_len, FlatSet::Elem(len.into()), &self.map); } @@ -411,7 +411,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { let place_ty = place.ty(self.local_decls, self.tcx); if let ty::Array(_, len) = place_ty.ty.kind() { Const::Ty(self.tcx.types.usize, *len) - .try_eval_scalar(self.tcx, self.param_env) + .try_eval_scalar(self.tcx, self.typing_env) .map_or(FlatSet::Top, FlatSet::Elem) } else if let [ProjectionElem::Deref] = place.projection[..] { state.get_len(place.local.into(), &self.map) @@ -420,7 +420,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { } } Rvalue::Cast(CastKind::IntToInt | CastKind::IntToFloat, operand, ty) => { - let Ok(layout) = self.tcx.layout_of(self.param_env.and(*ty)) else { + let Ok(layout) = self.tcx.layout_of(self.typing_env.as_query_input(*ty)) else { return ValueOrPlace::Value(FlatSet::Top); }; match self.eval_operand(operand, state) { @@ -434,7 +434,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { } } Rvalue::Cast(CastKind::FloatToInt | CastKind::FloatToFloat, operand, ty) => { - let Ok(layout) = self.tcx.layout_of(self.param_env.and(*ty)) else { + let Ok(layout) = self.tcx.layout_of(self.typing_env.as_query_input(*ty)) else { return ValueOrPlace::Value(FlatSet::Top); }; match self.eval_operand(operand, state) { @@ -470,7 +470,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { FlatSet::Top => FlatSet::Top, }, Rvalue::NullaryOp(null_op, ty) => { - let Ok(layout) = self.tcx.layout_of(self.param_env.and(*ty)) else { + let Ok(layout) = self.tcx.layout_of(self.typing_env.as_query_input(*ty)) else { return ValueOrPlace::Value(FlatSet::Top); }; let val = match null_op { @@ -479,7 +479,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { NullOp::OffsetOf(fields) => self .ecx .tcx - .offset_of_subfield(self.ecx.param_env(), layout, fields.iter()) + .offset_of_subfield(self.typing_env, layout, fields.iter()) .bytes(), _ => return ValueOrPlace::Value(FlatSet::Top), }; @@ -514,7 +514,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { ) -> FlatSet { constant .const_ - .try_eval_scalar(self.tcx, self.param_env) + .try_eval_scalar(self.tcx, self.typing_env) .map_or(FlatSet::Top, FlatSet::Elem) } @@ -554,7 +554,8 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { } else if rhs.projection.first() == Some(&PlaceElem::Deref) && let FlatSet::Elem(pointer) = state.get(rhs.local.into(), &self.map) && let rhs_ty = self.local_decls[rhs.local].ty - && let Ok(rhs_layout) = self.tcx.layout_of(self.param_env.and(rhs_ty)) + && let Ok(rhs_layout) = + self.tcx.layout_of(self.typing_env.as_query_input(rhs_ty)) { let op = ImmTy::from_scalar(pointer, rhs_layout).into(); self.assign_constant(state, place, op, rhs.projection); @@ -614,8 +615,10 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { TrackElem::DerefLen => { let op: OpTy<'_> = self.ecx.deref_pointer(op).discard_err()?.into(); let len_usize = op.len(&self.ecx).discard_err()?; - let layout = - self.tcx.layout_of(self.param_env.and(self.tcx.types.usize)).unwrap(); + let layout = self + .tcx + .layout_of(self.typing_env.as_query_input(self.tcx.types.usize)) + .unwrap(); Some(ImmTy::from_uint(len_usize, layout).into()) } }, @@ -702,9 +705,11 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { FlatSet::Top => FlatSet::Top, FlatSet::Elem(scalar) => { let ty = op.ty(self.local_decls, self.tcx); - self.tcx.layout_of(self.param_env.and(ty)).map_or(FlatSet::Top, |layout| { - FlatSet::Elem(ImmTy::from_scalar(scalar, layout)) - }) + self.tcx + .layout_of(self.typing_env.as_query_input(ty)) + .map_or(FlatSet::Top, |layout| { + FlatSet::Elem(ImmTy::from_scalar(scalar, layout)) + }) } FlatSet::Bottom => FlatSet::Bottom, } @@ -714,7 +719,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { if !enum_ty.is_enum() { return None; } - let enum_ty_layout = self.tcx.layout_of(self.param_env.and(enum_ty)).ok()?; + let enum_ty_layout = self.tcx.layout_of(self.typing_env.as_query_input(enum_ty)).ok()?; let discr_value = self.ecx.discriminant_for_variant(enum_ty_layout.ty, variant_index).discard_err()?; Some(discr_value.to_scalar()) diff --git a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs index 753bae8e1568..db72ec522a22 100644 --- a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs +++ b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs @@ -198,7 +198,7 @@ pub(super) fn deduced_param_attrs<'tcx>( // see [1]. // // [1]: https://github.com/rust-lang/rust/pull/103172#discussion_r999139997 - let param_env = tcx.param_env_reveal_all_normalized(def_id); + let typing_env = body.typing_env(tcx); let mut deduced_param_attrs = tcx.arena.alloc_from_iter( body.local_decls.iter().skip(1).take(body.arg_count).enumerate().map( |(arg_index, local_decl)| DeducedParamAttrs { @@ -207,8 +207,8 @@ pub(super) fn deduced_param_attrs<'tcx>( // their generic parameters, otherwise we'll see exponential // blow-up in compile times: #113372 && tcx - .normalize_erasing_regions(param_env, local_decl.ty) - .is_freeze(tcx, param_env), + .normalize_erasing_regions(typing_env, local_decl.ty) + .is_freeze(tcx, typing_env.param_env), }, ), ); diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs index 74572100db3f..b0f041d8722b 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drops.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs @@ -3,6 +3,7 @@ use std::fmt; use rustc_abi::{FieldIdx, VariantIdx}; use rustc_index::IndexVec; use rustc_index::bit_set::BitSet; +use rustc_infer::traits::Reveal; use rustc_middle::mir::patch::MirPatch; use rustc_middle::mir::*; use rustc_middle::ty::{self, TyCtxt}; @@ -53,14 +54,14 @@ impl<'tcx> crate::MirPass<'tcx> for ElaborateDrops { #[instrument(level = "trace", skip(self, tcx, body))] fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { debug!("elaborate_drops({:?} @ {:?})", body.source, body.span); - - let def_id = body.source.def_id(); - let param_env = tcx.param_env_reveal_all_normalized(def_id); + // FIXME(#132279): This is used during the phase transition from analysis + // to runtime, so we have to manually specify the correct typing mode. + let typing_env = ty::TypingEnv::post_analysis(tcx, body.source.def_id()); // For types that do not need dropping, the behaviour is trivial. So we only need to track // init/uninit for types that do need dropping. - let move_data = MoveData::gather_moves(body, tcx, |ty| ty.needs_drop(tcx, param_env)); + let move_data = MoveData::gather_moves(body, tcx, |ty| ty.needs_drop(tcx, typing_env)); let elaborate_patch = { - let env = MoveDataParamEnv { move_data, param_env }; + let env = MoveDataParamEnv { move_data, param_env: typing_env.param_env }; let mut inits = MaybeInitializedPlaces::new(tcx, body, &env.move_data) .skipping_unreachable_unwind() @@ -147,8 +148,8 @@ impl<'a, 'tcx> DropElaborator<'a, 'tcx> for ElaborateDropsCtxt<'a, 'tcx> { self.tcx } - fn param_env(&self) -> ty::ParamEnv<'tcx> { - self.param_env() + fn typing_env(&self) -> ty::TypingEnv<'tcx> { + self.typing_env() } #[instrument(level = "debug", skip(self), ret)] @@ -250,6 +251,11 @@ impl<'a, 'tcx> ElaborateDropsCtxt<'a, 'tcx> { self.env.param_env } + fn typing_env(&self) -> ty::TypingEnv<'tcx> { + debug_assert_eq!(self.param_env().reveal(), Reveal::All); + ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env: self.param_env() } + } + fn create_drop_flag(&mut self, index: MovePathIndex, span: Span) { let patch = &mut self.patch; debug!("create_drop_flag({:?})", self.body.span); @@ -335,7 +341,7 @@ impl<'a, 'tcx> ElaborateDropsCtxt<'a, 'tcx> { if !place .ty(&self.body.local_decls, self.tcx) .ty - .needs_drop(self.tcx, self.env.param_env) + .needs_drop(self.tcx, self.typing_env()) { self.patch.patch_terminator(bb, TerminatorKind::Goto { target }); continue; diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 274eea9563fe..27fe0ad72e7c 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -100,7 +100,7 @@ use rustc_middle::bug; use rustc_middle::mir::interpret::GlobalAlloc; use rustc_middle::mir::visit::*; use rustc_middle::mir::*; -use rustc_middle::ty::layout::{HasParamEnv, LayoutOf}; +use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::DUMMY_SP; use rustc_span::def_id::DefId; @@ -295,6 +295,10 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { } } + fn typing_env(&self) -> ty::TypingEnv<'tcx> { + ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env: self.param_env } + } + #[instrument(level = "trace", skip(self), ret)] fn insert(&mut self, value: Value<'tcx>) -> VnIndex { let (index, new) = self.values.insert_full(value); @@ -531,7 +535,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { NullOp::OffsetOf(fields) => self .ecx .tcx - .offset_of_subfield(self.ecx.param_env(), layout, fields.iter()) + .offset_of_subfield(self.typing_env(), layout, fields.iter()) .bytes(), NullOp::UbChecks => return None, }; @@ -1476,8 +1480,9 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { if left_meta_ty == right_meta_ty { true } else if let Ok(left) = - self.tcx.try_normalize_erasing_regions(self.param_env, left_meta_ty) - && let Ok(right) = self.tcx.try_normalize_erasing_regions(self.param_env, right_meta_ty) + self.tcx.try_normalize_erasing_regions(self.typing_env(), left_meta_ty) + && let Ok(right) = + self.tcx.try_normalize_erasing_regions(self.typing_env(), right_meta_ty) { left == right } else { diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index e95ab4ffe16c..fcb51fbddd90 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -13,9 +13,7 @@ use rustc_middle::bug; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; use rustc_middle::mir::visit::*; use rustc_middle::mir::*; -use rustc_middle::ty::{ - self, Instance, InstanceKind, ParamEnv, Ty, TyCtxt, TypeFlags, TypeVisitableExt, -}; +use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TyCtxt, TypeFlags, TypeVisitableExt}; use rustc_session::config::{DebugInfo, OptLevel}; use rustc_span::source_map::Spanned; use rustc_span::sym; @@ -94,12 +92,12 @@ fn inline<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool { return false; } - let param_env = tcx.param_env_reveal_all_normalized(def_id); + let typing_env = body.typing_env(tcx); let codegen_fn_attrs = tcx.codegen_fn_attrs(def_id); let mut this = Inliner { tcx, - param_env, + typing_env, codegen_fn_attrs, history: Vec::new(), changed: false, @@ -115,7 +113,7 @@ fn inline<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool { struct Inliner<'tcx> { tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, /// Caller codegen attributes. codegen_fn_attrs: &'tcx CodegenFnAttrs, /// Stack of inlined instances. @@ -201,7 +199,11 @@ impl<'tcx> Inliner<'tcx> { let TerminatorKind::Call { args, destination, .. } = &terminator.kind else { bug!() }; let destination_ty = destination.ty(&caller_body.local_decls, self.tcx).ty; for arg in args { - if !arg.node.ty(&caller_body.local_decls, self.tcx).is_sized(self.tcx, self.param_env) { + if !arg + .node + .ty(&caller_body.local_decls, self.tcx) + .is_sized(self.tcx, self.typing_env.param_env) + { // We do not allow inlining functions with unsized params. Inlining these functions // could create unsized locals, which are unsound and being phased out. return Err("Call has unsized argument"); @@ -219,7 +221,7 @@ impl<'tcx> Inliner<'tcx> { let Ok(callee_body) = callsite.callee.try_instantiate_mir_and_normalize_erasing_regions( self.tcx, - self.param_env, + self.typing_env, ty::EarlyBinder::bind(callee_body.clone()), ) else { return Err("failed to normalize callee body"); @@ -230,7 +232,7 @@ impl<'tcx> Inliner<'tcx> { if !validate_types( self.tcx, MirPhase::Runtime(RuntimePhase::Optimized), - self.param_env, + self.typing_env, &callee_body, &caller_body, ) @@ -243,13 +245,7 @@ impl<'tcx> Inliner<'tcx> { // Normally, this shouldn't be required, but trait normalization failure can create a // validation ICE. let output_type = callee_body.return_ty(); - if !util::sub_types( - self.tcx, - caller_body.typing_mode(self.tcx), - self.param_env, - output_type, - destination_ty, - ) { + if !util::sub_types(self.tcx, self.typing_env, output_type, destination_ty) { trace!(?output_type, ?destination_ty); return Err("failed to normalize return type"); } @@ -279,13 +275,7 @@ impl<'tcx> Inliner<'tcx> { self_arg_ty.into_iter().chain(arg_tuple_tys).zip(callee_body.args_iter()) { let input_type = callee_body.local_decls[input].ty; - if !util::sub_types( - self.tcx, - caller_body.typing_mode(self.tcx), - self.param_env, - input_type, - arg_ty, - ) { + if !util::sub_types(self.tcx, self.typing_env, input_type, arg_ty) { trace!(?arg_ty, ?input_type); return Err("failed to normalize tuple argument type"); } @@ -294,13 +284,7 @@ impl<'tcx> Inliner<'tcx> { for (arg, input) in args.iter().zip(callee_body.args_iter()) { let input_type = callee_body.local_decls[input].ty; let arg_ty = arg.node.ty(&caller_body.local_decls, self.tcx); - if !util::sub_types( - self.tcx, - caller_body.typing_mode(self.tcx), - self.param_env, - input_type, - arg_ty, - ) { + if !util::sub_types(self.tcx, self.typing_env, input_type, arg_ty) { trace!(?arg_ty, ?input_type); return Err("failed to normalize argument type"); } @@ -402,9 +386,10 @@ impl<'tcx> Inliner<'tcx> { let func_ty = func.ty(caller_body, self.tcx); if let ty::FnDef(def_id, args) = *func_ty.kind() { // To resolve an instance its args have to be fully normalized. - let args = self.tcx.try_normalize_erasing_regions(self.param_env, args).ok()?; - let callee = - Instance::try_resolve(self.tcx, self.param_env, def_id, args).ok().flatten()?; + let args = self.tcx.try_normalize_erasing_regions(self.typing_env, args).ok()?; + let callee = Instance::try_resolve(self.tcx, self.typing_env, def_id, args) + .ok() + .flatten()?; if let InstanceKind::Virtual(..) | InstanceKind::Intrinsic(_) = callee.def { return None; @@ -528,7 +513,7 @@ impl<'tcx> Inliner<'tcx> { // FIXME: Give a bonus to functions with only a single caller let mut checker = - CostChecker::new(self.tcx, self.param_env, Some(callsite.callee), callee_body); + CostChecker::new(self.tcx, self.typing_env, Some(callsite.callee), callee_body); checker.add_function_level_costs(); @@ -552,7 +537,7 @@ impl<'tcx> Inliner<'tcx> { self.tcx, ty::EarlyBinder::bind(&place.ty(callee_body, tcx).ty), ); - if ty.needs_drop(tcx, self.param_env) + if ty.needs_drop(tcx, self.typing_env) && let UnwindAction::Cleanup(unwind) = unwind { work_list.push(unwind); diff --git a/compiler/rustc_mir_transform/src/inline/cycle.rs b/compiler/rustc_mir_transform/src/inline/cycle.rs index 9828e90de883..a40768300f5d 100644 --- a/compiler/rustc_mir_transform/src/inline/cycle.rs +++ b/compiler/rustc_mir_transform/src/inline/cycle.rs @@ -15,7 +15,6 @@ pub(crate) fn mir_callgraph_reachable<'tcx>( (root, target): (ty::Instance<'tcx>, LocalDefId), ) -> bool { trace!(%root, target = %tcx.def_path_str(target)); - let param_env = tcx.param_env_reveal_all_normalized(target); assert_ne!( root.def_id().expect_local(), target, @@ -31,11 +30,11 @@ pub(crate) fn mir_callgraph_reachable<'tcx>( ); #[instrument( level = "debug", - skip(tcx, param_env, target, stack, seen, recursion_limiter, caller, recursion_limit) + skip(tcx, typing_env, target, stack, seen, recursion_limiter, caller, recursion_limit) )] fn process<'tcx>( tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, caller: ty::Instance<'tcx>, target: LocalDefId, stack: &mut Vec>, @@ -47,13 +46,13 @@ pub(crate) fn mir_callgraph_reachable<'tcx>( for &(callee, args) in tcx.mir_inliner_callees(caller.def) { let Ok(args) = caller.try_instantiate_mir_and_normalize_erasing_regions( tcx, - param_env, + typing_env, ty::EarlyBinder::bind(args), ) else { - trace!(?caller, ?param_env, ?args, "cannot normalize, skipping"); + trace!(?caller, ?typing_env, ?args, "cannot normalize, skipping"); continue; }; - let Ok(Some(callee)) = ty::Instance::try_resolve(tcx, param_env, callee, args) else { + let Ok(Some(callee)) = ty::Instance::try_resolve(tcx, typing_env, callee, args) else { trace!(?callee, "cannot resolve, skipping"); continue; }; @@ -115,7 +114,7 @@ pub(crate) fn mir_callgraph_reachable<'tcx>( let found_recursion = ensure_sufficient_stack(|| { process( tcx, - param_env, + typing_env, callee, target, stack, @@ -146,7 +145,7 @@ pub(crate) fn mir_callgraph_reachable<'tcx>( let recursion_limit = tcx.recursion_limit() / 2; process( tcx, - param_env, + ty::TypingEnv::post_analysis(tcx, target), root, target, &mut Vec::new(), diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index 9471c1b2a9a1..b80abcca969f 100644 --- a/compiler/rustc_mir_transform/src/instsimplify.rs +++ b/compiler/rustc_mir_transform/src/instsimplify.rs @@ -69,6 +69,12 @@ struct InstSimplifyContext<'a, 'tcx> { param_env: ParamEnv<'tcx>, } +impl<'tcx> InstSimplifyContext<'_, 'tcx> { + fn typing_env(&self) -> ty::TypingEnv<'tcx> { + ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env: self.param_env } + } +} + impl<'tcx> InstSimplifyContext<'_, 'tcx> { fn should_simplify(&self, source_info: &SourceInfo, rvalue: &Rvalue<'tcx>) -> bool { self.should_simplify_custom(source_info, "Rvalue", rvalue) @@ -348,7 +354,7 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> { } let known_is_valid = - intrinsic_assert_panics(self.tcx, self.param_env, args[0], intrinsic_name); + intrinsic_assert_panics(self.tcx, self.typing_env(), args[0], intrinsic_name); match known_is_valid { // We don't know the layout or it's not validity assertion at all, don't touch it None => {} @@ -366,13 +372,13 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> { fn intrinsic_assert_panics<'tcx>( tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, arg: ty::GenericArg<'tcx>, intrinsic_name: Symbol, ) -> Option { let requirement = ValidityRequirement::from_intrinsic(intrinsic_name)?; let ty = arg.expect_ty(); - Some(!tcx.check_validity_requirement((requirement, param_env.and(ty))).ok()?) + Some(!tcx.check_validity_requirement((requirement, typing_env.as_query_input(ty))).ok()?) } fn resolve_rust_intrinsic<'tcx>( diff --git a/compiler/rustc_mir_transform/src/jump_threading.rs b/compiler/rustc_mir_transform/src/jump_threading.rs index 3772589ac4ea..71a843a785c6 100644 --- a/compiler/rustc_mir_transform/src/jump_threading.rs +++ b/compiler/rustc_mir_transform/src/jump_threading.rs @@ -77,13 +77,12 @@ impl<'tcx> crate::MirPass<'tcx> for JumpThreading { return; } - let param_env = tcx.param_env_reveal_all_normalized(def_id); - + let typing_env = body.typing_env(tcx); let arena = &DroplessArena::default(); let mut finder = TOFinder { tcx, - param_env, - ecx: InterpCx::new(tcx, DUMMY_SP, param_env, DummyMachine), + typing_env, + ecx: InterpCx::new(tcx, DUMMY_SP, typing_env.param_env, DummyMachine), body, arena, map: Map::new(tcx, body, Some(MAX_PLACES)), @@ -119,7 +118,7 @@ struct ThreadingOpportunity { struct TOFinder<'a, 'tcx> { tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ecx: InterpCx<'tcx, DummyMachine>, body: &'a Body<'tcx>, map: Map<'tcx>, @@ -207,7 +206,7 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> { let Some(discr) = self.map.find(discr.as_ref()) else { return }; debug!(?discr); - let cost = CostChecker::new(self.tcx, self.param_env, None, self.body); + let cost = CostChecker::new(self.tcx, self.typing_env, None, self.body); let mut state = State::new_reachable(); let conds = if let Some((value, then, else_)) = targets.as_static_if() { @@ -528,7 +527,8 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> { // Avoid handling them, though this could be extended in the future. return; } - let Some(value) = value.const_.try_eval_scalar_int(self.tcx, self.param_env) else { + let Some(value) = value.const_.try_eval_scalar_int(self.tcx, self.typing_env) + else { return; }; let conds = conditions.map(self.arena, |c| Condition { diff --git a/compiler/rustc_mir_transform/src/known_panics_lint.rs b/compiler/rustc_mir_transform/src/known_panics_lint.rs index 0604665642ab..3911b0a2db68 100644 --- a/compiler/rustc_mir_transform/src/known_panics_lint.rs +++ b/compiler/rustc_mir_transform/src/known_panics_lint.rs @@ -18,7 +18,7 @@ use rustc_middle::bug; use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::layout::{LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout}; -use rustc_middle::ty::{self, ConstInt, ParamEnv, ScalarInt, Ty, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{self, ConstInt, ScalarInt, Ty, TyCtxt, TypeVisitableExt}; use rustc_span::Span; use tracing::{debug, instrument, trace}; @@ -65,7 +65,7 @@ impl<'tcx> crate::MirLint<'tcx> for KnownPanicsLint { struct ConstPropagator<'mir, 'tcx> { ecx: InterpCx<'tcx, DummyMachine>, tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, worklist: Vec, visited_blocks: BitSet, locals: IndexVec>, @@ -169,25 +169,26 @@ impl<'tcx> ty::layout::HasTyCtxt<'tcx> for ConstPropagator<'_, 'tcx> { } } -impl<'tcx> ty::layout::HasParamEnv<'tcx> for ConstPropagator<'_, 'tcx> { +impl<'tcx> ty::layout::HasTypingEnv<'tcx> for ConstPropagator<'_, 'tcx> { #[inline] - fn param_env(&self) -> ty::ParamEnv<'tcx> { - self.param_env + fn typing_env(&self) -> ty::TypingEnv<'tcx> { + self.typing_env } } impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { fn new(body: &'mir Body<'tcx>, tcx: TyCtxt<'tcx>) -> ConstPropagator<'mir, 'tcx> { let def_id = body.source.def_id(); - let param_env = tcx.param_env_reveal_all_normalized(def_id); - - let can_const_prop = CanConstProp::check(tcx, param_env, body); - let ecx = InterpCx::new(tcx, tcx.def_span(def_id), param_env, DummyMachine); + // FIXME(#132279): This is used during the phase transition from analysis + // to runtime, so we have to manually specify the correct typing mode. + let typing_env = ty::TypingEnv::post_analysis(tcx, body.source.def_id()); + let can_const_prop = CanConstProp::check(tcx, typing_env, body); + let ecx = InterpCx::new(tcx, tcx.def_span(def_id), typing_env.param_env, DummyMachine); ConstPropagator { ecx, tcx, - param_env, + typing_env, worklist: vec![START_BLOCK], visited_blocks: BitSet::new_empty(body.basic_blocks.len()), locals: IndexVec::from_elem_n(Value::Uninit, body.local_decls.len()), @@ -260,7 +261,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { // that the `RevealAll` pass has happened and that the body's consts // are normalized, so any call to resolve before that needs to be // manually normalized. - let val = self.tcx.try_normalize_erasing_regions(self.param_env, c.const_).ok()?; + let val = self.tcx.try_normalize_erasing_regions(self.typing_env, c.const_).ok()?; self.use_ecx(|this| this.ecx.eval_mir_constant(&val, c.span, None))? .as_mplace_or_imm() @@ -450,7 +451,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { if rvalue.has_param() { return None; } - if !rvalue.ty(self.local_decls(), self.tcx).is_sized(self.tcx, self.param_env) { + if !rvalue.ty(self.local_decls(), self.tcx).is_sized(self.tcx, self.typing_env.param_env) { // the interpreter doesn't support unsized locals (only unsized arguments), // but rustc does (in a kinda broken way), so we have to skip them here return None; @@ -622,7 +623,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { NullOp::AlignOf => op_layout.align.abi.bytes(), NullOp::OffsetOf(fields) => self .tcx - .offset_of_subfield(self.param_env, op_layout, fields.iter()) + .offset_of_subfield(self.typing_env, op_layout, fields.iter()) .bytes(), NullOp::UbChecks => return None, }; @@ -873,7 +874,7 @@ impl CanConstProp { /// Returns true if `local` can be propagated fn check<'tcx>( tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, body: &Body<'tcx>, ) -> IndexVec { let mut cpv = CanConstProp { @@ -888,7 +889,7 @@ impl CanConstProp { // variant of a union *val = ConstPropMode::NoPropagation; } else { - match tcx.layout_of(param_env.and(ty)) { + match tcx.layout_of(typing_env.as_query_input(ty)) { Ok(layout) if layout.size < Size::from_bytes(MAX_ALLOC_LIMIT) => {} // Either the layout fails to compute, then we can't use this local anyway // or the local is too large, then we don't want to. diff --git a/compiler/rustc_mir_transform/src/large_enums.rs b/compiler/rustc_mir_transform/src/large_enums.rs index fa659a56a274..8be5a63d0087 100644 --- a/compiler/rustc_mir_transform/src/large_enums.rs +++ b/compiler/rustc_mir_transform/src/large_enums.rs @@ -3,7 +3,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_middle::mir::interpret::AllocId; use rustc_middle::mir::*; use rustc_middle::ty::util::IntTypeExt; -use rustc_middle::ty::{self, AdtDef, ParamEnv, Ty, TyCtxt}; +use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt}; use rustc_session::Session; /// A pass that seeks to optimize unnecessary moves of large enum types, if there is a large @@ -39,8 +39,7 @@ impl<'tcx> crate::MirPass<'tcx> for EnumSizeOpt { // platform, but it will still be valid. let mut alloc_cache = FxHashMap::default(); - let body_did = body.source.def_id(); - let param_env = tcx.param_env_reveal_all_normalized(body_did); + let typing_env = body.typing_env(tcx); let blocks = body.basic_blocks.as_mut(); let local_decls = &mut body.local_decls; @@ -58,7 +57,7 @@ impl<'tcx> crate::MirPass<'tcx> for EnumSizeOpt { let ty = lhs.ty(local_decls, tcx).ty; let (adt_def, num_variants, alloc_id) = - self.candidate(tcx, param_env, ty, &mut alloc_cache)?; + self.candidate(tcx, typing_env, ty, &mut alloc_cache)?; let source_info = st.source_info; let span = source_info.span; @@ -207,7 +206,7 @@ impl EnumSizeOpt { fn candidate<'tcx>( &self, tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ty: Ty<'tcx>, alloc_cache: &mut FxHashMap, AllocId>, ) -> Option<(AdtDef<'tcx>, usize, AllocId)> { @@ -215,7 +214,7 @@ impl EnumSizeOpt { ty::Adt(adt_def, _args) if adt_def.is_enum() => adt_def, _ => return None, }; - let layout = tcx.layout_of(param_env.and(ty)).ok()?; + let layout = tcx.layout_of(typing_env.as_query_input(ty)).ok()?; let variants = match &layout.variants { Variants::Single { .. } => return None, Variants::Multiple { tag_encoding: TagEncoding::Niche { .. }, .. } => return None, diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index d2d5facbbdc8..5651bf469d54 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -333,10 +333,14 @@ fn mir_keys(tcx: TyCtxt<'_>, (): ()) -> FxIndexSet { } fn mir_const_qualif(tcx: TyCtxt<'_>, def: LocalDefId) -> ConstQualifs { - let const_kind = tcx.hir().body_const_context(def); - + // N.B., this `borrow()` is guaranteed to be valid (i.e., the value + // cannot yet be stolen), because `mir_promoted()`, which steals + // from `mir_built()`, forces this query to execute before + // performing the steal. + let body = &tcx.mir_built(def).borrow(); + let ccx = check_consts::ConstCx::new(tcx, body); // No need to const-check a non-const `fn`. - match const_kind { + match ccx.const_kind { Some(ConstContext::Const { .. } | ConstContext::Static(_) | ConstContext::ConstFn) => {} None => span_bug!( tcx.def_span(def), @@ -344,20 +348,12 @@ fn mir_const_qualif(tcx: TyCtxt<'_>, def: LocalDefId) -> ConstQualifs { ), } - // N.B., this `borrow()` is guaranteed to be valid (i.e., the value - // cannot yet be stolen), because `mir_promoted()`, which steals - // from `mir_built()`, forces this query to execute before - // performing the steal. - let body = &tcx.mir_built(def).borrow(); - if body.return_ty().references_error() { // It's possible to reach here without an error being emitted (#121103). tcx.dcx().span_delayed_bug(body.span, "mir_const_qualif: MIR had errors"); return Default::default(); } - let ccx = check_consts::ConstCx { body, tcx, const_kind, param_env: tcx.param_env(def) }; - let mut validator = check_consts::check::Checker::new(&ccx); validator.check_body(); diff --git a/compiler/rustc_mir_transform/src/match_branches.rs b/compiler/rustc_mir_transform/src/match_branches.rs index 237227f5294d..ff027680c492 100644 --- a/compiler/rustc_mir_transform/src/match_branches.rs +++ b/compiler/rustc_mir_transform/src/match_branches.rs @@ -5,7 +5,7 @@ use rustc_index::IndexSlice; use rustc_middle::mir::patch::MirPatch; use rustc_middle::mir::*; use rustc_middle::ty::layout::{IntegerExt, TyAndLayout}; -use rustc_middle::ty::{ParamEnv, ScalarInt, Ty, TyCtxt}; +use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt}; use rustc_type_ir::TyKind::*; use super::simplify::simplify_cfg; @@ -19,8 +19,7 @@ impl<'tcx> crate::MirPass<'tcx> for MatchBranchSimplification { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let def_id = body.source.def_id(); - let param_env = tcx.param_env_reveal_all_normalized(def_id); - + let typing_env = body.typing_env(tcx); let mut should_cleanup = false; for i in 0..body.basic_blocks.len() { let bbs = &*body.basic_blocks; @@ -40,11 +39,11 @@ impl<'tcx> crate::MirPass<'tcx> for MatchBranchSimplification { _ => continue, }; - if SimplifyToIf.simplify(tcx, body, bb_idx, param_env).is_some() { + if SimplifyToIf.simplify(tcx, body, bb_idx, typing_env).is_some() { should_cleanup = true; continue; } - if SimplifyToExp::default().simplify(tcx, body, bb_idx, param_env).is_some() { + if SimplifyToExp::default().simplify(tcx, body, bb_idx, typing_env).is_some() { should_cleanup = true; continue; } @@ -65,7 +64,7 @@ trait SimplifyMatch<'tcx> { tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, switch_bb_idx: BasicBlock, - param_env: ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ) -> Option<()> { let bbs = &body.basic_blocks; let (discr, targets) = match bbs[switch_bb_idx].terminator().kind { @@ -74,7 +73,7 @@ trait SimplifyMatch<'tcx> { }; let discr_ty = discr.ty(body.local_decls(), tcx); - self.can_simplify(tcx, targets, param_env, bbs, discr_ty)?; + self.can_simplify(tcx, targets, typing_env, bbs, discr_ty)?; let mut patch = MirPatch::new(body); @@ -90,7 +89,16 @@ trait SimplifyMatch<'tcx> { let parent_end = Location { block: switch_bb_idx, statement_index }; patch.add_statement(parent_end, StatementKind::StorageLive(discr_local)); patch.add_assign(parent_end, Place::from(discr_local), Rvalue::Use(discr)); - self.new_stmts(tcx, targets, param_env, &mut patch, parent_end, bbs, discr_local, discr_ty); + self.new_stmts( + tcx, + targets, + typing_env, + &mut patch, + parent_end, + bbs, + discr_local, + discr_ty, + ); patch.add_statement(parent_end, StatementKind::StorageDead(discr_local)); patch.patch_terminator(switch_bb_idx, bbs[first].terminator().kind.clone()); patch.apply(body); @@ -104,7 +112,7 @@ trait SimplifyMatch<'tcx> { &mut self, tcx: TyCtxt<'tcx>, targets: &SwitchTargets, - param_env: ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, bbs: &IndexSlice>, discr_ty: Ty<'tcx>, ) -> Option<()>; @@ -113,7 +121,7 @@ trait SimplifyMatch<'tcx> { &self, tcx: TyCtxt<'tcx>, targets: &SwitchTargets, - param_env: ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, patch: &mut MirPatch<'tcx>, parent_end: Location, bbs: &IndexSlice>, @@ -160,7 +168,7 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToIf { &mut self, tcx: TyCtxt<'tcx>, targets: &SwitchTargets, - param_env: ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, bbs: &IndexSlice>, _discr_ty: Ty<'tcx>, ) -> Option<()> { @@ -197,8 +205,8 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToIf { ) if lhs_f == lhs_s && f_c.const_.ty().is_bool() && s_c.const_.ty().is_bool() - && f_c.const_.try_eval_bool(tcx, param_env).is_some() - && s_c.const_.try_eval_bool(tcx, param_env).is_some() => {} + && f_c.const_.try_eval_bool(tcx, typing_env).is_some() + && s_c.const_.try_eval_bool(tcx, typing_env).is_some() => {} // Otherwise we cannot optimize. Try another block. _ => return None, @@ -211,7 +219,7 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToIf { &self, tcx: TyCtxt<'tcx>, targets: &SwitchTargets, - param_env: ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, patch: &mut MirPatch<'tcx>, parent_end: Location, bbs: &IndexSlice>, @@ -235,15 +243,15 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToIf { StatementKind::Assign(box (_, Rvalue::Use(Operand::Constant(s_c)))), ) => { // From earlier loop we know that we are dealing with bool constants only: - let f_b = f_c.const_.try_eval_bool(tcx, param_env).unwrap(); - let s_b = s_c.const_.try_eval_bool(tcx, param_env).unwrap(); + let f_b = f_c.const_.try_eval_bool(tcx, typing_env).unwrap(); + let s_b = s_c.const_.try_eval_bool(tcx, typing_env).unwrap(); if f_b == s_b { // Same value in both blocks. Use statement as is. patch.add_statement(parent_end, f.kind.clone()); } else { // Different value between blocks. Make value conditional on switch // condition. - let size = tcx.layout_of(param_env.and(discr_ty)).unwrap().size; + let size = tcx.layout_of(typing_env.as_query_input(discr_ty)).unwrap().size; let const_cmp = Operand::const_from_scalar( tcx, discr_ty, @@ -363,7 +371,7 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToExp { &mut self, tcx: TyCtxt<'tcx>, targets: &SwitchTargets, - param_env: ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, bbs: &IndexSlice>, discr_ty: Ty<'tcx>, ) -> Option<()> { @@ -388,7 +396,7 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToExp { return None; } - let discr_layout = tcx.layout_of(param_env.and(discr_ty)).unwrap(); + let discr_layout = tcx.layout_of(typing_env.as_query_input(discr_ty)).unwrap(); let first_stmts = &bbs[first_target].statements; let (second_case_val, second_target) = target_iter.next().unwrap(); let second_stmts = &bbs[second_target].statements; @@ -414,8 +422,8 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToExp { && f_c.const_.ty().is_integral() => { match ( - f_c.const_.try_eval_scalar_int(tcx, param_env), - s_c.const_.try_eval_scalar_int(tcx, param_env), + f_c.const_.try_eval_scalar_int(tcx, typing_env), + s_c.const_.try_eval_scalar_int(tcx, typing_env), ) { (Some(f), Some(s)) if f == s => ExpectedTransformKind::SameByEq { place: lhs_f, @@ -467,11 +475,11 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToExp { StatementKind::Assign(box (lhs_s, Rvalue::Use(Operand::Constant(s_c)))), ) if lhs_f == lhs_s && s_c.const_.ty() == f_ty - && s_c.const_.try_eval_scalar_int(tcx, param_env) == Some(scalar) => {} + && s_c.const_.try_eval_scalar_int(tcx, typing_env) == Some(scalar) => {} ( ExpectedTransformKind::Cast { place: lhs_f, ty: f_ty }, StatementKind::Assign(box (lhs_s, Rvalue::Use(Operand::Constant(s_c)))), - ) if let Some(f) = s_c.const_.try_eval_scalar_int(tcx, param_env) + ) if let Some(f) = s_c.const_.try_eval_scalar_int(tcx, typing_env) && lhs_f == lhs_s && s_c.const_.ty() == f_ty && can_cast(tcx, other_val, discr_layout, f_ty, f) => {} @@ -487,7 +495,7 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToExp { &self, _tcx: TyCtxt<'tcx>, targets: &SwitchTargets, - _param_env: ParamEnv<'tcx>, + _typing_env: ty::TypingEnv<'tcx>, patch: &mut MirPatch<'tcx>, parent_end: Location, bbs: &IndexSlice>, diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs index fa9a6bfcf7cc..6be95b1f0f1e 100644 --- a/compiler/rustc_mir_transform/src/promote_consts.rs +++ b/compiler/rustc_mir_transform/src/promote_consts.rs @@ -325,7 +325,7 @@ impl<'tcx> Validator<'_, 'tcx> { if let TempState::Defined { location: loc, .. } = self.temps[local] && let Left(statement) = self.body.stmt_at(loc) && let Some((_, Rvalue::Use(Operand::Constant(c)))) = statement.kind.as_assign() - && let Some(idx) = c.const_.try_eval_target_usize(self.tcx, self.param_env) + && let Some(idx) = c.const_.try_eval_target_usize(self.tcx, self.typing_env) // Determine the type of the thing we are indexing. && let ty::Array(_, len) = place_base.ty(self.body, self.tcx).ty.kind() // It's an array; determine its length. @@ -490,7 +490,7 @@ impl<'tcx> Validator<'_, 'tcx> { // Integer division: the RHS must be a non-zero const. let rhs_val = match rhs { Operand::Constant(c) => { - c.const_.try_eval_scalar_int(self.tcx, self.param_env) + c.const_.try_eval_scalar_int(self.tcx, self.typing_env) } _ => None, }; @@ -509,7 +509,7 @@ impl<'tcx> Validator<'_, 'tcx> { let lhs_val = match lhs { Operand::Constant(c) => c .const_ - .try_eval_scalar_int(self.tcx, self.param_env), + .try_eval_scalar_int(self.tcx, self.typing_env), _ => None, }; let lhs_min = sz.signed_int_min(); diff --git a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs index 20c34a7469e3..f786c676e9e4 100644 --- a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs +++ b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs @@ -1,7 +1,7 @@ use rustc_abi::FieldIdx; use rustc_index::bit_set::ChunkedBitSet; use rustc_middle::mir::{Body, TerminatorKind}; -use rustc_middle::ty::{self, GenericArgsRef, ParamEnv, Ty, TyCtxt, VariantDef}; +use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, VariantDef}; use rustc_mir_dataflow::impls::MaybeInitializedPlaces; use rustc_mir_dataflow::move_paths::{LookupResult, MoveData, MovePathIndex}; use rustc_mir_dataflow::{Analysis, MaybeReachable, move_path_children_matching}; @@ -18,8 +18,8 @@ pub(super) struct RemoveUninitDrops; impl<'tcx> crate::MirPass<'tcx> for RemoveUninitDrops { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - let param_env = tcx.param_env(body.source.def_id()); - let move_data = MoveData::gather_moves(body, tcx, |ty| ty.needs_drop(tcx, param_env)); + let typing_env = body.typing_env(tcx); + let move_data = MoveData::gather_moves(body, tcx, |ty| ty.needs_drop(tcx, typing_env)); let mut maybe_inits = MaybeInitializedPlaces::new(tcx, body, &move_data) .iterate_to_fixpoint(tcx, body, Some("remove_uninit_drops")) @@ -40,7 +40,7 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveUninitDrops { let should_keep = is_needs_drop_and_init( tcx, - param_env, + typing_env, maybe_inits, &move_data, place.ty(body, tcx).ty, @@ -66,24 +66,24 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveUninitDrops { fn is_needs_drop_and_init<'tcx>( tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, maybe_inits: &ChunkedBitSet, move_data: &MoveData<'tcx>, ty: Ty<'tcx>, mpi: MovePathIndex, ) -> bool { // No need to look deeper if the root is definitely uninit or if it has no `Drop` impl. - if !maybe_inits.contains(mpi) || !ty.needs_drop(tcx, param_env) { + if !maybe_inits.contains(mpi) || !ty.needs_drop(tcx, typing_env) { return false; } let field_needs_drop_and_init = |(f, f_ty, mpi)| { let child = move_path_children_matching(move_data, mpi, |x| x.is_field_to(f)); let Some(mpi) = child else { - return Ty::needs_drop(f_ty, tcx, param_env); + return Ty::needs_drop(f_ty, tcx, typing_env); }; - is_needs_drop_and_init(tcx, param_env, maybe_inits, move_data, f_ty, mpi) + is_needs_drop_and_init(tcx, typing_env, maybe_inits, move_data, f_ty, mpi) }; // This pass is only needed for const-checking, so it doesn't handle as many cases as @@ -110,7 +110,7 @@ fn is_needs_drop_and_init<'tcx>( let downcast = move_path_children_matching(move_data, mpi, |x| x.is_downcast_to(vid)); let Some(dc_mpi) = downcast else { - return variant_needs_drop(tcx, param_env, args, variant); + return variant_needs_drop(tcx, typing_env, args, variant); }; dc_mpi @@ -139,12 +139,12 @@ fn is_needs_drop_and_init<'tcx>( fn variant_needs_drop<'tcx>( tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, args: GenericArgsRef<'tcx>, variant: &VariantDef, ) -> bool { variant.fields.iter().any(|field| { let f_ty = field.ty(tcx, args); - f_ty.needs_drop(tcx, param_env) + f_ty.needs_drop(tcx, typing_env) }) } diff --git a/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs b/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs index 28925ba1beb1..ad62b47a66d6 100644 --- a/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs +++ b/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs @@ -16,18 +16,18 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveUnneededDrops { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { trace!("Running RemoveUnneededDrops on {:?}", body.source); - let did = body.source.def_id(); - let param_env = tcx.param_env_reveal_all_normalized(did); + let typing_env = body.typing_env(tcx); let mut should_simplify = false; - for block in body.basic_blocks.as_mut() { let terminator = block.terminator_mut(); if let TerminatorKind::Drop { place, target, .. } = terminator.kind { let ty = place.ty(&body.local_decls, tcx); - if ty.ty.needs_drop(tcx, param_env) { + if ty.ty.needs_drop(tcx, typing_env) { continue; } - if !tcx.consider_optimizing(|| format!("RemoveUnneededDrops {did:?} ")) { + if !tcx.consider_optimizing(|| { + format!("RemoveUnneededDrops {:?}", body.source.def_id()) + }) { continue; } debug!("SUCCESS: replacing `drop` with goto({:?})", target); diff --git a/compiler/rustc_mir_transform/src/remove_zsts.rs b/compiler/rustc_mir_transform/src/remove_zsts.rs index f13bb1c5993d..2f723bccc191 100644 --- a/compiler/rustc_mir_transform/src/remove_zsts.rs +++ b/compiler/rustc_mir_transform/src/remove_zsts.rs @@ -21,9 +21,9 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveZsts { return; } - let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); + let typing_env = body.typing_env(tcx); let local_decls = &body.local_decls; - let mut replacer = Replacer { tcx, param_env, local_decls }; + let mut replacer = Replacer { tcx, typing_env, local_decls }; for var_debug_info in &mut body.var_debug_info { replacer.visit_var_debug_info(var_debug_info); } @@ -35,7 +35,7 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveZsts { struct Replacer<'a, 'tcx> { tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, local_decls: &'a LocalDecls<'tcx>, } @@ -61,7 +61,7 @@ impl<'tcx> Replacer<'_, 'tcx> { if !maybe_zst(ty) { return false; } - let Ok(layout) = self.tcx.layout_of(self.param_env.and(ty)) else { + let Ok(layout) = self.tcx.layout_of(self.typing_env.as_query_input(ty)) else { return false; }; layout.is_zst() diff --git a/compiler/rustc_mir_transform/src/reveal_all.rs b/compiler/rustc_mir_transform/src/reveal_all.rs index f3b2f78b31c3..587032ee7208 100644 --- a/compiler/rustc_mir_transform/src/reveal_all.rs +++ b/compiler/rustc_mir_transform/src/reveal_all.rs @@ -8,14 +8,16 @@ pub(super) struct RevealAll; impl<'tcx> crate::MirPass<'tcx> for RevealAll { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); - RevealAllVisitor { tcx, param_env }.visit_body_preserves_cfg(body); + // FIXME(#132279): This is used during the phase transition from analysis + // to runtime, so we have to manually specify the correct typing mode. + let typing_env = ty::TypingEnv::post_analysis(tcx, body.source.def_id()); + RevealAllVisitor { tcx, typing_env }.visit_body_preserves_cfg(body); } } struct RevealAllVisitor<'tcx> { tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, } impl<'tcx> MutVisitor<'tcx> for RevealAllVisitor<'tcx> { @@ -53,7 +55,7 @@ impl<'tcx> MutVisitor<'tcx> for RevealAllVisitor<'tcx> { // We have to use `try_normalize_erasing_regions` here, since it's // possible that we visit impossible-to-satisfy where clauses here, // see #91745 - if let Ok(c) = self.tcx.try_normalize_erasing_regions(self.param_env, constant.const_) { + if let Ok(c) = self.tcx.try_normalize_erasing_regions(self.typing_env, constant.const_) { constant.const_ = c; } self.super_const_operand(constant, location); @@ -64,7 +66,7 @@ impl<'tcx> MutVisitor<'tcx> for RevealAllVisitor<'tcx> { // We have to use `try_normalize_erasing_regions` here, since it's // possible that we visit impossible-to-satisfy where clauses here, // see #91745 - if let Ok(t) = self.tcx.try_normalize_erasing_regions(self.param_env, *ty) { + if let Ok(t) = self.tcx.try_normalize_erasing_regions(self.typing_env, *ty) { *ty = t; } } diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index ffa11f5b2135..f16cde7cd4eb 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -274,9 +274,9 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option>) if ty.is_some() { let patch = { - let param_env = tcx.param_env_reveal_all_normalized(def_id); + let typing_env = ty::TypingEnv::post_analysis(tcx, def_id); let mut elaborator = - DropShimElaborator { body: &body, patch: MirPatch::new(&body), tcx, param_env }; + DropShimElaborator { body: &body, patch: MirPatch::new(&body), tcx, typing_env }; let dropee = tcx.mk_place_deref(dropee_ptr); let resume_block = elaborator.patch.resume_block(); elaborate_drops::elaborate_drop( @@ -334,7 +334,7 @@ pub(super) struct DropShimElaborator<'a, 'tcx> { pub body: &'a Body<'tcx>, pub patch: MirPatch<'tcx>, pub tcx: TyCtxt<'tcx>, - pub param_env: ty::ParamEnv<'tcx>, + pub typing_env: ty::TypingEnv<'tcx>, } impl fmt::Debug for DropShimElaborator<'_, '_> { @@ -355,8 +355,8 @@ impl<'a, 'tcx> DropElaborator<'a, 'tcx> for DropShimElaborator<'a, 'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } - fn param_env(&self) -> ty::ParamEnv<'tcx> { - self.param_env + fn typing_env(&self) -> ty::TypingEnv<'tcx> { + self.typing_env } fn drop_style(&self, _path: Self::Path, mode: DropFlagMode) -> DropStyle { @@ -914,7 +914,7 @@ fn build_call_shim<'tcx>( pub(super) fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> { debug_assert!(tcx.is_constructor(ctor_id)); - let param_env = tcx.param_env_reveal_all_normalized(ctor_id); + let typing_env = ty::TypingEnv::post_analysis(tcx, ctor_id); // Normalize the sig. let sig = tcx @@ -922,7 +922,7 @@ pub(super) fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> { .instantiate_identity() .no_bound_vars() .expect("LBR in ADT constructor signature"); - let sig = tcx.normalize_erasing_regions(param_env, sig); + let sig = tcx.normalize_erasing_regions(typing_env, sig); let ty::Adt(adt_def, args) = sig.output().kind() else { bug!("unexpected type for ADT ctor {:?}", sig.output()); diff --git a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs index f1672272862c..139b25be0ab2 100644 --- a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs +++ b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs @@ -48,7 +48,7 @@ struct AsyncDestructorCtorShimBuilder<'tcx> { self_ty: Option>, span: Span, source_info: SourceInfo, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, stack: Vec>, last_bb: BasicBlock, @@ -86,14 +86,14 @@ impl<'tcx> AsyncDestructorCtorShimBuilder<'tcx> { // Usual case: noop() + unwind resume + return let mut bbs = IndexVec::with_capacity(3); - let param_env = tcx.param_env_reveal_all_normalized(def_id); + let typing_env = ty::TypingEnv::post_analysis(tcx, def_id); AsyncDestructorCtorShimBuilder { tcx, def_id, self_ty, span, source_info, - param_env, + typing_env, stack: Vec::with_capacity(Self::MAX_STACK_LEN), last_bb: bbs.push(BasicBlockData::new(None)), @@ -422,7 +422,7 @@ impl<'tcx> AsyncDestructorCtorShimBuilder<'tcx> { statements: Vec::new(), terminator: Some(Terminator { source_info, - kind: if self.locals[local].ty.needs_drop(self.tcx, self.param_env) { + kind: if self.locals[local].ty.needs_drop(self.tcx, self.typing_env) { TerminatorKind::Drop { place: local.into(), target: *top_cleanup_bb, diff --git a/compiler/rustc_mir_transform/src/simplify_branches.rs b/compiler/rustc_mir_transform/src/simplify_branches.rs index e83b4727c485..bea3d0d8557a 100644 --- a/compiler/rustc_mir_transform/src/simplify_branches.rs +++ b/compiler/rustc_mir_transform/src/simplify_branches.rs @@ -18,14 +18,14 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyConstCondition { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { trace!("Running SimplifyConstCondition on {:?}", body.source); - let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); + let typing_env = body.typing_env(tcx); 'blocks: for block in body.basic_blocks_mut() { for stmt in block.statements.iter_mut() { // Simplify `assume` of a known value: either a NOP or unreachable. if let StatementKind::Intrinsic(box ref intrinsic) = stmt.kind && let NonDivergingIntrinsic::Assume(discr) = intrinsic && let Operand::Constant(ref c) = discr - && let Some(constant) = c.const_.try_eval_bool(tcx, param_env) + && let Some(constant) = c.const_.try_eval_bool(tcx, typing_env) { if constant { stmt.make_nop(); @@ -42,7 +42,7 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyConstCondition { TerminatorKind::SwitchInt { discr: Operand::Constant(ref c), ref targets, .. } => { - let constant = c.const_.try_eval_bits(tcx, param_env); + let constant = c.const_.try_eval_bits(tcx, typing_env); if let Some(constant) = constant { let target = targets.target_for_value(constant); TerminatorKind::Goto { target } @@ -52,7 +52,7 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyConstCondition { } TerminatorKind::Assert { target, cond: Operand::Constant(ref c), expected, .. - } => match c.const_.try_eval_bool(tcx, param_env) { + } => match c.const_.try_eval_bool(tcx, typing_env) { Some(v) if v == expected => TerminatorKind::Goto { target }, _ => continue, }, diff --git a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs index 26496b7f3fe1..b6d801730866 100644 --- a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs +++ b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs @@ -37,7 +37,7 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyComparisonIntegral { let opts = helper.find_optimizations(); let mut storage_deads_to_insert = vec![]; let mut storage_deads_to_remove: Vec<(usize, BasicBlock)> = vec![]; - let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); + let typing_env = body.typing_env(tcx); for opt in opts { trace!("SUCCESS: Applying {:?}", opt); // replace terminator with a switchInt that switches on the integer directly @@ -46,7 +46,7 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyComparisonIntegral { let new_value = match opt.branch_value_scalar { Scalar::Int(int) => { let layout = tcx - .layout_of(param_env.and(opt.branch_value_ty)) + .layout_of(typing_env.as_query_input(opt.branch_value_ty)) .expect("if we have an evaluated constant we must know the layout"); int.to_bits(layout.size) } diff --git a/compiler/rustc_mir_transform/src/sroa.rs b/compiler/rustc_mir_transform/src/sroa.rs index 53bbb1220967..52b9ec1e0a35 100644 --- a/compiler/rustc_mir_transform/src/sroa.rs +++ b/compiler/rustc_mir_transform/src/sroa.rs @@ -28,12 +28,12 @@ impl<'tcx> crate::MirPass<'tcx> for ScalarReplacementOfAggregates { } let mut excluded = excluded_locals(body); - let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); + let typing_env = body.typing_env(tcx); loop { debug!(?excluded); - let escaping = escaping_locals(tcx, param_env, &excluded, body); + let escaping = escaping_locals(tcx, typing_env, &excluded, body); debug!(?escaping); - let replacements = compute_flattening(tcx, param_env, body, escaping); + let replacements = compute_flattening(tcx, typing_env, body, escaping); debug!(?replacements); let all_dead_locals = replace_flattened_locals(tcx, body, replacements); if !all_dead_locals.is_empty() { @@ -59,7 +59,7 @@ impl<'tcx> crate::MirPass<'tcx> for ScalarReplacementOfAggregates { /// client code. fn escaping_locals<'tcx>( tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, excluded: &BitSet, body: &Body<'tcx>, ) -> BitSet { @@ -84,7 +84,7 @@ fn escaping_locals<'tcx>( // niche, so we do not want to automatically exclude it. return false; } - let Ok(layout) = tcx.layout_of(param_env.and(ty)) else { + let Ok(layout) = tcx.layout_of(typing_env.as_query_input(ty)) else { // We can't get the layout return true; }; @@ -196,7 +196,7 @@ impl<'tcx> ReplacementMap<'tcx> { /// The replacement will be done later in `ReplacementVisitor`. fn compute_flattening<'tcx>( tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, body: &mut Body<'tcx>, escaping: BitSet, ) -> ReplacementMap<'tcx> { @@ -208,7 +208,7 @@ fn compute_flattening<'tcx>( } let decl = body.local_decls[local].clone(); let ty = decl.ty; - iter_fields(ty, tcx, param_env, |variant, field, field_ty| { + iter_fields(ty, tcx, typing_env, |variant, field, field_ty| { if variant.is_some() { // Downcasts are currently not supported. return; diff --git a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs index 3011af4d9d7d..57e255b7c32c 100644 --- a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs +++ b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs @@ -92,9 +92,7 @@ impl<'tcx> crate::MirPass<'tcx> for UnreachableEnumBranching { let Some(discriminant_ty) = get_switched_on_type(bb_data, tcx, body) else { continue }; - let layout = tcx.layout_of( - tcx.param_env_reveal_all_normalized(body.source.def_id()).and(discriminant_ty), - ); + let layout = tcx.layout_of(body.typing_env(tcx).as_query_input(discriminant_ty)); let mut allowed_variants = if let Ok(layout) = layout { // Find allowed variants based on uninhabited. diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index ae4e6ea6a749..ae0e6f594ee2 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -12,8 +12,7 @@ use rustc_middle::mir::visit::{NonUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::adjustment::PointerCoercion; use rustc_middle::ty::{ - self, CoroutineArgsExt, InstanceKind, ParamEnv, ScalarInt, Ty, TyCtxt, TypeVisitableExt, - Variance, + self, CoroutineArgsExt, InstanceKind, ScalarInt, Ty, TyCtxt, TypeVisitableExt, Variance, }; use rustc_middle::{bug, span_bug}; use rustc_trait_selection::traits::ObligationCtxt; @@ -47,9 +46,10 @@ impl<'tcx> crate::MirPass<'tcx> for Validator { if matches!(body.source.instance, InstanceKind::Intrinsic(..) | InstanceKind::Virtual(..)) { return; } + debug_assert_eq!(self.mir_phase, body.phase); let def_id = body.source.def_id(); - let mir_phase = self.mir_phase; - let param_env = mir_phase.param_env(tcx, def_id); + let mir_phase = body.phase; + let typing_env = body.typing_env(tcx); let can_unwind = if mir_phase <= MirPhase::Runtime(RuntimePhase::Initial) { // In this case `AbortUnwindingCalls` haven't yet been executed. true @@ -86,7 +86,7 @@ impl<'tcx> crate::MirPass<'tcx> for Validator { cfg_checker.check_cleanup_control_flow(); // Also run the TypeChecker. - for (location, msg) in validate_types(tcx, self.mir_phase, param_env, body, body) { + for (location, msg) in validate_types(tcx, self.mir_phase, typing_env, body, body) { cfg_checker.fail(location, msg); } @@ -532,12 +532,12 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { pub(super) fn validate_types<'tcx>( tcx: TyCtxt<'tcx>, mir_phase: MirPhase, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, body: &Body<'tcx>, caller_body: &Body<'tcx>, ) -> Vec<(Location, String)> { let mut type_checker = - TypeChecker { body, caller_body, tcx, param_env, mir_phase, failures: Vec::new() }; + TypeChecker { body, caller_body, tcx, typing_env, mir_phase, failures: Vec::new() }; type_checker.visit_body(body); type_checker.failures } @@ -546,7 +546,7 @@ struct TypeChecker<'a, 'tcx> { body: &'a Body<'tcx>, caller_body: &'a Body<'tcx>, tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, mir_phase: MirPhase, failures: Vec<(Location, String)>, } @@ -582,14 +582,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { Variance::Covariant }; - crate::util::relate_types( - self.tcx, - self.body.typing_mode(self.tcx), - self.param_env, - variance, - src, - dest, - ) + crate::util::relate_types(self.tcx, self.typing_env, variance, src, dest) } /// Check that the given predicate definitely holds in the param-env of this MIR body. @@ -608,12 +601,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { return true; } - let infcx = self.tcx.infer_ctxt().build(self.body.typing_mode(self.tcx)); + let (infcx, param_env) = self.tcx.infer_ctxt().build_with_typing_env(self.typing_env); let ocx = ObligationCtxt::new(&infcx); ocx.register_obligation(Obligation::new( self.tcx, ObligationCause::dummy(), - self.param_env, + param_env, pred, )); ocx.select_all_or_error().is_empty() @@ -630,7 +623,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { if let Operand::Copy(place) = operand { let ty = place.ty(&self.body.local_decls, self.tcx).ty; - if !ty.is_copy_modulo_regions(self.tcx, self.param_env) { + if !ty.is_copy_modulo_regions(self.tcx, self.typing_env.param_env) { self.fail(location, format!("`Operand::Copy` with non-`Copy` type {ty}")); } } @@ -802,8 +795,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { ProjectionElem::Subtype(ty) => { if !util::sub_types( self.tcx, - self.body.typing_mode(self.tcx), - self.param_env, + self.typing_env, ty, place_ref.ty(&self.body.local_decls, self.tcx).ty, ) { @@ -916,7 +908,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { assert!(adt_def.is_union()); assert_eq!(idx, FIRST_VARIANT); let dest_ty = self.tcx.normalize_erasing_regions( - self.param_env, + self.typing_env, adt_def.non_enum_variant().fields[field].ty(self.tcx, args), ); if let [field] = fields.raw.as_slice() { @@ -938,7 +930,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { for (src, dest) in std::iter::zip(fields, &variant.fields) { let dest_ty = self .tcx - .normalize_erasing_regions(self.param_env, dest.ty(self.tcx, args)); + .normalize_erasing_regions(self.typing_env, dest.ty(self.tcx, args)); if !self.mir_assign_valid_types(src.ty(self.body, self.tcx), dest_ty) { self.fail(location, "adt field has the wrong type"); } @@ -997,7 +989,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } // FIXME: check `Thin` instead of `Sized` - if !in_pointee.is_sized(self.tcx, self.param_env) { + if !in_pointee.is_sized(self.tcx, self.typing_env.param_env) { self.fail(location, "input pointer must be thin"); } } else { @@ -1012,7 +1004,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { if !self.mir_assign_valid_types(metadata_ty, self.tcx.types.usize) { self.fail(location, "slice metadata must be usize"); } - } else if pointee_ty.is_sized(self.tcx, self.param_env) { + } else if pointee_ty.is_sized(self.tcx, self.typing_env.param_env) { if metadata_ty != self.tcx.types.unit { self.fail(location, "metadata for pointer-to-thin must be unit"); } @@ -1301,8 +1293,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { if !self .tcx - .normalize_erasing_regions(self.param_env, op_ty) - .is_sized(self.tcx, self.param_env) + .normalize_erasing_regions(self.typing_env, op_ty) + .is_sized(self.tcx, self.typing_env.param_env) { self.fail( location, @@ -1311,8 +1303,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } if !self .tcx - .normalize_erasing_regions(self.param_env, *target_type) - .is_sized(self.tcx, self.param_env) + .normalize_erasing_regions(self.typing_env, *target_type) + .is_sized(self.tcx, self.typing_env.param_env) { self.fail( location, @@ -1353,7 +1345,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { return; }; - current_ty = self.tcx.normalize_erasing_regions(self.param_env, f_ty); + current_ty = self.tcx.normalize_erasing_regions(self.typing_env, f_ty); } ty::Adt(adt_def, args) => { let Some(field) = adt_def.variant(variant).fields.get(field) else { @@ -1362,7 +1354,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { }; let f_ty = field.ty(self.tcx, args); - current_ty = self.tcx.normalize_erasing_regions(self.param_env, f_ty); + current_ty = self.tcx.normalize_erasing_regions(self.typing_env, f_ty); } _ => { self.fail( diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 322deb539cdb..1b94c627f81c 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -427,7 +427,7 @@ fn collect_items_rec<'tcx>( let DefKind::Static { nested, .. } = tcx.def_kind(def_id) else { bug!() }; // Nested statics have no type. if !nested { - let ty = instance.ty(tcx, ty::ParamEnv::reveal_all()); + let ty = instance.ty(tcx, ty::TypingEnv::fully_monomorphized()); visit_drop_use(tcx, ty, true, starting_item.span, &mut used_items); } @@ -636,7 +636,7 @@ impl<'a, 'tcx> MirUsedCollector<'a, 'tcx> { trace!("monomorphize: self.instance={:?}", self.instance); self.instance.instantiate_mir_and_normalize_erasing_regions( self.tcx, - ty::ParamEnv::reveal_all(), + ty::TypingEnv::fully_monomorphized(), ty::EarlyBinder::bind(value), ) } @@ -647,12 +647,11 @@ impl<'a, 'tcx> MirUsedCollector<'a, 'tcx> { constant: &mir::ConstOperand<'tcx>, ) -> Option> { let const_ = self.monomorphize(constant.const_); - let param_env = ty::ParamEnv::reveal_all(); // Evaluate the constant. This makes const eval failure a collection-time error (rather than // a codegen-time error). rustc stops after collection if there was an error, so this // ensures codegen never has to worry about failing consts. // (codegen relies on this and ICEs will happen if this is violated.) - match const_.eval(self.tcx, param_env, constant.span) { + match const_.eval(self.tcx, ty::TypingEnv::fully_monomorphized(), constant.span) { Ok(v) => Some(v), Err(ErrorHandled::TooGeneric(..)) => span_bug!( constant.span, @@ -863,9 +862,20 @@ fn visit_fn_use<'tcx>( ) { if let ty::FnDef(def_id, args) = *ty.kind() { let instance = if is_direct_call { - ty::Instance::expect_resolve(tcx, ty::ParamEnv::reveal_all(), def_id, args, source) + ty::Instance::expect_resolve( + tcx, + ty::TypingEnv::fully_monomorphized(), + def_id, + args, + source, + ) } else { - match ty::Instance::resolve_for_fn_ptr(tcx, ty::ParamEnv::reveal_all(), def_id, args) { + match ty::Instance::resolve_for_fn_ptr( + tcx, + ty::TypingEnv::fully_monomorphized(), + def_id, + args, + ) { Some(instance) => instance, _ => bug!("failed to resolve instance for {ty}"), } @@ -1024,12 +1034,12 @@ fn find_vtable_types_for_unsizing<'tcx>( target_ty: Ty<'tcx>, ) -> (Ty<'tcx>, Ty<'tcx>) { let ptr_vtable = |inner_source: Ty<'tcx>, inner_target: Ty<'tcx>| { - let param_env = ty::ParamEnv::reveal_all(); + let typing_env = ty::TypingEnv::fully_monomorphized(); let type_has_metadata = |ty: Ty<'tcx>| -> bool { - if ty.is_sized(tcx.tcx, param_env) { + if ty.is_sized(tcx.tcx, typing_env.param_env) { return false; } - let tail = tcx.struct_tail_for_codegen(ty, param_env); + let tail = tcx.struct_tail_for_codegen(ty, typing_env); match tail.kind() { ty::Foreign(..) => false, ty::Str | ty::Slice(..) | ty::Dynamic(..) => true, @@ -1039,7 +1049,7 @@ fn find_vtable_types_for_unsizing<'tcx>( if type_has_metadata(inner_source) { (inner_source, inner_target) } else { - tcx.struct_lockstep_tails_for_codegen(inner_source, inner_target, param_env) + tcx.struct_lockstep_tails_for_codegen(inner_source, inner_target, typing_env) } }; @@ -1270,8 +1280,13 @@ fn visit_mentioned_item<'tcx>( match *item { MentionedItem::Fn(ty) => { if let ty::FnDef(def_id, args) = *ty.kind() { - let instance = - Instance::expect_resolve(tcx, ty::ParamEnv::reveal_all(), def_id, args, span); + let instance = Instance::expect_resolve( + tcx, + ty::TypingEnv::fully_monomorphized(), + def_id, + args, + span, + ); // `visit_instance_use` was written for "used" item collection but works just as well // for "mentioned" item collection. // We can set `is_direct_call`; that just means we'll skip a bunch of shims that anyway @@ -1487,13 +1502,13 @@ impl<'v> RootCollector<'_, 'v> { // regions must appear in the argument // listing. let main_ret_ty = self.tcx.normalize_erasing_regions( - ty::ParamEnv::reveal_all(), + ty::TypingEnv::fully_monomorphized(), main_ret_ty.no_bound_vars().unwrap(), ); let start_instance = Instance::expect_resolve( self.tcx, - ty::ParamEnv::reveal_all(), + ty::TypingEnv::fully_monomorphized(), start_def_id, self.tcx.mk_args(&[main_ret_ty.into()]), DUMMY_SP, @@ -1551,8 +1566,8 @@ fn create_mono_items_for_default_impls<'tcx>( return; } - let param_env = ty::ParamEnv::reveal_all(); - let trait_ref = tcx.normalize_erasing_regions(param_env, trait_ref); + let typing_env = ty::TypingEnv::fully_monomorphized(); + let trait_ref = tcx.normalize_erasing_regions(typing_env, trait_ref); let overridden_methods = tcx.impl_item_implementor_ids(item.owner_id); for method in tcx.provided_trait_methods(trait_ref.def_id) { if overridden_methods.contains_key(&method.def_id) { @@ -1567,7 +1582,7 @@ fn create_mono_items_for_default_impls<'tcx>( // only has lifetime generic parameters. This is validated by calling // `own_requires_monomorphization` on both the impl and method. let args = trait_ref.args.extend_to(tcx, method.def_id, only_region_params); - let instance = ty::Instance::expect_resolve(tcx, param_env, method.def_id, args, DUMMY_SP); + let instance = ty::Instance::expect_resolve(tcx, typing_env, method.def_id, args, DUMMY_SP); let mono_item = create_fn_mono_item(tcx, instance, DUMMY_SP); if mono_item.node.is_instantiable(tcx) && tcx.should_codegen_locally(instance) { diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs index eb576317678c..0f08930fb4c8 100644 --- a/compiler/rustc_monomorphize/src/lib.rs +++ b/compiler/rustc_monomorphize/src/lib.rs @@ -35,7 +35,9 @@ fn custom_coerce_unsize_info<'tcx>( [source_ty, target_ty], ); - match tcx.codegen_select_candidate((ty::ParamEnv::reveal_all(), trait_ref)) { + match tcx + .codegen_select_candidate(ty::TypingEnv::fully_monomorphized().as_query_input(trait_ref)) + { Ok(traits::ImplSource::UserDefined(traits::ImplSourceUserDefinedData { impl_def_id, .. diff --git a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs index 02b361456e48..30e634d82527 100644 --- a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs +++ b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs @@ -3,7 +3,7 @@ use rustc_hir::CRATE_HIR_ID; use rustc_middle::mir::{self, traversal}; use rustc_middle::ty::inherent::*; -use rustc_middle::ty::{self, Instance, InstanceKind, ParamEnv, Ty, TyCtxt}; +use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TyCtxt}; use rustc_session::lint::builtin::ABI_UNSUPPORTED_VECTOR_TYPES; use rustc_span::def_id::DefId; use rustc_span::{DUMMY_SP, Span, Symbol}; @@ -62,8 +62,9 @@ fn do_check_abi<'tcx>( /// Checks that the ABI of a given instance of a function does not contain vector-passed arguments /// or return values for which the corresponding target feature is not enabled. fn check_instance_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) { - let param_env = ParamEnv::reveal_all(); - let Ok(abi) = tcx.fn_abi_of_instance(param_env.and((instance, ty::List::empty()))) else { + let typing_env = ty::TypingEnv::fully_monomorphized(); + let Ok(abi) = tcx.fn_abi_of_instance(typing_env.as_query_input((instance, ty::List::empty()))) + else { // An error will be reported during codegen if we cannot determine the ABI of this // function. return; @@ -100,18 +101,18 @@ fn check_call_site_abi<'tcx>( // "Rust" ABI never passes arguments in vector registers. return; } - let param_env = ParamEnv::reveal_all(); + let typing_env = ty::TypingEnv::fully_monomorphized(); let callee_abi = match *callee.kind() { ty::FnPtr(..) => { - tcx.fn_abi_of_fn_ptr(param_env.and((callee.fn_sig(tcx), ty::List::empty()))) + tcx.fn_abi_of_fn_ptr(typing_env.as_query_input((callee.fn_sig(tcx), ty::List::empty()))) } ty::FnDef(def_id, args) => { // Intrinsics are handled separately by the compiler. if tcx.intrinsic(def_id).is_some() { return; } - let instance = ty::Instance::expect_resolve(tcx, param_env, def_id, args, DUMMY_SP); - tcx.fn_abi_of_instance(param_env.and((instance, ty::List::empty()))) + let instance = ty::Instance::expect_resolve(tcx, typing_env, def_id, args, DUMMY_SP); + tcx.fn_abi_of_instance(typing_env.as_query_input((instance, ty::List::empty()))) } _ => { panic!("Invalid function call"); @@ -151,7 +152,7 @@ fn check_callees_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, body: &m let callee_ty = func.ty(body, tcx); let callee_ty = instance.instantiate_mir_and_normalize_erasing_regions( tcx, - ty::ParamEnv::reveal_all(), + ty::TypingEnv::fully_monomorphized(), ty::EarlyBinder::bind(callee_ty), ); check_call_site_abi(tcx, callee_ty, *fn_span, body.source.instance); diff --git a/compiler/rustc_monomorphize/src/mono_checks/move_check.rs b/compiler/rustc_monomorphize/src/mono_checks/move_check.rs index 7f04bdf46f11..438d49fd7fb4 100644 --- a/compiler/rustc_monomorphize/src/mono_checks/move_check.rs +++ b/compiler/rustc_monomorphize/src/mono_checks/move_check.rs @@ -61,7 +61,7 @@ impl<'tcx> MoveCheckVisitor<'tcx> { trace!("monomorphize: self.instance={:?}", self.instance); self.instance.instantiate_mir_and_normalize_erasing_regions( self.tcx, - ty::ParamEnv::reveal_all(), + ty::TypingEnv::fully_monomorphized(), ty::EarlyBinder::bind(value), ) } @@ -128,7 +128,9 @@ impl<'tcx> MoveCheckVisitor<'tcx> { ) -> Option { let ty = operand.ty(self.body, self.tcx); let ty = self.monomorphize(ty); - let Ok(layout) = self.tcx.layout_of(ty::ParamEnv::reveal_all().and(ty)) else { + let Ok(layout) = + self.tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)) + else { return None; }; if layout.size.bytes_usize() > limit.0 { diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index 84e08ea881da..7240cfce0f7f 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs @@ -666,7 +666,7 @@ fn characteristic_def_id_of_mono_item<'tcx>( // This is a method within an impl, find out what the self-type is: let impl_self_ty = tcx.instantiate_and_normalize_erasing_regions( instance.args, - ty::ParamEnv::reveal_all(), + ty::TypingEnv::fully_monomorphized(), tcx.type_of(impl_def_id), ); if let Some(def_id) = characteristic_def_id_of_type(impl_self_ty) { diff --git a/compiler/rustc_monomorphize/src/util.rs b/compiler/rustc_monomorphize/src/util.rs index 093a697beeba..deb4ab433bfe 100644 --- a/compiler/rustc_monomorphize/src/util.rs +++ b/compiler/rustc_monomorphize/src/util.rs @@ -22,29 +22,29 @@ pub(crate) fn dump_closure_profile<'tcx>(tcx: TyCtxt<'tcx>, closure_instance: In let typeck_results = tcx.typeck(closure_def_id); if typeck_results.closure_size_eval.contains_key(&closure_def_id) { - let param_env = ty::ParamEnv::reveal_all(); + let typing_env = ty::TypingEnv::fully_monomorphized(); let ClosureSizeProfileData { before_feature_tys, after_feature_tys } = typeck_results.closure_size_eval[&closure_def_id]; let before_feature_tys = tcx.instantiate_and_normalize_erasing_regions( closure_instance.args, - param_env, + typing_env, ty::EarlyBinder::bind(before_feature_tys), ); let after_feature_tys = tcx.instantiate_and_normalize_erasing_regions( closure_instance.args, - param_env, + typing_env, ty::EarlyBinder::bind(after_feature_tys), ); let new_size = tcx - .layout_of(param_env.and(after_feature_tys)) + .layout_of(typing_env.as_query_input(after_feature_tys)) .map(|l| format!("{:?}", l.size.bytes())) .unwrap_or_else(|e| format!("Failed {e:?}")); let old_size = tcx - .layout_of(param_env.and(before_feature_tys)) + .layout_of(typing_env.as_query_input(before_feature_tys)) .map(|l| format!("{:?}", l.size.bytes())) .unwrap_or_else(|e| format!("Failed {e:?}")); diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index df4f0ffdd576..5f7405907127 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -262,7 +262,11 @@ where return ecx.forced_ambiguity(MaybeCause::Ambiguity); } - if cx.layout_is_pointer_like(goal.param_env, goal.predicate.self_ty()) { + if cx.layout_is_pointer_like( + ecx.typing_mode(goal.param_env), + goal.param_env, + goal.predicate.self_ty(), + ) { ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc) .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)) } else { diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 6b4e2d0f4e2f..fddbf5896ad8 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -77,18 +77,35 @@ impl<'a> Parser<'a> { if !self.eat(term) { let token_str = super::token_descr(&self.token); if !self.maybe_consume_incorrect_semicolon(items.last().map(|x| &**x)) { + let is_let = self.token.is_keyword(kw::Let); + let is_let_mut = is_let && self.look_ahead(1, |t| t.is_keyword(kw::Mut)); + let let_has_ident = is_let && !is_let_mut && self.is_kw_followed_by_ident(kw::Let); + let msg = format!("expected item, found {token_str}"); let mut err = self.dcx().struct_span_err(self.token.span, msg); - let span = self.token.span; - if self.is_kw_followed_by_ident(kw::Let) { - err.span_label( - span, - "consider using `const` or `static` instead of `let` for global variables", - ); + + let label = if is_let { + "`let` cannot be used for global variables" } else { - err.span_label(span, "expected item") - .note("for a full list of items that can appear in modules, see "); + "expected item" }; + err.span_label(self.token.span, label); + + if is_let { + if is_let_mut { + err.help("consider using `static` and a `Mutex` instead of `let mut`"); + } else if let_has_ident { + err.span_suggestion_short( + self.token.span, + "consider using `static` or `const` instead of `let`", + "static", + Applicability::MaybeIncorrect, + ); + } else { + err.help("consider using `static` or `const` instead of `let`"); + } + } + err.note("for a full list of items that can appear in modules, see "); return Err(err); } } diff --git a/compiler/rustc_passes/src/abi_test.rs b/compiler/rustc_passes/src/abi_test.rs index b1267562f7b8..4db8584b8841 100644 --- a/compiler/rustc_passes/src/abi_test.rs +++ b/compiler/rustc_passes/src/abi_test.rs @@ -59,9 +59,9 @@ fn unwrap_fn_abi<'tcx>( } fn dump_abi_of_fn_item(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) { - let param_env = tcx.param_env(item_def_id); + let typing_env = ty::TypingEnv::post_analysis(tcx, item_def_id); let args = GenericArgs::identity_for_item(tcx, item_def_id); - let instance = match Instance::try_resolve(tcx, param_env, item_def_id.into(), args) { + let instance = match Instance::try_resolve(tcx, typing_env, item_def_id.into(), args) { Ok(Some(instance)) => instance, Ok(None) => { // Not sure what to do here, but `LayoutError::Unknown` seems reasonable? @@ -75,7 +75,9 @@ fn dump_abi_of_fn_item(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribut Err(_guaranteed) => return, }; let abi = unwrap_fn_abi( - tcx.fn_abi_of_instance(param_env.and((instance, /* extra_args */ ty::List::empty()))), + tcx.fn_abi_of_instance( + typing_env.as_query_input((instance, /* extra_args */ ty::List::empty())), + ), tcx, item_def_id, ); @@ -117,10 +119,10 @@ fn test_abi_eq<'tcx>(abi1: &'tcx FnAbi<'tcx, Ty<'tcx>>, abi2: &'tcx FnAbi<'tcx, } fn dump_abi_of_fn_type(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) { - let param_env = tcx.param_env(item_def_id); + let typing_env = ty::TypingEnv::post_analysis(tcx, item_def_id); let ty = tcx.type_of(item_def_id).instantiate_identity(); let span = tcx.def_span(item_def_id); - if !ensure_wf(tcx, param_env, ty, item_def_id, span) { + if !ensure_wf(tcx, typing_env, ty, item_def_id, span) { return; } let meta_items = attr.meta_item_list().unwrap_or_default(); @@ -134,10 +136,10 @@ fn dump_abi_of_fn_type(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribut ); }; let abi = unwrap_fn_abi( - tcx.fn_abi_of_fn_ptr( - param_env - .and((sig_tys.with(*hdr), /* extra_args */ ty::List::empty())), - ), + tcx.fn_abi_of_fn_ptr(typing_env.as_query_input(( + sig_tys.with(*hdr), + /* extra_args */ ty::List::empty(), + ))), tcx, item_def_id, ); @@ -165,10 +167,10 @@ fn dump_abi_of_fn_type(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribut ); }; let abi1 = unwrap_fn_abi( - tcx.fn_abi_of_fn_ptr( - param_env - .and((sig_tys1.with(*hdr1), /* extra_args */ ty::List::empty())), - ), + tcx.fn_abi_of_fn_ptr(typing_env.as_query_input(( + sig_tys1.with(*hdr1), + /* extra_args */ ty::List::empty(), + ))), tcx, item_def_id, ); @@ -179,10 +181,10 @@ fn dump_abi_of_fn_type(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribut ); }; let abi2 = unwrap_fn_abi( - tcx.fn_abi_of_fn_ptr( - param_env - .and((sig_tys2.with(*hdr2), /* extra_args */ ty::List::empty())), - ), + tcx.fn_abi_of_fn_ptr(typing_env.as_query_input(( + sig_tys2.with(*hdr2), + /* extra_args */ ty::List::empty(), + ))), tcx, item_def_id, ); diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index b1db66fa52d4..ecf8d34ad840 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -273,7 +273,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { data.get(expr.hir_id).expect("no offset_of_data for offset_of"); let body_did = self.typeck_results().hir_owner.to_def_id(); - let param_env = self.tcx.param_env(body_did); + let typing_env = ty::TypingEnv::non_body_analysis(self.tcx, body_did); let mut current_ty = container; @@ -285,13 +285,13 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { self.insert_def_id(field.did); let field_ty = field.ty(self.tcx, args); - current_ty = self.tcx.normalize_erasing_regions(param_env, field_ty); + current_ty = self.tcx.normalize_erasing_regions(typing_env, field_ty); } // we don't need to mark tuple fields as live, // but we may need to mark subfields ty::Tuple(tys) => { current_ty = - self.tcx.normalize_erasing_regions(param_env, tys[field.as_usize()]); + self.tcx.normalize_erasing_regions(typing_env, tys[field.as_usize()]); } _ => span_bug!(expr.span, "named field access on non-ADT"), } @@ -944,7 +944,10 @@ impl<'tcx> DeadVisitor<'tcx> { if is_positional && self .tcx - .layout_of(self.tcx.param_env(field.did).and(field_type)) + .layout_of( + ty::TypingEnv::non_body_analysis(self.tcx, field.did) + .as_query_input(field_type), + ) .map_or(true, |layout| layout.is_zst()) { return ShouldWarnAboutField::No; diff --git a/compiler/rustc_passes/src/layout_test.rs b/compiler/rustc_passes/src/layout_test.rs index 986dce5b56dc..bb90b5a1e31c 100644 --- a/compiler/rustc_passes/src/layout_test.rs +++ b/compiler/rustc_passes/src/layout_test.rs @@ -2,10 +2,9 @@ use rustc_abi::{HasDataLayout, TargetDataLayout}; use rustc_ast::Attribute; use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; -use rustc_middle::infer::canonical::ir::TypingMode; use rustc_middle::span_bug; -use rustc_middle::ty::layout::{HasParamEnv, HasTyCtxt, LayoutError, LayoutOfHelpers}; -use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt}; +use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutError, LayoutOfHelpers}; +use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::Span; use rustc_span::source_map::Spanned; use rustc_span::symbol::sym; @@ -39,11 +38,13 @@ pub fn test_layout(tcx: TyCtxt<'_>) { pub fn ensure_wf<'tcx>( tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ty: Ty<'tcx>, def_id: LocalDefId, span: Span, ) -> bool { + let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env); + let ocx = traits::ObligationCtxt::new_with_diagnostics(&infcx); let pred = ty::ClauseKind::WellFormed(ty.into()); let obligation = traits::Obligation::new( tcx, @@ -55,8 +56,6 @@ pub fn ensure_wf<'tcx>( param_env, pred, ); - let infcx = tcx.infer_ctxt().build(TypingMode::from_param_env(param_env)); - let ocx = traits::ObligationCtxt::new_with_diagnostics(&infcx); ocx.register_obligation(obligation); let errors = ocx.select_all_or_error(); if !errors.is_empty() { @@ -69,13 +68,13 @@ pub fn ensure_wf<'tcx>( } fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) { - let param_env = tcx.param_env(item_def_id); + let typing_env = ty::TypingEnv::post_analysis(tcx, item_def_id); let ty = tcx.type_of(item_def_id).instantiate_identity(); let span = tcx.def_span(item_def_id.to_def_id()); - if !ensure_wf(tcx, param_env, ty, item_def_id, span) { + if !ensure_wf(tcx, typing_env, ty, item_def_id, span) { return; } - match tcx.layout_of(param_env.and(ty)) { + match tcx.layout_of(typing_env.as_query_input(ty)) { Ok(ty_layout) => { // Check out the `#[rustc_layout(..)]` attribute to tell what to dump. // The `..` are the names of fields to dump. @@ -107,19 +106,15 @@ fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) { span, homogeneous_aggregate: format!( "{:?}", - ty_layout.homogeneous_aggregate(&UnwrapLayoutCx { tcx, param_env }) + ty_layout + .homogeneous_aggregate(&UnwrapLayoutCx { tcx, typing_env }) ), }); } sym::debug => { - let normalized_ty = format!( - "{}", - tcx.normalize_erasing_regions( - param_env.with_reveal_all_normalized(tcx), - ty, - ) - ); + let normalized_ty = + format!("{}", tcx.normalize_erasing_regions(typing_env, ty)); // FIXME: using the `Debug` impl here isn't ideal. let ty_layout = format!("{:#?}", *ty_layout); tcx.dcx().emit_err(LayoutOf { span, normalized_ty, ty_layout }); @@ -140,7 +135,7 @@ fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) { struct UnwrapLayoutCx<'tcx> { tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, } impl<'tcx> LayoutOfHelpers<'tcx> for UnwrapLayoutCx<'tcx> { @@ -155,9 +150,9 @@ impl<'tcx> HasTyCtxt<'tcx> for UnwrapLayoutCx<'tcx> { } } -impl<'tcx> HasParamEnv<'tcx> for UnwrapLayoutCx<'tcx> { - fn param_env(&self) -> ParamEnv<'tcx> { - self.param_env +impl<'tcx> HasTypingEnv<'tcx> for UnwrapLayoutCx<'tcx> { + fn typing_env(&self) -> ty::TypingEnv<'tcx> { + self.typing_env } } diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index 366f7dd293c4..c6c998529522 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -1297,7 +1297,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { fn check_is_ty_uninhabited(&mut self, expr: &Expr<'_>, succ: LiveNode) -> LiveNode { let ty = self.typeck_results.expr_ty(expr); let m = self.ir.tcx.parent_module(expr.hir_id).to_def_id(); - if ty.is_inhabited_from(self.ir.tcx, m, self.param_env) { + if ty.is_inhabited_from(self.ir.tcx, m, ty::TypingEnv::from_param_env(self.param_env)) { return succ; } match self.ir.lnks[succ] { diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index 7cc6ba24450a..cc0763ac751d 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -9,6 +9,7 @@ use rustc_index::{Idx, IndexVec}; use rustc_middle::middle::stability::EvalResult; use rustc_middle::mir::{self, Const}; use rustc_middle::thir::{self, Pat, PatKind, PatRange, PatRangeBoundary}; +use rustc_middle::traits::Reveal; use rustc_middle::ty::layout::IntegerExt; use rustc_middle::ty::{ self, FieldDef, OpaqueTypeKey, ScalarInt, Ty, TyCtxt, TypeVisitableExt, VariantDef, @@ -108,6 +109,17 @@ impl<'p, 'tcx: 'p> fmt::Debug for RustcPatCtxt<'p, 'tcx> { } impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { + pub fn typing_mode(&self) -> ty::TypingMode<'tcx> { + debug_assert_eq!(self.param_env.reveal(), Reveal::UserFacing); + // FIXME(#132279): This is inside of a body. If we need to use the `param_env` + // and `typing_mode` we should reveal opaques defined by that body. + ty::TypingMode::non_body_analysis() + } + + pub fn typing_env(&self) -> ty::TypingEnv<'tcx> { + ty::TypingEnv { typing_mode: self.typing_mode(), param_env: self.param_env } + } + /// Type inference occasionally gives us opaque types in places where corresponding patterns /// have more specific types. To avoid inconsistencies as well as detect opaque uninhabited /// types, we use the corresponding concrete type if possible. @@ -139,7 +151,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { pub fn is_uninhabited(&self, ty: Ty<'tcx>) -> bool { !ty.inhabited_predicate(self.tcx).apply_revealing_opaque( self.tcx, - self.param_env, + self.typing_env(), self.module, &|key| self.reveal_opaque_key(key), ) @@ -179,7 +191,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { variant.fields.iter().map(move |field| { let ty = field.ty(self.tcx, args); // `field.ty()` doesn't normalize after instantiating. - let ty = self.tcx.normalize_erasing_regions(self.param_env, ty); + let ty = self.tcx.normalize_erasing_regions(self.typing_env(), ty); let ty = self.reveal_opaque_ty(ty); (field, ty) }) @@ -369,7 +381,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { let is_inhabited = v .inhabited_predicate(cx.tcx, *def) .instantiate(cx.tcx, args) - .apply_revealing_opaque(cx.tcx, cx.param_env, cx.module, &|key| { + .apply_revealing_opaque(cx.tcx, cx.typing_env(), cx.module, &|key| { cx.reveal_opaque_key(key) }); // Variants that depend on a disabled unstable feature. @@ -430,7 +442,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { match bdy { PatRangeBoundary::NegInfinity => MaybeInfiniteInt::NegInfinity, PatRangeBoundary::Finite(value) => { - let bits = value.eval_bits(self.tcx, self.param_env); + let bits = value.eval_bits(self.tcx, self.typing_env()); match *ty.kind() { ty::Int(ity) => { let size = Integer::from_int_ty(&self.tcx, ity).size().bits(); @@ -539,7 +551,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { PatKind::Constant { value } => { match ty.kind() { ty::Bool => { - ctor = match value.try_eval_bool(cx.tcx, cx.param_env) { + ctor = match value.try_eval_bool(cx.tcx, cx.typing_env()) { Some(b) => Bool(b), None => Opaque(OpaqueId::new()), }; @@ -547,7 +559,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { arity = 0; } ty::Char | ty::Int(_) | ty::Uint(_) => { - ctor = match value.try_eval_bits(cx.tcx, cx.param_env) { + ctor = match value.try_eval_bits(cx.tcx, cx.typing_env()) { Some(bits) => { let x = match *ty.kind() { ty::Int(ity) => { @@ -564,7 +576,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { arity = 0; } ty::Float(ty::FloatTy::F16) => { - ctor = match value.try_eval_bits(cx.tcx, cx.param_env) { + ctor = match value.try_eval_bits(cx.tcx, cx.typing_env()) { Some(bits) => { use rustc_apfloat::Float; let value = rustc_apfloat::ieee::Half::from_bits(bits); @@ -576,7 +588,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { arity = 0; } ty::Float(ty::FloatTy::F32) => { - ctor = match value.try_eval_bits(cx.tcx, cx.param_env) { + ctor = match value.try_eval_bits(cx.tcx, cx.typing_env()) { Some(bits) => { use rustc_apfloat::Float; let value = rustc_apfloat::ieee::Single::from_bits(bits); @@ -588,7 +600,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { arity = 0; } ty::Float(ty::FloatTy::F64) => { - ctor = match value.try_eval_bits(cx.tcx, cx.param_env) { + ctor = match value.try_eval_bits(cx.tcx, cx.typing_env()) { Some(bits) => { use rustc_apfloat::Float; let value = rustc_apfloat::ieee::Double::from_bits(bits); @@ -600,7 +612,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { arity = 0; } ty::Float(ty::FloatTy::F128) => { - ctor = match value.try_eval_bits(cx.tcx, cx.param_env) { + ctor = match value.try_eval_bits(cx.tcx, cx.typing_env()) { Some(bits) => { use rustc_apfloat::Float; let value = rustc_apfloat::ieee::Quad::from_bits(bits); @@ -649,8 +661,8 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { } ty::Float(fty) => { use rustc_apfloat::Float; - let lo = lo.as_finite().map(|c| c.eval_bits(cx.tcx, cx.param_env)); - let hi = hi.as_finite().map(|c| c.eval_bits(cx.tcx, cx.param_env)); + let lo = lo.as_finite().map(|c| c.eval_bits(cx.tcx, cx.typing_env())); + let hi = hi.as_finite().map(|c| c.eval_bits(cx.tcx, cx.typing_env())); match fty { ty::FloatTy::F16 => { use rustc_apfloat::ieee::Half; diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs index 0e6f905e7a10..2f4387e412d9 100644 --- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs +++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs @@ -133,7 +133,7 @@ fn encode_const<'tcx>( match ct_ty.kind() { ty::Int(ity) => { let bits = c - .try_to_bits(tcx, ty::ParamEnv::reveal_all()) + .try_to_bits(tcx, ty::TypingEnv::fully_monomorphized()) .expect("expected monomorphic const in cfi"); let val = Integer::from_int_ty(&tcx, *ity).size().sign_extend(bits) as i128; if val < 0 { @@ -143,7 +143,7 @@ fn encode_const<'tcx>( } ty::Uint(_) => { let val = c - .try_to_bits(tcx, ty::ParamEnv::reveal_all()) + .try_to_bits(tcx, ty::TypingEnv::fully_monomorphized()) .expect("expected monomorphic const in cfi"); let _ = write!(s, "{val}"); } diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/mod.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/mod.rs index 01568a0f61c3..562e288afaaf 100644 --- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/mod.rs +++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/mod.rs @@ -117,7 +117,9 @@ pub fn typeid_for_instance<'tcx>( .unwrap_or_else(|| bug!("typeid_for_instance: invalid option(s) `{:?}`", options.bits())); let instance = transform_instance(tcx, instance, transform_ty_options); let fn_abi = tcx - .fn_abi_of_instance(ty::ParamEnv::reveal_all().and((instance, ty::List::empty()))) + .fn_abi_of_instance( + ty::TypingEnv::fully_monomorphized().as_query_input((instance, ty::List::empty())), + ) .unwrap_or_else(|error| { bug!("typeid_for_instance: couldn't get fn_abi of instance {instance:?}: {error:?}") }); diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs index cba79a02f8b7..9c01bd043534 100644 --- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs +++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs @@ -136,18 +136,18 @@ impl<'tcx> TypeFolder> for TransformTy<'tcx> { return t; } let variant = adt_def.non_enum_variant(); - let param_env = self.tcx.param_env(variant.def_id); + let typing_env = ty::TypingEnv::post_analysis(self.tcx, variant.def_id); let field = variant.fields.iter().find(|field| { let ty = self.tcx.type_of(field.did).instantiate_identity(); let is_zst = self .tcx - .layout_of(param_env.and(ty)) + .layout_of(typing_env.as_query_input(ty)) .is_ok_and(|layout| layout.is_zst()); !is_zst }); if let Some(field) = field { let ty0 = self.tcx.normalize_erasing_regions( - ty::ParamEnv::reveal_all(), + ty::TypingEnv::fully_monomorphized(), field.ty(self.tcx, args), ); // Generalize any repr(transparent) user-defined type that is either a @@ -209,9 +209,9 @@ impl<'tcx> TypeFolder> for TransformTy<'tcx> { } } - ty::Alias(..) => { - self.fold_ty(self.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), t)) - } + ty::Alias(..) => self.fold_ty( + self.tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), t), + ), ty::Bound(..) | ty::Error(..) | ty::Infer(..) | ty::Param(..) | ty::Placeholder(..) => { bug!("fold_ty: unexpected `{:?}`", t.kind()); @@ -241,7 +241,7 @@ fn trait_object_ty<'tcx>(tcx: TyCtxt<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tc let alias_ty = ty::AliasTy::new_from_args(tcx, assoc_ty.def_id, super_trait_ref.args); let resolved = tcx.normalize_erasing_regions( - ty::ParamEnv::reveal_all(), + ty::TypingEnv::fully_monomorphized(), alias_ty.to_ty(tcx), ); debug!("Resolved {:?} -> {resolved}", alias_ty.to_ty(tcx)); @@ -376,7 +376,7 @@ pub(crate) fn transform_instance<'tcx>( // implementation will not. We need to walk back to the more general trait method let trait_ref = tcx.instantiate_and_normalize_erasing_regions( instance.args, - ty::ParamEnv::reveal_all(), + ty::TypingEnv::fully_monomorphized(), trait_ref, ); let invoke_ty = trait_object_ty(tcx, ty::Binder::dummy(trait_ref)); @@ -397,7 +397,7 @@ pub(crate) fn transform_instance<'tcx>( } else if tcx.is_closure_like(instance.def_id()) { // We're either a closure or a coroutine. Our goal is to find the trait we're defined on, // instantiate it, and take the type of its only method as our own. - let closure_ty = instance.ty(tcx, ty::ParamEnv::reveal_all()); + let closure_ty = instance.ty(tcx, ty::TypingEnv::fully_monomorphized()); let (trait_id, inputs) = match closure_ty.kind() { ty::Closure(..) => { let closure_args = instance.args.as_closure(); diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 44721bd889a0..f6e6fd33c48e 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -30,17 +30,18 @@ use rustc_target::spec::{ }; use tracing::debug; +pub use crate::config::cfg::{Cfg, CheckCfg, ExpectedValues}; +use crate::config::native_libs::parse_native_libs; use crate::errors::FileWriteFail; pub use crate::options::*; use crate::search_paths::SearchPath; -use crate::utils::{CanonicalizedPath, NativeLib, NativeLibKind}; +use crate::utils::CanonicalizedPath; use crate::{EarlyDiagCtxt, HashStableContext, Session, filesearch, lint}; mod cfg; +mod native_libs; pub mod sigpipe; -pub use cfg::{Cfg, CheckCfg, ExpectedValues}; - /// The different settings that the `-C strip` flag can have. #[derive(Clone, Copy, PartialEq, Hash, Debug)] pub enum Strip { @@ -2134,143 +2135,6 @@ fn parse_assert_incr_state( } } -fn parse_native_lib_kind( - early_dcx: &EarlyDiagCtxt, - matches: &getopts::Matches, - kind: &str, -) -> (NativeLibKind, Option) { - let (kind, modifiers) = match kind.split_once(':') { - None => (kind, None), - Some((kind, modifiers)) => (kind, Some(modifiers)), - }; - - let kind = match kind { - "static" => NativeLibKind::Static { bundle: None, whole_archive: None }, - "dylib" => NativeLibKind::Dylib { as_needed: None }, - "framework" => NativeLibKind::Framework { as_needed: None }, - "link-arg" => { - if !nightly_options::is_unstable_enabled(matches) { - let why = if nightly_options::match_is_nightly_build(matches) { - " and only accepted on the nightly compiler" - } else { - ", the `-Z unstable-options` flag must also be passed to use it" - }; - early_dcx.early_fatal(format!("library kind `link-arg` is unstable{why}")) - } - NativeLibKind::LinkArg - } - _ => early_dcx.early_fatal(format!( - "unknown library kind `{kind}`, expected one of: static, dylib, framework, link-arg" - )), - }; - match modifiers { - None => (kind, None), - Some(modifiers) => parse_native_lib_modifiers(early_dcx, kind, modifiers, matches), - } -} - -fn parse_native_lib_modifiers( - early_dcx: &EarlyDiagCtxt, - mut kind: NativeLibKind, - modifiers: &str, - matches: &getopts::Matches, -) -> (NativeLibKind, Option) { - let mut verbatim = None; - for modifier in modifiers.split(',') { - let (modifier, value) = match modifier.strip_prefix(['+', '-']) { - Some(m) => (m, modifier.starts_with('+')), - None => early_dcx.early_fatal( - "invalid linking modifier syntax, expected '+' or '-' prefix \ - before one of: bundle, verbatim, whole-archive, as-needed", - ), - }; - - let report_unstable_modifier = || { - if !nightly_options::is_unstable_enabled(matches) { - let why = if nightly_options::match_is_nightly_build(matches) { - " and only accepted on the nightly compiler" - } else { - ", the `-Z unstable-options` flag must also be passed to use it" - }; - early_dcx.early_fatal(format!("linking modifier `{modifier}` is unstable{why}")) - } - }; - let assign_modifier = |dst: &mut Option| { - if dst.is_some() { - let msg = format!("multiple `{modifier}` modifiers in a single `-l` option"); - early_dcx.early_fatal(msg) - } else { - *dst = Some(value); - } - }; - match (modifier, &mut kind) { - ("bundle", NativeLibKind::Static { bundle, .. }) => assign_modifier(bundle), - ("bundle", _) => early_dcx.early_fatal( - "linking modifier `bundle` is only compatible with `static` linking kind", - ), - - ("verbatim", _) => assign_modifier(&mut verbatim), - - ("whole-archive", NativeLibKind::Static { whole_archive, .. }) => { - assign_modifier(whole_archive) - } - ("whole-archive", _) => early_dcx.early_fatal( - "linking modifier `whole-archive` is only compatible with `static` linking kind", - ), - - ("as-needed", NativeLibKind::Dylib { as_needed }) - | ("as-needed", NativeLibKind::Framework { as_needed }) => { - report_unstable_modifier(); - assign_modifier(as_needed) - } - ("as-needed", _) => early_dcx.early_fatal( - "linking modifier `as-needed` is only compatible with \ - `dylib` and `framework` linking kinds", - ), - - // Note: this error also excludes the case with empty modifier - // string, like `modifiers = ""`. - _ => early_dcx.early_fatal(format!( - "unknown linking modifier `{modifier}`, expected one \ - of: bundle, verbatim, whole-archive, as-needed" - )), - } - } - - (kind, verbatim) -} - -fn parse_libs(early_dcx: &EarlyDiagCtxt, matches: &getopts::Matches) -> Vec { - matches - .opt_strs("l") - .into_iter() - .map(|s| { - // Parse string of the form "[KIND[:MODIFIERS]=]lib[:new_name]", - // where KIND is one of "dylib", "framework", "static", "link-arg" and - // where MODIFIERS are a comma separated list of supported modifiers - // (bundle, verbatim, whole-archive, as-needed). Each modifier is prefixed - // with either + or - to indicate whether it is enabled or disabled. - // The last value specified for a given modifier wins. - let (name, kind, verbatim) = match s.split_once('=') { - None => (s, NativeLibKind::Unspecified, None), - Some((kind, name)) => { - let (kind, verbatim) = parse_native_lib_kind(early_dcx, matches, kind); - (name.to_string(), kind, verbatim) - } - }; - - let (name, new_name) = match name.split_once(':') { - None => (name, None), - Some((name, new_name)) => (name.to_string(), Some(new_name.to_owned())), - }; - if name.is_empty() { - early_dcx.early_fatal("library name must not be empty"); - } - NativeLib { name, new_name, kind, verbatim } - }) - .collect() -} - pub fn parse_externs( early_dcx: &EarlyDiagCtxt, matches: &getopts::Matches, @@ -2644,7 +2508,10 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M let debuginfo = select_debuginfo(matches, &cg); let debuginfo_compression = unstable_opts.debuginfo_compression; - let libs = parse_libs(early_dcx, matches); + let crate_name = matches.opt_str("crate-name"); + let unstable_features = UnstableFeatures::from_environment(crate_name.as_deref()); + // Parse any `-l` flags, which link to native libraries. + let libs = parse_native_libs(early_dcx, &unstable_opts, unstable_features, matches); let test = matches.opt_present("test"); @@ -2659,8 +2526,6 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M let externs = parse_externs(early_dcx, matches, &unstable_opts); - let crate_name = matches.opt_str("crate-name"); - let remap_path_prefix = parse_remap_path_prefix(early_dcx, matches, &unstable_opts); let pretty = parse_pretty(early_dcx, &unstable_opts); @@ -2734,7 +2599,7 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M error_format, diagnostic_width, externs, - unstable_features: UnstableFeatures::from_environment(crate_name.as_deref()), + unstable_features, crate_name, libs, debug_assertions, diff --git a/compiler/rustc_session/src/config/native_libs.rs b/compiler/rustc_session/src/config/native_libs.rs new file mode 100644 index 000000000000..f1f0aeb5e599 --- /dev/null +++ b/compiler/rustc_session/src/config/native_libs.rs @@ -0,0 +1,192 @@ +//! Parser for the `-l` command-line option, which links the generated crate to +//! a native library. +//! +//! (There is also a similar but separate syntax for `#[link]` attributes, +//! which have their own parser in `rustc_metadata`.) + +use rustc_feature::UnstableFeatures; + +use crate::EarlyDiagCtxt; +use crate::config::UnstableOptions; +use crate::utils::{NativeLib, NativeLibKind}; + +#[cfg(test)] +mod tests; + +/// Parses all `-l` options. +pub(crate) fn parse_native_libs( + early_dcx: &EarlyDiagCtxt, + unstable_opts: &UnstableOptions, + unstable_features: UnstableFeatures, + matches: &getopts::Matches, +) -> Vec { + let cx = ParseNativeLibCx { + early_dcx, + unstable_options_enabled: unstable_opts.unstable_options, + is_nightly: unstable_features.is_nightly_build(), + }; + matches.opt_strs("l").into_iter().map(|value| parse_native_lib(&cx, &value)).collect() +} + +struct ParseNativeLibCx<'a> { + early_dcx: &'a EarlyDiagCtxt, + unstable_options_enabled: bool, + is_nightly: bool, +} + +impl ParseNativeLibCx<'_> { + /// If unstable values are not permitted, exits with a fatal error made by + /// combining the given strings. + fn on_unstable_value(&self, message: &str, if_nightly: &str, if_stable: &str) { + if self.unstable_options_enabled { + return; + } + + let suffix = if self.is_nightly { if_nightly } else { if_stable }; + self.early_dcx.early_fatal(format!("{message}{suffix}")); + } +} + +/// Parses the value of a single `-l` option. +fn parse_native_lib(cx: &ParseNativeLibCx<'_>, value: &str) -> NativeLib { + let NativeLibParts { kind, modifiers, name, new_name } = split_native_lib_value(value); + + let kind = kind.map_or(NativeLibKind::Unspecified, |kind| match kind { + "static" => NativeLibKind::Static { bundle: None, whole_archive: None }, + "dylib" => NativeLibKind::Dylib { as_needed: None }, + "framework" => NativeLibKind::Framework { as_needed: None }, + "link-arg" => { + cx.on_unstable_value( + "library kind `link-arg` is unstable", + ", the `-Z unstable-options` flag must also be passed to use it", + " and only accepted on the nightly compiler", + ); + NativeLibKind::LinkArg + } + _ => cx.early_dcx.early_fatal(format!( + "unknown library kind `{kind}`, expected one of: static, dylib, framework, link-arg" + )), + }); + + // Provisionally create the result, so that modifiers can modify it. + let mut native_lib = NativeLib { + name: name.to_owned(), + new_name: new_name.map(str::to_owned), + kind, + verbatim: None, + }; + + if let Some(modifiers) = modifiers { + // If multiple modifiers are present, they are separated by commas. + for modifier in modifiers.split(',') { + parse_and_apply_modifier(cx, modifier, &mut native_lib); + } + } + + if native_lib.name.is_empty() { + cx.early_dcx.early_fatal("library name must not be empty"); + } + + native_lib +} + +/// Parses one of the comma-separated modifiers (prefixed by `+` or `-`), and +/// modifies `native_lib` appropriately. +/// +/// Exits with a fatal error if a malformed/unknown/inappropriate modifier is +/// found. +fn parse_and_apply_modifier(cx: &ParseNativeLibCx<'_>, modifier: &str, native_lib: &mut NativeLib) { + let early_dcx = cx.early_dcx; + + // Split off the leading `+` or `-` into a boolean value. + let (modifier, value) = match modifier.split_at_checked(1) { + Some(("+", m)) => (m, true), + Some(("-", m)) => (m, false), + _ => cx.early_dcx.early_fatal( + "invalid linking modifier syntax, expected '+' or '-' prefix \ + before one of: bundle, verbatim, whole-archive, as-needed", + ), + }; + + // Assigns the value (from `+` or `-`) to an empty `Option`, or emits + // a fatal error if the option has already been set. + let assign_modifier = |opt_bool: &mut Option| { + if opt_bool.is_some() { + let msg = format!("multiple `{modifier}` modifiers in a single `-l` option"); + early_dcx.early_fatal(msg) + } + *opt_bool = Some(value); + }; + + // Check that the modifier is applicable to the native lib kind, and apply it. + match (modifier, &mut native_lib.kind) { + ("bundle", NativeLibKind::Static { bundle, .. }) => assign_modifier(bundle), + ("bundle", _) => early_dcx + .early_fatal("linking modifier `bundle` is only compatible with `static` linking kind"), + + ("verbatim", _) => assign_modifier(&mut native_lib.verbatim), + + ("whole-archive", NativeLibKind::Static { whole_archive, .. }) => { + assign_modifier(whole_archive) + } + ("whole-archive", _) => early_dcx.early_fatal( + "linking modifier `whole-archive` is only compatible with `static` linking kind", + ), + + ("as-needed", NativeLibKind::Dylib { as_needed }) + | ("as-needed", NativeLibKind::Framework { as_needed }) => { + cx.on_unstable_value( + "linking modifier `as-needed` is unstable", + ", the `-Z unstable-options` flag must also be passed to use it", + " and only accepted on the nightly compiler", + ); + assign_modifier(as_needed) + } + ("as-needed", _) => early_dcx.early_fatal( + "linking modifier `as-needed` is only compatible with \ + `dylib` and `framework` linking kinds", + ), + + _ => early_dcx.early_fatal(format!( + "unknown linking modifier `{modifier}`, expected one \ + of: bundle, verbatim, whole-archive, as-needed" + )), + } +} + +#[derive(Debug, PartialEq, Eq)] +struct NativeLibParts<'a> { + kind: Option<&'a str>, + modifiers: Option<&'a str>, + name: &'a str, + new_name: Option<&'a str>, +} + +/// Splits a string of the form `[KIND[:MODIFIERS]=]NAME[:NEW_NAME]` into those +/// individual parts. This cannot fail, but the resulting strings require +/// further validation. +fn split_native_lib_value(value: &str) -> NativeLibParts<'_> { + // Split the initial value into `[KIND=]NAME`. + let name = value; + let (kind, name) = match name.split_once('=') { + Some((prefix, name)) => (Some(prefix), name), + None => (None, name), + }; + + // Split the kind part, if present, into `KIND[:MODIFIERS]`. + let (kind, modifiers) = match kind { + Some(kind) => match kind.split_once(':') { + Some((kind, modifiers)) => (Some(kind), Some(modifiers)), + None => (Some(kind), None), + }, + None => (None, None), + }; + + // Split the name part into `NAME[:NEW_NAME]`. + let (name, new_name) = match name.split_once(':') { + Some((name, new_name)) => (name, Some(new_name)), + None => (name, None), + }; + + NativeLibParts { kind, modifiers, name, new_name } +} diff --git a/compiler/rustc_session/src/config/native_libs/tests.rs b/compiler/rustc_session/src/config/native_libs/tests.rs new file mode 100644 index 000000000000..3bcab93ef4b8 --- /dev/null +++ b/compiler/rustc_session/src/config/native_libs/tests.rs @@ -0,0 +1,50 @@ +use crate::config::native_libs::{NativeLibParts, split_native_lib_value}; + +#[test] +fn split() { + // This is a unit test for some implementation details, so consider deleting + // it if it gets in the way. + use NativeLibParts as P; + + let examples = &[ + ("", P { kind: None, modifiers: None, name: "", new_name: None }), + ("foo", P { kind: None, modifiers: None, name: "foo", new_name: None }), + ("foo:", P { kind: None, modifiers: None, name: "foo", new_name: Some("") }), + ("foo:bar", P { kind: None, modifiers: None, name: "foo", new_name: Some("bar") }), + (":bar", P { kind: None, modifiers: None, name: "", new_name: Some("bar") }), + ("kind=foo", P { kind: Some("kind"), modifiers: None, name: "foo", new_name: None }), + (":mods=foo", P { kind: Some(""), modifiers: Some("mods"), name: "foo", new_name: None }), + (":mods=:bar", P { + kind: Some(""), + modifiers: Some("mods"), + name: "", + new_name: Some("bar"), + }), + ("kind=foo:bar", P { + kind: Some("kind"), + modifiers: None, + name: "foo", + new_name: Some("bar"), + }), + ("kind:mods=foo", P { + kind: Some("kind"), + modifiers: Some("mods"), + name: "foo", + new_name: None, + }), + ("kind:mods=foo:bar", P { + kind: Some("kind"), + modifiers: Some("mods"), + name: "foo", + new_name: Some("bar"), + }), + ("::==::", P { kind: Some(""), modifiers: Some(":"), name: "=", new_name: Some(":") }), + ("==::==", P { kind: Some(""), modifiers: None, name: "=", new_name: Some(":==") }), + ]; + + for &(value, ref expected) in examples { + println!("{value:?}"); + let actual = split_native_lib_value(value); + assert_eq!(&actual, expected); + } +} diff --git a/compiler/rustc_smir/src/rustc_smir/alloc.rs b/compiler/rustc_smir/src/rustc_smir/alloc.rs index 5c09879f60e1..4e8db6096d4f 100644 --- a/compiler/rustc_smir/src/rustc_smir/alloc.rs +++ b/compiler/rustc_smir/src/rustc_smir/alloc.rs @@ -41,7 +41,7 @@ pub(crate) fn try_new_allocation<'tcx>( let size = scalar.size(); let align = tables .tcx - .layout_of(rustc_middle::ty::ParamEnv::reveal_all().and(ty)) + .layout_of(rustc_middle::ty::TypingEnv::fully_monomorphized().as_query_input(ty)) .map_err(|e| e.stable(tables))? .align; let mut allocation = rustc_middle::mir::interpret::Allocation::uninit(size, align.abi); @@ -53,7 +53,7 @@ pub(crate) fn try_new_allocation<'tcx>( ConstValue::ZeroSized => { let align = tables .tcx - .layout_of(rustc_middle::ty::ParamEnv::empty().and(ty)) + .layout_of(rustc_middle::ty::TypingEnv::fully_monomorphized().as_query_input(ty)) .map_err(|e| e.stable(tables))? .align; new_empty_allocation(align.abi) @@ -66,7 +66,7 @@ pub(crate) fn try_new_allocation<'tcx>( rustc_middle::mir::interpret::Scalar::from_target_usize(meta, &tables.tcx); let layout = tables .tcx - .layout_of(rustc_middle::ty::ParamEnv::reveal_all().and(ty)) + .layout_of(rustc_middle::ty::TypingEnv::fully_monomorphized().as_query_input(ty)) .map_err(|e| e.stable(tables))?; let mut allocation = rustc_middle::mir::interpret::Allocation::uninit(layout.size, layout.align.abi); @@ -90,7 +90,7 @@ pub(crate) fn try_new_allocation<'tcx>( let alloc = tables.tcx.global_alloc(alloc_id).unwrap_memory(); let ty_size = tables .tcx - .layout_of(rustc_middle::ty::ParamEnv::reveal_all().and(ty)) + .layout_of(rustc_middle::ty::TypingEnv::fully_monomorphized().as_query_input(ty)) .map_err(|e| e.stable(tables))? .size; allocation_filter(&alloc.0, alloc_range(offset, ty_size), tables) diff --git a/compiler/rustc_smir/src/rustc_smir/builder.rs b/compiler/rustc_smir/src/rustc_smir/builder.rs index cd91fc26c101..2eb0cea0e853 100644 --- a/compiler/rustc_smir/src/rustc_smir/builder.rs +++ b/compiler/rustc_smir/src/rustc_smir/builder.rs @@ -40,7 +40,7 @@ impl<'tcx> BodyBuilder<'tcx> { { let mut mono_body = self.instance.instantiate_mir_and_normalize_erasing_regions( tables.tcx, - ty::ParamEnv::reveal_all(), + ty::TypingEnv::fully_monomorphized(), ty::EarlyBinder::bind(body), ); self.visit_body(&mut mono_body); @@ -60,7 +60,7 @@ impl<'tcx> MutVisitor<'tcx> for BodyBuilder<'tcx> { location: mir::Location, ) { let const_ = constant.const_; - let val = match const_.eval(self.tcx, ty::ParamEnv::reveal_all(), constant.span) { + let val = match const_.eval(self.tcx, ty::TypingEnv::fully_monomorphized(), constant.span) { Ok(v) => v, Err(mir::interpret::ErrorHandled::Reported(..)) => return, Err(mir::interpret::ErrorHandled::TooGeneric(..)) => { diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs index 3db65692af78..b19adf321c32 100644 --- a/compiler/rustc_smir/src/rustc_smir/context.rs +++ b/compiler/rustc_smir/src/rustc_smir/context.rs @@ -11,7 +11,7 @@ use std::iter; use rustc_abi::HasDataLayout; use rustc_hir::LangItem; use rustc_middle::ty::layout::{ - FnAbiOf, FnAbiOfHelpers, HasParamEnv, HasTyCtxt, LayoutOf, LayoutOfHelpers, + FnAbiOf, FnAbiOfHelpers, HasTyCtxt, HasTypingEnv, LayoutOf, LayoutOfHelpers, }; use rustc_middle::ty::print::{with_forced_trimmed_paths, with_no_trimmed_paths}; use rustc_middle::ty::{ @@ -410,7 +410,7 @@ impl<'tcx> Context for TablesWrapper<'tcx> { let tcx = tables.tcx; let mir_const = cnst.internal(&mut *tables, tcx); mir_const - .try_eval_target_usize(tables.tcx, ParamEnv::empty()) + .try_eval_target_usize(tables.tcx, ty::TypingEnv::fully_monomorphized()) .ok_or_else(|| Error::new(format!("Const `{cnst:?}` cannot be encoded as u64"))) } fn eval_target_usize_ty(&self, cnst: &TyConst) -> Result { @@ -428,7 +428,7 @@ impl<'tcx> Context for TablesWrapper<'tcx> { let ty_internal = ty.internal(&mut *tables, tcx); let size = tables .tcx - .layout_of(ParamEnv::empty().and(ty_internal)) + .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty_internal)) .map_err(|err| { Error::new(format!( "Cannot create a zero-sized constant for type `{ty_internal}`: {err}" @@ -469,7 +469,11 @@ impl<'tcx> Context for TablesWrapper<'tcx> { let mut tables = self.0.borrow_mut(); let tcx = tables.tcx; let ty = ty::Ty::new_uint(tcx, uint_ty.internal(&mut *tables, tcx)); - let size = tables.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap().size; + let size = tables + .tcx + .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)) + .unwrap() + .size; // We don't use Const::from_bits since it doesn't have any error checking. let scalar = ScalarInt::try_from_uint(value, size).ok_or_else(|| { @@ -486,7 +490,11 @@ impl<'tcx> Context for TablesWrapper<'tcx> { let mut tables = self.0.borrow_mut(); let tcx = tables.tcx; let ty = ty::Ty::new_uint(tcx, uint_ty.internal(&mut *tables, tcx)); - let size = tables.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap().size; + let size = tables + .tcx + .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)) + .unwrap() + .size; // We don't use Const::from_bits since it doesn't have any error checking. let scalar = ScalarInt::try_from_uint(value, size).ok_or_else(|| { @@ -523,7 +531,11 @@ impl<'tcx> Context for TablesWrapper<'tcx> { let def_ty = tables.tcx.type_of(item.internal(&mut *tables, tcx)); tables .tcx - .instantiate_and_normalize_erasing_regions(args, ty::ParamEnv::reveal_all(), def_ty) + .instantiate_and_normalize_erasing_regions( + args, + ty::TypingEnv::fully_monomorphized(), + def_ty, + ) .stable(&mut *tables) } @@ -573,7 +585,7 @@ impl<'tcx> Context for TablesWrapper<'tcx> { let mut tables = self.0.borrow_mut(); let instance = tables.instances[def]; assert!(!instance.has_non_region_param(), "{instance:?} needs further instantiation"); - instance.ty(tables.tcx, ParamEnv::reveal_all()).stable(&mut *tables) + instance.ty(tables.tcx, ty::TypingEnv::fully_monomorphized()).stable(&mut *tables) } fn instance_args(&self, def: InstanceDef) -> GenericArgs { @@ -642,7 +654,12 @@ impl<'tcx> Context for TablesWrapper<'tcx> { let tcx = tables.tcx; let def_id = def.0.internal(&mut *tables, tcx); let args_ref = args.internal(&mut *tables, tcx); - match Instance::try_resolve(tables.tcx, ParamEnv::reveal_all(), def_id, args_ref) { + match Instance::try_resolve( + tables.tcx, + ty::TypingEnv::fully_monomorphized(), + def_id, + args_ref, + ) { Ok(Some(instance)) => Some(instance.stable(&mut *tables)), Ok(None) | Err(_) => None, } @@ -665,8 +682,13 @@ impl<'tcx> Context for TablesWrapper<'tcx> { let tcx = tables.tcx; let def_id = def.0.internal(&mut *tables, tcx); let args_ref = args.internal(&mut *tables, tcx); - Instance::resolve_for_fn_ptr(tables.tcx, ParamEnv::reveal_all(), def_id, args_ref) - .stable(&mut *tables) + Instance::resolve_for_fn_ptr( + tables.tcx, + ty::TypingEnv::fully_monomorphized(), + def_id, + args_ref, + ) + .stable(&mut *tables) } fn resolve_closure( @@ -827,9 +849,9 @@ impl<'tcx> LayoutOfHelpers<'tcx> for Tables<'tcx> { } } -impl<'tcx> HasParamEnv<'tcx> for Tables<'tcx> { - fn param_env(&self) -> ty::ParamEnv<'tcx> { - ty::ParamEnv::reveal_all() +impl<'tcx> HasTypingEnv<'tcx> for Tables<'tcx> { + fn typing_env(&self) -> ty::TypingEnv<'tcx> { + ty::TypingEnv::fully_monomorphized() } } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 5d4ba4be5b8d..a562d34abdee 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1666,7 +1666,6 @@ symbols! { rustc_const_panic_str, rustc_const_stable, rustc_const_stable_indirect, - rustc_const_stable_intrinsic, rustc_const_unstable, rustc_conversion_suggestion, rustc_deallocator, @@ -1696,6 +1695,7 @@ symbols! { rustc_inherit_overflow_checks, rustc_insignificant_dtor, rustc_intrinsic, + rustc_intrinsic_const_stable_indirect, rustc_intrinsic_must_be_overridden, rustc_layout, rustc_layout_scalar_valid_range_end, diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 05b4ff327a97..94f51b87cff6 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -26,7 +26,7 @@ pub(super) fn mangle<'tcx>( ) -> String { let def_id = instance.def_id(); // FIXME(eddyb) this should ideally not be needed. - let args = tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), instance.args); + let args = tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), instance.args); let prefix = "_R"; let mut cx: SymbolMangler<'_> = SymbolMangler { @@ -237,15 +237,16 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { if !args.is_empty() { param_env = EarlyBinder::bind(param_env).instantiate(self.tcx, args); } + let typing_env = ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env }; match &mut impl_trait_ref { Some(impl_trait_ref) => { assert_eq!(impl_trait_ref.self_ty(), self_ty); - *impl_trait_ref = self.tcx.normalize_erasing_regions(param_env, *impl_trait_ref); + *impl_trait_ref = self.tcx.normalize_erasing_regions(typing_env, *impl_trait_ref); self_ty = impl_trait_ref.self_ty(); } None => { - self_ty = self.tcx.normalize_erasing_regions(param_env, self_ty); + self_ty = self.tcx.normalize_erasing_regions(typing_env, self_ty); } } @@ -591,7 +592,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { ct_ty.print(self)?; let mut bits = ct - .try_to_bits(self.tcx, ty::ParamEnv::reveal_all()) + .try_to_bits(self.tcx, ty::TypingEnv::fully_monomorphized()) .expect("expected const to be monomorphic"); // Negative integer values are mangled using `n` as a "sign prefix". diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs index 808e6a50d85d..9a7bdaa5b570 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs @@ -528,7 +528,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { // Find the method being called. let Ok(Some(instance)) = ty::Instance::try_resolve( tcx, - ctxt.param_env, + self.cx.typing_env(ctxt.param_env), ctxt.assoc_item.def_id, self.cx.resolve_vars_if_possible(ctxt.args), ) else { diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 1109b11d2a71..4e7d7b79ff4d 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -2079,7 +2079,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { cand.trait_ref = self .tcx .try_normalize_erasing_regions( - self.tcx.param_env(cand.impl_def_id), + ty::TypingEnv::non_body_analysis(self.tcx, cand.impl_def_id), cand.trait_ref, ) .unwrap_or(cand.trait_ref); diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index c00246cfd7d0..cf63f14fb937 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -513,7 +513,7 @@ fn check_receiver_correct<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId, method: let method_def_id = method.def_id; let sig = tcx.fn_sig(method_def_id).instantiate_identity(); - let param_env = tcx.param_env(method_def_id); + let typing_env = ty::TypingEnv::non_body_analysis(tcx, method_def_id); let receiver_ty = tcx.liberate_late_bound_regions(method_def_id, sig.input(0)); if receiver_ty == tcx.types.self_param { @@ -523,7 +523,7 @@ fn check_receiver_correct<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId, method: // e.g., `Rc<()>` let unit_receiver_ty = receiver_for_self_ty(tcx, receiver_ty, tcx.types.unit, method_def_id); - match tcx.layout_of(param_env.and(unit_receiver_ty)).map(|l| l.backend_repr) { + match tcx.layout_of(typing_env.as_query_input(unit_receiver_ty)).map(|l| l.backend_repr) { Ok(BackendRepr::Scalar(..)) => (), abi => { tcx.dcx().span_delayed_bug( @@ -538,7 +538,7 @@ fn check_receiver_correct<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId, method: // e.g., `Rc` let trait_object_receiver = receiver_for_self_ty(tcx, receiver_ty, trait_object_ty, method_def_id); - match tcx.layout_of(param_env.and(trait_object_receiver)).map(|l| l.backend_repr) { + match tcx.layout_of(typing_env.as_query_input(trait_object_receiver)).map(|l| l.backend_repr) { Ok(BackendRepr::ScalarPair(..)) => (), abi => { tcx.dcx().span_delayed_bug( diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index fe90066b4e7e..c0603c06d422 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -611,11 +611,12 @@ pub fn try_evaluate_const<'tcx>( // // FIXME: `const_eval_resolve_for_typeck` should probably just set the env to `Reveal::All` // instead of having this logic here - let env = tcx.erase_regions(param_env).with_reveal_all_normalized(tcx); + let typing_env = + tcx.erase_regions(infcx.typing_env(param_env)).with_reveal_all_normalized(tcx); let erased_uv = tcx.erase_regions(uv); use rustc_middle::mir::interpret::ErrorHandled; - match tcx.const_eval_resolve_for_typeck(env, erased_uv, DUMMY_SP) { + match tcx.const_eval_resolve_for_typeck(typing_env, erased_uv, DUMMY_SP) { Ok(Ok(val)) => Ok(ty::Const::new_value( tcx, val, diff --git a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs index 4ff0910c9b96..1d3e8d43af74 100644 --- a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs +++ b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs @@ -144,7 +144,14 @@ pub fn compute_dropck_outlives_inner<'tcx>( result.overflows.len(), ty_stack.len() ); - dtorck_constraint_for_ty_inner(tcx, param_env, DUMMY_SP, depth, ty, &mut constraints)?; + dtorck_constraint_for_ty_inner( + tcx, + ocx.infcx.typing_env(param_env), + DUMMY_SP, + depth, + ty, + &mut constraints, + )?; // "outlives" represent types/regions that may be touched // by a destructor. @@ -196,10 +203,10 @@ pub fn compute_dropck_outlives_inner<'tcx>( /// Returns a set of constraints that needs to be satisfied in /// order for `ty` to be valid for destruction. -#[instrument(level = "debug", skip(tcx, param_env, span, constraints))] +#[instrument(level = "debug", skip(tcx, typing_env, span, constraints))] pub fn dtorck_constraint_for_ty_inner<'tcx>( tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, span: Span, depth: usize, ty: Ty<'tcx>, @@ -234,20 +241,20 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>( ty::Pat(ety, _) | ty::Array(ety, _) | ty::Slice(ety) => { // single-element containers, behave like their element rustc_data_structures::stack::ensure_sufficient_stack(|| { - dtorck_constraint_for_ty_inner(tcx, param_env, span, depth + 1, *ety, constraints) + dtorck_constraint_for_ty_inner(tcx, typing_env, span, depth + 1, *ety, constraints) })?; } ty::Tuple(tys) => rustc_data_structures::stack::ensure_sufficient_stack(|| { for ty in tys.iter() { - dtorck_constraint_for_ty_inner(tcx, param_env, span, depth + 1, ty, constraints)?; + dtorck_constraint_for_ty_inner(tcx, typing_env, span, depth + 1, ty, constraints)?; } Ok::<_, NoSolution>(()) })?, ty::Closure(_, args) => rustc_data_structures::stack::ensure_sufficient_stack(|| { for ty in args.as_closure().upvar_tys() { - dtorck_constraint_for_ty_inner(tcx, param_env, span, depth + 1, ty, constraints)?; + dtorck_constraint_for_ty_inner(tcx, typing_env, span, depth + 1, ty, constraints)?; } Ok::<_, NoSolution>(()) })?, @@ -257,7 +264,7 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>( for ty in args.as_coroutine_closure().upvar_tys() { dtorck_constraint_for_ty_inner( tcx, - param_env, + typing_env, span, depth + 1, ty, @@ -296,7 +303,7 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>( // While we conservatively assume that all coroutines require drop // to avoid query cycles during MIR building, we can check the actual // witness during borrowck to avoid unnecessary liveness constraints. - if args.witness().needs_drop(tcx, tcx.erase_regions(param_env)) { + if args.witness().needs_drop(tcx, tcx.erase_regions(typing_env)) { constraints.outlives.extend(args.upvar_tys().iter().map(ty::GenericArg::from)); constraints.outlives.push(args.resume_ty().into()); } diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index bf3f83ec8279..1e0c487c4d49 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -1224,16 +1224,20 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // The regions of a type don't affect the size of the type let tcx = self.tcx(); let self_ty = tcx.instantiate_bound_regions_with_erased(obligation.predicate.self_ty()); - // We should erase regions from both the param-env and type, since both - // may have infer regions. Specifically, after canonicalizing and instantiating, - // early bound regions turn into region vars in both the new and old solver. - let key = tcx.erase_regions(obligation.param_env.and(self_ty)); + // But if there are inference variables, we have to wait until it's resolved. - if key.has_non_region_infer() { + if (obligation.param_env, self_ty).has_non_region_infer() { candidates.ambiguous = true; return; } + // We should erase regions from both the param-env and type, since both + // may have infer regions. Specifically, after canonicalizing and instantiating, + // early bound regions turn into region vars in both the new and old solver. + let key = self.infcx.pseudo_canonicalize_query( + tcx.erase_regions(obligation.param_env), + tcx.erase_regions(self_ty), + ); if let Ok(layout) = tcx.layout_of(key) && layout.layout.is_pointer_like(&tcx.data_layout) { diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs index bb56d6eaf544..8352d31d13aa 100644 --- a/compiler/rustc_trait_selection/src/traits/vtable.rs +++ b/compiler/rustc_trait_selection/src/traits/vtable.rs @@ -276,8 +276,10 @@ fn vtable_entries<'tcx>( // The trait type may have higher-ranked lifetimes in it; // erase them if they appear, so that we get the type // at some particular call site. - let args = - tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), args); + let args = tcx.normalize_erasing_late_bound_regions( + ty::TypingEnv::fully_monomorphized(), + args, + ); // It's possible that the method relies on where-clauses that // do not hold for this particular set of type parameters. @@ -294,7 +296,7 @@ fn vtable_entries<'tcx>( let instance = ty::Instance::expect_resolve_for_vtable( tcx, - ty::ParamEnv::reveal_all(), + ty::TypingEnv::fully_monomorphized(), def_id, args, DUMMY_SP, diff --git a/compiler/rustc_traits/src/codegen.rs b/compiler/rustc_traits/src/codegen.rs index d8c1c50d79a8..57225df0819d 100644 --- a/compiler/rustc_traits/src/codegen.rs +++ b/compiler/rustc_traits/src/codegen.rs @@ -6,7 +6,7 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::bug; use rustc_middle::traits::CodegenObligationError; -use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt, TypingMode}; +use rustc_middle::ty::{self, PseudoCanonicalInput, TyCtxt, TypeVisitableExt}; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::traits::{ ImplSource, Obligation, ObligationCause, ObligationCtxt, ScrubbedTraitError, SelectionContext, @@ -23,14 +23,15 @@ use tracing::debug; /// This also expects that `trait_ref` is fully normalized. pub(crate) fn codegen_select_candidate<'tcx>( tcx: TyCtxt<'tcx>, - (param_env, trait_ref): (ty::ParamEnv<'tcx>, ty::TraitRef<'tcx>), + key: PseudoCanonicalInput<'tcx, ty::TraitRef<'tcx>>, ) -> Result<&'tcx ImplSource<'tcx, ()>, CodegenObligationError> { + let PseudoCanonicalInput { typing_env, value: trait_ref } = key; // We expect the input to be fully normalized. - debug_assert_eq!(trait_ref, tcx.normalize_erasing_regions(param_env, trait_ref)); + debug_assert_eq!(trait_ref, tcx.normalize_erasing_regions(typing_env, trait_ref)); // Do the initial selection for the obligation. This yields the // shallow result we are looking for -- that is, what specific impl. - let infcx = tcx.infer_ctxt().ignoring_regions().build(TypingMode::from_param_env(param_env)); + let (infcx, param_env) = tcx.infer_ctxt().ignoring_regions().build_with_typing_env(typing_env); let mut selcx = SelectionContext::new(&infcx); let obligation_cause = ObligationCause::dummy(); diff --git a/compiler/rustc_traits/src/dropck_outlives.rs b/compiler/rustc_traits/src/dropck_outlives.rs index 4e5309eea287..51e4dbe81b3d 100644 --- a/compiler/rustc_traits/src/dropck_outlives.rs +++ b/compiler/rustc_traits/src/dropck_outlives.rs @@ -5,7 +5,7 @@ use rustc_infer::infer::canonical::{Canonical, QueryResponse}; use rustc_middle::bug; use rustc_middle::query::Providers; use rustc_middle::traits::query::{DropckConstraint, DropckOutlivesResult}; -use rustc_middle::ty::{GenericArgs, TyCtxt}; +use rustc_middle::ty::{self, GenericArgs, TyCtxt}; use rustc_trait_selection::infer::InferCtxtBuilderExt; use rustc_trait_selection::traits::query::dropck_outlives::{ compute_dropck_outlives_inner, dtorck_constraint_for_ty_inner, @@ -35,7 +35,7 @@ pub(crate) fn adt_dtorck_constraint( ) -> Result<&DropckConstraint<'_>, NoSolution> { let def = tcx.adt_def(def_id); let span = tcx.def_span(def_id); - let param_env = tcx.param_env(def_id); + let typing_env = ty::TypingEnv::non_body_analysis(tcx, def_id); debug!("dtorck_constraint: {:?}", def); if def.is_manually_drop() { @@ -57,7 +57,7 @@ pub(crate) fn adt_dtorck_constraint( let mut result = DropckConstraint::empty(); for field in def.all_fields() { let fty = tcx.type_of(field.did).instantiate_identity(); - dtorck_constraint_for_ty_inner(tcx, param_env, span, 0, fty, &mut result)?; + dtorck_constraint_for_ty_inner(tcx, typing_env, span, 0, fty, &mut result)?; } result.outlives.extend(tcx.destructor_constraints(def)); dedup_dtorck_constraint(&mut result); diff --git a/compiler/rustc_traits/src/normalize_erasing_regions.rs b/compiler/rustc_traits/src/normalize_erasing_regions.rs index d79059a39a1d..68ff66bbce7c 100644 --- a/compiler/rustc_traits/src/normalize_erasing_regions.rs +++ b/compiler/rustc_traits/src/normalize_erasing_regions.rs @@ -1,7 +1,7 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::query::Providers; use rustc_middle::traits::query::NoSolution; -use rustc_middle::ty::{self, ParamEnvAnd, TyCtxt, TypeFoldable, TypeVisitableExt, TypingMode}; +use rustc_middle::ty::{self, PseudoCanonicalInput, TyCtxt, TypeFoldable, TypeVisitableExt}; use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt; use rustc_trait_selection::traits::{Normalized, ObligationCause}; use tracing::debug; @@ -19,10 +19,10 @@ pub(crate) fn provide(p: &mut Providers) { fn try_normalize_after_erasing_regions<'tcx, T: TypeFoldable> + PartialEq + Copy>( tcx: TyCtxt<'tcx>, - goal: ParamEnvAnd<'tcx, T>, + goal: PseudoCanonicalInput<'tcx, T>, ) -> Result { - let ParamEnvAnd { param_env, value } = goal; - let infcx = tcx.infer_ctxt().build(TypingMode::from_param_env(param_env)); + let PseudoCanonicalInput { typing_env, value } = goal; + let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env); let cause = ObligationCause::dummy(); match infcx.at(&cause, param_env).query_normalize(value) { Ok(Normalized { value: normalized_value, obligations: normalized_obligations }) => { diff --git a/compiler/rustc_transmute/src/maybe_transmutable/mod.rs b/compiler/rustc_transmute/src/maybe_transmutable/mod.rs index 9dabcea706f4..023c8fad781d 100644 --- a/compiler/rustc_transmute/src/maybe_transmutable/mod.rs +++ b/compiler/rustc_transmute/src/maybe_transmutable/mod.rs @@ -31,7 +31,7 @@ where #[cfg(feature = "rustc")] mod rustc { use rustc_middle::ty::layout::LayoutCx; - use rustc_middle::ty::{ParamEnv, Ty, TyCtxt}; + use rustc_middle::ty::{Ty, TyCtxt, TypingEnv}; use super::*; use crate::layout::tree::rustc::Err; @@ -43,7 +43,7 @@ mod rustc { pub(crate) fn answer(self) -> Answer< as QueryContext>::Ref> { let Self { src, dst, assume, context } = self; - let layout_cx = LayoutCx::new(context, ParamEnv::reveal_all()); + let layout_cx = LayoutCx::new(context, TypingEnv::fully_monomorphized()); // Convert `src` and `dst` from their rustc representations, to `Tree`-based // representations. diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index 0184e93acf18..e2283383196b 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -7,7 +7,7 @@ use rustc_hir::lang_items::LangItem; use rustc_middle::bug; use rustc_middle::query::Providers; use rustc_middle::ty::layout::{ - FnAbiError, HasParamEnv, HasTyCtxt, LayoutCx, LayoutOf, TyAndLayout, fn_can_unwind, + FnAbiError, HasTyCtxt, HasTypingEnv, LayoutCx, LayoutOf, TyAndLayout, fn_can_unwind, }; use rustc_middle::ty::{self, InstanceKind, Ty, TyCtxt}; use rustc_session::config::OptLevel; @@ -26,11 +26,11 @@ pub(crate) fn provide(providers: &mut Providers) { // for `Instance` (e.g. typeck would use `Ty::fn_sig` instead), // or should go through `FnAbi` instead, to avoid losing any // adjustments `fn_abi_of_instance` might be performing. -#[tracing::instrument(level = "debug", skip(tcx, param_env))] +#[tracing::instrument(level = "debug", skip(tcx, typing_env))] fn fn_sig_for_fn_abi<'tcx>( tcx: TyCtxt<'tcx>, instance: ty::Instance<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ) -> ty::PolyFnSig<'tcx> { if let InstanceKind::ThreadLocalShim(..) = instance.def { return ty::Binder::dummy(tcx.mk_fn_sig( @@ -42,7 +42,7 @@ fn fn_sig_for_fn_abi<'tcx>( )); } - let ty = instance.ty(tcx, param_env); + let ty = instance.ty(tcx, typing_env); match *ty.kind() { ty::FnDef(..) => { // HACK(davidtwco,eddyb): This is a workaround for polymorphization considering @@ -56,7 +56,10 @@ fn fn_sig_for_fn_abi<'tcx>( ty::FnDef(def_id, args) => tcx .fn_sig(def_id) .map_bound(|fn_sig| { - tcx.normalize_erasing_regions(tcx.param_env(def_id), fn_sig) + tcx.normalize_erasing_regions( + ty::TypingEnv::non_body_analysis(tcx, def_id), + fn_sig, + ) }) .instantiate(tcx, args), _ => unreachable!(), @@ -329,27 +332,26 @@ fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: ExternAbi, c_variadic: bool) -> Conv fn fn_abi_of_fn_ptr<'tcx>( tcx: TyCtxt<'tcx>, - query: ty::ParamEnvAnd<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List>)>, + query: ty::PseudoCanonicalInput<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List>)>, ) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, &'tcx FnAbiError<'tcx>> { - let (param_env, (sig, extra_args)) = query.into_parts(); - - let cx = LayoutCx::new(tcx, param_env); + let ty::PseudoCanonicalInput { typing_env, value: (sig, extra_args) } = query; + let cx = LayoutCx::new(tcx, typing_env); fn_abi_new_uncached(&cx, sig, extra_args, None, None, false) } fn fn_abi_of_instance<'tcx>( tcx: TyCtxt<'tcx>, - query: ty::ParamEnvAnd<'tcx, (ty::Instance<'tcx>, &'tcx ty::List>)>, + query: ty::PseudoCanonicalInput<'tcx, (ty::Instance<'tcx>, &'tcx ty::List>)>, ) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, &'tcx FnAbiError<'tcx>> { - let (param_env, (instance, extra_args)) = query.into_parts(); + let ty::PseudoCanonicalInput { typing_env, value: (instance, extra_args) } = query; - let sig = fn_sig_for_fn_abi(tcx, instance, param_env); + let sig = fn_sig_for_fn_abi(tcx, instance, typing_env); let caller_location = instance.def.requires_caller_location(tcx).then(|| tcx.caller_location_ty()); fn_abi_new_uncached( - &LayoutCx::new(tcx, param_env), + &LayoutCx::new(tcx, typing_env), sig, extra_args, caller_location, @@ -395,7 +397,7 @@ fn adjust_for_rust_scalar<'tcx>( Some(kind) } else if let Some(pointee) = drop_target_pointee { // The argument to `drop_in_place` is semantically equivalent to a mutable reference. - Some(PointerKind::MutableRef { unpin: pointee.is_unpin(tcx, cx.param_env()) }) + Some(PointerKind::MutableRef { unpin: pointee.is_unpin(tcx, cx.typing_env.param_env) }) } else { None }; @@ -542,7 +544,7 @@ fn fn_abi_sanity_check<'tcx>( // With metadata. Must be unsized and not on the stack. assert!(arg.layout.is_unsized() && !on_stack); // Also, must not be `extern` type. - let tail = tcx.struct_tail_for_codegen(arg.layout.ty, cx.param_env()); + let tail = tcx.struct_tail_for_codegen(arg.layout.ty, cx.typing_env); if matches!(tail.kind(), ty::Foreign(..)) { // These types do not have metadata, so having `meta_attrs` is bogus. // Conceptually, unsized arguments must be copied around, which requires dynamically @@ -573,7 +575,7 @@ fn fn_abi_new_uncached<'tcx>( force_thin_self_ptr: bool, ) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, &'tcx FnAbiError<'tcx>> { let tcx = cx.tcx(); - let sig = tcx.normalize_erasing_late_bound_regions(cx.param_env, sig); + let sig = tcx.normalize_erasing_late_bound_regions(cx.typing_env, sig); let conv = conv_from_spec_abi(cx.tcx(), sig.abi, sig.c_variadic); @@ -744,7 +746,7 @@ fn fn_abi_adjust_for_abi<'tcx>( #[tracing::instrument(level = "debug", skip(cx))] fn make_thin_self_ptr<'tcx>( - cx: &(impl HasTyCtxt<'tcx> + HasParamEnv<'tcx>), + cx: &(impl HasTyCtxt<'tcx> + HasTypingEnv<'tcx>), layout: TyAndLayout<'tcx>, ) -> TyAndLayout<'tcx> { let tcx = cx.tcx(); @@ -784,6 +786,6 @@ fn make_thin_self_ptr<'tcx>( // NOTE(eddyb) using an empty `ParamEnv`, and `unwrap`-ing the `Result` // should always work because the type is always `*mut ()`. - ..tcx.layout_of(ty::ParamEnv::reveal_all().and(unit_ptr_ty)).unwrap() + ..tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(unit_ptr_ty)).unwrap() } } diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 1d8a08807601..84fc03a8f139 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -6,7 +6,9 @@ use rustc_middle::bug; use rustc_middle::query::Providers; use rustc_middle::traits::{BuiltinImplSource, CodegenObligationError}; use rustc_middle::ty::util::AsyncDropGlueMorphology; -use rustc_middle::ty::{self, GenericArgsRef, Instance, TyCtxt, TypeVisitableExt, TypingMode}; +use rustc_middle::ty::{ + self, GenericArgsRef, Instance, PseudoCanonicalInput, TyCtxt, TypeVisitableExt, +}; use rustc_span::sym; use rustc_trait_selection::traits; use rustc_type_ir::ClosureKind; @@ -17,18 +19,18 @@ use crate::errors::UnexpectedFnPtrAssociatedItem; fn resolve_instance_raw<'tcx>( tcx: TyCtxt<'tcx>, - key: ty::ParamEnvAnd<'tcx, (DefId, GenericArgsRef<'tcx>)>, + key: ty::PseudoCanonicalInput<'tcx, (DefId, GenericArgsRef<'tcx>)>, ) -> Result>, ErrorGuaranteed> { - let (param_env, (def_id, args)) = key.into_parts(); + let PseudoCanonicalInput { typing_env, value: (def_id, args) } = key; let result = if let Some(trait_def_id) = tcx.trait_of_item(def_id) { - debug!(" => associated item, attempting to find impl in param_env {:#?}", param_env); + debug!(" => associated item, attempting to find impl in typing_env {:#?}", typing_env); resolve_associated_item( tcx, def_id, - param_env, + typing_env, trait_def_id, - tcx.normalize_erasing_regions(param_env, args), + tcx.normalize_erasing_regions(typing_env, args), ) } else { let def = if tcx.intrinsic(def_id).is_some() { @@ -37,7 +39,7 @@ fn resolve_instance_raw<'tcx>( } else if tcx.is_lang_item(def_id, LangItem::DropInPlace) { let ty = args.type_at(0); - if ty.needs_drop(tcx, param_env) { + if ty.needs_drop(tcx, typing_env) { debug!(" => nontrivial drop glue"); match *ty.kind() { ty::Closure(..) @@ -93,15 +95,16 @@ fn resolve_instance_raw<'tcx>( fn resolve_associated_item<'tcx>( tcx: TyCtxt<'tcx>, trait_item_id: DefId, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, trait_id: DefId, rcvr_args: GenericArgsRef<'tcx>, ) -> Result>, ErrorGuaranteed> { - debug!(?trait_item_id, ?param_env, ?trait_id, ?rcvr_args, "resolve_associated_item"); + debug!(?trait_item_id, ?typing_env, ?trait_id, ?rcvr_args, "resolve_associated_item"); let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_args); - let vtbl = match tcx.codegen_select_candidate((param_env, trait_ref)) { + let input = typing_env.as_query_input(trait_ref); + let vtbl = match tcx.codegen_select_candidate(input) { Ok(vtbl) => vtbl, Err( CodegenObligationError::Ambiguity @@ -116,7 +119,7 @@ fn resolve_associated_item<'tcx>( traits::ImplSource::UserDefined(impl_data) => { debug!( "resolving ImplSource::UserDefined: {:?}, {:?}, {:?}, {:?}", - param_env, trait_item_id, rcvr_args, impl_data + typing_env, trait_item_id, rcvr_args, impl_data ); assert!(!rcvr_args.has_infer()); assert!(!trait_ref.has_infer()); @@ -129,8 +132,9 @@ fn resolve_associated_item<'tcx>( .unwrap_or_else(|| { bug!("{:?} not found in {:?}", trait_item_id, impl_data.impl_def_id); }); - let infcx = tcx.infer_ctxt().build(TypingMode::PostAnalysis); - let param_env = param_env.with_reveal_all_normalized(tcx); + + let typing_env = typing_env.with_reveal_all_normalized(tcx); + let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env); let args = rcvr_args.rebase_onto(tcx, trait_def_id, impl_data.args); let args = translate_args( &infcx, diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 63421dfdce6c..02ee3f329159 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -19,7 +19,8 @@ use rustc_middle::ty::layout::{ }; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{ - self, AdtDef, CoroutineArgsExt, EarlyBinder, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt, + self, AdtDef, CoroutineArgsExt, EarlyBinder, GenericArgsRef, PseudoCanonicalInput, Ty, TyCtxt, + TypeVisitableExt, }; use rustc_session::{DataTypeKind, FieldInfo, FieldKind, SizeKind, VariantInfo}; use rustc_span::sym; @@ -40,22 +41,22 @@ pub(crate) fn provide(providers: &mut Providers) { #[instrument(skip(tcx, query), level = "debug")] fn layout_of<'tcx>( tcx: TyCtxt<'tcx>, - query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>, + query: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>, ) -> Result, &'tcx LayoutError<'tcx>> { - let (param_env, ty) = query.into_parts(); + let PseudoCanonicalInput { typing_env, value: ty } = query; debug!(?ty); // Optimization: We convert to RevealAll and convert opaque types in the where bounds // to their hidden types. This reduces overall uncached invocations of `layout_of` and // is thus a small performance improvement. - let param_env = param_env.with_reveal_all_normalized(tcx); + let typing_env = typing_env.with_reveal_all_normalized(tcx); let unnormalized_ty = ty; // FIXME: We might want to have two different versions of `layout_of`: // One that can be called after typecheck has completed and can use // `normalize_erasing_regions` here and another one that can be called // before typecheck has completed and uses `try_normalize_erasing_regions`. - let ty = match tcx.try_normalize_erasing_regions(param_env, ty) { + let ty = match tcx.try_normalize_erasing_regions(typing_env, ty) { Ok(t) => t, Err(normalization_error) => { return Err(tcx @@ -66,10 +67,10 @@ fn layout_of<'tcx>( if ty != unnormalized_ty { // Ensure this layout is also cached for the normalized type. - return tcx.layout_of(param_env.and(ty)); + return tcx.layout_of(typing_env.as_query_input(ty)); } - let cx = LayoutCx::new(tcx, param_env); + let cx = LayoutCx::new(tcx, typing_env); let layout = layout_of_uncached(&cx, ty)?; let layout = TyAndLayout { ty, layout }; @@ -104,7 +105,7 @@ fn map_error<'tcx>( // This is sometimes not a compile error if there are trivially false where clauses. // See `tests/ui/layout/trivial-bounds-sized.rs` for an example. assert!(field.layout.is_unsized(), "invalid layout error {err:#?}"); - if !field.ty.is_sized(cx.tcx(), cx.param_env) { + if !field.ty.is_sized(cx.tcx(), cx.typing_env.param_env) { cx.tcx().dcx().delayed_bug(format!( "encountered unexpected unsized field in layout of {ty:?}: {field:#?}" )); @@ -152,7 +153,6 @@ fn layout_of_uncached<'tcx>( } let tcx = cx.tcx(); - let param_env = cx.param_env; let dl = cx.data_layout(); let scalar_unit = |value: Primitive| { let size = value.size(dl); @@ -178,12 +178,12 @@ fn layout_of_uncached<'tcx>( { if let Some(start) = start { scalar.valid_range_mut().start = start - .try_to_bits(tcx, param_env) + .try_to_bits(tcx, cx.typing_env) .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?; } if let Some(end) = end { let mut end = end - .try_to_bits(tcx, param_env) + .try_to_bits(tcx, cx.typing_env) .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?; if !include_end { end = end.wrapping_sub(1); @@ -235,8 +235,8 @@ fn layout_of_uncached<'tcx>( data_ptr.valid_range_mut().start = 1; } - let pointee = tcx.normalize_erasing_regions(param_env, pointee); - if pointee.is_sized(tcx, param_env) { + let pointee = tcx.normalize_erasing_regions(cx.typing_env, pointee); + if pointee.is_sized(tcx, cx.typing_env.param_env) { return Ok(tcx.mk_layout(LayoutData::scalar(cx, data_ptr))); } @@ -247,7 +247,7 @@ fn layout_of_uncached<'tcx>( { let pointee_metadata = Ty::new_projection(tcx, metadata_def_id, [pointee]); let metadata_ty = - match tcx.try_normalize_erasing_regions(param_env, pointee_metadata) { + match tcx.try_normalize_erasing_regions(cx.typing_env, pointee_metadata) { Ok(metadata_ty) => metadata_ty, Err(mut err) => { // Usually `::Metadata` can't be normalized because @@ -259,7 +259,7 @@ fn layout_of_uncached<'tcx>( // that is an alias, which is likely the cause of the normalization // error. match tcx.try_normalize_erasing_regions( - param_env, + cx.typing_env, tcx.struct_tail_raw(pointee, |ty| ty, || {}), ) { Ok(_) => {} @@ -283,7 +283,7 @@ fn layout_of_uncached<'tcx>( metadata } else { - let unsized_part = tcx.struct_tail_for_codegen(pointee, param_env); + let unsized_part = tcx.struct_tail_for_codegen(pointee, cx.typing_env); match unsized_part.kind() { ty::Foreign(..) => { @@ -316,7 +316,7 @@ fn layout_of_uncached<'tcx>( // Arrays and slices. ty::Array(element, mut count) => { if count.has_aliases() { - count = tcx.normalize_erasing_regions(param_env, count); + count = tcx.normalize_erasing_regions(cx.typing_env, count); if count.has_aliases() { return Err(error(cx, LayoutError::Unknown(ty))); } @@ -331,7 +331,7 @@ fn layout_of_uncached<'tcx>( .checked_mul(count, dl) .ok_or_else(|| error(cx, LayoutError::SizeOverflow(ty)))?; - let abi = if count != 0 && ty.is_privately_uninhabited(tcx, param_env) { + let abi = if count != 0 && ty.is_privately_uninhabited(tcx, cx.typing_env) { BackendRepr::Uninhabited } else { BackendRepr::Memory { sized: true } @@ -620,7 +620,11 @@ fn layout_of_uncached<'tcx>( // If the struct tail is sized and can be unsized, check that unsizing doesn't move the fields around. if cfg!(debug_assertions) && maybe_unsized - && def.non_enum_variant().tail().ty(tcx, args).is_sized(tcx, cx.param_env) + && def + .non_enum_variant() + .tail() + .ty(tcx, args) + .is_sized(tcx, cx.typing_env.param_env) { let mut variants = variants; let tail_replacement = cx.layout_of(Ty::new_slice(tcx, tcx.types.u8)).unwrap(); @@ -1024,7 +1028,7 @@ fn record_layout_for_printing<'tcx>(cx: &LayoutCx<'tcx>, layout: TyAndLayout<'tc // Ignore layouts that are done with non-empty environments or // non-monomorphic layouts, as the user only wants to see the stuff // resulting from the final codegen session. - if layout.ty.has_non_region_param() || !cx.param_env.caller_bounds().is_empty() { + if layout.ty.has_non_region_param() || !cx.typing_env.param_env.caller_bounds().is_empty() { return; } diff --git a/compiler/rustc_ty_utils/src/layout/invariant.rs b/compiler/rustc_ty_utils/src/layout/invariant.rs index fc05dd8256b6..26ea81daf784 100644 --- a/compiler/rustc_ty_utils/src/layout/invariant.rs +++ b/compiler/rustc_ty_utils/src/layout/invariant.rs @@ -9,7 +9,7 @@ pub(super) fn partially_check_layout<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLa let tcx = cx.tcx(); // Type-level uninhabitedness should always imply ABI uninhabitedness. - if layout.ty.is_privately_uninhabited(tcx, cx.param_env) { + if layout.ty.is_privately_uninhabited(tcx, cx.typing_env) { assert!(layout.is_uninhabited()); } diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs index 5fecbd310b77..d462dbd94167 100644 --- a/compiler/rustc_ty_utils/src/needs_drop.rs +++ b/compiler/rustc_ty_utils/src/needs_drop.rs @@ -14,14 +14,17 @@ use crate::errors::NeedsDropOverflow; type NeedsDropResult = Result; -fn needs_drop_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { +fn needs_drop_raw<'tcx>( + tcx: TyCtxt<'tcx>, + query: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>, +) -> bool { // If we don't know a type doesn't need drop, for example if it's a type // parameter without a `Copy` bound, then we conservatively return that it // needs drop. let adt_has_dtor = |adt_def: ty::AdtDef<'tcx>| adt_def.destructor(tcx).map(|_| DtorType::Significant); - let res = drop_tys_helper(tcx, query.value, query.param_env, adt_has_dtor, false) - .filter(filter_array_elements(tcx, query.param_env)) + let res = drop_tys_helper(tcx, query.value, query.typing_env, adt_has_dtor, false) + .filter(filter_array_elements(tcx, query.typing_env)) .next() .is_some(); @@ -29,14 +32,17 @@ fn needs_drop_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx> res } -fn needs_async_drop_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { +fn needs_async_drop_raw<'tcx>( + tcx: TyCtxt<'tcx>, + query: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>, +) -> bool { // If we don't know a type doesn't need async drop, for example if it's a // type parameter without a `Copy` bound, then we conservatively return that // it needs async drop. let adt_has_async_dtor = |adt_def: ty::AdtDef<'tcx>| adt_def.async_destructor(tcx).map(|_| DtorType::Significant); - let res = drop_tys_helper(tcx, query.value, query.param_env, adt_has_async_dtor, false) - .filter(filter_array_elements(tcx, query.param_env)) + let res = drop_tys_helper(tcx, query.value, query.typing_env, adt_has_async_dtor, false) + .filter(filter_array_elements(tcx, query.typing_env)) .next() .is_some(); @@ -50,11 +56,11 @@ fn needs_async_drop_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty /// logic that is easier to follow while not repeating any checks that may thus diverge. fn filter_array_elements<'tcx>( tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ) -> impl Fn(&Result, AlwaysRequiresDrop>) -> bool { move |ty| match ty { Ok(ty) => match *ty.kind() { - ty::Array(elem, _) => tcx.needs_drop_raw(param_env.and(elem)), + ty::Array(elem, _) => tcx.needs_drop_raw(typing_env.as_query_input(elem)), _ => true, }, Err(AlwaysRequiresDrop) => true, @@ -63,16 +69,16 @@ fn filter_array_elements<'tcx>( fn has_significant_drop_raw<'tcx>( tcx: TyCtxt<'tcx>, - query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>, + query: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>, ) -> bool { let res = drop_tys_helper( tcx, query.value, - query.param_env, + query.typing_env, adt_consider_insignificant_dtor(tcx), true, ) - .filter(filter_array_elements(tcx, query.param_env)) + .filter(filter_array_elements(tcx, query.typing_env)) .next() .is_some(); debug!("has_significant_drop_raw({:?}) = {:?}", query, res); @@ -81,7 +87,7 @@ fn has_significant_drop_raw<'tcx>( struct NeedsDropTypes<'tcx, F> { tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, // Whether to reveal coroutine witnesses, this is set // to `false` unless we compute `needs_drop` for a coroutine witness. reveal_coroutine_witnesses: bool, @@ -99,7 +105,7 @@ struct NeedsDropTypes<'tcx, F> { impl<'tcx, F> NeedsDropTypes<'tcx, F> { fn new( tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ty: Ty<'tcx>, adt_components: F, ) -> Self { @@ -107,7 +113,7 @@ impl<'tcx, F> NeedsDropTypes<'tcx, F> { seen_tys.insert(ty); Self { tcx, - param_env, + typing_env, reveal_coroutine_witnesses: false, seen_tys, query_ty: ty, @@ -180,7 +186,7 @@ where } } - _ if component.is_copy_modulo_regions(tcx, self.param_env) => (), + _ if component.is_copy_modulo_regions(tcx, self.typing_env.param_env) => (), ty::Closure(_, args) => { for upvar in args.as_closure().upvar_tys() { @@ -204,7 +210,7 @@ where }; for required_ty in tys { let required = tcx - .try_normalize_erasing_regions(self.param_env, required_ty) + .try_normalize_erasing_regions(self.typing_env, required_ty) .unwrap_or(required_ty); queue_type(self, required); @@ -271,7 +277,7 @@ enum DtorType { fn drop_tys_helper<'tcx>( tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, - param_env: rustc_middle::ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, adt_has_dtor: impl Fn(ty::AdtDef<'tcx>) -> Option, only_significant: bool, ) -> impl Iterator>> { @@ -337,7 +343,7 @@ fn drop_tys_helper<'tcx>( .map(|v| v.into_iter()) }; - NeedsDropTypes::new(tcx, param_env, ty, adt_components) + NeedsDropTypes::new(tcx, typing_env, ty, adt_components) } fn adt_consider_insignificant_dtor<'tcx>( @@ -375,7 +381,7 @@ fn adt_drop_tys<'tcx>( drop_tys_helper( tcx, tcx.type_of(def_id).instantiate_identity(), - tcx.param_env(def_id), + ty::TypingEnv::non_body_analysis(tcx, def_id), adt_has_dtor, false, ) @@ -392,7 +398,7 @@ fn adt_significant_drop_tys( drop_tys_helper( tcx, tcx.type_of(def_id).instantiate_identity(), // identical to `tcx.make_adt(def, identity_args)` - tcx.param_env(def_id), + ty::TypingEnv::non_body_analysis(tcx, def_id), adt_consider_insignificant_dtor(tcx), true, ) diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs index aadb64f45d77..105ae76708bb 100644 --- a/compiler/rustc_type_ir/src/infer_ctxt.rs +++ b/compiler/rustc_type_ir/src/infer_ctxt.rs @@ -1,6 +1,7 @@ use derive_where::derive_where; #[cfg(feature = "nightly")] use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable}; +use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic}; use crate::fold::TypeFoldable; use crate::inherent::*; @@ -20,6 +21,7 @@ use crate::{self as ty, Interner}; /// If neither of these functions are available, feel free to reach out to /// t-types for help. #[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)] +#[derive(TypeVisitable_Generic, TypeFoldable_Generic)] #[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))] pub enum TypingMode { /// When checking whether impls overlap, we check whether any obligations diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 36ddddccfa25..f988f003c0f9 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -13,7 +13,7 @@ use crate::lang_items::TraitSolverLangItem; use crate::relate::Relate; use crate::solve::{CanonicalInput, ExternalConstraintsData, PredefinedOpaquesData, QueryResult}; use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable}; -use crate::{self as ty, search_graph}; +use crate::{self as ty, TypingMode, search_graph}; pub trait Interner: Sized @@ -277,7 +277,12 @@ pub trait Interner: fn coroutine_is_gen(self, coroutine_def_id: Self::DefId) -> bool; fn coroutine_is_async_gen(self, coroutine_def_id: Self::DefId) -> bool; - fn layout_is_pointer_like(self, param_env: Self::ParamEnv, ty: Self::Ty) -> bool; + fn layout_is_pointer_like( + self, + typing_mode: TypingMode, + param_env: Self::ParamEnv, + ty: Self::Ty, + ) -> bool; type UnsizingParams: Deref>; fn unsizing_params_for_adt(self, adt_def_id: Self::DefId) -> Self::UnsizingParams; diff --git a/config.example.toml b/config.example.toml index 9dc71b10f702..d3233ad17b51 100644 --- a/config.example.toml +++ b/config.example.toml @@ -81,7 +81,7 @@ # Indicates whether the LLVM plugin is enabled or not #plugins = false -# Wheter to build Enzyme as AutoDiff backend. +# Whether to build Enzyme as AutoDiff backend. #enzyme = false # Whether to build LLVM with support for it's gpu offload runtime. diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 8a986337aa15..e9859a58696d 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -15,7 +15,7 @@ //! and make the intrinsic declaration a `const fn`. //! //! If an intrinsic is supposed to be used from a `const fn` with a `rustc_const_stable` attribute, -//! `#[rustc_const_stable_intrinsic]` needs to be added to the intrinsic. Such a change requires +//! `#[rustc_intrinsic_const_stable_indirect]` needs to be added to the intrinsic. Such a change requires //! T-lang approval, because it may bake a feature into the language that cannot be replicated in //! user code without compiler support. //! @@ -1435,7 +1435,7 @@ pub fn abort() -> ! { bootstrap, rustc_const_stable(feature = "const_unreachable_unchecked", since = "1.57.0") )] -#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -1454,7 +1454,7 @@ pub const unsafe fn unreachable() -> ! { /// /// The stabilized version of this intrinsic is [`core::hint::assert_unchecked`]. #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_assume", since = "1.77.0"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_intrinsic] @@ -1571,7 +1571,7 @@ pub fn select_unpredictable(b: bool, true_val: T, false_val: T) -> T { /// /// This intrinsic does not have a stable counterpart. #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_assert_type", since = "1.59.0"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -1584,7 +1584,7 @@ pub const fn assert_inhabited() { /// /// This intrinsic does not have a stable counterpart. #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_assert_type2", since = "1.75.0"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -1596,7 +1596,7 @@ pub const fn assert_zero_valid() { /// /// This intrinsic does not have a stable counterpart. #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_assert_type2", since = "1.75.0"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -1613,7 +1613,7 @@ pub const fn assert_mem_uninitialized_valid() { /// /// Consider using [`core::panic::Location::caller`] instead. #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_caller_location", since = "1.79.0"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -1631,7 +1631,7 @@ pub const fn caller_location() -> &'static crate::panic::Location<'static> { /// Therefore, implementations must not require the user to uphold /// any safety invariants. #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_intrinsic_forget", since = "1.83.0"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -1945,7 +1945,7 @@ pub const unsafe fn transmute(_src: Src) -> Dst { /// This is not expected to ever be exposed directly to users, rather it /// may eventually be exposed through some more-constrained API. #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_transmute", since = "1.56.0"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -1967,7 +1967,7 @@ pub const unsafe fn transmute_unchecked(_src: Src) -> Dst { /// /// The stabilized version of this intrinsic is [`mem::needs_drop`](crate::mem::needs_drop). #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_needs_drop", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -1993,7 +1993,7 @@ pub const fn needs_drop() -> bool { /// The stabilized version of this intrinsic is [`pointer::offset`]. #[must_use = "returns a new pointer rather than modifying its argument"] #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -2016,7 +2016,7 @@ pub const unsafe fn offset(_dst: Ptr, _offset: Delta) -> Ptr { /// The stabilized version of this intrinsic is [`pointer::wrapping_offset`]. #[must_use = "returns a new pointer rather than modifying its argument"] #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -2724,7 +2724,7 @@ pub fn frem_algebraic(_a: T, _b: T) -> T { /// primitives via the `count_ones` method. For example, /// [`u32::count_ones`] #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ctpop", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -2769,7 +2769,7 @@ pub const fn ctpop(_x: T) -> u32 { /// assert_eq!(num_leading, 16); /// ``` #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ctlz", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -2795,7 +2795,7 @@ pub const fn ctlz(_x: T) -> u32 { /// assert_eq!(num_leading, 3); /// ``` #[cfg_attr(bootstrap, rustc_const_stable(feature = "constctlz", since = "1.50.0"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -2840,7 +2840,7 @@ pub const unsafe fn ctlz_nonzero(_x: T) -> u32 { /// assert_eq!(num_trailing, 16); /// ``` #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_cttz", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -2866,7 +2866,7 @@ pub const fn cttz(_x: T) -> u32 { /// assert_eq!(num_trailing, 3); /// ``` #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_cttz_nonzero", since = "1.53.0"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -2885,7 +2885,7 @@ pub const unsafe fn cttz_nonzero(_x: T) -> u32 { /// primitives via the `swap_bytes` method. For example, /// [`u32::swap_bytes`] #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_bswap", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -2904,7 +2904,7 @@ pub const fn bswap(_x: T) -> T { /// primitives via the `reverse_bits` method. For example, /// [`u32::reverse_bits`] #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_bitreverse", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -2937,7 +2937,7 @@ pub const fn three_way_compare(_lhs: T, _rhss: T) -> crate::cmp::Orderi /// primitives via the `overflowing_add` method. For example, /// [`u32::overflowing_add`] #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_overflow", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -2956,7 +2956,7 @@ pub const fn add_with_overflow(_x: T, _y: T) -> (T, bool) { /// primitives via the `overflowing_sub` method. For example, /// [`u32::overflowing_sub`] #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_overflow", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -2975,7 +2975,7 @@ pub const fn sub_with_overflow(_x: T, _y: T) -> (T, bool) { /// primitives via the `overflowing_mul` method. For example, /// [`u32::overflowing_mul`] #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_overflow", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3002,7 +3002,7 @@ pub const unsafe fn exact_div(_x: T, _y: T) -> T { /// primitives via the `checked_div` method. For example, /// [`u32::checked_div`] #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_unchecked_div", since = "1.52.0"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3016,7 +3016,7 @@ pub const unsafe fn unchecked_div(_x: T, _y: T) -> T { /// primitives via the `checked_rem` method. For example, /// [`u32::checked_rem`] #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_unchecked_rem", since = "1.52.0"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3031,7 +3031,7 @@ pub const unsafe fn unchecked_rem(_x: T, _y: T) -> T { /// primitives via the `checked_shl` method. For example, /// [`u32::checked_shl`] #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_unchecked", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3045,7 +3045,7 @@ pub const unsafe fn unchecked_shl(_x: T, _y: U) -> T { /// primitives via the `checked_shr` method. For example, /// [`u32::checked_shr`] #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_unchecked", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3059,7 +3059,7 @@ pub const unsafe fn unchecked_shr(_x: T, _y: U) -> T { /// The stable counterpart of this intrinsic is `unchecked_add` on the various /// integer types, such as [`u16::unchecked_add`] and [`i64::unchecked_add`]. #[cfg_attr(bootstrap, rustc_const_stable(feature = "unchecked_math", since = "1.79.0"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3073,7 +3073,7 @@ pub const unsafe fn unchecked_add(_x: T, _y: T) -> T { /// The stable counterpart of this intrinsic is `unchecked_sub` on the various /// integer types, such as [`u16::unchecked_sub`] and [`i64::unchecked_sub`]. #[cfg_attr(bootstrap, rustc_const_stable(feature = "unchecked_math", since = "1.79.0"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3087,7 +3087,7 @@ pub const unsafe fn unchecked_sub(_x: T, _y: T) -> T { /// The stable counterpart of this intrinsic is `unchecked_mul` on the various /// integer types, such as [`u16::unchecked_mul`] and [`i64::unchecked_mul`]. #[cfg_attr(bootstrap, rustc_const_stable(feature = "unchecked_math", since = "1.79.0"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3106,7 +3106,7 @@ pub const unsafe fn unchecked_mul(_x: T, _y: T) -> T { /// primitives via the `rotate_left` method. For example, /// [`u32::rotate_left`] #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_rotate", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3125,7 +3125,7 @@ pub const fn rotate_left(_x: T, _shift: u32) -> T { /// primitives via the `rotate_right` method. For example, /// [`u32::rotate_right`] #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_rotate", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3144,7 +3144,7 @@ pub const fn rotate_right(_x: T, _shift: u32) -> T { /// primitives via the `wrapping_add` method. For example, /// [`u32::wrapping_add`] #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3162,7 +3162,7 @@ pub const fn wrapping_add(_a: T, _b: T) -> T { /// primitives via the `wrapping_sub` method. For example, /// [`u32::wrapping_sub`] #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3180,7 +3180,7 @@ pub const fn wrapping_sub(_a: T, _b: T) -> T { /// primitives via the `wrapping_mul` method. For example, /// [`u32::wrapping_mul`] #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3199,7 +3199,7 @@ pub const fn wrapping_mul(_a: T, _b: T) -> T { /// primitives via the `saturating_add` method. For example, /// [`u32::saturating_add`] #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_saturating", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3217,7 +3217,7 @@ pub const fn saturating_add(_a: T, _b: T) -> T { /// primitives via the `saturating_sub` method. For example, /// [`u32::saturating_sub`] #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_saturating", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3232,7 +3232,7 @@ pub const fn saturating_sub(_a: T, _b: T) -> T { /// projections (`read_via_copy(ptr)`, not `read_via_copy(*ptr)`) so that it /// trivially obeys runtime-MIR rules about derefs in operands. #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ptr_read", since = "1.71.0"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3247,7 +3247,7 @@ pub const unsafe fn read_via_copy(_ptr: *const T) -> T { /// projections (`write_via_move(ptr, x)`, not `write_via_move(*ptr, x)`) so /// that it trivially obeys runtime-MIR rules about derefs in operands. #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ptr_write", since = "1.83.0"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3265,7 +3265,7 @@ pub const unsafe fn write_via_move(_ptr: *mut T, _value: T) { /// /// The stabilized version of this intrinsic is [`core::mem::discriminant`]. #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_discriminant", since = "1.75.0"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3305,7 +3305,7 @@ extern "rust-intrinsic" { /// See documentation of `<*const T>::offset_from` for details. #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ptr_offset_from", since = "1.65.0"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3674,7 +3674,7 @@ pub const unsafe fn typed_swap(x: *mut T, y: *mut T) { /// user has UB checks disabled, the checks will still get optimized out. This intrinsic is /// primarily used by [`ub_checks::assert_unsafe_precondition`]. #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_ub_checks", issue = "none"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] // just for UB checks +#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] // just for UB checks #[inline(always)] #[rustc_intrinsic] pub const fn ub_checks() -> bool { @@ -3758,7 +3758,7 @@ pub unsafe fn vtable_align(_ptr: *const ()) -> usize { #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_size_of", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn size_of() -> usize { @@ -3776,7 +3776,7 @@ pub const fn size_of() -> usize { #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_min_align_of", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn min_align_of() -> usize { @@ -3890,7 +3890,7 @@ pub const fn type_id() -> u128 { #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] #[cfg_attr(bootstrap, rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn aggregate_raw_ptr, D, M>(_data: D, _meta: M) -> P { @@ -3919,7 +3919,7 @@ impl AggregateRawPtr<*mut T> for *mut P { bootstrap, cfg_attr(bootstrap, rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0")) )] -#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn ptr_metadata + ?Sized, M>(_ptr: *const P) -> M { @@ -4026,7 +4026,7 @@ pub const fn ptr_metadata + ?Sized, M>(_ptr: *cons #[rustc_diagnostic_item = "ptr_copy_nonoverlapping"] pub const unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize) { #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0"))] - #[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] + #[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -4133,7 +4133,7 @@ pub const unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: us #[rustc_diagnostic_item = "ptr_copy"] pub const unsafe fn copy(src: *const T, dst: *mut T, count: usize) { #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0"))] - #[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] + #[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -4217,7 +4217,7 @@ pub const unsafe fn copy(src: *const T, dst: *mut T, count: usize) { #[rustc_diagnostic_item = "ptr_write_bytes"] pub const unsafe fn write_bytes(dst: *mut T, val: u8, count: usize) { #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ptr_write", since = "1.83.0"))] - #[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] + #[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] diff --git a/library/std/src/keyword_docs.rs b/library/std/src/keyword_docs.rs index 30d43c8bbfd8..4302e24781ee 100644 --- a/library/std/src/keyword_docs.rs +++ b/library/std/src/keyword_docs.rs @@ -1448,6 +1448,9 @@ mod self_upper_keyword {} /// in a multithreaded context. As such, all accesses to mutable `static`s /// require an [`unsafe`] block. /// +/// When possible, it's often better to use a non-mutable `static` with an +/// interior mutable type such as [`Mutex`], [`OnceLock`], or an [atomic]. +/// /// Despite their unsafety, mutable `static`s are necessary in many contexts: /// they can be used to represent global state shared by the whole program or in /// [`extern`] blocks to bind to variables from C libraries. @@ -1468,7 +1471,10 @@ mod self_upper_keyword {} /// [`extern`]: keyword.extern.html /// [`mut`]: keyword.mut.html /// [`unsafe`]: keyword.unsafe.html +/// [`Mutex`]: sync::Mutex +/// [`OnceLock`]: sync::OnceLock /// [`RefCell`]: cell::RefCell +/// [atomic]: sync::atomic /// [Reference]: ../reference/items/static-items.html mod static_keyword {} diff --git a/library/std/src/sync/rwlock.rs b/library/std/src/sync/rwlock.rs index da2da6f9dfc5..d55d1c80dcae 100644 --- a/library/std/src/sync/rwlock.rs +++ b/library/std/src/sync/rwlock.rs @@ -4,10 +4,10 @@ mod tests; use crate::cell::UnsafeCell; use crate::fmt; use crate::marker::PhantomData; -use crate::mem::ManuallyDrop; +use crate::mem::{ManuallyDrop, forget}; use crate::ops::{Deref, DerefMut}; use crate::ptr::NonNull; -use crate::sync::{LockResult, TryLockError, TryLockResult, poison}; +use crate::sync::{LockResult, PoisonError, TryLockError, TryLockResult, poison}; use crate::sys::sync as sys; /// A reader-writer lock @@ -574,8 +574,12 @@ impl From for RwLock { impl<'rwlock, T: ?Sized> RwLockReadGuard<'rwlock, T> { /// Creates a new instance of `RwLockReadGuard` from a `RwLock`. - // SAFETY: if and only if `lock.inner.read()` (or `lock.inner.try_read()`) has been - // successfully called from the same thread before instantiating this object. + /// + /// # Safety + /// + /// This function is safe if and only if the same thread has successfully and safely called + /// `lock.inner.read()`, `lock.inner.try_read()`, or `lock.inner.downgrade()` before + /// instantiating this object. unsafe fn new(lock: &'rwlock RwLock) -> LockResult> { poison::map_result(lock.poison.borrow(), |()| RwLockReadGuard { data: unsafe { NonNull::new_unchecked(lock.data.get()) }, @@ -957,6 +961,68 @@ impl<'a, T: ?Sized> RwLockWriteGuard<'a, T> { None => Err(orig), } } + + /// Downgrades a write-locked `RwLockWriteGuard` into a read-locked [`RwLockReadGuard`]. + /// + /// This method will atomically change the state of the [`RwLock`] from exclusive mode into + /// shared mode. This means that it is impossible for a writing thread to get in between a + /// thread calling `downgrade` and the same thread reading whatever it wrote while it had the + /// [`RwLock`] in write mode. + /// + /// Note that since we have the `RwLockWriteGuard`, we know that the [`RwLock`] is already + /// locked for writing, so this method cannot fail. + /// + /// # Example + /// + /// ``` + /// #![feature(rwlock_downgrade)] + /// use std::sync::{Arc, RwLock, RwLockWriteGuard}; + /// + /// // The inner value starts as 0. + /// let rw = Arc::new(RwLock::new(0)); + /// + /// // Put the lock in write mode. + /// let mut main_write_guard = rw.write().unwrap(); + /// + /// let evil = rw.clone(); + /// let handle = std::thread::spawn(move || { + /// // This will not return until the main thread drops the `main_read_guard`. + /// let mut evil_guard = evil.write().unwrap(); + /// + /// assert_eq!(*evil_guard, 1); + /// *evil_guard = 2; + /// }); + /// + /// // After spawning the writer thread, set the inner value to 1. + /// *main_write_guard = 1; + /// + /// // Atomically downgrade the write guard into a read guard. + /// let main_read_guard = RwLockWriteGuard::downgrade(main_write_guard); + /// + /// // Since `downgrade` is atomic, the writer thread cannot have set the inner value to 2. + /// assert_eq!(*main_read_guard, 1, "`downgrade` was not atomic"); + /// + /// // Clean up everything now + /// drop(main_read_guard); + /// handle.join().unwrap(); + /// + /// let final_check = rw.read().unwrap(); + /// assert_eq!(*final_check, 2); + /// ``` + #[unstable(feature = "rwlock_downgrade", issue = "128203")] + pub fn downgrade(s: Self) -> RwLockReadGuard<'a, T> { + let lock = s.lock; + + // We don't want to call the destructor since that calls `write_unlock`. + forget(s); + + // SAFETY: We take ownership of a write guard, so we must already have the `RwLock` in write + // mode, satisfying the `downgrade` contract. + unsafe { lock.inner.downgrade() }; + + // SAFETY: We have just successfully called `downgrade`, so we fulfill the safety contract. + unsafe { RwLockReadGuard::new(lock).unwrap_or_else(PoisonError::into_inner) } + } } impl<'a, T: ?Sized> MappedRwLockWriteGuard<'a, T> { diff --git a/library/std/src/sync/rwlock/tests.rs b/library/std/src/sync/rwlock/tests.rs index 37a2e41641ac..02ac1c85b912 100644 --- a/library/std/src/sync/rwlock/tests.rs +++ b/library/std/src/sync/rwlock/tests.rs @@ -501,3 +501,108 @@ fn panic_while_mapping_write_unlocked_poison() { drop(lock); } + +#[test] +fn test_downgrade_basic() { + let r = RwLock::new(()); + + let write_guard = r.write().unwrap(); + let _read_guard = RwLockWriteGuard::downgrade(write_guard); +} + +#[test] +fn test_downgrade_observe() { + // Taken from the test `test_rwlock_downgrade` from: + // https://github.com/Amanieu/parking_lot/blob/master/src/rwlock.rs + + const W: usize = 20; + const N: usize = 100; + + // This test spawns `W` writer threads, where each will increment a counter `N` times, ensuring + // that the value they wrote has not changed after downgrading. + + let rw = Arc::new(RwLock::new(0)); + + // Spawn the writers that will do `W * N` operations and checks. + let handles: Vec<_> = (0..W) + .map(|_| { + let rw = rw.clone(); + thread::spawn(move || { + for _ in 0..N { + // Increment the counter. + let mut write_guard = rw.write().unwrap(); + *write_guard += 1; + let cur_val = *write_guard; + + // Downgrade the lock to read mode, where the value protected cannot be modified. + let read_guard = RwLockWriteGuard::downgrade(write_guard); + assert_eq!(cur_val, *read_guard); + } + }) + }) + .collect(); + + for handle in handles { + handle.join().unwrap(); + } + + assert_eq!(*rw.read().unwrap(), W * N); +} + +#[test] +fn test_downgrade_atomic() { + const NEW_VALUE: i32 = -1; + + // This test checks that `downgrade` is atomic, meaning as soon as a write lock has been + // downgraded, the lock must be in read mode and no other threads can take the write lock to + // modify the protected value. + + // `W` is the number of evil writer threads. + const W: usize = 20; + let rwlock = Arc::new(RwLock::new(0)); + + // Spawns many evil writer threads that will try and write to the locked value before the + // initial writer (who has the exclusive lock) can read after it downgrades. + // If the `RwLock` behaves correctly, then the initial writer should read the value it wrote + // itself as no other thread should be able to mutate the protected value. + + // Put the lock in write mode, causing all future threads trying to access this go to sleep. + let mut main_write_guard = rwlock.write().unwrap(); + + // Spawn all of the evil writer threads. They will each increment the protected value by 1. + let handles: Vec<_> = (0..W) + .map(|_| { + let rwlock = rwlock.clone(); + thread::spawn(move || { + // Will go to sleep since the main thread initially has the write lock. + let mut evil_guard = rwlock.write().unwrap(); + *evil_guard += 1; + }) + }) + .collect(); + + // Wait for a good amount of time so that evil threads go to sleep. + // Note: this is not strictly necessary... + let eternity = crate::time::Duration::from_millis(42); + thread::sleep(eternity); + + // Once everyone is asleep, set the value to `NEW_VALUE`. + *main_write_guard = NEW_VALUE; + + // Atomically downgrade the write guard into a read guard. + let main_read_guard = RwLockWriteGuard::downgrade(main_write_guard); + + // If the above is not atomic, then it would be possible for an evil thread to get in front of + // this read and change the value to be non-negative. + assert_eq!(*main_read_guard, NEW_VALUE, "`downgrade` was not atomic"); + + // Drop the main read guard and allow the evil writer threads to start incrementing. + drop(main_read_guard); + + for handle in handles { + handle.join().unwrap(); + } + + let final_check = rwlock.read().unwrap(); + assert_eq!(*final_check, W as i32 + NEW_VALUE); +} diff --git a/library/std/src/sys/sync/rwlock/futex.rs b/library/std/src/sys/sync/rwlock/futex.rs index 447048edf762..961819cae8d6 100644 --- a/library/std/src/sys/sync/rwlock/futex.rs +++ b/library/std/src/sys/sync/rwlock/futex.rs @@ -18,6 +18,7 @@ pub struct RwLock { const READ_LOCKED: Primitive = 1; const MASK: Primitive = (1 << 30) - 1; const WRITE_LOCKED: Primitive = MASK; +const DOWNGRADE: Primitive = READ_LOCKED.wrapping_sub(WRITE_LOCKED); // READ_LOCKED - WRITE_LOCKED const MAX_READERS: Primitive = MASK - 1; const READERS_WAITING: Primitive = 1 << 30; const WRITERS_WAITING: Primitive = 1 << 31; @@ -53,6 +54,24 @@ fn is_read_lockable(state: Primitive) -> bool { state & MASK < MAX_READERS && !has_readers_waiting(state) && !has_writers_waiting(state) } +#[inline] +fn is_read_lockable_after_wakeup(state: Primitive) -> bool { + // We make a special case for checking if we can read-lock _after_ a reader thread that went to + // sleep has been woken up by a call to `downgrade`. + // + // `downgrade` will wake up all readers and place the lock in read mode. Thus, there should be + // no readers waiting and the lock should be read-locked (not write-locked or unlocked). + // + // Note that we do not check if any writers are waiting. This is because a call to `downgrade` + // implies that the caller wants other readers to read the value protected by the lock. If we + // did not allow readers to acquire the lock before writers after a `downgrade`, then only the + // original writer would be able to read the value, thus defeating the purpose of `downgrade`. + state & MASK < MAX_READERS + && !has_readers_waiting(state) + && !is_write_locked(state) + && !is_unlocked(state) +} + #[inline] fn has_reached_max_readers(state: Primitive) -> bool { state & MASK == MAX_READERS @@ -84,6 +103,9 @@ impl RwLock { } } + /// # Safety + /// + /// The `RwLock` must be read-locked (N readers) in order to call this. #[inline] pub unsafe fn read_unlock(&self) { let state = self.state.fetch_sub(READ_LOCKED, Release) - READ_LOCKED; @@ -100,11 +122,13 @@ impl RwLock { #[cold] fn read_contended(&self) { + let mut has_slept = false; let mut state = self.spin_read(); loop { - // If we can lock it, lock it. - if is_read_lockable(state) { + // If we have just been woken up, first check for a `downgrade` call. + // Otherwise, if we can read-lock it, lock it. + if (has_slept && is_read_lockable_after_wakeup(state)) || is_read_lockable(state) { match self.state.compare_exchange_weak(state, state + READ_LOCKED, Acquire, Relaxed) { Ok(_) => return, // Locked! @@ -116,9 +140,7 @@ impl RwLock { } // Check for overflow. - if has_reached_max_readers(state) { - panic!("too many active read locks on RwLock"); - } + assert!(!has_reached_max_readers(state), "too many active read locks on RwLock"); // Make sure the readers waiting bit is set before we go to sleep. if !has_readers_waiting(state) { @@ -132,6 +154,7 @@ impl RwLock { // Wait for the state to change. futex_wait(&self.state, state | READERS_WAITING, None); + has_slept = true; // Spin again after waking up. state = self.spin_read(); @@ -152,6 +175,9 @@ impl RwLock { } } + /// # Safety + /// + /// The `RwLock` must be write-locked (single writer) in order to call this. #[inline] pub unsafe fn write_unlock(&self) { let state = self.state.fetch_sub(WRITE_LOCKED, Release) - WRITE_LOCKED; @@ -163,6 +189,22 @@ impl RwLock { } } + /// # Safety + /// + /// The `RwLock` must be write-locked (single writer) in order to call this. + #[inline] + pub unsafe fn downgrade(&self) { + // Removes all write bits and adds a single read bit. + let state = self.state.fetch_add(DOWNGRADE, Release); + debug_assert!(is_write_locked(state), "RwLock must be write locked to call `downgrade`"); + + if has_readers_waiting(state) { + // Since we had the exclusive lock, nobody else can unset this bit. + self.state.fetch_sub(READERS_WAITING, Relaxed); + futex_wake_all(&self.state); + } + } + #[cold] fn write_contended(&self) { let mut state = self.spin_write(); diff --git a/library/std/src/sys/sync/rwlock/no_threads.rs b/library/std/src/sys/sync/rwlock/no_threads.rs index 6965e2e2cabe..c11e59f719e9 100644 --- a/library/std/src/sys/sync/rwlock/no_threads.rs +++ b/library/std/src/sys/sync/rwlock/no_threads.rs @@ -62,4 +62,9 @@ impl RwLock { pub unsafe fn write_unlock(&self) { assert_eq!(self.mode.replace(0), -1); } + + #[inline] + pub unsafe fn downgrade(&self) { + assert_eq!(self.mode.replace(1), -1); + } } diff --git a/library/std/src/sys/sync/rwlock/queue.rs b/library/std/src/sys/sync/rwlock/queue.rs index 889961915f4e..51330f8fafe5 100644 --- a/library/std/src/sys/sync/rwlock/queue.rs +++ b/library/std/src/sys/sync/rwlock/queue.rs @@ -1,37 +1,38 @@ //! Efficient read-write locking without `pthread_rwlock_t`. //! -//! The readers-writer lock provided by the `pthread` library has a number of -//! problems which make it a suboptimal choice for `std`: +//! The readers-writer lock provided by the `pthread` library has a number of problems which make it +//! a suboptimal choice for `std`: //! -//! * It is non-movable, so it needs to be allocated (lazily, to make the -//! constructor `const`). -//! * `pthread` is an external library, meaning the fast path of acquiring an -//! uncontended lock cannot be inlined. -//! * Some platforms (at least glibc before version 2.25) have buggy implementations -//! that can easily lead to undefined behavior in safe Rust code when not properly -//! guarded against. +//! * It is non-movable, so it needs to be allocated (lazily, to make the constructor `const`). +//! * `pthread` is an external library, meaning the fast path of acquiring an uncontended lock +//! cannot be inlined. +//! * Some platforms (at least glibc before version 2.25) have buggy implementations that can easily +//! lead to undefined behaviour in safe Rust code when not properly guarded against. //! * On some platforms (e.g. macOS), the lock is very slow. //! -//! Therefore, we implement our own `RwLock`! Naively, one might reach for a -//! spinlock, but those [can be quite problematic] when the lock is contended. -//! Instead, this readers-writer lock copies its implementation strategy from -//! the Windows [SRWLOCK] and the [usync] library. Spinning is still used for the -//! fast path, but it is bounded: after spinning fails, threads will locklessly -//! add an information structure containing a [`Thread`] handle into a queue of -//! waiters associated with the lock. The lock owner, upon releasing the lock, -//! will scan through the queue and wake up threads as appropriate, which will -//! then again try to acquire the lock. The resulting [`RwLock`] is: +//! Therefore, we implement our own [`RwLock`]! Naively, one might reach for a spinlock, but those +//! can be quite [problematic] when the lock is contended. //! -//! * adaptive, since it spins before doing any heavywheight parking operations -//! * allocation-free, modulo the per-thread [`Thread`] handle, which is -//! allocated regardless when using threads created by `std` +//! Instead, this [`RwLock`] copies its implementation strategy from the Windows [SRWLOCK] and the +//! [usync] library implementations. +//! +//! Spinning is still used for the fast path, but it is bounded: after spinning fails, threads will +//! locklessly add an information structure ([`Node`]) containing a [`Thread`] handle into a queue +//! of waiters associated with the lock. The lock owner, upon releasing the lock, will scan through +//! the queue and wake up threads as appropriate, and the newly-awoken threads will then try to +//! acquire the lock themselves. +//! +//! The resulting [`RwLock`] is: +//! +//! * adaptive, since it spins before doing any heavyweight parking operations +//! * allocation-free, modulo the per-thread [`Thread`] handle, which is allocated anyways when +//! using threads created by `std` //! * writer-preferring, even if some readers may still slip through -//! * unfair, which reduces context-switching and thus drastically improves -//! performance +//! * unfair, which reduces context-switching and thus drastically improves performance //! //! and also quite fast in most cases. //! -//! [can be quite problematic]: https://matklad.github.io/2020/01/02/spinlocks-considered-harmful.html +//! [problematic]: https://matklad.github.io/2020/01/02/spinlocks-considered-harmful.html //! [SRWLOCK]: https://learn.microsoft.com/en-us/windows/win32/sync/slim-reader-writer--srw--locks //! [usync]: https://crates.io/crates/usync //! @@ -39,33 +40,37 @@ //! //! ## State //! -//! A single [`AtomicPtr`] is used as state variable. The lowest three bits are used -//! to indicate the meaning of the remaining bits: +//! A single [`AtomicPtr`] is used as state variable. The lowest four bits are used to indicate the +//! meaning of the remaining bits: //! -//! | [`LOCKED`] | [`QUEUED`] | [`QUEUE_LOCKED`] | Remaining | | -//! |:-----------|:-----------|:-----------------|:-------------|:----------------------------------------------------------------------------------------------------------------------------| -//! | 0 | 0 | 0 | 0 | The lock is unlocked, no threads are waiting | -//! | 1 | 0 | 0 | 0 | The lock is write-locked, no threads waiting | -//! | 1 | 0 | 0 | n > 0 | The lock is read-locked with n readers | -//! | 0 | 1 | * | `*mut Node` | The lock is unlocked, but some threads are waiting. Only writers may lock the lock | -//! | 1 | 1 | * | `*mut Node` | The lock is locked, but some threads are waiting. If the lock is read-locked, the last queue node contains the reader count | +//! | [`LOCKED`] | [`QUEUED`] | [`QUEUE_LOCKED`] | [`DOWNGRADED`] | Remaining | | +//! |------------|:-----------|:-----------------|:---------------|:-------------|:----------------------------------------------------------------------------------------------------------------------------| +//! | 0 | 0 | 0 | 0 | 0 | The lock is unlocked, no threads are waiting | +//! | 1 | 0 | 0 | 0 | 0 | The lock is write-locked, no threads waiting | +//! | 1 | 0 | 0 | 0 | n > 0 | The lock is read-locked with n readers | +//! | 0 | 1 | * | 0 | `*mut Node` | The lock is unlocked, but some threads are waiting. Only writers may lock the lock | +//! | 1 | 1 | * | * | `*mut Node` | The lock is locked, but some threads are waiting. If the lock is read-locked, the last queue node contains the reader count | //! -//! ## Waiter queue +//! ## Waiter Queue //! -//! When threads are waiting on the lock (`QUEUE` is set), the lock state -//! points to a queue of waiters, which is implemented as a linked list of -//! nodes stored on the stack to avoid memory allocation. To enable lockless -//! enqueuing of new nodes to the queue, the linked list is single-linked upon -//! creation. Since when the lock is read-locked, the lock count is stored in -//! the last link of the queue, threads have to traverse the queue to find the -//! last element upon releasing the lock. To avoid having to traverse the whole -//! list again and again, a pointer to the found tail is cached in the (current) -//! first element of the queue. +//! When threads are waiting on the lock (the `QUEUE` bit is set), the lock state points to a queue +//! of waiters, which is implemented as a linked list of nodes stored on the stack to avoid memory +//! allocation. //! -//! Also, while the lock is unfair for performance reasons, it is still best to -//! wake the tail node first, which requires backlinks to previous nodes to be -//! created. This is done at the same time as finding the tail, and thus a set -//! tail field indicates the remaining portion of the queue is initialized. +//! To enable lock-free enqueuing of new nodes to the queue, the linked list is singly-linked upon +//! creation. +//! +//! When the lock is read-locked, the lock count (number of readers) is stored in the last link of +//! the queue. Threads have to traverse the queue to find the last element upon releasing the lock. +//! To avoid having to traverse the entire list every time we want to access the reader count, a +//! pointer to the found tail is cached in the (current) first element of the queue. +//! +//! Also, while the lock is unfair for performance reasons, it is still best to wake the tail node +//! first (FIFO ordering). Since we always pop nodes off the tail of the queue, we must store +//! backlinks to previous nodes so that we can update the `tail` field of the (current) first +//! element of the queue. Adding backlinks is done at the same time as finding the tail (via the +//! function [`find_tail_and_add_backlinks`]), and thus encountering a set tail field on a node +//! indicates that all following nodes in the queue are initialized. //! //! TLDR: Here's a diagram of what the queue looks like: //! @@ -89,21 +94,21 @@ //! 3. All nodes preceding this node must have a correct, non-null `next` field. //! 4. All nodes following this node must have a correct, non-null `prev` field. //! -//! Access to the queue is controlled by the `QUEUE_LOCKED` bit, which threads -//! try to set both after enqueuing themselves to eagerly add backlinks to the -//! queue, which drastically improves performance, and after unlocking the lock -//! to wake the next waiter(s). This is done atomically at the same time as the -//! enqueuing/unlocking operation. The thread releasing the `QUEUE_LOCK` bit -//! will check the state of the lock and wake up waiters as appropriate. This -//! guarantees forward-progress even if the unlocking thread could not acquire -//! the queue lock. +//! Access to the queue is controlled by the `QUEUE_LOCKED` bit. Threads will try to set this bit +//! in two cases: one is when a thread enqueues itself and eagerly adds backlinks to the queue +//! (which drastically improves performance), and the other is after a thread unlocks the lock to +//! wake up the next waiter(s). //! -//! ## Memory orderings +//! `QUEUE_LOCKED` is set atomically at the same time as the enqueuing/unlocking operations. The +//! thread releasing the `QUEUE_LOCKED` bit will check the state of the lock (in particular, whether +//! a downgrade was requested using the [`DOWNGRADED`] bit) and wake up waiters as appropriate. This +//! guarantees forward progress even if the unlocking thread could not acquire the queue lock. //! -//! To properly synchronize changes to the data protected by the lock, the lock -//! is acquired and released with [`Acquire`] and [`Release`] ordering, respectively. -//! To propagate the initialization of nodes, changes to the queue lock are also -//! performed using these orderings. +//! ## Memory Orderings +//! +//! To properly synchronize changes to the data protected by the lock, the lock is acquired and +//! released with [`Acquire`] and [`Release`] ordering, respectively. To propagate the +//! initialization of nodes, changes to the queue lock are also performed using these orderings. #![forbid(unsafe_op_in_unsafe_fn)] @@ -115,26 +120,30 @@ use crate::sync::atomic::Ordering::{AcqRel, Acquire, Relaxed, Release}; use crate::sync::atomic::{AtomicBool, AtomicPtr}; use crate::thread::{self, Thread, ThreadId}; -// Locking uses exponential backoff. `SPIN_COUNT` indicates how many times the -// locking operation will be retried. -// `spin_loop` will be called `2.pow(SPIN_COUNT) - 1` times. -const SPIN_COUNT: usize = 7; - -type State = *mut (); +/// The atomic lock state. type AtomicState = AtomicPtr<()>; +/// The inner lock state. +type State = *mut (); const UNLOCKED: State = without_provenance_mut(0); -const LOCKED: usize = 1; -const QUEUED: usize = 2; -const QUEUE_LOCKED: usize = 4; -const SINGLE: usize = 8; -const MASK: usize = !(QUEUE_LOCKED | QUEUED | LOCKED); +const LOCKED: usize = 1 << 0; +const QUEUED: usize = 1 << 1; +const QUEUE_LOCKED: usize = 1 << 2; +const DOWNGRADED: usize = 1 << 3; +const SINGLE: usize = 1 << 4; +const STATE: usize = DOWNGRADED | QUEUE_LOCKED | QUEUED | LOCKED; +const NODE_MASK: usize = !STATE; + +/// Locking uses exponential backoff. `SPIN_COUNT` indicates how many times the locking operation +/// will be retried. +/// +/// In other words, `spin_loop` will be called `2.pow(SPIN_COUNT) - 1` times. +const SPIN_COUNT: usize = 7; /// Marks the state as write-locked, if possible. #[inline] fn write_lock(state: State) -> Option { - let state = state.wrapping_byte_add(LOCKED); - if state.addr() & LOCKED == LOCKED { Some(state) } else { None } + if state.addr() & LOCKED == 0 { Some(state.map_addr(|addr| addr | LOCKED)) } else { None } } /// Marks the state as read-locked, if possible. @@ -147,13 +156,32 @@ fn read_lock(state: State) -> Option { } } -/// Masks the state, assuming it points to a queue node. +/// Converts a `State` into a `Node` by masking out the bottom bits of the state, assuming that the +/// state points to a queue node. /// /// # Safety +/// /// The state must contain a valid pointer to a queue node. #[inline] unsafe fn to_node(state: State) -> NonNull { - unsafe { NonNull::new_unchecked(state.mask(MASK)).cast() } + unsafe { NonNull::new_unchecked(state.mask(NODE_MASK)).cast() } +} + +/// The representation of a thread waiting on the lock queue. +/// +/// We initialize these `Node`s on thread execution stacks to avoid allocation. +/// +/// Note that we need an alignment of 16 to ensure that the last 4 bits of any +/// pointers to `Node`s are always zeroed (for the bit flags described in the +/// module-level documentation). +#[repr(align(16))] +struct Node { + next: AtomicLink, + prev: AtomicLink, + tail: AtomicLink, + write: bool, + thread: OnceCell, + completed: AtomicBool, } /// An atomic node pointer with relaxed operations. @@ -173,16 +201,6 @@ impl AtomicLink { } } -#[repr(align(8))] -struct Node { - next: AtomicLink, - prev: AtomicLink, - tail: AtomicLink, - write: bool, - thread: OnceCell, - completed: AtomicBool, -} - impl Node { /// Creates a new queue node. fn new(write: bool) -> Node { @@ -198,17 +216,17 @@ impl Node { /// Prepare this node for waiting. fn prepare(&mut self) { - // Fall back to creating an unnamed `Thread` handle to allow locking in - // TLS destructors. + // Fall back to creating an unnamed `Thread` handle to allow locking in TLS destructors. self.thread.get_or_init(|| { thread::try_current().unwrap_or_else(|| Thread::new_unnamed(ThreadId::new())) }); self.completed = AtomicBool::new(false); } - /// Wait until this node is marked as completed. + /// Wait until this node is marked as [`complete`](Node::complete)d by another thread. /// /// # Safety + /// /// May only be called from the thread that created the node. unsafe fn wait(&self) { while !self.completed.load(Acquire) { @@ -218,51 +236,48 @@ impl Node { } } - /// Atomically mark this node as completed. The node may not outlive this call. - unsafe fn complete(this: NonNull) { - // Since the node may be destroyed immediately after the completed flag - // is set, clone the thread handle before that. - let thread = unsafe { this.as_ref().thread.get().unwrap().clone() }; + /// Atomically mark this node as completed. + /// + /// # Safety + /// + /// `node` must point to a valid `Node`, and the node may not outlive this call. + unsafe fn complete(node: NonNull) { + // Since the node may be destroyed immediately after the completed flag is set, clone the + // thread handle before that. + let thread = unsafe { node.as_ref().thread.get().unwrap().clone() }; unsafe { - this.as_ref().completed.store(true, Release); + node.as_ref().completed.store(true, Release); } thread.unpark(); } } -struct PanicGuard; - -impl Drop for PanicGuard { - fn drop(&mut self) { - rtabort!("tried to drop node in intrusive list."); - } -} - -/// Add backlinks to the queue, returning the tail. +/// Traverse the queue and find the tail, adding backlinks to the queue while traversing. /// -/// May be called from multiple threads at the same time, while the queue is not +/// This may be called from multiple threads at the same time as long as the queue is not being /// modified (this happens when unlocking multiple readers). /// /// # Safety +/// /// * `head` must point to a node in a valid queue. -/// * `head` must be or be in front of the head of the queue at the time of the -/// last removal. -/// * The part of the queue starting with `head` must not be modified during this -/// call. -unsafe fn add_backlinks_and_find_tail(head: NonNull) -> NonNull { +/// * `head` must be in front of the previous head node that was used to perform the last removal. +/// * The part of the queue starting with `head` must not be modified during this call. +unsafe fn find_tail_and_add_backlinks(head: NonNull) -> NonNull { let mut current = head; + + // Traverse the queue until we find a node that has a set `tail`. let tail = loop { let c = unsafe { current.as_ref() }; - match c.tail.get() { - Some(tail) => break tail, - // SAFETY: - // All `next` fields before the first node with a `set` tail are - // non-null and valid (invariant 3). - None => unsafe { - let next = c.next.get().unwrap_unchecked(); - next.as_ref().prev.set(Some(current)); - current = next; - }, + if let Some(tail) = c.tail.get() { + break tail; + } + + // SAFETY: All `next` fields before the first node with a set `tail` are non-null and valid + // (by Invariant 3). + unsafe { + let next = c.next.get().unwrap_unchecked(); + next.as_ref().prev.set(Some(current)); + current = next; } }; @@ -272,6 +287,38 @@ unsafe fn add_backlinks_and_find_tail(head: NonNull) -> NonNull { } } +/// [`complete`](Node::complete)s all threads in the queue ending with `tail`. +/// +/// # Safety +/// +/// * `tail` must be a valid tail of a fully linked queue. +/// * The current thread must have exclusive access to that queue. +unsafe fn complete_all(tail: NonNull) { + let mut current = tail; + + // Traverse backwards through the queue (FIFO) and `complete` all of the nodes. + loop { + let prev = unsafe { current.as_ref().prev.get() }; + unsafe { + Node::complete(current); + } + match prev { + Some(prev) => current = prev, + None => return, + } + } +} + +/// A type to guard against the unwinds of stacks that nodes are located on due to panics. +struct PanicGuard; + +impl Drop for PanicGuard { + fn drop(&mut self) { + rtabort!("tried to drop node in intrusive list."); + } +} + +/// The public inner `RwLock` type. pub struct RwLock { state: AtomicState, } @@ -296,11 +343,10 @@ impl RwLock { #[inline] pub fn try_write(&self) -> bool { - // Atomically set the `LOCKED` bit. This is lowered to a single atomic - // instruction on most modern processors (e.g. "lock bts" on x86 and - // "ldseta" on modern AArch64), and therefore is more efficient than - // `fetch_update(lock(true))`, which can spuriously fail if a new node - // is appended to the queue. + // Atomically set the `LOCKED` bit. This is lowered to a single atomic instruction on most + // modern processors (e.g. "lock bts" on x86 and "ldseta" on modern AArch64), and therefore + // is more efficient than `fetch_update(lock(true))`, which can spuriously fail if a new + // node is appended to the queue. self.state.fetch_or(LOCKED, Acquire).addr() & LOCKED == 0 } @@ -313,88 +359,97 @@ impl RwLock { #[cold] fn lock_contended(&self, write: bool) { - let update = if write { write_lock } else { read_lock }; let mut node = Node::new(write); let mut state = self.state.load(Relaxed); let mut count = 0; + let update_fn = if write { write_lock } else { read_lock }; + loop { - if let Some(next) = update(state) { + // Optimistically update the state. + if let Some(next) = update_fn(state) { // The lock is available, try locking it. match self.state.compare_exchange_weak(state, next, Acquire, Relaxed) { Ok(_) => return, Err(new) => state = new, } + continue; } else if state.addr() & QUEUED == 0 && count < SPIN_COUNT { - // If the lock is not available and no threads are queued, spin - // for a while, using exponential backoff to decrease cache - // contention. + // If the lock is not available and no threads are queued, optimistically spin for a + // while, using exponential backoff to decrease cache contention. for _ in 0..(1 << count) { spin_loop(); } state = self.state.load(Relaxed); count += 1; - } else { - // Fall back to parking. First, prepare the node. - node.prepare(); - - // If there are threads queued, set the `next` field to a - // pointer to the next node in the queue. Otherwise set it to - // the lock count if the state is read-locked or to zero if it - // is write-locked. - node.next.0 = AtomicPtr::new(state.mask(MASK).cast()); - node.prev = AtomicLink::new(None); - let mut next = ptr::from_ref(&node) - .map_addr(|addr| addr | QUEUED | (state.addr() & LOCKED)) - as State; - - if state.addr() & QUEUED == 0 { - // If this is the first node in the queue, set the tail field to - // the node itself to ensure there is a current `tail` field in - // the queue (invariants 1 and 2). This needs to use `set` to - // avoid invalidating the new pointer. - node.tail.set(Some(NonNull::from(&node))); - } else { - // Otherwise, the tail of the queue is not known. - node.tail.set(None); - // Try locking the queue to eagerly add backlinks. - next = next.map_addr(|addr| addr | QUEUE_LOCKED); - } - - // Register the node, using release ordering to propagate our - // changes to the waking thread. - if let Err(new) = self.state.compare_exchange_weak(state, next, AcqRel, Relaxed) { - // The state has changed, just try again. - state = new; - continue; - } - - // The node is registered, so the structure must not be - // mutably accessed or destroyed while other threads may - // be accessing it. Guard against unwinds using a panic - // guard that aborts when dropped. - let guard = PanicGuard; - - // If the current thread locked the queue, unlock it again, - // linking it in the process. - if state.addr() & (QUEUE_LOCKED | QUEUED) == QUEUED { - unsafe { - self.unlock_queue(next); - } - } - - // Wait until the node is removed from the queue. - // SAFETY: the node was created by the current thread. - unsafe { - node.wait(); - } - - // The node was removed from the queue, disarm the guard. - mem::forget(guard); - - // Reload the state and try again. - state = self.state.load(Relaxed); - count = 0; + continue; } + // The optimistic paths did not succeed, so fall back to parking the thread. + + // First, prepare the node. + node.prepare(); + + // If there are threads queued, this will set the `next` field to be a pointer to the + // first node in the queue. + // If the state is read-locked, this will set `next` to the lock count. + // If it is write-locked, it will set `next` to zero. + node.next.0 = AtomicPtr::new(state.mask(NODE_MASK).cast()); + node.prev = AtomicLink::new(None); + + // Set the `QUEUED` bit and preserve the `LOCKED` and `DOWNGRADED` bit. + let mut next = ptr::from_ref(&node) + .map_addr(|addr| addr | QUEUED | (state.addr() & (DOWNGRADED | LOCKED))) + as State; + + let mut is_queue_locked = false; + if state.addr() & QUEUED == 0 { + // If this is the first node in the queue, set the `tail` field to the node itself + // to ensure there is a valid `tail` field in the queue (Invariants 1 & 2). + // This needs to use `set` to avoid invalidating the new pointer. + node.tail.set(Some(NonNull::from(&node))); + } else { + // Otherwise, the tail of the queue is not known. + node.tail.set(None); + + // Try locking the queue to eagerly add backlinks. + next = next.map_addr(|addr| addr | QUEUE_LOCKED); + + // Track if we changed the `QUEUE_LOCKED` bit from off to on. + is_queue_locked = state.addr() & QUEUE_LOCKED == 0; + } + + // Register the node, using release ordering to propagate our changes to the waking + // thread. + if let Err(new) = self.state.compare_exchange_weak(state, next, AcqRel, Relaxed) { + // The state has changed, just try again. + state = new; + continue; + } + // The node has been registered, so the structure must not be mutably accessed or + // destroyed while other threads may be accessing it. + + // Guard against unwinds using a `PanicGuard` that aborts when dropped. + let guard = PanicGuard; + + // If the current thread locked the queue, unlock it to eagerly adding backlinks. + if is_queue_locked { + // SAFETY: This thread set the `QUEUE_LOCKED` bit above. + unsafe { + self.unlock_queue(next); + } + } + + // Wait until the node is removed from the queue. + // SAFETY: the node was created by the current thread. + unsafe { + node.wait(); + } + + // The node was removed from the queue, disarm the guard. + mem::forget(guard); + + // Reload the state and try again. + state = self.state.load(Relaxed); + count = 0; } } @@ -402,39 +457,51 @@ impl RwLock { pub unsafe fn read_unlock(&self) { match self.state.fetch_update(Release, Acquire, |state| { if state.addr() & QUEUED == 0 { + // If there are no threads queued, simply decrement the reader count. let count = state.addr() - (SINGLE | LOCKED); Some(if count > 0 { without_provenance_mut(count | LOCKED) } else { UNLOCKED }) + } else if state.addr() & DOWNGRADED != 0 { + // This thread used to have exclusive access, but requested a downgrade. This has + // not been completed yet, so we still have exclusive access. + // Retract the downgrade request and unlock, but leave waking up new threads to the + // thread that already holds the queue lock. + Some(state.mask(!(DOWNGRADED | LOCKED))) } else { None } }) { Ok(_) => {} - // There are waiters queued and the lock count was moved to the - // tail of the queue. + // There are waiters queued and the lock count was moved to the tail of the queue. Err(state) => unsafe { self.read_unlock_contended(state) }, } } + /// # Safety + /// + /// * There must be threads queued on the lock. + /// * `state` must be a pointer to a node in a valid queue. + /// * There cannot be a `downgrade` in progress. #[cold] unsafe fn read_unlock_contended(&self, state: State) { - // The state was observed with acquire ordering above, so the current - // thread will observe all node initializations. - // SAFETY: - // Because new read-locks cannot be acquired while threads are queued, - // all queue-lock owners will observe the set `LOCKED` bit. Because they - // do not modify the queue while there is a lock owner, the queue will - // not be removed from here. - let tail = unsafe { add_backlinks_and_find_tail(to_node(state)).as_ref() }; + // The state was observed with acquire ordering above, so the current thread will have + // observed all node initializations. + // We also know that no threads can be modifying the queue starting at `state`: because new + // read-locks cannot be acquired while there are any threads queued on the lock, all + // queue-lock owners will observe a set `LOCKED` bit in `self.state` and will not modify + // the queue. The other case that a thread could modify the queue is if a downgrade is in + // progress (removal of the entire queue), but since that is part of this function's safety + // contract, we can guarantee that no other threads can modify the queue. + let tail = unsafe { find_tail_and_add_backlinks(to_node(state)).as_ref() }; + // The lock count is stored in the `next` field of `tail`. - // Decrement it, making sure to observe all changes made to the queue - // by the other lock owners by using acquire-release ordering. + // Decrement it, making sure to observe all changes made to the queue by the other lock + // owners by using acquire-release ordering. let was_last = tail.next.0.fetch_byte_sub(SINGLE, AcqRel).addr() - SINGLE == 0; if was_last { - // SAFETY: - // Other threads cannot read-lock while threads are queued. Also, - // the `LOCKED` bit is still set, so there are no writers. Therefore, - // the current thread exclusively owns the lock. + // SAFETY: Other threads cannot read-lock while threads are queued. Also, the `LOCKED` + // bit is still set, so there are no writers. Thus the current thread exclusively owns + // this lock, even though it is a reader. unsafe { self.unlock_contended(state) } } } @@ -444,49 +511,143 @@ impl RwLock { if let Err(state) = self.state.compare_exchange(without_provenance_mut(LOCKED), UNLOCKED, Release, Relaxed) { - // SAFETY: - // Since other threads cannot acquire the lock, the state can only - // have changed because there are threads queued on the lock. + // SAFETY: Since other threads cannot acquire the lock, the state can only have changed + // because there are threads queued on the lock. unsafe { self.unlock_contended(state) } } } /// # Safety + /// /// * The lock must be exclusively owned by this thread. /// * There must be threads queued on the lock. + /// * `state` must be a pointer to a node in a valid queue. + /// * There cannot be a `downgrade` in progress. #[cold] - unsafe fn unlock_contended(&self, mut state: State) { + unsafe fn unlock_contended(&self, state: State) { + debug_assert_eq!(state.addr() & (DOWNGRADED | QUEUED | LOCKED), QUEUED | LOCKED); + + let mut current = state; + + // We want to atomically release the lock and try to acquire the queue lock. loop { + // First check if the queue lock is already held. + if current.addr() & QUEUE_LOCKED != 0 { + // Another thread holds the queue lock, so let them wake up waiters for us. + let next = current.mask(!LOCKED); + match self.state.compare_exchange_weak(current, next, Release, Relaxed) { + Ok(_) => return, + Err(new) => { + current = new; + continue; + } + } + } + // Atomically release the lock and try to acquire the queue lock. - let next = state.map_addr(|a| (a & !LOCKED) | QUEUE_LOCKED); - match self.state.compare_exchange_weak(state, next, AcqRel, Relaxed) { - // The queue lock was acquired. Release it, waking up the next - // waiter in the process. - Ok(_) if state.addr() & QUEUE_LOCKED == 0 => unsafe { - return self.unlock_queue(next); - }, - // Another thread already holds the queue lock, leave waking up - // waiters to it. - Ok(_) => return, - Err(new) => state = new, + let next = current.map_addr(|addr| (addr & !LOCKED) | QUEUE_LOCKED); + match self.state.compare_exchange_weak(current, next, AcqRel, Relaxed) { + // Now that we have the queue lock, we can wake up the next waiter. + Ok(_) => { + // SAFETY: This thread just acquired the queue lock, and this function's safety + // contract requires that there are threads already queued on the lock. + unsafe { self.unlock_queue(next) }; + return; + } + Err(new) => current = new, } } } - /// Unlocks the queue. If the lock is unlocked, wakes up the next eligible - /// thread(s). + /// # Safety + /// + /// * The lock must be write-locked by this thread. + #[inline] + pub unsafe fn downgrade(&self) { + // Optimistically change the state from write-locked with a single writer and no waiters to + // read-locked with a single reader and no waiters. + if let Err(state) = self.state.compare_exchange( + without_provenance_mut(LOCKED), + without_provenance_mut(SINGLE | LOCKED), + Release, + Relaxed, + ) { + // SAFETY: The only way the state can have changed is if there are threads queued. + // Wake all of them up. + unsafe { self.downgrade_slow(state) } + } + } + + /// Downgrades the lock from write-locked to read-locked in the case that there are threads + /// waiting on the wait queue. + /// + /// This function will either wake up all of the waiters on the wait queue or designate the + /// current holder of the queue lock to wake up all of the waiters instead. Once the waiters + /// wake up, they will continue in the execution loop of `lock_contended`. /// /// # Safety - /// The queue lock must be held by the current thread. + /// + /// * The lock must be write-locked by this thread. + /// * `state` must be a pointer to a node in a valid queue. + /// * There must be threads queued on the lock. + #[cold] + unsafe fn downgrade_slow(&self, mut state: State) { + debug_assert_eq!(state.addr() & (DOWNGRADED | QUEUED | LOCKED), QUEUED | LOCKED); + + // Attempt to wake up all waiters by taking ownership of the entire waiter queue. + loop { + if state.addr() & QUEUE_LOCKED != 0 { + // Another thread already holds the queue lock. Tell it to wake up all waiters. + // If the other thread succeeds in waking up waiters before we release our lock, the + // effect will be just the same as if we had changed the state below. + // Otherwise, the `DOWNGRADED` bit will still be set, meaning that when this thread + // calls `read_unlock` later (because it holds a read lock and must unlock + // eventually), it will realize that the lock is still exclusively locked and act + // accordingly. + let next = state.map_addr(|addr| addr | DOWNGRADED); + match self.state.compare_exchange_weak(state, next, Release, Relaxed) { + Ok(_) => return, + Err(new) => state = new, + } + } else { + // Grab the entire queue by swapping the `state` with a single reader. + let next = ptr::without_provenance_mut(SINGLE | LOCKED); + if let Err(new) = self.state.compare_exchange_weak(state, next, AcqRel, Relaxed) { + state = new; + continue; + } + + // SAFETY: We have full ownership of this queue now, so nobody else can modify it. + let tail = unsafe { find_tail_and_add_backlinks(to_node(state)) }; + + // Wake up all waiters. + // SAFETY: `tail` was just computed, meaning the whole queue is linked, and we have + // full ownership of the queue, so we have exclusive access. + unsafe { complete_all(tail) }; + + return; + } + } + } + + /// Unlocks the queue. Wakes up all threads if a downgrade was requested, otherwise wakes up the + /// next eligible thread(s) if the lock is unlocked. + /// + /// # Safety + /// + /// * The queue lock must be held by the current thread. + /// * `state` must be a pointer to a node in a valid queue. + /// * There must be threads queued on the lock. unsafe fn unlock_queue(&self, mut state: State) { debug_assert_eq!(state.addr() & (QUEUED | QUEUE_LOCKED), QUEUED | QUEUE_LOCKED); loop { - let tail = unsafe { add_backlinks_and_find_tail(to_node(state)) }; + // SAFETY: Since we have the queue lock, nobody else can be modifying the queue. + let tail = unsafe { find_tail_and_add_backlinks(to_node(state)) }; - if state.addr() & LOCKED == LOCKED { - // Another thread has locked the lock. Leave waking up waiters - // to them by releasing the queue lock. + if state.addr() & (DOWNGRADED | LOCKED) == LOCKED { + // Another thread has locked the lock and no downgrade was requested. + // Leave waking up waiters to them by releasing the queue lock. match self.state.compare_exchange_weak( state, state.mask(!QUEUE_LOCKED), @@ -501,53 +662,63 @@ impl RwLock { } } - let is_writer = unsafe { tail.as_ref().write }; - if is_writer && let Some(prev) = unsafe { tail.as_ref().prev.get() } { - // `tail` is a writer and there is a node before `tail`. - // Split off `tail`. + // Since we hold the queue lock and downgrades cannot be requested if the lock is + // already read-locked, we have exclusive control over the queue here and can make + // modifications. - // There are no set `tail` links before the node pointed to by - // `state`, so the first non-null tail field will be current - // (invariant 2). Invariant 4 is fullfilled since `find_tail` - // was called on this node, which ensures all backlinks are set. + let downgrade = state.addr() & DOWNGRADED != 0; + let is_writer = unsafe { tail.as_ref().write }; + if !downgrade + && is_writer + && let Some(prev) = unsafe { tail.as_ref().prev.get() } + { + // If we are not downgrading and the next thread is a writer, only wake up that + // writing thread. + + // Split off `tail`. + // There are no set `tail` links before the node pointed to by `state`, so the first + // non-null tail field will be current (Invariant 2). + // We also fulfill Invariant 4 since `find_tail` was called on this node, which + // ensures all backlinks are set. unsafe { to_node(state).as_ref().tail.set(Some(prev)); } - // Release the queue lock. Doing this by subtraction is more - // efficient on modern processors since it is a single instruction - // instead of an update loop, which will fail if new threads are - // added to the list. - self.state.fetch_byte_sub(QUEUE_LOCKED, Release); - - // The tail was split off and the lock released. Mark the node as - // completed. - unsafe { - return Node::complete(tail); - } - } else { - // The next waiter is a reader or the queue only consists of one - // waiter. Just wake all threads. - - // The lock cannot be locked (checked above), so mark it as - // unlocked to reset the queue. - if let Err(new) = - self.state.compare_exchange_weak(state, UNLOCKED, Release, Acquire) - { + // Try to release the queue lock. We need to check the state again since another + // thread might have acquired the lock and requested a downgrade. + let next = state.mask(!QUEUE_LOCKED); + if let Err(new) = self.state.compare_exchange_weak(state, next, Release, Acquire) { + // Undo the tail modification above, so that we can find the tail again above. + // As mentioned above, we have exclusive control over the queue, so no other + // thread could have noticed the change. + unsafe { + to_node(state).as_ref().tail.set(Some(tail)); + } state = new; continue; } - let mut current = tail; - loop { - let prev = unsafe { current.as_ref().prev.get() }; - unsafe { - Node::complete(current); - } - match prev { - Some(prev) => current = prev, - None => return, - } + // The tail was split off and the lock was released. Mark the node as completed. + unsafe { + return Node::complete(tail); + } + } else { + // We are either downgrading, the next waiter is a reader, or the queue only + // consists of one waiter. In any case, just wake all threads. + + // Clear the queue. + let next = + if downgrade { ptr::without_provenance_mut(SINGLE | LOCKED) } else { UNLOCKED }; + if let Err(new) = self.state.compare_exchange_weak(state, next, Release, Acquire) { + state = new; + continue; + } + + // SAFETY: we computed `tail` above, and no new nodes can have been added since + // (otherwise the CAS above would have failed). + // Thus we have complete control over the whole queue. + unsafe { + return complete_all(tail); } } } diff --git a/library/std/src/sys/sync/rwlock/solid.rs b/library/std/src/sys/sync/rwlock/solid.rs index 7703082f9511..f664fef90740 100644 --- a/library/std/src/sys/sync/rwlock/solid.rs +++ b/library/std/src/sys/sync/rwlock/solid.rs @@ -79,6 +79,12 @@ impl RwLock { let rwl = self.raw(); expect_success_aborting(unsafe { abi::rwl_unl_rwl(rwl) }, &"rwl_unl_rwl"); } + + #[inline] + pub unsafe fn downgrade(&self) { + // The SOLID platform does not support the `downgrade` operation for reader writer locks, so + // this function is simply a no-op as only 1 reader can read: the original writer. + } } impl Drop for RwLock { diff --git a/library/std/src/sys/sync/rwlock/teeos.rs b/library/std/src/sys/sync/rwlock/teeos.rs index 763430223834..4a71a3abc272 100644 --- a/library/std/src/sys/sync/rwlock/teeos.rs +++ b/library/std/src/sys/sync/rwlock/teeos.rs @@ -41,4 +41,10 @@ impl RwLock { pub unsafe fn write_unlock(&self) { unsafe { self.inner.unlock() }; } + + #[inline] + pub unsafe fn downgrade(&self) { + // Since there is no difference between read-locked and write-locked on this platform, this + // function is simply a no-op as only 1 reader can read: the original writer. + } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 9e11360cab4a..f0787d286fd0 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1819,8 +1819,8 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T { // Only anon consts can implicitly capture params. // FIXME: is this correct behavior? - let param_env = cx.tcx.param_env(*def_id); - cx.tcx.normalize_erasing_regions(param_env, ct) + let typing_env = ty::TypingEnv::from_param_env(cx.tcx.param_env(*def_id)); + cx.tcx.normalize_erasing_regions(typing_env, ct) } else { ct }; @@ -2039,7 +2039,7 @@ pub(crate) fn clean_middle_ty<'tcx>( format!("{pat:?}").into_boxed_str(), ), ty::Array(ty, n) => { - let n = cx.tcx.normalize_erasing_regions(cx.param_env, n); + let n = cx.tcx.normalize_erasing_regions(cx.typing_env(), n); let n = print_const(cx, n); Array(Box::new(clean_middle_ty(bound_ty.rebind(ty), cx, None, None)), n.into()) } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index e3a0dbe1a7f3..a10a6a92bf57 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -772,8 +772,10 @@ impl Item { .find(|field| { let ty = field.ty(tcx, ty::GenericArgs::identity_for_item(tcx, field.did)); - tcx.layout_of(tcx.param_env(field.did).and(ty)) - .is_ok_and(|layout| !layout.is_1zst()) + tcx.layout_of( + ty::TypingEnv::post_analysis(tcx, field.did).as_query_input(ty), + ) + .is_ok_and(|layout| !layout.is_1zst()) }) .map_or_else( || adt.all_fields().any(|field| field.vis.is_public()), diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index e551e0170c60..d59b4e4081ca 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -419,7 +419,10 @@ fn print_const_with_custom_print_scalar<'tcx>( } (mir::Const::Val(mir::ConstValue::Scalar(int), _), ty::Int(i)) => { let ty = ct.ty(); - let size = tcx.layout_of(ty::ParamEnv::empty().and(ty)).unwrap().size; + let size = tcx + .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)) + .unwrap() + .size; let sign_extended_data = int.assert_scalar_int().to_int(size); let mut output = if with_underscores { format_integer_with_underscore_sep(&sign_extended_data.to_string()) diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index d5f6bfe415de..a562a9eee717 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -19,7 +19,7 @@ use rustc_hir::{HirId, Path}; use rustc_interface::interface; use rustc_lint::{MissingDoc, late_lint_mod}; use rustc_middle::hir::nested_filter; -use rustc_middle::ty::{ParamEnv, Ty, TyCtxt}; +use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt}; use rustc_session::config::{self, CrateType, ErrorOutputType, Input, ResolveDocLinks}; pub(crate) use rustc_session::config::{Options, UnstableOptions}; use rustc_session::{Session, lint}; @@ -88,6 +88,13 @@ impl<'tcx> DocContext<'tcx> { ret } + pub(crate) fn typing_env(&self) -> ty::TypingEnv<'tcx> { + ty::TypingEnv { + typing_mode: ty::TypingMode::non_body_analysis(), + param_env: self.param_env, + } + } + /// Call the closure with the given parameters set as /// the generic parameters for a type alias' RHS. pub(crate) fn enter_alias( diff --git a/src/librustdoc/html/render/type_layout.rs b/src/librustdoc/html/render/type_layout.rs index d85ba3a2b14b..9317844956de 100644 --- a/src/librustdoc/html/render/type_layout.rs +++ b/src/librustdoc/html/render/type_layout.rs @@ -37,9 +37,9 @@ pub(crate) fn document_type_layout<'a, 'cx: 'a>( } let tcx = cx.tcx(); - let param_env = tcx.param_env(ty_def_id); + let typing_env = ty::TypingEnv::post_analysis(tcx, ty_def_id); let ty = tcx.type_of(ty_def_id).instantiate_identity(); - let type_layout = tcx.layout_of(param_env.and(ty)); + let type_layout = tcx.layout_of(typing_env.as_query_input(ty)); let variants = if let Ok(type_layout) = type_layout && let Variants::Multiple { variants, tag, tag_encoding, .. } = @@ -71,7 +71,7 @@ pub(crate) fn document_type_layout<'a, 'cx: 'a>( Vec::new() }; - let type_layout_size = tcx.layout_of(param_env.and(ty)).map(|layout| { + let type_layout_size = tcx.layout_of(typing_env.as_query_input(ty)).map(|layout| { let is_unsized = layout.is_unsized(); let is_uninhabited = layout.is_uninhabited(); let size = layout.size.bytes(); diff --git a/src/tools/clippy/clippy_lints/src/assigning_clones.rs b/src/tools/clippy/clippy_lints/src/assigning_clones.rs index 0b82c0cd04c1..00626a37ef84 100644 --- a/src/tools/clippy/clippy_lints/src/assigning_clones.rs +++ b/src/tools/clippy/clippy_lints/src/assigning_clones.rs @@ -96,7 +96,7 @@ impl<'tcx> LateLintPass<'tcx> for AssigningClones { }, _ => return, } - && let Ok(Some(resolved_fn)) = Instance::try_resolve(cx.tcx, cx.param_env, fn_id, fn_gen_args) + && let Ok(Some(resolved_fn)) = Instance::try_resolve(cx.tcx, cx.typing_env(), fn_id, fn_gen_args) // TODO: This check currently bails if the local variable has no initializer. // That is overly conservative - the lint should fire even if there was no initializer, // but the variable has been initialized before `lhs` was evaluated. diff --git a/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs b/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs index 7d89195eeca7..adac2f27ea8c 100644 --- a/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs +++ b/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs @@ -62,7 +62,7 @@ fn is_impl_not_trait_with_bool_out<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) - }) .is_some_and(|assoc_item| { let proj = Ty::new_projection(cx.tcx, assoc_item.def_id, cx.tcx.mk_args_trait(ty, [])); - let nty = cx.tcx.normalize_erasing_regions(cx.param_env, proj); + let nty = cx.tcx.normalize_erasing_regions(cx.typing_env(), proj); nty.is_bool() }) diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs index b167d7f22087..f864b7a5a8af 100644 --- a/src/tools/clippy/clippy_lints/src/dereference.rs +++ b/src/tools/clippy/clippy_lints/src/dereference.rs @@ -17,7 +17,7 @@ use rustc_hir::{ }; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability}; -use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, TypeVisitableExt, TypeckResults}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, TypeckResults}; use rustc_session::impl_lint_pass; use rustc_span::symbol::sym; use rustc_span::{Span, Symbol}; @@ -755,7 +755,8 @@ impl TyCoercionStability { DefinedTy::Hir(ty) => Self::for_hir_ty(ty), DefinedTy::Mir(ty) => Self::for_mir_ty( cx.tcx, - ty.param_env, + // FIXME(#132279): convert `DefinedTy` to use `TypingEnv` instead. + ty::TypingEnv::from_param_env(ty.param_env), cx.tcx.instantiate_bound_regions_with_erased(ty.value), for_return, ), @@ -823,12 +824,12 @@ impl TyCoercionStability { } } - fn for_mir_ty<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: Ty<'tcx>, for_return: bool) -> Self { + fn for_mir_ty<'tcx>(tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>, ty: Ty<'tcx>, for_return: bool) -> Self { let ty::Ref(_, mut ty, _) = *ty.kind() else { return Self::None; }; - ty = tcx.try_normalize_erasing_regions(param_env, ty).unwrap_or(ty); + ty = tcx.try_normalize_erasing_regions(typing_env, ty).unwrap_or(ty); loop { break match *ty.kind() { ty::Ref(_, ref_ty, _) => { diff --git a/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs b/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs index 55afdbf22e1f..617982f4da30 100644 --- a/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs +++ b/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs @@ -99,7 +99,7 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetRef { sym::mem_forget if is_copy => return, sym::mem_drop if is_type_lang_item(cx, arg_ty, LangItem::ManuallyDrop) => return, sym::mem_drop - if !(arg_ty.needs_drop(cx.tcx, cx.param_env) + if !(arg_ty.needs_drop(cx.tcx, cx.typing_env()) || is_must_use_func_call(cx, arg) || is_must_use_ty(cx, arg_ty) || drop_is_single_call_in_arm) => @@ -107,7 +107,7 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetRef { (DROP_NON_DROP, DROP_NON_DROP_SUMMARY.into(), Some(arg.span)) }, sym::mem_forget => { - if arg_ty.needs_drop(cx.tcx, cx.param_env) { + if arg_ty.needs_drop(cx.tcx, cx.typing_env()) { ( MEM_FORGET, Cow::Owned(format!( diff --git a/src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs b/src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs index 25105817ad97..4bc6ad0798c9 100644 --- a/src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs +++ b/src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs @@ -70,7 +70,7 @@ fn check_sig(cx: &LateContext<'_>, name: Symbol, sig: &FnSig<'_>, fn_id: LocalDe .instantiate_bound_regions_with_erased(cx.tcx.fn_sig(fn_id).instantiate_identity().output()); let ret_ty = cx .tcx - .try_normalize_erasing_regions(cx.param_env, ret_ty) + .try_normalize_erasing_regions(cx.typing_env(), ret_ty) .unwrap_or(ret_ty); if cx .tcx diff --git a/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs b/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs index 314d0dfa26ce..906da81b1837 100644 --- a/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs +++ b/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs @@ -215,7 +215,7 @@ impl {self_ty_without_ref} {{ && implements_trait(cx, ret_ty, iterator_did, &[]) && let Some(iter_ty) = make_normalized_projection( cx.tcx, - cx.param_env, + cx.typing_env(), iterator_did, sym::Item, [ret_ty], diff --git a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs index c5a2760234fc..644365c9fe56 100644 --- a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs +++ b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs @@ -4,7 +4,7 @@ use rustc_errors::Applicability; use rustc_hir::{Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::layout::LayoutOf; -use rustc_middle::ty::{self, ParamEnv}; +use rustc_middle::ty; use rustc_session::impl_lint_pass; use rustc_span::{BytePos, Pos, Span}; @@ -57,7 +57,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeConstArrays { && let ty = cx.tcx.type_of(item.owner_id).instantiate_identity() && let ty::Array(element_type, cst) = ty.kind() && let Some((ty::ValTree::Leaf(element_count), _)) = cx.tcx - .try_normalize_erasing_regions(ParamEnv::empty(), *cst).unwrap_or(*cst).try_to_valtree() + .try_normalize_erasing_regions(cx.typing_env(), *cst).unwrap_or(*cst).try_to_valtree() && let element_count = element_count.to_target_usize(cx.tcx) && let Ok(element_size) = cx.layout_of(*element_type).map(|l| l.size.bytes()) && u128::from(self.maximum_allowed_size) < u128::from(element_count) * u128::from(element_size) diff --git a/src/tools/clippy/clippy_lints/src/large_futures.rs b/src/tools/clippy/clippy_lints/src/large_futures.rs index 25f9be8b2d7a..593704f206a1 100644 --- a/src/tools/clippy/clippy_lints/src/large_futures.rs +++ b/src/tools/clippy/clippy_lints/src/large_futures.rs @@ -63,7 +63,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeFuture { && let ty = cx.typeck_results().expr_ty(arg) && let Some(future_trait_def_id) = cx.tcx.lang_items().future_trait() && implements_trait(cx, ty, future_trait_def_id, &[]) - && let Ok(layout) = cx.tcx.layout_of(cx.param_env.and(ty)) + && let Ok(layout) = cx.tcx.layout_of(cx.typing_env().as_query_input(ty)) && let size = layout.layout.size() && size >= Size::from_bytes(self.future_size_threshold) { diff --git a/src/tools/clippy/clippy_lints/src/large_stack_frames.rs b/src/tools/clippy/clippy_lints/src/large_stack_frames.rs index d2bdf194adad..5ed948c02bbc 100644 --- a/src/tools/clippy/clippy_lints/src/large_stack_frames.rs +++ b/src/tools/clippy/clippy_lints/src/large_stack_frames.rs @@ -150,11 +150,11 @@ impl<'tcx> LateLintPass<'tcx> for LargeStackFrames { } let mir = cx.tcx.optimized_mir(def_id); - let param_env = cx.tcx.param_env(def_id); + let typing_env = mir.typing_env(cx.tcx); let sizes_of_locals = || { mir.local_decls.iter().filter_map(|local| { - let layout = cx.tcx.layout_of(param_env.and(local.ty)).ok()?; + let layout = cx.tcx.layout_of(typing_env.as_query_input(local.ty)).ok()?; Some((local, layout.size.bytes())) }) }; diff --git a/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs b/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs index ee561ea85ed1..48318682f33c 100644 --- a/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs @@ -151,7 +151,7 @@ fn is_ref_iterable<'tcx>( // Using by value won't consume anything if implements_trait(cx, self_ty, trait_id, &[]) && let Some(ty) = - make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [self_ty]) + make_normalized_projection(cx.tcx, cx.typing_env(), trait_id, sym!(IntoIter), [self_ty]) && ty == res_ty { return Some((AdjustKind::None, self_ty)); @@ -168,7 +168,7 @@ fn is_ref_iterable<'tcx>( }; if implements_trait(cx, self_ty, trait_id, &[]) && let Some(ty) = - make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [self_ty]) + make_normalized_projection(cx.tcx, cx.typing_env(), trait_id, sym!(IntoIter), [self_ty]) && ty == res_ty { return Some((AdjustKind::reborrow(mutbl), self_ty)); @@ -181,7 +181,7 @@ fn is_ref_iterable<'tcx>( // Attempt to borrow let self_ty = Ty::new_ref(cx.tcx, cx.tcx.lifetimes.re_erased, self_ty, mutbl); if implements_trait(cx, self_ty, trait_id, &[]) - && let Some(ty) = make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [self_ty]) + && let Some(ty) = make_normalized_projection(cx.tcx, cx.typing_env(), trait_id, sym!(IntoIter), [self_ty]) && ty == res_ty { return Some((AdjustKind::borrow(mutbl), self_ty)); @@ -204,7 +204,7 @@ fn is_ref_iterable<'tcx>( && target != self_ty && implements_trait(cx, target, trait_id, &[]) && let Some(ty) = - make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [target]) + make_normalized_projection(cx.tcx, cx.typing_env(), trait_id, sym!(IntoIter), [target]) && ty == res_ty { Some((AdjustKind::auto_reborrow(mutbl), target)) @@ -222,7 +222,7 @@ fn is_ref_iterable<'tcx>( if is_copy(cx, target) && implements_trait(cx, target, trait_id, &[]) && let Some(ty) = - make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [target]) + make_normalized_projection(cx.tcx, cx.typing_env(), trait_id, sym!(IntoIter), [target]) && ty == res_ty { Some((AdjustKind::Deref, target)) @@ -240,7 +240,7 @@ fn is_ref_iterable<'tcx>( if self_ty.is_ref() && implements_trait(cx, target, trait_id, &[]) && let Some(ty) = - make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [target]) + make_normalized_projection(cx.tcx, cx.typing_env(), trait_id, sym!(IntoIter), [target]) && ty == res_ty { Some((AdjustKind::auto_borrow(mutbl), target)) diff --git a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs index 9c41528e6476..c00b9b368c43 100644 --- a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs +++ b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs @@ -203,10 +203,10 @@ fn is_is_empty_sig(cx: &LateContext<'_>, call_id: HirId) -> bool { fn iterates_same_ty<'tcx>(cx: &LateContext<'tcx>, iter_ty: Ty<'tcx>, collect_ty: Ty<'tcx>) -> bool { if let Some(iter_trait) = cx.tcx.get_diagnostic_item(sym::Iterator) && let Some(into_iter_trait) = cx.tcx.get_diagnostic_item(sym::IntoIterator) - && let Some(iter_item_ty) = make_normalized_projection(cx.tcx, cx.param_env, iter_trait, sym::Item, [iter_ty]) + && let Some(iter_item_ty) = make_normalized_projection(cx.tcx, cx.typing_env(), iter_trait, sym::Item, [iter_ty]) && let Some(into_iter_item_proj) = make_projection(cx.tcx, into_iter_trait, sym::Item, [collect_ty]) && let Ok(into_iter_item_ty) = cx.tcx.try_normalize_erasing_regions( - cx.param_env, + cx.typing_env(), Ty::new_projection_from_args(cx.tcx, into_iter_item_proj.def_id, into_iter_item_proj.args), ) { @@ -237,7 +237,7 @@ fn is_contains_sig(cx: &LateContext<'_>, call_id: HirId, iter_expr: &Expr<'_>) - ) && let args = cx.tcx.mk_args(&[GenericArg::from(typeck.expr_ty_adjusted(iter_expr))]) && let proj_ty = Ty::new_projection_from_args(cx.tcx, iter_item.def_id, args) - && let Ok(item_ty) = cx.tcx.try_normalize_erasing_regions(cx.param_env, proj_ty) + && let Ok(item_ty) = cx.tcx.try_normalize_erasing_regions(cx.typing_env(), proj_ty) { item_ty == EarlyBinder::bind(search_ty).instantiate(cx.tcx, cx.typeck_results().node_args(call_id)) } else { diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_min_or_max.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_min_or_max.rs index 062d1348555c..7d01bdc2269b 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_min_or_max.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_min_or_max.rs @@ -19,7 +19,7 @@ pub(super) fn check<'tcx>( arg: &'tcx Expr<'_>, ) { let typeck_results = cx.typeck_results(); - let ecx = ConstEvalCtxt::with_env(cx.tcx, cx.param_env, typeck_results); + let ecx = ConstEvalCtxt::with_env(cx.tcx, cx.typing_env(), typeck_results); if let Some(id) = typeck_results.type_dependent_def_id(expr.hir_id) && (cx.tcx.is_diagnostic_item(sym::cmp_ord_min, id) || cx.tcx.is_diagnostic_item(sym::cmp_ord_max, id)) { diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs index 82549413fa91..84ea3554a358 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs @@ -578,7 +578,7 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty< if output_ty.contains(param_ty) { if let Ok(new_ty) = cx.tcx.try_instantiate_and_normalize_erasing_regions( new_subst, - cx.param_env, + cx.typing_env(), bound_fn_sig.rebind(output_ty), ) { expr = parent_expr; diff --git a/src/tools/clippy/clippy_lints/src/methods/zst_offset.rs b/src/tools/clippy/clippy_lints/src/methods/zst_offset.rs index d33021c2a7bf..102fa7bc8953 100644 --- a/src/tools/clippy/clippy_lints/src/methods/zst_offset.rs +++ b/src/tools/clippy/clippy_lints/src/methods/zst_offset.rs @@ -7,7 +7,7 @@ use super::ZST_OFFSET; pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>) { if let ty::RawPtr(ty, _) = cx.typeck_results().expr_ty(recv).kind() - && let Ok(layout) = cx.tcx.layout_of(cx.param_env.and(*ty)) + && let Ok(layout) = cx.tcx.layout_of(cx.typing_env().as_query_input(*ty)) && layout.is_zst() { span_lint(cx, ZST_OFFSET, expr.span, "offset calculation on zero-sized value"); diff --git a/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs b/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs index c1424b9f1dc8..43b885fbd2c9 100644 --- a/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs +++ b/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs @@ -421,7 +421,7 @@ fn replace_types<'tcx>( .expect_ty(cx.tcx) .to_ty(cx.tcx); - if let Ok(projected_ty) = cx.tcx.try_normalize_erasing_regions(cx.param_env, projection) + if let Ok(projected_ty) = cx.tcx.try_normalize_erasing_regions(cx.typing_env(), projection) && args[term_param_ty.index as usize] != GenericArg::from(projected_ty) { deque.push_back((*term_param_ty, projected_ty)); diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs index 5e20b4064260..57fa4797c5e5 100644 --- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs +++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs @@ -278,23 +278,23 @@ impl<'tcx> NonCopyConst<'tcx> { fn is_value_unfrozen_expr(cx: &LateContext<'tcx>, hir_id: HirId, def_id: DefId, ty: Ty<'tcx>) -> bool { let args = cx.typeck_results().node_args(hir_id); - let result = Self::const_eval_resolve(cx.tcx, cx.param_env, ty::UnevaluatedConst::new(def_id, args), DUMMY_SP); + let result = Self::const_eval_resolve(cx.tcx, cx.typing_env(), ty::UnevaluatedConst::new(def_id, args), DUMMY_SP); Self::is_value_unfrozen_raw(cx, result, ty) } pub fn const_eval_resolve( tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ct: ty::UnevaluatedConst<'tcx>, span: Span, ) -> EvalToValTreeResult<'tcx> { - match ty::Instance::try_resolve(tcx, param_env, ct.def, ct.args) { + match ty::Instance::try_resolve(tcx, typing_env, ct.def, ct.args) { Ok(Some(instance)) => { let cid = GlobalId { instance, promoted: None, }; - tcx.const_eval_global_id_for_typeck(param_env, cid, span) + tcx.const_eval_global_id_for_typeck(typing_env.param_env, cid, span) }, Ok(None) => Err(ErrorHandled::TooGeneric(span)), Err(err) => Err(ErrorHandled::Reported(err.into(), span)), @@ -321,7 +321,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst<'tcx> { // Normalize assoc types because ones originated from generic params // bounded other traits could have their bound. - let normalized = cx.tcx.normalize_erasing_regions(cx.param_env, ty); + let normalized = cx.tcx.normalize_erasing_regions(cx.typing_env(), ty); if self.interior_mut.is_interior_mut_ty(cx, normalized) // When there's no default value, lint it only according to its type; // in other words, lint consts whose value *could* be unfrozen, not definitely is. @@ -361,12 +361,12 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst<'tcx> { .trait_item_def_id && cx .tcx - .layout_of(cx.tcx.param_env(of_trait_def_id).and( + .layout_of(ty::TypingEnv::post_analysis(cx.tcx, of_trait_def_id).as_query_input( // Normalize assoc types because ones originated from generic params // bounded other traits could have their bound at the trait defs; // and, in that case, the definition is *not* generic. cx.tcx.normalize_erasing_regions( - cx.tcx.param_env(of_trait_def_id), + ty::TypingEnv::post_analysis(cx.tcx, of_trait_def_id), cx.tcx.type_of(of_assoc_item).instantiate_identity(), ), )) @@ -376,7 +376,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst<'tcx> { // similar to unknown layouts. // e.g. `layout_of(...).is_err() || has_frozen_variant(...);` && let ty = cx.tcx.type_of(impl_item.owner_id).instantiate_identity() - && let normalized = cx.tcx.normalize_erasing_regions(cx.param_env, ty) + && let normalized = cx.tcx.normalize_erasing_regions(cx.typing_env(), ty) && self.interior_mut.is_interior_mut_ty(cx, normalized) && Self::is_value_unfrozen_poly(cx, *body_id, normalized) { @@ -386,7 +386,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst<'tcx> { ItemKind::Impl(Impl { of_trait: None, .. }) => { let ty = cx.tcx.type_of(impl_item.owner_id).instantiate_identity(); // Normalize assoc types originated from generic params. - let normalized = cx.tcx.normalize_erasing_regions(cx.param_env, ty); + let normalized = cx.tcx.normalize_erasing_regions(cx.typing_env(), ty); if self.interior_mut.is_interior_mut_ty(cx, normalized) && Self::is_value_unfrozen_poly(cx, *body_id, normalized) diff --git a/src/tools/clippy/clippy_lints/src/operators/const_comparisons.rs b/src/tools/clippy/clippy_lints/src/operators/const_comparisons.rs index 5d94cfab3b02..1a0bfd8b9970 100644 --- a/src/tools/clippy/clippy_lints/src/operators/const_comparisons.rs +++ b/src/tools/clippy/clippy_lints/src/operators/const_comparisons.rs @@ -26,7 +26,7 @@ fn comparison_to_const<'tcx>( if let ExprKind::Binary(operator, left, right) = expr.kind && let Ok(cmp_op) = CmpOp::try_from(operator.node) { - let ecx = ConstEvalCtxt::with_env(cx.tcx, cx.param_env, typeck); + let ecx = ConstEvalCtxt::with_env(cx.tcx, cx.typing_env(), typeck); match (ecx.eval(left), ecx.eval(right)) { (Some(_), Some(_)) => None, (_, Some(con)) => Some((cmp_op, left, right, con, typeck.expr_ty(right))), diff --git a/src/tools/clippy/clippy_lints/src/operators/erasing_op.rs b/src/tools/clippy/clippy_lints/src/operators/erasing_op.rs index 24bfe2b050bb..e3fc8d8fea7d 100644 --- a/src/tools/clippy/clippy_lints/src/operators/erasing_op.rs +++ b/src/tools/clippy/clippy_lints/src/operators/erasing_op.rs @@ -39,7 +39,7 @@ fn check_op<'tcx>( other: &Expr<'tcx>, parent: &Expr<'tcx>, ) { - if ConstEvalCtxt::with_env(cx.tcx, cx.param_env, tck).eval_simple(op) == Some(Constant::Int(0)) { + if ConstEvalCtxt::with_env(cx.tcx, cx.typing_env(), tck).eval_simple(op) == Some(Constant::Int(0)) { if different_types(tck, other, parent) { return; } diff --git a/src/tools/clippy/clippy_lints/src/operators/float_cmp.rs b/src/tools/clippy/clippy_lints/src/operators/float_cmp.rs index ab5f91c1d672..8272d3643d42 100644 --- a/src/tools/clippy/clippy_lints/src/operators/float_cmp.rs +++ b/src/tools/clippy/clippy_lints/src/operators/float_cmp.rs @@ -17,8 +17,7 @@ pub(crate) fn check<'tcx>( right: &'tcx Expr<'_>, ) { if (op == BinOpKind::Eq || op == BinOpKind::Ne) && is_float(cx, left) { - let typeck = cx.typeck_results(); - let ecx = ConstEvalCtxt::with_env(cx.tcx, cx.param_env, typeck); + let ecx = ConstEvalCtxt::new(cx); let left_is_local = match ecx.eval_with_source(left) { Some((c, s)) if !is_allowed(&c) => s.is_local(), Some(_) => return, diff --git a/src/tools/clippy/clippy_lints/src/redundant_slicing.rs b/src/tools/clippy/clippy_lints/src/redundant_slicing.rs index dc66fb28fa8c..0ac818c21d9b 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_slicing.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_slicing.rs @@ -136,7 +136,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantSlicing { }); } else if let Some(target_id) = cx.tcx.lang_items().deref_target() { if let Ok(deref_ty) = cx.tcx.try_normalize_erasing_regions( - cx.param_env, + cx.typing_env(), Ty::new_projection_from_args(cx.tcx, target_id, cx.tcx.mk_args(&[GenericArg::from(indexed_ty)])), ) { if deref_ty == expr_ty { diff --git a/src/tools/clippy/clippy_lints/src/returns.rs b/src/tools/clippy/clippy_lints/src/returns.rs index 1e0f6dff1abe..aeff31d02d26 100644 --- a/src/tools/clippy/clippy_lints/src/returns.rs +++ b/src/tools/clippy/clippy_lints/src/returns.rs @@ -391,7 +391,7 @@ fn check_final_expr<'tcx>( if let Some(inner) = inner { if for_each_unconsumed_temporary(cx, inner, |temporary_ty| { - if temporary_ty.has_significant_drop(cx.tcx, cx.param_env) + if temporary_ty.has_significant_drop(cx.tcx, cx.typing_env()) && temporary_ty .walk() .any(|arg| matches!(arg.unpack(), GenericArgKind::Lifetime(re) if !re.is_static())) diff --git a/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs b/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs index abd8363456df..1a5b958e6a67 100644 --- a/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs +++ b/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs @@ -154,7 +154,7 @@ impl<'cx, 'others, 'tcx> AttrChecker<'cx, 'others, 'tcx> { let ty = self .cx .tcx - .try_normalize_erasing_regions(self.cx.param_env, ty) + .try_normalize_erasing_regions(self.cx.typing_env(), ty) .unwrap_or(ty); match self.type_cache.entry(ty) { Entry::Occupied(e) => return *e.get(), diff --git a/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs b/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs index 52bb7c4bd68a..50a1577b2884 100644 --- a/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs +++ b/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs @@ -58,7 +58,7 @@ fn is_struct_with_trailing_zero_sized_array<'tcx>(cx: &LateContext<'tcx>, item: && let Some(last_field) = data.fields().last() && let field_ty = cx .tcx - .normalize_erasing_regions(cx.param_env, cx.tcx.type_of(last_field.def_id).instantiate_identity()) + .normalize_erasing_regions(cx.typing_env(), cx.tcx.type_of(last_field.def_id).instantiate_identity()) && let ty::Array(_, array_len) = *field_ty.kind() && let Some(0) = array_len.try_to_target_usize(cx.tcx) { diff --git a/src/tools/clippy/clippy_lints/src/transmute/eager_transmute.rs b/src/tools/clippy/clippy_lints/src/transmute/eager_transmute.rs index ca9daf2d2a03..1209bd5b34f2 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/eager_transmute.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/eager_transmute.rs @@ -88,8 +88,8 @@ pub(super) fn check<'tcx>( && is_normalizable(cx, cx.param_env, to_ty) // we only want to lint if the target type has a niche that is larger than the one of the source type // e.g. `u8` to `NonZero` should lint, but `NonZero` to `u8` should not - && let Ok(from_layout) = cx.tcx.layout_of(cx.param_env.and(from_ty)) - && let Ok(to_layout) = cx.tcx.layout_of(cx.param_env.and(to_ty)) + && let Ok(from_layout) = cx.tcx.layout_of(cx.typing_env().as_query_input(from_ty)) + && let Ok(to_layout) = cx.tcx.layout_of(cx.typing_env().as_query_input(to_ty)) && match (from_layout.largest_niche, to_layout.largest_niche) { (Some(from_niche), Some(to_niche)) => !range_fully_contained(from_niche.valid_range, to_niche.valid_range), (None, Some(_)) => true, diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs index 3b32e4396b9f..4dc1290e8b15 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs @@ -244,7 +244,7 @@ enum ReducedTy<'tcx> { /// Reduce structs containing a single non-zero sized field to it's contained type. fn reduce_ty<'tcx>(cx: &LateContext<'tcx>, mut ty: Ty<'tcx>) -> ReducedTy<'tcx> { loop { - ty = cx.tcx.try_normalize_erasing_regions(cx.param_env, ty).unwrap_or(ty); + ty = cx.tcx.try_normalize_erasing_regions(cx.typing_env(), ty).unwrap_or(ty); return match *ty.kind() { ty::Array(sub_ty, _) if matches!(sub_ty.kind(), ty::Int(_) | ty::Uint(_)) => { ReducedTy::TypeErasure { raw_ptr_only: false } @@ -297,8 +297,8 @@ fn reduce_ty<'tcx>(cx: &LateContext<'tcx>, mut ty: Ty<'tcx>) -> ReducedTy<'tcx> } fn is_zero_sized_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { - if let Ok(ty) = cx.tcx.try_normalize_erasing_regions(cx.param_env, ty) - && let Ok(layout) = cx.tcx.layout_of(cx.param_env.and(ty)) + if let Ok(ty) = cx.tcx.try_normalize_erasing_regions(cx.typing_env(), ty) + && let Ok(layout) = cx.tcx.layout_of(cx.typing_env().as_query_input(ty)) { layout.layout.size().bytes() == 0 } else { diff --git a/src/tools/clippy/clippy_lints/src/transmute/utils.rs b/src/tools/clippy/clippy_lints/src/transmute/utils.rs index e8ccd35b4daf..5baa67b1f3e8 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/utils.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/utils.rs @@ -4,10 +4,11 @@ use rustc_middle::ty::Ty; // check if the component types of the transmuted collection and the result have different ABI, // size or alignment pub(super) fn is_layout_incompatible<'tcx>(cx: &LateContext<'tcx>, from: Ty<'tcx>, to: Ty<'tcx>) -> bool { - if let Ok(from) = cx.tcx.try_normalize_erasing_regions(cx.param_env, from) - && let Ok(to) = cx.tcx.try_normalize_erasing_regions(cx.param_env, to) - && let Ok(from_layout) = cx.tcx.layout_of(cx.param_env.and(from)) - && let Ok(to_layout) = cx.tcx.layout_of(cx.param_env.and(to)) + let typing_env = cx.typing_env(); + if let Ok(from) = cx.tcx.try_normalize_erasing_regions(typing_env, from) + && let Ok(to) = cx.tcx.try_normalize_erasing_regions(typing_env, to) + && let Ok(from_layout) = cx.tcx.layout_of(typing_env.as_query_input(from)) + && let Ok(to_layout) = cx.tcx.layout_of(typing_env.as_query_input(to)) { from_layout.size != to_layout.size || from_layout.align.abi != to_layout.align.abi } else { diff --git a/src/tools/clippy/clippy_lints/src/uninhabited_references.rs b/src/tools/clippy/clippy_lints/src/uninhabited_references.rs index cfa565cf8037..ee9ef0172538 100644 --- a/src/tools/clippy/clippy_lints/src/uninhabited_references.rs +++ b/src/tools/clippy/clippy_lints/src/uninhabited_references.rs @@ -46,7 +46,7 @@ impl LateLintPass<'_> for UninhabitedReferences { if let ExprKind::Unary(UnOp::Deref, _) = expr.kind { let ty = cx.typeck_results().expr_ty_adjusted(expr); - if ty.is_privately_uninhabited(cx.tcx, cx.param_env) { + if ty.is_privately_uninhabited(cx.tcx, cx.typing_env()) { span_lint( cx, UNINHABITED_REFERENCES, @@ -71,7 +71,7 @@ impl LateLintPass<'_> for UninhabitedReferences { } if let FnRetTy::Return(hir_ty) = fndecl.output && let TyKind::Ref(_, mut_ty) = hir_ty.kind - && lower_ty(cx.tcx, mut_ty.ty).is_privately_uninhabited(cx.tcx, cx.param_env) + && lower_ty(cx.tcx, mut_ty.ty).is_privately_uninhabited(cx.tcx, cx.typing_env()) { span_lint( cx, diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs index 24a02c7ef871..52c986462899 100644 --- a/src/tools/clippy/clippy_utils/src/consts.rs +++ b/src/tools/clippy/clippy_utils/src/consts.rs @@ -18,7 +18,7 @@ use rustc_lexer::tokenize; use rustc_lint::LateContext; use rustc_middle::mir::ConstValue; use rustc_middle::mir::interpret::{Scalar, alloc_range}; -use rustc_middle::ty::{self, FloatTy, IntTy, ParamEnv, ScalarInt, Ty, TyCtxt, TypeckResults, UintTy}; +use rustc_middle::ty::{self, FloatTy, IntTy, ScalarInt, Ty, TyCtxt, TypeckResults, UintTy}; use rustc_middle::{bug, mir, span_bug}; use rustc_span::def_id::DefId; use rustc_span::symbol::Ident; @@ -387,7 +387,7 @@ impl Ord for FullInt { /// See the module level documentation for some context. pub struct ConstEvalCtxt<'tcx> { tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, typeck: &'tcx TypeckResults<'tcx>, source: Cell, } @@ -398,17 +398,17 @@ impl<'tcx> ConstEvalCtxt<'tcx> { pub fn new(cx: &LateContext<'tcx>) -> Self { Self { tcx: cx.tcx, - param_env: cx.param_env, + typing_env: cx.typing_env(), typeck: cx.typeck_results(), source: Cell::new(ConstantSource::Local), } } /// Creates an evaluation context. - pub fn with_env(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, typeck: &'tcx TypeckResults<'tcx>) -> Self { + pub fn with_env(tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>, typeck: &'tcx TypeckResults<'tcx>) -> Self { Self { tcx, - param_env, + typing_env, typeck, source: Cell::new(ConstantSource::Local), } @@ -643,7 +643,7 @@ impl<'tcx> ConstEvalCtxt<'tcx> { let args = self.typeck.node_args(id); let result = self .tcx - .const_eval_resolve(self.param_env, mir::UnevaluatedConst::new(def_id, args), qpath.span()) + .const_eval_resolve(self.typing_env, mir::UnevaluatedConst::new(def_id, args), qpath.span()) .ok() .map(|val| mir::Const::from_value(val, ty))?; f(self, result) diff --git a/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs b/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs index a2e97919d042..7f0363ac9426 100644 --- a/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs +++ b/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs @@ -105,7 +105,7 @@ fn res_has_significant_drop(res: Res, cx: &LateContext<'_>, e: &Expr<'_>) -> boo { cx.typeck_results() .expr_ty(e) - .has_significant_drop(cx.tcx, cx.param_env) + .has_significant_drop(cx.tcx, cx.typing_env()) } else { false } diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index c73ab4bfa688..ea866a78d87f 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -297,8 +297,8 @@ impl HirEqInterExpr<'_, '_, '_> { if let Some((typeck_lhs, typeck_rhs)) = self.inner.maybe_typeck_results && typeck_lhs.expr_ty(left) == typeck_rhs.expr_ty(right) && let (Some(l), Some(r)) = ( - ConstEvalCtxt::with_env(self.inner.cx.tcx, self.inner.cx.param_env, typeck_lhs).eval_simple(left), - ConstEvalCtxt::with_env(self.inner.cx.tcx, self.inner.cx.param_env, typeck_rhs).eval_simple(right), + ConstEvalCtxt::with_env(self.inner.cx.tcx, self.inner.cx.typing_env(), typeck_lhs).eval_simple(left), + ConstEvalCtxt::with_env(self.inner.cx.tcx, self.inner.cx.typing_env(), typeck_rhs).eval_simple(right), ) && l == r { @@ -813,7 +813,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { #[expect(clippy::too_many_lines)] pub fn hash_expr(&mut self, e: &Expr<'_>) { let simple_const = self.maybe_typeck_results.and_then(|typeck_results| { - ConstEvalCtxt::with_env(self.cx.tcx, self.cx.param_env, typeck_results).eval_simple(e) + ConstEvalCtxt::with_env(self.cx.tcx, self.cx.typing_env(), typeck_results).eval_simple(e) }); // const hashing may result in the same hash as some unrelated node, so add a sort of diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 19316a906835..f28e5c9ed0e3 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -1631,7 +1631,7 @@ pub fn is_integer_const(cx: &LateContext<'_>, e: &Expr<'_>, value: u128) -> bool } let enclosing_body = cx.tcx.hir().enclosing_body_owner(e.hir_id); if let Some(Constant::Int(v)) = - ConstEvalCtxt::with_env(cx.tcx, cx.tcx.param_env(enclosing_body), cx.tcx.typeck(enclosing_body)).eval(e) + ConstEvalCtxt::with_env(cx.tcx, cx.typing_env(), cx.tcx.typeck(enclosing_body)).eval(e) { return value == v; } diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index 971f8eeb1b33..abadca714001 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -142,7 +142,7 @@ fn check_rvalue<'tcx>( // We cannot allow this for now. return Err((span, "unsizing casts are only allowed for references right now".into())); }; - let unsized_ty = tcx.struct_tail_for_codegen(pointee_ty, tcx.param_env(def_id)); + let unsized_ty = tcx.struct_tail_for_codegen(pointee_ty, ty::TypingEnv::post_analysis(tcx, def_id)); if let ty::Slice(_) | ty::Str = unsized_ty.kind() { check_operand(tcx, op, span, body, msrv)?; // Casting/coercing things to slices is fine. @@ -408,15 +408,17 @@ fn is_ty_const_destruct<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, body: &Body<'tcx> return true; } + + let (infcx, param_env) = + tcx.infer_ctxt().build_with_typing_env(body.typing_env(tcx)); // FIXME(const_trait_impl) constness let obligation = Obligation::new( tcx, ObligationCause::dummy_with_span(body.span), - ConstCx::new(tcx, body).param_env, + param_env, TraitRef::new(tcx, tcx.require_lang_item(LangItem::Destruct, Some(body.span)), [ty]), ); - let infcx = tcx.infer_ctxt().build(body.typing_mode(tcx)); let mut selcx = SelectionContext::new(&infcx); let Some(impl_src) = selcx.select(&obligation).ok().flatten() else { return false; @@ -434,5 +436,5 @@ fn is_ty_const_destruct<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, body: &Body<'tcx> ocx.select_all_or_error().is_empty() } - !ty.needs_drop(tcx, ConstCx::new(tcx, body).param_env) + !ty.needs_drop(tcx, ConstCx::new(tcx, body).typing_env) } diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index 770cd9c37865..2aad867dc0d6 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -467,7 +467,7 @@ pub fn needs_ordered_drop<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { if !seen.insert(ty) { return false; } - if !ty.has_significant_drop(cx.tcx, cx.param_env) { + if !ty.has_significant_drop(cx.tcx, cx.typing_env()) { false } // Check for std types which implement drop, but only for memory allocation. @@ -575,8 +575,9 @@ pub fn same_type_and_consts<'tcx>(a: Ty<'tcx>, b: Ty<'tcx>) -> bool { /// Checks if a given type looks safe to be uninitialized. pub fn is_uninit_value_valid_for_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { + let typing_env = cx.typing_env().with_reveal_all_normalized(cx.tcx); cx.tcx - .check_validity_requirement((ValidityRequirement::Uninit, cx.param_env.and(ty))) + .check_validity_requirement((ValidityRequirement::Uninit, typing_env.as_query_input(ty))) .unwrap_or_else(|_| is_uninit_value_valid_for_ty_fallback(cx, ty)) } @@ -725,7 +726,7 @@ pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option None, } }, - ty::Alias(ty::Projection, proj) => match cx.tcx.try_normalize_erasing_regions(cx.param_env, ty) { + ty::Alias(ty::Projection, proj) => match cx.tcx.try_normalize_erasing_regions(cx.typing_env(), ty) { Ok(normalized_ty) if normalized_ty != ty => ty_sig(cx, normalized_ty), _ => sig_for_projection(cx, proj).or_else(|| sig_from_bounds(cx, ty, cx.param_env.caller_bounds(), None)), }, @@ -1111,12 +1112,12 @@ pub fn make_projection<'tcx>( /// succeeds as well as everything checked by `make_projection`. pub fn make_normalized_projection<'tcx>( tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, container_id: DefId, assoc_ty: Symbol, args: impl IntoIterator>>, ) -> Option> { - fn helper<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: AliasTy<'tcx>) -> Option> { + fn helper<'tcx>(tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>, ty: AliasTy<'tcx>) -> Option> { #[cfg(debug_assertions)] if let Some((i, arg)) = ty .args @@ -1132,7 +1133,7 @@ pub fn make_normalized_projection<'tcx>( ); return None; } - match tcx.try_normalize_erasing_regions(param_env, Ty::new_projection_from_args(tcx, ty.def_id, ty.args)) { + match tcx.try_normalize_erasing_regions(typing_env, Ty::new_projection_from_args(tcx, ty.def_id, ty.args)) { Ok(ty) => Some(ty), Err(e) => { debug_assert!(false, "failed to normalize type `{ty}`: {e:#?}"); @@ -1140,7 +1141,7 @@ pub fn make_normalized_projection<'tcx>( }, } } - helper(tcx, param_env, make_projection(tcx, container_id, assoc_ty, args)?) + helper(tcx, typing_env, make_projection(tcx, container_id, assoc_ty, args)?) } /// Helper to check if given type has inner mutability such as [`std::cell::Cell`] or @@ -1300,7 +1301,7 @@ pub fn deref_chain<'cx, 'tcx>(cx: &'cx LateContext<'tcx>, ty: Ty<'tcx>) -> impl if let Some(deref_did) = cx.tcx.lang_items().deref_trait() && implements_trait(cx, ty, deref_did, &[]) { - make_normalized_projection(cx.tcx, cx.param_env, deref_did, sym::Target, [ty]) + make_normalized_projection(cx.tcx, cx.typing_env(), deref_did, sym::Target, [ty]) } else { None } diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs index 16fcc26be33a..745316913d99 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs @@ -12,7 +12,7 @@ use std::{cmp, mem}; use rustc_abi::{BackendRepr, Size}; use rustc_data_structures::fx::FxHashSet; use rustc_middle::mir::{Mutability, RetagKind}; -use rustc_middle::ty::layout::HasParamEnv; +use rustc_middle::ty::layout::HasTypingEnv; use rustc_middle::ty::{self, Ty}; use self::diagnostics::{RetagCause, RetagInfo}; diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs index f92150758dc3..255a3578aaec 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs @@ -1,6 +1,6 @@ use rustc_abi::{BackendRepr, Size}; use rustc_middle::mir::{Mutability, RetagKind}; -use rustc_middle::ty::layout::HasParamEnv; +use rustc_middle::ty::layout::HasTypingEnv; use rustc_middle::ty::{self, Ty}; use rustc_span::def_id::DefId; diff --git a/src/tools/miri/src/eval.rs b/src/tools/miri/src/eval.rs index 1e56e1049187..5ec497ef0ea0 100644 --- a/src/tools/miri/src/eval.rs +++ b/src/tools/miri/src/eval.rs @@ -268,10 +268,14 @@ pub fn create_ecx<'tcx>( entry_type: EntryFnType, config: &MiriConfig, ) -> InterpResult<'tcx, InterpCx<'tcx, MiriMachine<'tcx>>> { - let param_env = ty::ParamEnv::reveal_all(); - let layout_cx = LayoutCx::new(tcx, param_env); - let mut ecx = - InterpCx::new(tcx, rustc_span::DUMMY_SP, param_env, MiriMachine::new(config, layout_cx)); + let typing_env = ty::TypingEnv::fully_monomorphized(); + let layout_cx = LayoutCx::new(tcx, typing_env); + let mut ecx = InterpCx::new( + tcx, + rustc_span::DUMMY_SP, + typing_env.param_env, + MiriMachine::new(config, layout_cx) + ); // Some parts of initialization require a full `InterpCx`. MiriMachine::late_init(&mut ecx, config, { @@ -376,7 +380,7 @@ pub fn create_ecx<'tcx>( let main_ret_ty = main_ret_ty.no_bound_vars().unwrap(); let start_instance = ty::Instance::try_resolve( tcx, - ty::ParamEnv::reveal_all(), + typing_env, start_id, tcx.mk_args(&[ty::GenericArg::from(main_ret_ty)]), ) diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index b28bd2eacb7e..9377c1299cd9 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -116,8 +116,8 @@ pub fn resolve_path<'tcx>( /// Gets the layout of a type at a path. #[track_caller] pub fn path_ty_layout<'tcx>(cx: &impl LayoutOf<'tcx>, path: &[&str]) -> TyAndLayout<'tcx> { - let ty = - resolve_path(cx.tcx(), path, Namespace::TypeNS).ty(cx.tcx(), ty::ParamEnv::reveal_all()); + let ty = resolve_path(cx.tcx(), path, Namespace::TypeNS) + .ty(cx.tcx(), cx.typing_env()); cx.layout_of(ty).to_result().ok().unwrap() } diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 6e9d8d3a65e5..937c927c746f 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -1127,7 +1127,9 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { }; let info = ecx.get_alloc_info(alloc_id); let def_ty = ecx.tcx.type_of(def_id).instantiate_identity(); - let extern_decl_layout = ecx.tcx.layout_of(ty::ParamEnv::empty().and(def_ty)).unwrap(); + let extern_decl_layout = ecx.tcx.layout_of( + ecx.typing_env().as_query_input(def_ty) + ).unwrap(); if extern_decl_layout.size != info.size || extern_decl_layout.align.abi != info.align { throw_unsup_format!( "extern static `{link_name}` has been declared as `{krate}::{name}` \ diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock index 55705de9b2c2..019609e6a5be 100644 --- a/src/tools/rust-analyzer/Cargo.lock +++ b/src/tools/rust-analyzer/Cargo.lock @@ -2625,18 +2625,18 @@ checksum = "672423d4fea7ffa2f6c25ba60031ea13dc6258070556f125cc4d790007d4a155" [[package]] name = "xshell" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db0ab86eae739efd1b054a8d3d16041914030ac4e01cd1dca0cf252fd8b6437" +checksum = "9e7290c623014758632efe00737145b6867b66292c42167f2ec381eb566a373d" dependencies = [ "xshell-macros", ] [[package]] name = "xshell-macros" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d422e8e38ec76e2f06ee439ccc765e9c6a9638b9e7c9f2e8255e4d41e8bd852" +checksum = "32ac00cd3f8ec9c1d33fb3e7958a82df6989c42d747bd326c822b1d625283547" [[package]] name = "xtask" diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/reorder_fields.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/reorder_fields.rs index df7a5112f126..4d3e85ab1b20 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/reorder_fields.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/reorder_fields.rs @@ -1,7 +1,7 @@ use either::Either; use ide_db::FxHashMap; use itertools::Itertools; -use syntax::{ast, ted, AstNode, SmolStr, ToSmolStr}; +use syntax::{ast, syntax_editor::SyntaxEditor, AstNode, SmolStr, SyntaxElement, ToSmolStr}; use crate::{AssistContext, AssistId, AssistKind, Assists}; @@ -24,6 +24,11 @@ pub(crate) fn reorder_fields(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti let record = path.syntax().parent().and_then(>::cast)?; + let parent_node = match ctx.covering_element() { + SyntaxElement::Node(n) => n, + SyntaxElement::Token(t) => t.parent()?, + }; + let ranks = compute_fields_ranks(&path, ctx)?; let get_rank_of_field = |of: Option| { *ranks.get(of.unwrap_or_default().trim_start_matches("r#")).unwrap_or(&usize::MAX) @@ -65,23 +70,31 @@ pub(crate) fn reorder_fields(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti AssistId("reorder_fields", AssistKind::RefactorRewrite), "Reorder record fields", target, - |builder| match fields { - Either::Left((sorted, field_list)) => { - replace(builder.make_mut(field_list).fields(), sorted) - } - Either::Right((sorted, field_list)) => { - replace(builder.make_mut(field_list).fields(), sorted) + |builder| { + let mut editor = builder.make_editor(&parent_node); + + match fields { + Either::Left((sorted, field_list)) => { + replace(&mut editor, field_list.fields(), sorted) + } + Either::Right((sorted, field_list)) => { + replace(&mut editor, field_list.fields(), sorted) + } } + + builder.add_file_edits(ctx.file_id(), editor); }, ) } fn replace( + editor: &mut SyntaxEditor, fields: impl Iterator, sorted_fields: impl IntoIterator, ) { fields.zip(sorted_fields).for_each(|(field, sorted_field)| { - ted::replace(field.syntax(), sorted_field.syntax().clone_for_update()) + // FIXME: remove `clone_for_update` when `SyntaxEditor` handles it for us + editor.replace(field.syntax(), sorted_field.syntax().clone_for_update()) }); } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs index a5c9d2823e08..4975467ece9b 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs @@ -511,12 +511,16 @@ pub(crate) fn handle_document_diagnostics( .into_iter() .filter_map(|d| { let file = d.range.file_id; - let diagnostic = convert_diagnostic(&line_index, d); if file == file_id { + let diagnostic = convert_diagnostic(&line_index, d); return Some(diagnostic); } if supports_related { - related_documents.entry(file).or_insert_with(Vec::new).push(diagnostic); + let (diagnostics, line_index) = related_documents + .entry(file) + .or_insert_with(|| (Vec::new(), snap.file_line_index(file).ok())); + let diagnostic = convert_diagnostic(line_index.as_mut()?, d); + diagnostics.push(diagnostic); } None }); @@ -529,7 +533,7 @@ pub(crate) fn handle_document_diagnostics( related_documents: related_documents.is_empty().not().then(|| { related_documents .into_iter() - .map(|(id, items)| { + .map(|(id, (items, _))| { ( to_proto::url(&snap, id), lsp_types::DocumentDiagnosticReportKind::Full( diff --git a/tests/incremental/hygiene/load_cached_hygiene.rs b/tests/incremental/hygiene/load_cached_hygiene.rs index 4ad9c7d49fda..101d280cd492 100644 --- a/tests/incremental/hygiene/load_cached_hygiene.rs +++ b/tests/incremental/hygiene/load_cached_hygiene.rs @@ -7,7 +7,7 @@ // This causes hygiene information to be saved to the incr cache. // 2. One function is the foreign crate is modified. This causes the // optimized mir for an unmodified function to be loaded from the -//@ incremental cache and written out to the crate metadata. +// incremental cache and written out to the crate metadata. // 3. In the process of loading and writing out this function's MIR, // we load hygiene information from the incremental cache and // write it to our metadata. diff --git a/tests/rustdoc-js/trailing.js b/tests/rustdoc-js/trailing.js new file mode 100644 index 000000000000..df5dd22ca4e1 --- /dev/null +++ b/tests/rustdoc-js/trailing.js @@ -0,0 +1,7 @@ +// exact-check +const EXPECTED = { + 'query': 'inner::', + 'others': [ + { 'path': 'trailing::inner', 'name': 'function' }, + ], +} diff --git a/tests/rustdoc-js/trailing.rs b/tests/rustdoc-js/trailing.rs new file mode 100644 index 000000000000..5c7c9362ffb3 --- /dev/null +++ b/tests/rustdoc-js/trailing.rs @@ -0,0 +1,3 @@ +pub mod inner { + pub fn function() {} +} diff --git a/tests/ui/auxiliary/pub-and-stability.rs b/tests/ui/auxiliary/pub-and-stability.rs index ee05a07dbb29..d2d07f993984 100644 --- a/tests/ui/auxiliary/pub-and-stability.rs +++ b/tests/ui/auxiliary/pub-and-stability.rs @@ -5,8 +5,8 @@ // The basic stability pattern in this file has four cases: // 1. no stability attribute at all // 2. a stable attribute (feature "unit_test") -// 3. an unstable attribute that unit test declares (feature "unstable_declared") -// 4. an unstable attribute that unit test fails to declare (feature "unstable_undeclared") +// 3. an unstable attribute that unit test enables (feature "unstable_declared") +// 4. an unstable attribute that unit test fails to enable (feature "unstable_undeclared") // // This file also covers four kinds of visibility: private, // pub(module), pub(crate), and pub. diff --git a/tests/ui/bootstrap/rustc_bootstap.force_stable.stderr b/tests/ui/bootstrap/rustc_bootstap.force_stable.stderr new file mode 100644 index 000000000000..f378f3c70dd0 --- /dev/null +++ b/tests/ui/bootstrap/rustc_bootstap.force_stable.stderr @@ -0,0 +1,10 @@ +error: the option `Z` is only accepted on the nightly compiler + +help: consider switching to a nightly toolchain: `rustup default nightly` + +note: selecting a toolchain with `+toolchain` arguments require a rustup proxy; see + +note: for more information about Rust's stability policy, see + +error: 1 nightly option were parsed + diff --git a/tests/ui/bootstrap/rustc_bootstap.rs b/tests/ui/bootstrap/rustc_bootstap.rs new file mode 100644 index 000000000000..3d792ef4be4e --- /dev/null +++ b/tests/ui/bootstrap/rustc_bootstap.rs @@ -0,0 +1,47 @@ +//! Check `RUSTC_BOOTSTRAP`'s behavior in relation to feature stability and what rustc considers +//! itself to be (stable vs non-stable ). +//! +//! `RUSTC_BOOTSTRAP` accepts: +//! +//! - `1`: cheat, allow usage of unstable features even if rustc thinks it is a stable compiler. +//! - `x,y,z`: comma-delimited list of crates. +//! - `-1`: force rustc to think it is a stable compiler. + +// ignore-tidy-linelength + +//@ revisions: default_nightly cheat cheat_single_crate cheat_multi_crate force_stable invalid_zero invalid_junk +//@ only-nightly + +//@[default_nightly] unset-rustc-env:RUSTC_BOOTSTRAP +//@[default_nightly] check-pass + +// For a nightly compiler, this is same as `default_nightly` as if `RUSTC_BOOTSTRAP` was unset. +//@[invalid_zero] rustc-env:RUSTC_BOOTSTRAP=0 +//@[invalid_zero] check-pass + +// Invalid values are silently discarded, same as `default_nightly`, i.e. as if `RUSTC_BOOTSTRAP` +// was unset. +//@[invalid_junk] rustc-env:RUSTC_BOOTSTRAP=* +//@[invalid_junk] check-pass + +//@[cheat] rustc-env:RUSTC_BOOTSTRAP=1 +//@[cheat] check-pass + +//@[cheat_single_crate] rustc-env:RUSTC_BOOTSTRAP=x +//@[cheat_single_crate] check-pass + +//@[cheat_multi_crate] rustc-env:RUSTC_BOOTSTRAP=x,y,z +//@[cheat_multi_crate] check-pass + +// Note: compiletest passes some `-Z` flags to the compiler for ui testing purposes, so here we +// instead abuse the fact that `-Z unstable-options` is also part of rustc's stability story and is +// also affected by `RUSTC_BOOTSTRAP`. +//@[force_stable] rustc-env:RUSTC_BOOTSTRAP=-1 +//@[force_stable] compile-flags: -Z unstable-options +//@[force_stable] regex-error-pattern: error: the option `Z` is only accepted on the nightly compiler + +#![crate_type = "lib"] + +// Note: `rustc_attrs` is a perma-unstable internal feature that is unlikely to change, which is +// used as a proxy to check `RUSTC_BOOTSTRAP` versus stability checking logic. +#![feature(rustc_attrs)] diff --git a/tests/ui/coercion/unboxing-needing-parenthases-issue-132924.rs b/tests/ui/coercion/unboxing-needing-parenthases-issue-132924.rs new file mode 100644 index 000000000000..fc4258fc0af8 --- /dev/null +++ b/tests/ui/coercion/unboxing-needing-parenthases-issue-132924.rs @@ -0,0 +1,18 @@ +//@ check-fail +fn main() { + let x = Box::new(Some(1)); + + let test: Option = x; + //~^ ERROR mismatched types + let x = Box::new(Some(1)); + let test: Option = { x as Box> }; + //~^ ERROR mismatched types + + let x = Box::new(Some(1)); + let test: Option = if true { x as Box> } else { None }; + //~^ ERROR mismatched types + + let x = std::rc::Rc::new(Some(1)); + let test: Option = x as std::rc::Rc>; + //~^ ERROR mismatched types +} diff --git a/tests/ui/coercion/unboxing-needing-parenthases-issue-132924.stderr b/tests/ui/coercion/unboxing-needing-parenthases-issue-132924.stderr new file mode 100644 index 000000000000..429b1b873575 --- /dev/null +++ b/tests/ui/coercion/unboxing-needing-parenthases-issue-132924.stderr @@ -0,0 +1,59 @@ +error[E0308]: mismatched types + --> $DIR/unboxing-needing-parenthases-issue-132924.rs:5:29 + | +LL | let test: Option = x; + | ----------- ^ expected `Option`, found `Box>` + | | + | expected due to this + | + = note: expected enum `Option` + found struct `Box>` +help: consider unboxing the value + | +LL | let test: Option = *x; + | + + +error[E0308]: mismatched types + --> $DIR/unboxing-needing-parenthases-issue-132924.rs:8:31 + | +LL | let test: Option = { x as Box> }; + | ^^^^^^^^^^^^^^^^^^^^^ expected `Option`, found `Box>` + | + = note: expected enum `Option<_>` + found struct `Box>` +help: consider unboxing the value + | +LL | let test: Option = { *(x as Box>) }; + | ++ + + +error[E0308]: mismatched types + --> $DIR/unboxing-needing-parenthases-issue-132924.rs:12:39 + | +LL | let test: Option = if true { x as Box> } else { None }; + | ^^^^^^^^^^^^^^^^^^^^^ expected `Option`, found `Box>` + | + = note: expected enum `Option<_>` + found struct `Box>` +help: consider unboxing the value + | +LL | let test: Option = if true { *(x as Box>) } else { None }; + | ++ + + +error[E0308]: mismatched types + --> $DIR/unboxing-needing-parenthases-issue-132924.rs:16:29 + | +LL | let test: Option = x as std::rc::Rc>; + | ----------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Option`, found `Rc>` + | | + | expected due to this + | + = note: expected enum `Option<_>` + found struct `Rc>` +help: consider dereferencing the type + | +LL | let test: Option = *(x as std::rc::Rc>); + | ++ + + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/consts/const-unstable-intrinsic.stderr b/tests/ui/consts/const-unstable-intrinsic.stderr index 8b61b0904a9c..dfca04bef075 100644 --- a/tests/ui/consts/const-unstable-intrinsic.stderr +++ b/tests/ui/consts/const-unstable-intrinsic.stderr @@ -74,7 +74,7 @@ error: intrinsic `copy::copy` cannot be (indirectly) exposed to stable LL | unsafe { copy(src, dst, count) } | ^^^^^^^^^^^^^^^^^^^^^ | - = help: mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_intrinsic]` (but this requires team approval) + = help: mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_intrinsic_const_stable_indirect]` (but this requires team approval) error: const function that might be (indirectly) exposed to stable cannot use `#[feature(local)]` --> $DIR/const-unstable-intrinsic.rs:61:9 diff --git a/tests/ui/debuginfo/debuginfo-inline-callsite-location-macro-1.rs b/tests/ui/debuginfo/debuginfo-inline-callsite-location-macro-1.rs new file mode 100644 index 000000000000..32ef849f47e1 --- /dev/null +++ b/tests/ui/debuginfo/debuginfo-inline-callsite-location-macro-1.rs @@ -0,0 +1,4124 @@ +//@ check-pass +//@ compile-flags: -Cdebuginfo=2 -Copt-level=0 -Zmir-enable-passes=+Inline +//@ ignore-msvc +// ignore-tidy-filelength + +#[derive(Default)] +struct Something {} + +#[collapse_debuginfo(yes)] +macro_rules! collapsed_macro { + ($code:expr) => { + // Important to use a function here, so it can be inlined + // at the MIR stage. + Something::default() + } +} + +fn collapsed_debuginfo() { + // LLVM allows 12 bits for encoding discriminators, so 4096+1 calls to a + // MIR-inlined function will exhaust it. But because we're using + // collapse_debuginfo(yes) for this macro, we shouldn't need discriminators + // at all. + collapsed_macro!(1); + collapsed_macro!(2); + collapsed_macro!(3); + collapsed_macro!(4); + collapsed_macro!(5); + collapsed_macro!(6); + collapsed_macro!(7); + collapsed_macro!(8); + collapsed_macro!(9); + collapsed_macro!(10); + collapsed_macro!(11); + collapsed_macro!(12); + collapsed_macro!(13); + collapsed_macro!(14); + collapsed_macro!(15); + collapsed_macro!(16); + collapsed_macro!(17); + collapsed_macro!(18); + collapsed_macro!(19); + collapsed_macro!(20); + collapsed_macro!(21); + collapsed_macro!(22); + collapsed_macro!(23); + collapsed_macro!(24); + collapsed_macro!(25); + collapsed_macro!(26); + collapsed_macro!(27); + collapsed_macro!(28); + collapsed_macro!(29); + collapsed_macro!(30); + collapsed_macro!(31); + collapsed_macro!(32); + collapsed_macro!(33); + collapsed_macro!(34); + collapsed_macro!(35); + collapsed_macro!(36); + collapsed_macro!(37); + collapsed_macro!(38); + collapsed_macro!(39); + collapsed_macro!(40); + collapsed_macro!(41); + collapsed_macro!(42); + collapsed_macro!(43); + collapsed_macro!(44); + collapsed_macro!(45); + collapsed_macro!(46); + collapsed_macro!(47); + collapsed_macro!(48); + collapsed_macro!(49); + collapsed_macro!(50); + collapsed_macro!(51); + collapsed_macro!(52); + collapsed_macro!(53); + collapsed_macro!(54); + collapsed_macro!(55); + collapsed_macro!(56); + collapsed_macro!(57); + collapsed_macro!(58); + collapsed_macro!(59); + collapsed_macro!(60); + collapsed_macro!(61); + collapsed_macro!(62); + collapsed_macro!(63); + collapsed_macro!(64); + collapsed_macro!(65); + collapsed_macro!(66); + collapsed_macro!(67); + collapsed_macro!(68); + collapsed_macro!(69); + collapsed_macro!(70); + collapsed_macro!(71); + collapsed_macro!(72); + collapsed_macro!(73); + collapsed_macro!(74); + collapsed_macro!(75); + collapsed_macro!(76); + collapsed_macro!(77); + collapsed_macro!(78); + collapsed_macro!(79); + collapsed_macro!(80); + collapsed_macro!(81); + collapsed_macro!(82); + collapsed_macro!(83); + collapsed_macro!(84); + collapsed_macro!(85); + collapsed_macro!(86); + collapsed_macro!(87); + collapsed_macro!(88); + collapsed_macro!(89); + collapsed_macro!(90); + collapsed_macro!(91); + collapsed_macro!(92); + collapsed_macro!(93); + collapsed_macro!(94); + collapsed_macro!(95); + collapsed_macro!(96); + collapsed_macro!(97); + collapsed_macro!(98); + collapsed_macro!(99); + collapsed_macro!(100); + collapsed_macro!(101); + collapsed_macro!(102); + collapsed_macro!(103); + collapsed_macro!(104); + collapsed_macro!(105); + collapsed_macro!(106); + collapsed_macro!(107); + collapsed_macro!(108); + collapsed_macro!(109); + collapsed_macro!(110); + collapsed_macro!(111); + collapsed_macro!(112); + collapsed_macro!(113); + collapsed_macro!(114); + collapsed_macro!(115); + collapsed_macro!(116); + collapsed_macro!(117); + collapsed_macro!(118); + collapsed_macro!(119); + collapsed_macro!(120); + collapsed_macro!(121); + collapsed_macro!(122); + collapsed_macro!(123); + collapsed_macro!(124); + collapsed_macro!(125); + collapsed_macro!(126); + collapsed_macro!(127); + collapsed_macro!(128); + collapsed_macro!(129); + collapsed_macro!(130); + collapsed_macro!(131); + collapsed_macro!(132); + collapsed_macro!(133); + collapsed_macro!(134); + collapsed_macro!(135); + collapsed_macro!(136); + collapsed_macro!(137); + collapsed_macro!(138); + collapsed_macro!(139); + collapsed_macro!(140); + collapsed_macro!(141); + collapsed_macro!(142); + collapsed_macro!(143); + collapsed_macro!(144); + collapsed_macro!(145); + collapsed_macro!(146); + collapsed_macro!(147); + collapsed_macro!(148); + collapsed_macro!(149); + collapsed_macro!(150); + collapsed_macro!(151); + collapsed_macro!(152); + collapsed_macro!(153); + collapsed_macro!(154); + collapsed_macro!(155); + collapsed_macro!(156); + collapsed_macro!(157); + collapsed_macro!(158); + collapsed_macro!(159); + collapsed_macro!(160); + collapsed_macro!(161); + collapsed_macro!(162); + collapsed_macro!(163); + collapsed_macro!(164); + collapsed_macro!(165); + collapsed_macro!(166); + collapsed_macro!(167); + collapsed_macro!(168); + collapsed_macro!(169); + collapsed_macro!(170); + collapsed_macro!(171); + collapsed_macro!(172); + collapsed_macro!(173); + collapsed_macro!(174); + collapsed_macro!(175); + collapsed_macro!(176); + collapsed_macro!(177); + collapsed_macro!(178); + collapsed_macro!(179); + collapsed_macro!(180); + collapsed_macro!(181); + collapsed_macro!(182); + collapsed_macro!(183); + collapsed_macro!(184); + collapsed_macro!(185); + collapsed_macro!(186); + collapsed_macro!(187); + collapsed_macro!(188); + collapsed_macro!(189); + collapsed_macro!(190); + collapsed_macro!(191); + collapsed_macro!(192); + collapsed_macro!(193); + collapsed_macro!(194); + collapsed_macro!(195); + collapsed_macro!(196); + collapsed_macro!(197); + collapsed_macro!(198); + collapsed_macro!(199); + collapsed_macro!(200); + collapsed_macro!(201); + collapsed_macro!(202); + collapsed_macro!(203); + collapsed_macro!(204); + collapsed_macro!(205); + collapsed_macro!(206); + collapsed_macro!(207); + collapsed_macro!(208); + collapsed_macro!(209); + collapsed_macro!(210); + collapsed_macro!(211); + collapsed_macro!(212); + collapsed_macro!(213); + collapsed_macro!(214); + collapsed_macro!(215); + collapsed_macro!(216); + collapsed_macro!(217); + collapsed_macro!(218); + collapsed_macro!(219); + collapsed_macro!(220); + collapsed_macro!(221); + collapsed_macro!(222); + collapsed_macro!(223); + collapsed_macro!(224); + collapsed_macro!(225); + collapsed_macro!(226); + collapsed_macro!(227); + collapsed_macro!(228); + collapsed_macro!(229); + collapsed_macro!(230); + collapsed_macro!(231); + collapsed_macro!(232); + collapsed_macro!(233); + collapsed_macro!(234); + collapsed_macro!(235); + collapsed_macro!(236); + collapsed_macro!(237); + collapsed_macro!(238); + collapsed_macro!(239); + collapsed_macro!(240); + collapsed_macro!(241); + collapsed_macro!(242); + collapsed_macro!(243); + collapsed_macro!(244); + collapsed_macro!(245); + collapsed_macro!(246); + collapsed_macro!(247); + collapsed_macro!(248); + collapsed_macro!(249); + collapsed_macro!(250); + collapsed_macro!(251); + collapsed_macro!(252); + collapsed_macro!(253); + collapsed_macro!(254); + collapsed_macro!(255); + collapsed_macro!(256); + collapsed_macro!(257); + collapsed_macro!(258); + collapsed_macro!(259); + collapsed_macro!(260); + collapsed_macro!(261); + collapsed_macro!(262); + collapsed_macro!(263); + collapsed_macro!(264); + collapsed_macro!(265); + collapsed_macro!(266); + collapsed_macro!(267); + collapsed_macro!(268); + collapsed_macro!(269); + collapsed_macro!(270); + collapsed_macro!(271); + collapsed_macro!(272); + collapsed_macro!(273); + collapsed_macro!(274); + collapsed_macro!(275); + collapsed_macro!(276); + collapsed_macro!(277); + collapsed_macro!(278); + collapsed_macro!(279); + collapsed_macro!(280); + collapsed_macro!(281); + collapsed_macro!(282); + collapsed_macro!(283); + collapsed_macro!(284); + collapsed_macro!(285); + collapsed_macro!(286); + collapsed_macro!(287); + collapsed_macro!(288); + collapsed_macro!(289); + collapsed_macro!(290); + collapsed_macro!(291); + collapsed_macro!(292); + collapsed_macro!(293); + collapsed_macro!(294); + collapsed_macro!(295); + collapsed_macro!(296); + collapsed_macro!(297); + collapsed_macro!(298); + collapsed_macro!(299); + collapsed_macro!(300); + collapsed_macro!(301); + collapsed_macro!(302); + collapsed_macro!(303); + collapsed_macro!(304); + collapsed_macro!(305); + collapsed_macro!(306); + collapsed_macro!(307); + collapsed_macro!(308); + collapsed_macro!(309); + collapsed_macro!(310); + collapsed_macro!(311); + collapsed_macro!(312); + collapsed_macro!(313); + collapsed_macro!(314); + collapsed_macro!(315); + collapsed_macro!(316); + collapsed_macro!(317); + collapsed_macro!(318); + collapsed_macro!(319); + collapsed_macro!(320); + collapsed_macro!(321); + collapsed_macro!(322); + collapsed_macro!(323); + collapsed_macro!(324); + collapsed_macro!(325); + collapsed_macro!(326); + collapsed_macro!(327); + collapsed_macro!(328); + collapsed_macro!(329); + collapsed_macro!(330); + collapsed_macro!(331); + collapsed_macro!(332); + collapsed_macro!(333); + collapsed_macro!(334); + collapsed_macro!(335); + collapsed_macro!(336); + collapsed_macro!(337); + collapsed_macro!(338); + collapsed_macro!(339); + collapsed_macro!(340); + collapsed_macro!(341); + collapsed_macro!(342); + collapsed_macro!(343); + collapsed_macro!(344); + collapsed_macro!(345); + collapsed_macro!(346); + collapsed_macro!(347); + collapsed_macro!(348); + collapsed_macro!(349); + collapsed_macro!(350); + collapsed_macro!(351); + collapsed_macro!(352); + collapsed_macro!(353); + collapsed_macro!(354); + collapsed_macro!(355); + collapsed_macro!(356); + collapsed_macro!(357); + collapsed_macro!(358); + collapsed_macro!(359); + collapsed_macro!(360); + collapsed_macro!(361); + collapsed_macro!(362); + collapsed_macro!(363); + collapsed_macro!(364); + collapsed_macro!(365); + collapsed_macro!(366); + collapsed_macro!(367); + collapsed_macro!(368); + collapsed_macro!(369); + collapsed_macro!(370); + collapsed_macro!(371); + collapsed_macro!(372); + collapsed_macro!(373); + collapsed_macro!(374); + collapsed_macro!(375); + collapsed_macro!(376); + collapsed_macro!(377); + collapsed_macro!(378); + collapsed_macro!(379); + collapsed_macro!(380); + collapsed_macro!(381); + collapsed_macro!(382); + collapsed_macro!(383); + collapsed_macro!(384); + collapsed_macro!(385); + collapsed_macro!(386); + collapsed_macro!(387); + collapsed_macro!(388); + collapsed_macro!(389); + collapsed_macro!(390); + collapsed_macro!(391); + collapsed_macro!(392); + collapsed_macro!(393); + collapsed_macro!(394); + collapsed_macro!(395); + collapsed_macro!(396); + collapsed_macro!(397); + collapsed_macro!(398); + collapsed_macro!(399); + collapsed_macro!(400); + collapsed_macro!(401); + collapsed_macro!(402); + collapsed_macro!(403); + collapsed_macro!(404); + collapsed_macro!(405); + collapsed_macro!(406); + collapsed_macro!(407); + collapsed_macro!(408); + collapsed_macro!(409); + collapsed_macro!(410); + collapsed_macro!(411); + collapsed_macro!(412); + collapsed_macro!(413); + collapsed_macro!(414); + collapsed_macro!(415); + collapsed_macro!(416); + collapsed_macro!(417); + collapsed_macro!(418); + collapsed_macro!(419); + collapsed_macro!(420); + collapsed_macro!(421); + collapsed_macro!(422); + collapsed_macro!(423); + collapsed_macro!(424); + collapsed_macro!(425); + collapsed_macro!(426); + collapsed_macro!(427); + collapsed_macro!(428); + collapsed_macro!(429); + collapsed_macro!(430); + collapsed_macro!(431); + collapsed_macro!(432); + collapsed_macro!(433); + collapsed_macro!(434); + collapsed_macro!(435); + collapsed_macro!(436); + collapsed_macro!(437); + collapsed_macro!(438); + collapsed_macro!(439); + collapsed_macro!(440); + collapsed_macro!(441); + collapsed_macro!(442); + collapsed_macro!(443); + collapsed_macro!(444); + collapsed_macro!(445); + collapsed_macro!(446); + collapsed_macro!(447); + collapsed_macro!(448); + collapsed_macro!(449); + collapsed_macro!(450); + collapsed_macro!(451); + collapsed_macro!(452); + collapsed_macro!(453); + collapsed_macro!(454); + collapsed_macro!(455); + collapsed_macro!(456); + collapsed_macro!(457); + collapsed_macro!(458); + collapsed_macro!(459); + collapsed_macro!(460); + collapsed_macro!(461); + collapsed_macro!(462); + collapsed_macro!(463); + collapsed_macro!(464); + collapsed_macro!(465); + collapsed_macro!(466); + collapsed_macro!(467); + collapsed_macro!(468); + collapsed_macro!(469); + collapsed_macro!(470); + collapsed_macro!(471); + collapsed_macro!(472); + collapsed_macro!(473); + collapsed_macro!(474); + collapsed_macro!(475); + collapsed_macro!(476); + collapsed_macro!(477); + collapsed_macro!(478); + collapsed_macro!(479); + collapsed_macro!(480); + collapsed_macro!(481); + collapsed_macro!(482); + collapsed_macro!(483); + collapsed_macro!(484); + collapsed_macro!(485); + collapsed_macro!(486); + collapsed_macro!(487); + collapsed_macro!(488); + collapsed_macro!(489); + collapsed_macro!(490); + collapsed_macro!(491); + collapsed_macro!(492); + collapsed_macro!(493); + collapsed_macro!(494); + collapsed_macro!(495); + collapsed_macro!(496); + collapsed_macro!(497); + collapsed_macro!(498); + collapsed_macro!(499); + collapsed_macro!(500); + collapsed_macro!(501); + collapsed_macro!(502); + collapsed_macro!(503); + collapsed_macro!(504); + collapsed_macro!(505); + collapsed_macro!(506); + collapsed_macro!(507); + collapsed_macro!(508); + collapsed_macro!(509); + collapsed_macro!(510); + collapsed_macro!(511); + collapsed_macro!(512); + collapsed_macro!(513); + collapsed_macro!(514); + collapsed_macro!(515); + collapsed_macro!(516); + collapsed_macro!(517); + collapsed_macro!(518); + collapsed_macro!(519); + collapsed_macro!(520); + collapsed_macro!(521); + collapsed_macro!(522); + collapsed_macro!(523); + collapsed_macro!(524); + collapsed_macro!(525); + collapsed_macro!(526); + collapsed_macro!(527); + collapsed_macro!(528); + collapsed_macro!(529); + collapsed_macro!(530); + collapsed_macro!(531); + collapsed_macro!(532); + collapsed_macro!(533); + collapsed_macro!(534); + collapsed_macro!(535); + collapsed_macro!(536); + collapsed_macro!(537); + collapsed_macro!(538); + collapsed_macro!(539); + collapsed_macro!(540); + collapsed_macro!(541); + collapsed_macro!(542); + collapsed_macro!(543); + collapsed_macro!(544); + collapsed_macro!(545); + collapsed_macro!(546); + collapsed_macro!(547); + collapsed_macro!(548); + collapsed_macro!(549); + collapsed_macro!(550); + collapsed_macro!(551); + collapsed_macro!(552); + collapsed_macro!(553); + collapsed_macro!(554); + collapsed_macro!(555); + collapsed_macro!(556); + collapsed_macro!(557); + collapsed_macro!(558); + collapsed_macro!(559); + collapsed_macro!(560); + collapsed_macro!(561); + collapsed_macro!(562); + collapsed_macro!(563); + collapsed_macro!(564); + collapsed_macro!(565); + collapsed_macro!(566); + collapsed_macro!(567); + collapsed_macro!(568); + collapsed_macro!(569); + collapsed_macro!(570); + collapsed_macro!(571); + collapsed_macro!(572); + collapsed_macro!(573); + collapsed_macro!(574); + collapsed_macro!(575); + collapsed_macro!(576); + collapsed_macro!(577); + collapsed_macro!(578); + collapsed_macro!(579); + collapsed_macro!(580); + collapsed_macro!(581); + collapsed_macro!(582); + collapsed_macro!(583); + collapsed_macro!(584); + collapsed_macro!(585); + collapsed_macro!(586); + collapsed_macro!(587); + collapsed_macro!(588); + collapsed_macro!(589); + collapsed_macro!(590); + collapsed_macro!(591); + collapsed_macro!(592); + collapsed_macro!(593); + collapsed_macro!(594); + collapsed_macro!(595); + collapsed_macro!(596); + collapsed_macro!(597); + collapsed_macro!(598); + collapsed_macro!(599); + collapsed_macro!(600); + collapsed_macro!(601); + collapsed_macro!(602); + collapsed_macro!(603); + collapsed_macro!(604); + collapsed_macro!(605); + collapsed_macro!(606); + collapsed_macro!(607); + collapsed_macro!(608); + collapsed_macro!(609); + collapsed_macro!(610); + collapsed_macro!(611); + collapsed_macro!(612); + collapsed_macro!(613); + collapsed_macro!(614); + collapsed_macro!(615); + collapsed_macro!(616); + collapsed_macro!(617); + collapsed_macro!(618); + collapsed_macro!(619); + collapsed_macro!(620); + collapsed_macro!(621); + collapsed_macro!(622); + collapsed_macro!(623); + collapsed_macro!(624); + collapsed_macro!(625); + collapsed_macro!(626); + collapsed_macro!(627); + collapsed_macro!(628); + collapsed_macro!(629); + collapsed_macro!(630); + collapsed_macro!(631); + collapsed_macro!(632); + collapsed_macro!(633); + collapsed_macro!(634); + collapsed_macro!(635); + collapsed_macro!(636); + collapsed_macro!(637); + collapsed_macro!(638); + collapsed_macro!(639); + collapsed_macro!(640); + collapsed_macro!(641); + collapsed_macro!(642); + collapsed_macro!(643); + collapsed_macro!(644); + collapsed_macro!(645); + collapsed_macro!(646); + collapsed_macro!(647); + collapsed_macro!(648); + collapsed_macro!(649); + collapsed_macro!(650); + collapsed_macro!(651); + collapsed_macro!(652); + collapsed_macro!(653); + collapsed_macro!(654); + collapsed_macro!(655); + collapsed_macro!(656); + collapsed_macro!(657); + collapsed_macro!(658); + collapsed_macro!(659); + collapsed_macro!(660); + collapsed_macro!(661); + collapsed_macro!(662); + collapsed_macro!(663); + collapsed_macro!(664); + collapsed_macro!(665); + collapsed_macro!(666); + collapsed_macro!(667); + collapsed_macro!(668); + collapsed_macro!(669); + collapsed_macro!(670); + collapsed_macro!(671); + collapsed_macro!(672); + collapsed_macro!(673); + collapsed_macro!(674); + collapsed_macro!(675); + collapsed_macro!(676); + collapsed_macro!(677); + collapsed_macro!(678); + collapsed_macro!(679); + collapsed_macro!(680); + collapsed_macro!(681); + collapsed_macro!(682); + collapsed_macro!(683); + collapsed_macro!(684); + collapsed_macro!(685); + collapsed_macro!(686); + collapsed_macro!(687); + collapsed_macro!(688); + collapsed_macro!(689); + collapsed_macro!(690); + collapsed_macro!(691); + collapsed_macro!(692); + collapsed_macro!(693); + collapsed_macro!(694); + collapsed_macro!(695); + collapsed_macro!(696); + collapsed_macro!(697); + collapsed_macro!(698); + collapsed_macro!(699); + collapsed_macro!(700); + collapsed_macro!(701); + collapsed_macro!(702); + collapsed_macro!(703); + collapsed_macro!(704); + collapsed_macro!(705); + collapsed_macro!(706); + collapsed_macro!(707); + collapsed_macro!(708); + collapsed_macro!(709); + collapsed_macro!(710); + collapsed_macro!(711); + collapsed_macro!(712); + collapsed_macro!(713); + collapsed_macro!(714); + collapsed_macro!(715); + collapsed_macro!(716); + collapsed_macro!(717); + collapsed_macro!(718); + collapsed_macro!(719); + collapsed_macro!(720); + collapsed_macro!(721); + collapsed_macro!(722); + collapsed_macro!(723); + collapsed_macro!(724); + collapsed_macro!(725); + collapsed_macro!(726); + collapsed_macro!(727); + collapsed_macro!(728); + collapsed_macro!(729); + collapsed_macro!(730); + collapsed_macro!(731); + collapsed_macro!(732); + collapsed_macro!(733); + collapsed_macro!(734); + collapsed_macro!(735); + collapsed_macro!(736); + collapsed_macro!(737); + collapsed_macro!(738); + collapsed_macro!(739); + collapsed_macro!(740); + collapsed_macro!(741); + collapsed_macro!(742); + collapsed_macro!(743); + collapsed_macro!(744); + collapsed_macro!(745); + collapsed_macro!(746); + collapsed_macro!(747); + collapsed_macro!(748); + collapsed_macro!(749); + collapsed_macro!(750); + collapsed_macro!(751); + collapsed_macro!(752); + collapsed_macro!(753); + collapsed_macro!(754); + collapsed_macro!(755); + collapsed_macro!(756); + collapsed_macro!(757); + collapsed_macro!(758); + collapsed_macro!(759); + collapsed_macro!(760); + collapsed_macro!(761); + collapsed_macro!(762); + collapsed_macro!(763); + collapsed_macro!(764); + collapsed_macro!(765); + collapsed_macro!(766); + collapsed_macro!(767); + collapsed_macro!(768); + collapsed_macro!(769); + collapsed_macro!(770); + collapsed_macro!(771); + collapsed_macro!(772); + collapsed_macro!(773); + collapsed_macro!(774); + collapsed_macro!(775); + collapsed_macro!(776); + collapsed_macro!(777); + collapsed_macro!(778); + collapsed_macro!(779); + collapsed_macro!(780); + collapsed_macro!(781); + collapsed_macro!(782); + collapsed_macro!(783); + collapsed_macro!(784); + collapsed_macro!(785); + collapsed_macro!(786); + collapsed_macro!(787); + collapsed_macro!(788); + collapsed_macro!(789); + collapsed_macro!(790); + collapsed_macro!(791); + collapsed_macro!(792); + collapsed_macro!(793); + collapsed_macro!(794); + collapsed_macro!(795); + collapsed_macro!(796); + collapsed_macro!(797); + collapsed_macro!(798); + collapsed_macro!(799); + collapsed_macro!(800); + collapsed_macro!(801); + collapsed_macro!(802); + collapsed_macro!(803); + collapsed_macro!(804); + collapsed_macro!(805); + collapsed_macro!(806); + collapsed_macro!(807); + collapsed_macro!(808); + collapsed_macro!(809); + collapsed_macro!(810); + collapsed_macro!(811); + collapsed_macro!(812); + collapsed_macro!(813); + collapsed_macro!(814); + collapsed_macro!(815); + collapsed_macro!(816); + collapsed_macro!(817); + collapsed_macro!(818); + collapsed_macro!(819); + collapsed_macro!(820); + collapsed_macro!(821); + collapsed_macro!(822); + collapsed_macro!(823); + collapsed_macro!(824); + collapsed_macro!(825); + collapsed_macro!(826); + collapsed_macro!(827); + collapsed_macro!(828); + collapsed_macro!(829); + collapsed_macro!(830); + collapsed_macro!(831); + collapsed_macro!(832); + collapsed_macro!(833); + collapsed_macro!(834); + collapsed_macro!(835); + collapsed_macro!(836); + collapsed_macro!(837); + collapsed_macro!(838); + collapsed_macro!(839); + collapsed_macro!(840); + collapsed_macro!(841); + collapsed_macro!(842); + collapsed_macro!(843); + collapsed_macro!(844); + collapsed_macro!(845); + collapsed_macro!(846); + collapsed_macro!(847); + collapsed_macro!(848); + collapsed_macro!(849); + collapsed_macro!(850); + collapsed_macro!(851); + collapsed_macro!(852); + collapsed_macro!(853); + collapsed_macro!(854); + collapsed_macro!(855); + collapsed_macro!(856); + collapsed_macro!(857); + collapsed_macro!(858); + collapsed_macro!(859); + collapsed_macro!(860); + collapsed_macro!(861); + collapsed_macro!(862); + collapsed_macro!(863); + collapsed_macro!(864); + collapsed_macro!(865); + collapsed_macro!(866); + collapsed_macro!(867); + collapsed_macro!(868); + collapsed_macro!(869); + collapsed_macro!(870); + collapsed_macro!(871); + collapsed_macro!(872); + collapsed_macro!(873); + collapsed_macro!(874); + collapsed_macro!(875); + collapsed_macro!(876); + collapsed_macro!(877); + collapsed_macro!(878); + collapsed_macro!(879); + collapsed_macro!(880); + collapsed_macro!(881); + collapsed_macro!(882); + collapsed_macro!(883); + collapsed_macro!(884); + collapsed_macro!(885); + collapsed_macro!(886); + collapsed_macro!(887); + collapsed_macro!(888); + collapsed_macro!(889); + collapsed_macro!(890); + collapsed_macro!(891); + collapsed_macro!(892); + collapsed_macro!(893); + collapsed_macro!(894); + collapsed_macro!(895); + collapsed_macro!(896); + collapsed_macro!(897); + collapsed_macro!(898); + collapsed_macro!(899); + collapsed_macro!(900); + collapsed_macro!(901); + collapsed_macro!(902); + collapsed_macro!(903); + collapsed_macro!(904); + collapsed_macro!(905); + collapsed_macro!(906); + collapsed_macro!(907); + collapsed_macro!(908); + collapsed_macro!(909); + collapsed_macro!(910); + collapsed_macro!(911); + collapsed_macro!(912); + collapsed_macro!(913); + collapsed_macro!(914); + collapsed_macro!(915); + collapsed_macro!(916); + collapsed_macro!(917); + collapsed_macro!(918); + collapsed_macro!(919); + collapsed_macro!(920); + collapsed_macro!(921); + collapsed_macro!(922); + collapsed_macro!(923); + collapsed_macro!(924); + collapsed_macro!(925); + collapsed_macro!(926); + collapsed_macro!(927); + collapsed_macro!(928); + collapsed_macro!(929); + collapsed_macro!(930); + collapsed_macro!(931); + collapsed_macro!(932); + collapsed_macro!(933); + collapsed_macro!(934); + collapsed_macro!(935); + collapsed_macro!(936); + collapsed_macro!(937); + collapsed_macro!(938); + collapsed_macro!(939); + collapsed_macro!(940); + collapsed_macro!(941); + collapsed_macro!(942); + collapsed_macro!(943); + collapsed_macro!(944); + collapsed_macro!(945); + collapsed_macro!(946); + collapsed_macro!(947); + collapsed_macro!(948); + collapsed_macro!(949); + collapsed_macro!(950); + collapsed_macro!(951); + collapsed_macro!(952); + collapsed_macro!(953); + collapsed_macro!(954); + collapsed_macro!(955); + collapsed_macro!(956); + collapsed_macro!(957); + collapsed_macro!(958); + collapsed_macro!(959); + collapsed_macro!(960); + collapsed_macro!(961); + collapsed_macro!(962); + collapsed_macro!(963); + collapsed_macro!(964); + collapsed_macro!(965); + collapsed_macro!(966); + collapsed_macro!(967); + collapsed_macro!(968); + collapsed_macro!(969); + collapsed_macro!(970); + collapsed_macro!(971); + collapsed_macro!(972); + collapsed_macro!(973); + collapsed_macro!(974); + collapsed_macro!(975); + collapsed_macro!(976); + collapsed_macro!(977); + collapsed_macro!(978); + collapsed_macro!(979); + collapsed_macro!(980); + collapsed_macro!(981); + collapsed_macro!(982); + collapsed_macro!(983); + collapsed_macro!(984); + collapsed_macro!(985); + collapsed_macro!(986); + collapsed_macro!(987); + collapsed_macro!(988); + collapsed_macro!(989); + collapsed_macro!(990); + collapsed_macro!(991); + collapsed_macro!(992); + collapsed_macro!(993); + collapsed_macro!(994); + collapsed_macro!(995); + collapsed_macro!(996); + collapsed_macro!(997); + collapsed_macro!(998); + collapsed_macro!(999); + collapsed_macro!(1000); + collapsed_macro!(1001); + collapsed_macro!(1002); + collapsed_macro!(1003); + collapsed_macro!(1004); + collapsed_macro!(1005); + collapsed_macro!(1006); + collapsed_macro!(1007); + collapsed_macro!(1008); + collapsed_macro!(1009); + collapsed_macro!(1010); + collapsed_macro!(1011); + collapsed_macro!(1012); + collapsed_macro!(1013); + collapsed_macro!(1014); + collapsed_macro!(1015); + collapsed_macro!(1016); + collapsed_macro!(1017); + collapsed_macro!(1018); + collapsed_macro!(1019); + collapsed_macro!(1020); + collapsed_macro!(1021); + collapsed_macro!(1022); + collapsed_macro!(1023); + collapsed_macro!(1024); + collapsed_macro!(1025); + collapsed_macro!(1026); + collapsed_macro!(1027); + collapsed_macro!(1028); + collapsed_macro!(1029); + collapsed_macro!(1030); + collapsed_macro!(1031); + collapsed_macro!(1032); + collapsed_macro!(1033); + collapsed_macro!(1034); + collapsed_macro!(1035); + collapsed_macro!(1036); + collapsed_macro!(1037); + collapsed_macro!(1038); + collapsed_macro!(1039); + collapsed_macro!(1040); + collapsed_macro!(1041); + collapsed_macro!(1042); + collapsed_macro!(1043); + collapsed_macro!(1044); + collapsed_macro!(1045); + collapsed_macro!(1046); + collapsed_macro!(1047); + collapsed_macro!(1048); + collapsed_macro!(1049); + collapsed_macro!(1050); + collapsed_macro!(1051); + collapsed_macro!(1052); + collapsed_macro!(1053); + collapsed_macro!(1054); + collapsed_macro!(1055); + collapsed_macro!(1056); + collapsed_macro!(1057); + collapsed_macro!(1058); + collapsed_macro!(1059); + collapsed_macro!(1060); + collapsed_macro!(1061); + collapsed_macro!(1062); + collapsed_macro!(1063); + collapsed_macro!(1064); + collapsed_macro!(1065); + collapsed_macro!(1066); + collapsed_macro!(1067); + collapsed_macro!(1068); + collapsed_macro!(1069); + collapsed_macro!(1070); + collapsed_macro!(1071); + collapsed_macro!(1072); + collapsed_macro!(1073); + collapsed_macro!(1074); + collapsed_macro!(1075); + collapsed_macro!(1076); + collapsed_macro!(1077); + collapsed_macro!(1078); + collapsed_macro!(1079); + collapsed_macro!(1080); + collapsed_macro!(1081); + collapsed_macro!(1082); + collapsed_macro!(1083); + collapsed_macro!(1084); + collapsed_macro!(1085); + collapsed_macro!(1086); + collapsed_macro!(1087); + collapsed_macro!(1088); + collapsed_macro!(1089); + collapsed_macro!(1090); + collapsed_macro!(1091); + collapsed_macro!(1092); + collapsed_macro!(1093); + collapsed_macro!(1094); + collapsed_macro!(1095); + collapsed_macro!(1096); + collapsed_macro!(1097); + collapsed_macro!(1098); + collapsed_macro!(1099); + collapsed_macro!(1100); + collapsed_macro!(1101); + collapsed_macro!(1102); + collapsed_macro!(1103); + collapsed_macro!(1104); + collapsed_macro!(1105); + collapsed_macro!(1106); + collapsed_macro!(1107); + collapsed_macro!(1108); + collapsed_macro!(1109); + collapsed_macro!(1110); + collapsed_macro!(1111); + collapsed_macro!(1112); + collapsed_macro!(1113); + collapsed_macro!(1114); + collapsed_macro!(1115); + collapsed_macro!(1116); + collapsed_macro!(1117); + collapsed_macro!(1118); + collapsed_macro!(1119); + collapsed_macro!(1120); + collapsed_macro!(1121); + collapsed_macro!(1122); + collapsed_macro!(1123); + collapsed_macro!(1124); + collapsed_macro!(1125); + collapsed_macro!(1126); + collapsed_macro!(1127); + collapsed_macro!(1128); + collapsed_macro!(1129); + collapsed_macro!(1130); + collapsed_macro!(1131); + collapsed_macro!(1132); + collapsed_macro!(1133); + collapsed_macro!(1134); + collapsed_macro!(1135); + collapsed_macro!(1136); + collapsed_macro!(1137); + collapsed_macro!(1138); + collapsed_macro!(1139); + collapsed_macro!(1140); + collapsed_macro!(1141); + collapsed_macro!(1142); + collapsed_macro!(1143); + collapsed_macro!(1144); + collapsed_macro!(1145); + collapsed_macro!(1146); + collapsed_macro!(1147); + collapsed_macro!(1148); + collapsed_macro!(1149); + collapsed_macro!(1150); + collapsed_macro!(1151); + collapsed_macro!(1152); + collapsed_macro!(1153); + collapsed_macro!(1154); + collapsed_macro!(1155); + collapsed_macro!(1156); + collapsed_macro!(1157); + collapsed_macro!(1158); + collapsed_macro!(1159); + collapsed_macro!(1160); + collapsed_macro!(1161); + collapsed_macro!(1162); + collapsed_macro!(1163); + collapsed_macro!(1164); + collapsed_macro!(1165); + collapsed_macro!(1166); + collapsed_macro!(1167); + collapsed_macro!(1168); + collapsed_macro!(1169); + collapsed_macro!(1170); + collapsed_macro!(1171); + collapsed_macro!(1172); + collapsed_macro!(1173); + collapsed_macro!(1174); + collapsed_macro!(1175); + collapsed_macro!(1176); + collapsed_macro!(1177); + collapsed_macro!(1178); + collapsed_macro!(1179); + collapsed_macro!(1180); + collapsed_macro!(1181); + collapsed_macro!(1182); + collapsed_macro!(1183); + collapsed_macro!(1184); + collapsed_macro!(1185); + collapsed_macro!(1186); + collapsed_macro!(1187); + collapsed_macro!(1188); + collapsed_macro!(1189); + collapsed_macro!(1190); + collapsed_macro!(1191); + collapsed_macro!(1192); + collapsed_macro!(1193); + collapsed_macro!(1194); + collapsed_macro!(1195); + collapsed_macro!(1196); + collapsed_macro!(1197); + collapsed_macro!(1198); + collapsed_macro!(1199); + collapsed_macro!(1200); + collapsed_macro!(1201); + collapsed_macro!(1202); + collapsed_macro!(1203); + collapsed_macro!(1204); + collapsed_macro!(1205); + collapsed_macro!(1206); + collapsed_macro!(1207); + collapsed_macro!(1208); + collapsed_macro!(1209); + collapsed_macro!(1210); + collapsed_macro!(1211); + collapsed_macro!(1212); + collapsed_macro!(1213); + collapsed_macro!(1214); + collapsed_macro!(1215); + collapsed_macro!(1216); + collapsed_macro!(1217); + collapsed_macro!(1218); + collapsed_macro!(1219); + collapsed_macro!(1220); + collapsed_macro!(1221); + collapsed_macro!(1222); + collapsed_macro!(1223); + collapsed_macro!(1224); + collapsed_macro!(1225); + collapsed_macro!(1226); + collapsed_macro!(1227); + collapsed_macro!(1228); + collapsed_macro!(1229); + collapsed_macro!(1230); + collapsed_macro!(1231); + collapsed_macro!(1232); + collapsed_macro!(1233); + collapsed_macro!(1234); + collapsed_macro!(1235); + collapsed_macro!(1236); + collapsed_macro!(1237); + collapsed_macro!(1238); + collapsed_macro!(1239); + collapsed_macro!(1240); + collapsed_macro!(1241); + collapsed_macro!(1242); + collapsed_macro!(1243); + collapsed_macro!(1244); + collapsed_macro!(1245); + collapsed_macro!(1246); + collapsed_macro!(1247); + collapsed_macro!(1248); + collapsed_macro!(1249); + collapsed_macro!(1250); + collapsed_macro!(1251); + collapsed_macro!(1252); + collapsed_macro!(1253); + collapsed_macro!(1254); + collapsed_macro!(1255); + collapsed_macro!(1256); + collapsed_macro!(1257); + collapsed_macro!(1258); + collapsed_macro!(1259); + collapsed_macro!(1260); + collapsed_macro!(1261); + collapsed_macro!(1262); + collapsed_macro!(1263); + collapsed_macro!(1264); + collapsed_macro!(1265); + collapsed_macro!(1266); + collapsed_macro!(1267); + collapsed_macro!(1268); + collapsed_macro!(1269); + collapsed_macro!(1270); + collapsed_macro!(1271); + collapsed_macro!(1272); + collapsed_macro!(1273); + collapsed_macro!(1274); + collapsed_macro!(1275); + collapsed_macro!(1276); + collapsed_macro!(1277); + collapsed_macro!(1278); + collapsed_macro!(1279); + collapsed_macro!(1280); + collapsed_macro!(1281); + collapsed_macro!(1282); + collapsed_macro!(1283); + collapsed_macro!(1284); + collapsed_macro!(1285); + collapsed_macro!(1286); + collapsed_macro!(1287); + collapsed_macro!(1288); + collapsed_macro!(1289); + collapsed_macro!(1290); + collapsed_macro!(1291); + collapsed_macro!(1292); + collapsed_macro!(1293); + collapsed_macro!(1294); + collapsed_macro!(1295); + collapsed_macro!(1296); + collapsed_macro!(1297); + collapsed_macro!(1298); + collapsed_macro!(1299); + collapsed_macro!(1300); + collapsed_macro!(1301); + collapsed_macro!(1302); + collapsed_macro!(1303); + collapsed_macro!(1304); + collapsed_macro!(1305); + collapsed_macro!(1306); + collapsed_macro!(1307); + collapsed_macro!(1308); + collapsed_macro!(1309); + collapsed_macro!(1310); + collapsed_macro!(1311); + collapsed_macro!(1312); + collapsed_macro!(1313); + collapsed_macro!(1314); + collapsed_macro!(1315); + collapsed_macro!(1316); + collapsed_macro!(1317); + collapsed_macro!(1318); + collapsed_macro!(1319); + collapsed_macro!(1320); + collapsed_macro!(1321); + collapsed_macro!(1322); + collapsed_macro!(1323); + collapsed_macro!(1324); + collapsed_macro!(1325); + collapsed_macro!(1326); + collapsed_macro!(1327); + collapsed_macro!(1328); + collapsed_macro!(1329); + collapsed_macro!(1330); + collapsed_macro!(1331); + collapsed_macro!(1332); + collapsed_macro!(1333); + collapsed_macro!(1334); + collapsed_macro!(1335); + collapsed_macro!(1336); + collapsed_macro!(1337); + collapsed_macro!(1338); + collapsed_macro!(1339); + collapsed_macro!(1340); + collapsed_macro!(1341); + collapsed_macro!(1342); + collapsed_macro!(1343); + collapsed_macro!(1344); + collapsed_macro!(1345); + collapsed_macro!(1346); + collapsed_macro!(1347); + collapsed_macro!(1348); + collapsed_macro!(1349); + collapsed_macro!(1350); + collapsed_macro!(1351); + collapsed_macro!(1352); + collapsed_macro!(1353); + collapsed_macro!(1354); + collapsed_macro!(1355); + collapsed_macro!(1356); + collapsed_macro!(1357); + collapsed_macro!(1358); + collapsed_macro!(1359); + collapsed_macro!(1360); + collapsed_macro!(1361); + collapsed_macro!(1362); + collapsed_macro!(1363); + collapsed_macro!(1364); + collapsed_macro!(1365); + collapsed_macro!(1366); + collapsed_macro!(1367); + collapsed_macro!(1368); + collapsed_macro!(1369); + collapsed_macro!(1370); + collapsed_macro!(1371); + collapsed_macro!(1372); + collapsed_macro!(1373); + collapsed_macro!(1374); + collapsed_macro!(1375); + collapsed_macro!(1376); + collapsed_macro!(1377); + collapsed_macro!(1378); + collapsed_macro!(1379); + collapsed_macro!(1380); + collapsed_macro!(1381); + collapsed_macro!(1382); + collapsed_macro!(1383); + collapsed_macro!(1384); + collapsed_macro!(1385); + collapsed_macro!(1386); + collapsed_macro!(1387); + collapsed_macro!(1388); + collapsed_macro!(1389); + collapsed_macro!(1390); + collapsed_macro!(1391); + collapsed_macro!(1392); + collapsed_macro!(1393); + collapsed_macro!(1394); + collapsed_macro!(1395); + collapsed_macro!(1396); + collapsed_macro!(1397); + collapsed_macro!(1398); + collapsed_macro!(1399); + collapsed_macro!(1400); + collapsed_macro!(1401); + collapsed_macro!(1402); + collapsed_macro!(1403); + collapsed_macro!(1404); + collapsed_macro!(1405); + collapsed_macro!(1406); + collapsed_macro!(1407); + collapsed_macro!(1408); + collapsed_macro!(1409); + collapsed_macro!(1410); + collapsed_macro!(1411); + collapsed_macro!(1412); + collapsed_macro!(1413); + collapsed_macro!(1414); + collapsed_macro!(1415); + collapsed_macro!(1416); + collapsed_macro!(1417); + collapsed_macro!(1418); + collapsed_macro!(1419); + collapsed_macro!(1420); + collapsed_macro!(1421); + collapsed_macro!(1422); + collapsed_macro!(1423); + collapsed_macro!(1424); + collapsed_macro!(1425); + collapsed_macro!(1426); + collapsed_macro!(1427); + collapsed_macro!(1428); + collapsed_macro!(1429); + collapsed_macro!(1430); + collapsed_macro!(1431); + collapsed_macro!(1432); + collapsed_macro!(1433); + collapsed_macro!(1434); + collapsed_macro!(1435); + collapsed_macro!(1436); + collapsed_macro!(1437); + collapsed_macro!(1438); + collapsed_macro!(1439); + collapsed_macro!(1440); + collapsed_macro!(1441); + collapsed_macro!(1442); + collapsed_macro!(1443); + collapsed_macro!(1444); + collapsed_macro!(1445); + collapsed_macro!(1446); + collapsed_macro!(1447); + collapsed_macro!(1448); + collapsed_macro!(1449); + collapsed_macro!(1450); + collapsed_macro!(1451); + collapsed_macro!(1452); + collapsed_macro!(1453); + collapsed_macro!(1454); + collapsed_macro!(1455); + collapsed_macro!(1456); + collapsed_macro!(1457); + collapsed_macro!(1458); + collapsed_macro!(1459); + collapsed_macro!(1460); + collapsed_macro!(1461); + collapsed_macro!(1462); + collapsed_macro!(1463); + collapsed_macro!(1464); + collapsed_macro!(1465); + collapsed_macro!(1466); + collapsed_macro!(1467); + collapsed_macro!(1468); + collapsed_macro!(1469); + collapsed_macro!(1470); + collapsed_macro!(1471); + collapsed_macro!(1472); + collapsed_macro!(1473); + collapsed_macro!(1474); + collapsed_macro!(1475); + collapsed_macro!(1476); + collapsed_macro!(1477); + collapsed_macro!(1478); + collapsed_macro!(1479); + collapsed_macro!(1480); + collapsed_macro!(1481); + collapsed_macro!(1482); + collapsed_macro!(1483); + collapsed_macro!(1484); + collapsed_macro!(1485); + collapsed_macro!(1486); + collapsed_macro!(1487); + collapsed_macro!(1488); + collapsed_macro!(1489); + collapsed_macro!(1490); + collapsed_macro!(1491); + collapsed_macro!(1492); + collapsed_macro!(1493); + collapsed_macro!(1494); + collapsed_macro!(1495); + collapsed_macro!(1496); + collapsed_macro!(1497); + collapsed_macro!(1498); + collapsed_macro!(1499); + collapsed_macro!(1500); + collapsed_macro!(1501); + collapsed_macro!(1502); + collapsed_macro!(1503); + collapsed_macro!(1504); + collapsed_macro!(1505); + collapsed_macro!(1506); + collapsed_macro!(1507); + collapsed_macro!(1508); + collapsed_macro!(1509); + collapsed_macro!(1510); + collapsed_macro!(1511); + collapsed_macro!(1512); + collapsed_macro!(1513); + collapsed_macro!(1514); + collapsed_macro!(1515); + collapsed_macro!(1516); + collapsed_macro!(1517); + collapsed_macro!(1518); + collapsed_macro!(1519); + collapsed_macro!(1520); + collapsed_macro!(1521); + collapsed_macro!(1522); + collapsed_macro!(1523); + collapsed_macro!(1524); + collapsed_macro!(1525); + collapsed_macro!(1526); + collapsed_macro!(1527); + collapsed_macro!(1528); + collapsed_macro!(1529); + collapsed_macro!(1530); + collapsed_macro!(1531); + collapsed_macro!(1532); + collapsed_macro!(1533); + collapsed_macro!(1534); + collapsed_macro!(1535); + collapsed_macro!(1536); + collapsed_macro!(1537); + collapsed_macro!(1538); + collapsed_macro!(1539); + collapsed_macro!(1540); + collapsed_macro!(1541); + collapsed_macro!(1542); + collapsed_macro!(1543); + collapsed_macro!(1544); + collapsed_macro!(1545); + collapsed_macro!(1546); + collapsed_macro!(1547); + collapsed_macro!(1548); + collapsed_macro!(1549); + collapsed_macro!(1550); + collapsed_macro!(1551); + collapsed_macro!(1552); + collapsed_macro!(1553); + collapsed_macro!(1554); + collapsed_macro!(1555); + collapsed_macro!(1556); + collapsed_macro!(1557); + collapsed_macro!(1558); + collapsed_macro!(1559); + collapsed_macro!(1560); + collapsed_macro!(1561); + collapsed_macro!(1562); + collapsed_macro!(1563); + collapsed_macro!(1564); + collapsed_macro!(1565); + collapsed_macro!(1566); + collapsed_macro!(1567); + collapsed_macro!(1568); + collapsed_macro!(1569); + collapsed_macro!(1570); + collapsed_macro!(1571); + collapsed_macro!(1572); + collapsed_macro!(1573); + collapsed_macro!(1574); + collapsed_macro!(1575); + collapsed_macro!(1576); + collapsed_macro!(1577); + collapsed_macro!(1578); + collapsed_macro!(1579); + collapsed_macro!(1580); + collapsed_macro!(1581); + collapsed_macro!(1582); + collapsed_macro!(1583); + collapsed_macro!(1584); + collapsed_macro!(1585); + collapsed_macro!(1586); + collapsed_macro!(1587); + collapsed_macro!(1588); + collapsed_macro!(1589); + collapsed_macro!(1590); + collapsed_macro!(1591); + collapsed_macro!(1592); + collapsed_macro!(1593); + collapsed_macro!(1594); + collapsed_macro!(1595); + collapsed_macro!(1596); + collapsed_macro!(1597); + collapsed_macro!(1598); + collapsed_macro!(1599); + collapsed_macro!(1600); + collapsed_macro!(1601); + collapsed_macro!(1602); + collapsed_macro!(1603); + collapsed_macro!(1604); + collapsed_macro!(1605); + collapsed_macro!(1606); + collapsed_macro!(1607); + collapsed_macro!(1608); + collapsed_macro!(1609); + collapsed_macro!(1610); + collapsed_macro!(1611); + collapsed_macro!(1612); + collapsed_macro!(1613); + collapsed_macro!(1614); + collapsed_macro!(1615); + collapsed_macro!(1616); + collapsed_macro!(1617); + collapsed_macro!(1618); + collapsed_macro!(1619); + collapsed_macro!(1620); + collapsed_macro!(1621); + collapsed_macro!(1622); + collapsed_macro!(1623); + collapsed_macro!(1624); + collapsed_macro!(1625); + collapsed_macro!(1626); + collapsed_macro!(1627); + collapsed_macro!(1628); + collapsed_macro!(1629); + collapsed_macro!(1630); + collapsed_macro!(1631); + collapsed_macro!(1632); + collapsed_macro!(1633); + collapsed_macro!(1634); + collapsed_macro!(1635); + collapsed_macro!(1636); + collapsed_macro!(1637); + collapsed_macro!(1638); + collapsed_macro!(1639); + collapsed_macro!(1640); + collapsed_macro!(1641); + collapsed_macro!(1642); + collapsed_macro!(1643); + collapsed_macro!(1644); + collapsed_macro!(1645); + collapsed_macro!(1646); + collapsed_macro!(1647); + collapsed_macro!(1648); + collapsed_macro!(1649); + collapsed_macro!(1650); + collapsed_macro!(1651); + collapsed_macro!(1652); + collapsed_macro!(1653); + collapsed_macro!(1654); + collapsed_macro!(1655); + collapsed_macro!(1656); + collapsed_macro!(1657); + collapsed_macro!(1658); + collapsed_macro!(1659); + collapsed_macro!(1660); + collapsed_macro!(1661); + collapsed_macro!(1662); + collapsed_macro!(1663); + collapsed_macro!(1664); + collapsed_macro!(1665); + collapsed_macro!(1666); + collapsed_macro!(1667); + collapsed_macro!(1668); + collapsed_macro!(1669); + collapsed_macro!(1670); + collapsed_macro!(1671); + collapsed_macro!(1672); + collapsed_macro!(1673); + collapsed_macro!(1674); + collapsed_macro!(1675); + collapsed_macro!(1676); + collapsed_macro!(1677); + collapsed_macro!(1678); + collapsed_macro!(1679); + collapsed_macro!(1680); + collapsed_macro!(1681); + collapsed_macro!(1682); + collapsed_macro!(1683); + collapsed_macro!(1684); + collapsed_macro!(1685); + collapsed_macro!(1686); + collapsed_macro!(1687); + collapsed_macro!(1688); + collapsed_macro!(1689); + collapsed_macro!(1690); + collapsed_macro!(1691); + collapsed_macro!(1692); + collapsed_macro!(1693); + collapsed_macro!(1694); + collapsed_macro!(1695); + collapsed_macro!(1696); + collapsed_macro!(1697); + collapsed_macro!(1698); + collapsed_macro!(1699); + collapsed_macro!(1700); + collapsed_macro!(1701); + collapsed_macro!(1702); + collapsed_macro!(1703); + collapsed_macro!(1704); + collapsed_macro!(1705); + collapsed_macro!(1706); + collapsed_macro!(1707); + collapsed_macro!(1708); + collapsed_macro!(1709); + collapsed_macro!(1710); + collapsed_macro!(1711); + collapsed_macro!(1712); + collapsed_macro!(1713); + collapsed_macro!(1714); + collapsed_macro!(1715); + collapsed_macro!(1716); + collapsed_macro!(1717); + collapsed_macro!(1718); + collapsed_macro!(1719); + collapsed_macro!(1720); + collapsed_macro!(1721); + collapsed_macro!(1722); + collapsed_macro!(1723); + collapsed_macro!(1724); + collapsed_macro!(1725); + collapsed_macro!(1726); + collapsed_macro!(1727); + collapsed_macro!(1728); + collapsed_macro!(1729); + collapsed_macro!(1730); + collapsed_macro!(1731); + collapsed_macro!(1732); + collapsed_macro!(1733); + collapsed_macro!(1734); + collapsed_macro!(1735); + collapsed_macro!(1736); + collapsed_macro!(1737); + collapsed_macro!(1738); + collapsed_macro!(1739); + collapsed_macro!(1740); + collapsed_macro!(1741); + collapsed_macro!(1742); + collapsed_macro!(1743); + collapsed_macro!(1744); + collapsed_macro!(1745); + collapsed_macro!(1746); + collapsed_macro!(1747); + collapsed_macro!(1748); + collapsed_macro!(1749); + collapsed_macro!(1750); + collapsed_macro!(1751); + collapsed_macro!(1752); + collapsed_macro!(1753); + collapsed_macro!(1754); + collapsed_macro!(1755); + collapsed_macro!(1756); + collapsed_macro!(1757); + collapsed_macro!(1758); + collapsed_macro!(1759); + collapsed_macro!(1760); + collapsed_macro!(1761); + collapsed_macro!(1762); + collapsed_macro!(1763); + collapsed_macro!(1764); + collapsed_macro!(1765); + collapsed_macro!(1766); + collapsed_macro!(1767); + collapsed_macro!(1768); + collapsed_macro!(1769); + collapsed_macro!(1770); + collapsed_macro!(1771); + collapsed_macro!(1772); + collapsed_macro!(1773); + collapsed_macro!(1774); + collapsed_macro!(1775); + collapsed_macro!(1776); + collapsed_macro!(1777); + collapsed_macro!(1778); + collapsed_macro!(1779); + collapsed_macro!(1780); + collapsed_macro!(1781); + collapsed_macro!(1782); + collapsed_macro!(1783); + collapsed_macro!(1784); + collapsed_macro!(1785); + collapsed_macro!(1786); + collapsed_macro!(1787); + collapsed_macro!(1788); + collapsed_macro!(1789); + collapsed_macro!(1790); + collapsed_macro!(1791); + collapsed_macro!(1792); + collapsed_macro!(1793); + collapsed_macro!(1794); + collapsed_macro!(1795); + collapsed_macro!(1796); + collapsed_macro!(1797); + collapsed_macro!(1798); + collapsed_macro!(1799); + collapsed_macro!(1800); + collapsed_macro!(1801); + collapsed_macro!(1802); + collapsed_macro!(1803); + collapsed_macro!(1804); + collapsed_macro!(1805); + collapsed_macro!(1806); + collapsed_macro!(1807); + collapsed_macro!(1808); + collapsed_macro!(1809); + collapsed_macro!(1810); + collapsed_macro!(1811); + collapsed_macro!(1812); + collapsed_macro!(1813); + collapsed_macro!(1814); + collapsed_macro!(1815); + collapsed_macro!(1816); + collapsed_macro!(1817); + collapsed_macro!(1818); + collapsed_macro!(1819); + collapsed_macro!(1820); + collapsed_macro!(1821); + collapsed_macro!(1822); + collapsed_macro!(1823); + collapsed_macro!(1824); + collapsed_macro!(1825); + collapsed_macro!(1826); + collapsed_macro!(1827); + collapsed_macro!(1828); + collapsed_macro!(1829); + collapsed_macro!(1830); + collapsed_macro!(1831); + collapsed_macro!(1832); + collapsed_macro!(1833); + collapsed_macro!(1834); + collapsed_macro!(1835); + collapsed_macro!(1836); + collapsed_macro!(1837); + collapsed_macro!(1838); + collapsed_macro!(1839); + collapsed_macro!(1840); + collapsed_macro!(1841); + collapsed_macro!(1842); + collapsed_macro!(1843); + collapsed_macro!(1844); + collapsed_macro!(1845); + collapsed_macro!(1846); + collapsed_macro!(1847); + collapsed_macro!(1848); + collapsed_macro!(1849); + collapsed_macro!(1850); + collapsed_macro!(1851); + collapsed_macro!(1852); + collapsed_macro!(1853); + collapsed_macro!(1854); + collapsed_macro!(1855); + collapsed_macro!(1856); + collapsed_macro!(1857); + collapsed_macro!(1858); + collapsed_macro!(1859); + collapsed_macro!(1860); + collapsed_macro!(1861); + collapsed_macro!(1862); + collapsed_macro!(1863); + collapsed_macro!(1864); + collapsed_macro!(1865); + collapsed_macro!(1866); + collapsed_macro!(1867); + collapsed_macro!(1868); + collapsed_macro!(1869); + collapsed_macro!(1870); + collapsed_macro!(1871); + collapsed_macro!(1872); + collapsed_macro!(1873); + collapsed_macro!(1874); + collapsed_macro!(1875); + collapsed_macro!(1876); + collapsed_macro!(1877); + collapsed_macro!(1878); + collapsed_macro!(1879); + collapsed_macro!(1880); + collapsed_macro!(1881); + collapsed_macro!(1882); + collapsed_macro!(1883); + collapsed_macro!(1884); + collapsed_macro!(1885); + collapsed_macro!(1886); + collapsed_macro!(1887); + collapsed_macro!(1888); + collapsed_macro!(1889); + collapsed_macro!(1890); + collapsed_macro!(1891); + collapsed_macro!(1892); + collapsed_macro!(1893); + collapsed_macro!(1894); + collapsed_macro!(1895); + collapsed_macro!(1896); + collapsed_macro!(1897); + collapsed_macro!(1898); + collapsed_macro!(1899); + collapsed_macro!(1900); + collapsed_macro!(1901); + collapsed_macro!(1902); + collapsed_macro!(1903); + collapsed_macro!(1904); + collapsed_macro!(1905); + collapsed_macro!(1906); + collapsed_macro!(1907); + collapsed_macro!(1908); + collapsed_macro!(1909); + collapsed_macro!(1910); + collapsed_macro!(1911); + collapsed_macro!(1912); + collapsed_macro!(1913); + collapsed_macro!(1914); + collapsed_macro!(1915); + collapsed_macro!(1916); + collapsed_macro!(1917); + collapsed_macro!(1918); + collapsed_macro!(1919); + collapsed_macro!(1920); + collapsed_macro!(1921); + collapsed_macro!(1922); + collapsed_macro!(1923); + collapsed_macro!(1924); + collapsed_macro!(1925); + collapsed_macro!(1926); + collapsed_macro!(1927); + collapsed_macro!(1928); + collapsed_macro!(1929); + collapsed_macro!(1930); + collapsed_macro!(1931); + collapsed_macro!(1932); + collapsed_macro!(1933); + collapsed_macro!(1934); + collapsed_macro!(1935); + collapsed_macro!(1936); + collapsed_macro!(1937); + collapsed_macro!(1938); + collapsed_macro!(1939); + collapsed_macro!(1940); + collapsed_macro!(1941); + collapsed_macro!(1942); + collapsed_macro!(1943); + collapsed_macro!(1944); + collapsed_macro!(1945); + collapsed_macro!(1946); + collapsed_macro!(1947); + collapsed_macro!(1948); + collapsed_macro!(1949); + collapsed_macro!(1950); + collapsed_macro!(1951); + collapsed_macro!(1952); + collapsed_macro!(1953); + collapsed_macro!(1954); + collapsed_macro!(1955); + collapsed_macro!(1956); + collapsed_macro!(1957); + collapsed_macro!(1958); + collapsed_macro!(1959); + collapsed_macro!(1960); + collapsed_macro!(1961); + collapsed_macro!(1962); + collapsed_macro!(1963); + collapsed_macro!(1964); + collapsed_macro!(1965); + collapsed_macro!(1966); + collapsed_macro!(1967); + collapsed_macro!(1968); + collapsed_macro!(1969); + collapsed_macro!(1970); + collapsed_macro!(1971); + collapsed_macro!(1972); + collapsed_macro!(1973); + collapsed_macro!(1974); + collapsed_macro!(1975); + collapsed_macro!(1976); + collapsed_macro!(1977); + collapsed_macro!(1978); + collapsed_macro!(1979); + collapsed_macro!(1980); + collapsed_macro!(1981); + collapsed_macro!(1982); + collapsed_macro!(1983); + collapsed_macro!(1984); + collapsed_macro!(1985); + collapsed_macro!(1986); + collapsed_macro!(1987); + collapsed_macro!(1988); + collapsed_macro!(1989); + collapsed_macro!(1990); + collapsed_macro!(1991); + collapsed_macro!(1992); + collapsed_macro!(1993); + collapsed_macro!(1994); + collapsed_macro!(1995); + collapsed_macro!(1996); + collapsed_macro!(1997); + collapsed_macro!(1998); + collapsed_macro!(1999); + collapsed_macro!(2000); + collapsed_macro!(2001); + collapsed_macro!(2002); + collapsed_macro!(2003); + collapsed_macro!(2004); + collapsed_macro!(2005); + collapsed_macro!(2006); + collapsed_macro!(2007); + collapsed_macro!(2008); + collapsed_macro!(2009); + collapsed_macro!(2010); + collapsed_macro!(2011); + collapsed_macro!(2012); + collapsed_macro!(2013); + collapsed_macro!(2014); + collapsed_macro!(2015); + collapsed_macro!(2016); + collapsed_macro!(2017); + collapsed_macro!(2018); + collapsed_macro!(2019); + collapsed_macro!(2020); + collapsed_macro!(2021); + collapsed_macro!(2022); + collapsed_macro!(2023); + collapsed_macro!(2024); + collapsed_macro!(2025); + collapsed_macro!(2026); + collapsed_macro!(2027); + collapsed_macro!(2028); + collapsed_macro!(2029); + collapsed_macro!(2030); + collapsed_macro!(2031); + collapsed_macro!(2032); + collapsed_macro!(2033); + collapsed_macro!(2034); + collapsed_macro!(2035); + collapsed_macro!(2036); + collapsed_macro!(2037); + collapsed_macro!(2038); + collapsed_macro!(2039); + collapsed_macro!(2040); + collapsed_macro!(2041); + collapsed_macro!(2042); + collapsed_macro!(2043); + collapsed_macro!(2044); + collapsed_macro!(2045); + collapsed_macro!(2046); + collapsed_macro!(2047); + collapsed_macro!(2048); + collapsed_macro!(2049); + collapsed_macro!(2050); + collapsed_macro!(2051); + collapsed_macro!(2052); + collapsed_macro!(2053); + collapsed_macro!(2054); + collapsed_macro!(2055); + collapsed_macro!(2056); + collapsed_macro!(2057); + collapsed_macro!(2058); + collapsed_macro!(2059); + collapsed_macro!(2060); + collapsed_macro!(2061); + collapsed_macro!(2062); + collapsed_macro!(2063); + collapsed_macro!(2064); + collapsed_macro!(2065); + collapsed_macro!(2066); + collapsed_macro!(2067); + collapsed_macro!(2068); + collapsed_macro!(2069); + collapsed_macro!(2070); + collapsed_macro!(2071); + collapsed_macro!(2072); + collapsed_macro!(2073); + collapsed_macro!(2074); + collapsed_macro!(2075); + collapsed_macro!(2076); + collapsed_macro!(2077); + collapsed_macro!(2078); + collapsed_macro!(2079); + collapsed_macro!(2080); + collapsed_macro!(2081); + collapsed_macro!(2082); + collapsed_macro!(2083); + collapsed_macro!(2084); + collapsed_macro!(2085); + collapsed_macro!(2086); + collapsed_macro!(2087); + collapsed_macro!(2088); + collapsed_macro!(2089); + collapsed_macro!(2090); + collapsed_macro!(2091); + collapsed_macro!(2092); + collapsed_macro!(2093); + collapsed_macro!(2094); + collapsed_macro!(2095); + collapsed_macro!(2096); + collapsed_macro!(2097); + collapsed_macro!(2098); + collapsed_macro!(2099); + collapsed_macro!(2100); + collapsed_macro!(2101); + collapsed_macro!(2102); + collapsed_macro!(2103); + collapsed_macro!(2104); + collapsed_macro!(2105); + collapsed_macro!(2106); + collapsed_macro!(2107); + collapsed_macro!(2108); + collapsed_macro!(2109); + collapsed_macro!(2110); + collapsed_macro!(2111); + collapsed_macro!(2112); + collapsed_macro!(2113); + collapsed_macro!(2114); + collapsed_macro!(2115); + collapsed_macro!(2116); + collapsed_macro!(2117); + collapsed_macro!(2118); + collapsed_macro!(2119); + collapsed_macro!(2120); + collapsed_macro!(2121); + collapsed_macro!(2122); + collapsed_macro!(2123); + collapsed_macro!(2124); + collapsed_macro!(2125); + collapsed_macro!(2126); + collapsed_macro!(2127); + collapsed_macro!(2128); + collapsed_macro!(2129); + collapsed_macro!(2130); + collapsed_macro!(2131); + collapsed_macro!(2132); + collapsed_macro!(2133); + collapsed_macro!(2134); + collapsed_macro!(2135); + collapsed_macro!(2136); + collapsed_macro!(2137); + collapsed_macro!(2138); + collapsed_macro!(2139); + collapsed_macro!(2140); + collapsed_macro!(2141); + collapsed_macro!(2142); + collapsed_macro!(2143); + collapsed_macro!(2144); + collapsed_macro!(2145); + collapsed_macro!(2146); + collapsed_macro!(2147); + collapsed_macro!(2148); + collapsed_macro!(2149); + collapsed_macro!(2150); + collapsed_macro!(2151); + collapsed_macro!(2152); + collapsed_macro!(2153); + collapsed_macro!(2154); + collapsed_macro!(2155); + collapsed_macro!(2156); + collapsed_macro!(2157); + collapsed_macro!(2158); + collapsed_macro!(2159); + collapsed_macro!(2160); + collapsed_macro!(2161); + collapsed_macro!(2162); + collapsed_macro!(2163); + collapsed_macro!(2164); + collapsed_macro!(2165); + collapsed_macro!(2166); + collapsed_macro!(2167); + collapsed_macro!(2168); + collapsed_macro!(2169); + collapsed_macro!(2170); + collapsed_macro!(2171); + collapsed_macro!(2172); + collapsed_macro!(2173); + collapsed_macro!(2174); + collapsed_macro!(2175); + collapsed_macro!(2176); + collapsed_macro!(2177); + collapsed_macro!(2178); + collapsed_macro!(2179); + collapsed_macro!(2180); + collapsed_macro!(2181); + collapsed_macro!(2182); + collapsed_macro!(2183); + collapsed_macro!(2184); + collapsed_macro!(2185); + collapsed_macro!(2186); + collapsed_macro!(2187); + collapsed_macro!(2188); + collapsed_macro!(2189); + collapsed_macro!(2190); + collapsed_macro!(2191); + collapsed_macro!(2192); + collapsed_macro!(2193); + collapsed_macro!(2194); + collapsed_macro!(2195); + collapsed_macro!(2196); + collapsed_macro!(2197); + collapsed_macro!(2198); + collapsed_macro!(2199); + collapsed_macro!(2200); + collapsed_macro!(2201); + collapsed_macro!(2202); + collapsed_macro!(2203); + collapsed_macro!(2204); + collapsed_macro!(2205); + collapsed_macro!(2206); + collapsed_macro!(2207); + collapsed_macro!(2208); + collapsed_macro!(2209); + collapsed_macro!(2210); + collapsed_macro!(2211); + collapsed_macro!(2212); + collapsed_macro!(2213); + collapsed_macro!(2214); + collapsed_macro!(2215); + collapsed_macro!(2216); + collapsed_macro!(2217); + collapsed_macro!(2218); + collapsed_macro!(2219); + collapsed_macro!(2220); + collapsed_macro!(2221); + collapsed_macro!(2222); + collapsed_macro!(2223); + collapsed_macro!(2224); + collapsed_macro!(2225); + collapsed_macro!(2226); + collapsed_macro!(2227); + collapsed_macro!(2228); + collapsed_macro!(2229); + collapsed_macro!(2230); + collapsed_macro!(2231); + collapsed_macro!(2232); + collapsed_macro!(2233); + collapsed_macro!(2234); + collapsed_macro!(2235); + collapsed_macro!(2236); + collapsed_macro!(2237); + collapsed_macro!(2238); + collapsed_macro!(2239); + collapsed_macro!(2240); + collapsed_macro!(2241); + collapsed_macro!(2242); + collapsed_macro!(2243); + collapsed_macro!(2244); + collapsed_macro!(2245); + collapsed_macro!(2246); + collapsed_macro!(2247); + collapsed_macro!(2248); + collapsed_macro!(2249); + collapsed_macro!(2250); + collapsed_macro!(2251); + collapsed_macro!(2252); + collapsed_macro!(2253); + collapsed_macro!(2254); + collapsed_macro!(2255); + collapsed_macro!(2256); + collapsed_macro!(2257); + collapsed_macro!(2258); + collapsed_macro!(2259); + collapsed_macro!(2260); + collapsed_macro!(2261); + collapsed_macro!(2262); + collapsed_macro!(2263); + collapsed_macro!(2264); + collapsed_macro!(2265); + collapsed_macro!(2266); + collapsed_macro!(2267); + collapsed_macro!(2268); + collapsed_macro!(2269); + collapsed_macro!(2270); + collapsed_macro!(2271); + collapsed_macro!(2272); + collapsed_macro!(2273); + collapsed_macro!(2274); + collapsed_macro!(2275); + collapsed_macro!(2276); + collapsed_macro!(2277); + collapsed_macro!(2278); + collapsed_macro!(2279); + collapsed_macro!(2280); + collapsed_macro!(2281); + collapsed_macro!(2282); + collapsed_macro!(2283); + collapsed_macro!(2284); + collapsed_macro!(2285); + collapsed_macro!(2286); + collapsed_macro!(2287); + collapsed_macro!(2288); + collapsed_macro!(2289); + collapsed_macro!(2290); + collapsed_macro!(2291); + collapsed_macro!(2292); + collapsed_macro!(2293); + collapsed_macro!(2294); + collapsed_macro!(2295); + collapsed_macro!(2296); + collapsed_macro!(2297); + collapsed_macro!(2298); + collapsed_macro!(2299); + collapsed_macro!(2300); + collapsed_macro!(2301); + collapsed_macro!(2302); + collapsed_macro!(2303); + collapsed_macro!(2304); + collapsed_macro!(2305); + collapsed_macro!(2306); + collapsed_macro!(2307); + collapsed_macro!(2308); + collapsed_macro!(2309); + collapsed_macro!(2310); + collapsed_macro!(2311); + collapsed_macro!(2312); + collapsed_macro!(2313); + collapsed_macro!(2314); + collapsed_macro!(2315); + collapsed_macro!(2316); + collapsed_macro!(2317); + collapsed_macro!(2318); + collapsed_macro!(2319); + collapsed_macro!(2320); + collapsed_macro!(2321); + collapsed_macro!(2322); + collapsed_macro!(2323); + collapsed_macro!(2324); + collapsed_macro!(2325); + collapsed_macro!(2326); + collapsed_macro!(2327); + collapsed_macro!(2328); + collapsed_macro!(2329); + collapsed_macro!(2330); + collapsed_macro!(2331); + collapsed_macro!(2332); + collapsed_macro!(2333); + collapsed_macro!(2334); + collapsed_macro!(2335); + collapsed_macro!(2336); + collapsed_macro!(2337); + collapsed_macro!(2338); + collapsed_macro!(2339); + collapsed_macro!(2340); + collapsed_macro!(2341); + collapsed_macro!(2342); + collapsed_macro!(2343); + collapsed_macro!(2344); + collapsed_macro!(2345); + collapsed_macro!(2346); + collapsed_macro!(2347); + collapsed_macro!(2348); + collapsed_macro!(2349); + collapsed_macro!(2350); + collapsed_macro!(2351); + collapsed_macro!(2352); + collapsed_macro!(2353); + collapsed_macro!(2354); + collapsed_macro!(2355); + collapsed_macro!(2356); + collapsed_macro!(2357); + collapsed_macro!(2358); + collapsed_macro!(2359); + collapsed_macro!(2360); + collapsed_macro!(2361); + collapsed_macro!(2362); + collapsed_macro!(2363); + collapsed_macro!(2364); + collapsed_macro!(2365); + collapsed_macro!(2366); + collapsed_macro!(2367); + collapsed_macro!(2368); + collapsed_macro!(2369); + collapsed_macro!(2370); + collapsed_macro!(2371); + collapsed_macro!(2372); + collapsed_macro!(2373); + collapsed_macro!(2374); + collapsed_macro!(2375); + collapsed_macro!(2376); + collapsed_macro!(2377); + collapsed_macro!(2378); + collapsed_macro!(2379); + collapsed_macro!(2380); + collapsed_macro!(2381); + collapsed_macro!(2382); + collapsed_macro!(2383); + collapsed_macro!(2384); + collapsed_macro!(2385); + collapsed_macro!(2386); + collapsed_macro!(2387); + collapsed_macro!(2388); + collapsed_macro!(2389); + collapsed_macro!(2390); + collapsed_macro!(2391); + collapsed_macro!(2392); + collapsed_macro!(2393); + collapsed_macro!(2394); + collapsed_macro!(2395); + collapsed_macro!(2396); + collapsed_macro!(2397); + collapsed_macro!(2398); + collapsed_macro!(2399); + collapsed_macro!(2400); + collapsed_macro!(2401); + collapsed_macro!(2402); + collapsed_macro!(2403); + collapsed_macro!(2404); + collapsed_macro!(2405); + collapsed_macro!(2406); + collapsed_macro!(2407); + collapsed_macro!(2408); + collapsed_macro!(2409); + collapsed_macro!(2410); + collapsed_macro!(2411); + collapsed_macro!(2412); + collapsed_macro!(2413); + collapsed_macro!(2414); + collapsed_macro!(2415); + collapsed_macro!(2416); + collapsed_macro!(2417); + collapsed_macro!(2418); + collapsed_macro!(2419); + collapsed_macro!(2420); + collapsed_macro!(2421); + collapsed_macro!(2422); + collapsed_macro!(2423); + collapsed_macro!(2424); + collapsed_macro!(2425); + collapsed_macro!(2426); + collapsed_macro!(2427); + collapsed_macro!(2428); + collapsed_macro!(2429); + collapsed_macro!(2430); + collapsed_macro!(2431); + collapsed_macro!(2432); + collapsed_macro!(2433); + collapsed_macro!(2434); + collapsed_macro!(2435); + collapsed_macro!(2436); + collapsed_macro!(2437); + collapsed_macro!(2438); + collapsed_macro!(2439); + collapsed_macro!(2440); + collapsed_macro!(2441); + collapsed_macro!(2442); + collapsed_macro!(2443); + collapsed_macro!(2444); + collapsed_macro!(2445); + collapsed_macro!(2446); + collapsed_macro!(2447); + collapsed_macro!(2448); + collapsed_macro!(2449); + collapsed_macro!(2450); + collapsed_macro!(2451); + collapsed_macro!(2452); + collapsed_macro!(2453); + collapsed_macro!(2454); + collapsed_macro!(2455); + collapsed_macro!(2456); + collapsed_macro!(2457); + collapsed_macro!(2458); + collapsed_macro!(2459); + collapsed_macro!(2460); + collapsed_macro!(2461); + collapsed_macro!(2462); + collapsed_macro!(2463); + collapsed_macro!(2464); + collapsed_macro!(2465); + collapsed_macro!(2466); + collapsed_macro!(2467); + collapsed_macro!(2468); + collapsed_macro!(2469); + collapsed_macro!(2470); + collapsed_macro!(2471); + collapsed_macro!(2472); + collapsed_macro!(2473); + collapsed_macro!(2474); + collapsed_macro!(2475); + collapsed_macro!(2476); + collapsed_macro!(2477); + collapsed_macro!(2478); + collapsed_macro!(2479); + collapsed_macro!(2480); + collapsed_macro!(2481); + collapsed_macro!(2482); + collapsed_macro!(2483); + collapsed_macro!(2484); + collapsed_macro!(2485); + collapsed_macro!(2486); + collapsed_macro!(2487); + collapsed_macro!(2488); + collapsed_macro!(2489); + collapsed_macro!(2490); + collapsed_macro!(2491); + collapsed_macro!(2492); + collapsed_macro!(2493); + collapsed_macro!(2494); + collapsed_macro!(2495); + collapsed_macro!(2496); + collapsed_macro!(2497); + collapsed_macro!(2498); + collapsed_macro!(2499); + collapsed_macro!(2500); + collapsed_macro!(2501); + collapsed_macro!(2502); + collapsed_macro!(2503); + collapsed_macro!(2504); + collapsed_macro!(2505); + collapsed_macro!(2506); + collapsed_macro!(2507); + collapsed_macro!(2508); + collapsed_macro!(2509); + collapsed_macro!(2510); + collapsed_macro!(2511); + collapsed_macro!(2512); + collapsed_macro!(2513); + collapsed_macro!(2514); + collapsed_macro!(2515); + collapsed_macro!(2516); + collapsed_macro!(2517); + collapsed_macro!(2518); + collapsed_macro!(2519); + collapsed_macro!(2520); + collapsed_macro!(2521); + collapsed_macro!(2522); + collapsed_macro!(2523); + collapsed_macro!(2524); + collapsed_macro!(2525); + collapsed_macro!(2526); + collapsed_macro!(2527); + collapsed_macro!(2528); + collapsed_macro!(2529); + collapsed_macro!(2530); + collapsed_macro!(2531); + collapsed_macro!(2532); + collapsed_macro!(2533); + collapsed_macro!(2534); + collapsed_macro!(2535); + collapsed_macro!(2536); + collapsed_macro!(2537); + collapsed_macro!(2538); + collapsed_macro!(2539); + collapsed_macro!(2540); + collapsed_macro!(2541); + collapsed_macro!(2542); + collapsed_macro!(2543); + collapsed_macro!(2544); + collapsed_macro!(2545); + collapsed_macro!(2546); + collapsed_macro!(2547); + collapsed_macro!(2548); + collapsed_macro!(2549); + collapsed_macro!(2550); + collapsed_macro!(2551); + collapsed_macro!(2552); + collapsed_macro!(2553); + collapsed_macro!(2554); + collapsed_macro!(2555); + collapsed_macro!(2556); + collapsed_macro!(2557); + collapsed_macro!(2558); + collapsed_macro!(2559); + collapsed_macro!(2560); + collapsed_macro!(2561); + collapsed_macro!(2562); + collapsed_macro!(2563); + collapsed_macro!(2564); + collapsed_macro!(2565); + collapsed_macro!(2566); + collapsed_macro!(2567); + collapsed_macro!(2568); + collapsed_macro!(2569); + collapsed_macro!(2570); + collapsed_macro!(2571); + collapsed_macro!(2572); + collapsed_macro!(2573); + collapsed_macro!(2574); + collapsed_macro!(2575); + collapsed_macro!(2576); + collapsed_macro!(2577); + collapsed_macro!(2578); + collapsed_macro!(2579); + collapsed_macro!(2580); + collapsed_macro!(2581); + collapsed_macro!(2582); + collapsed_macro!(2583); + collapsed_macro!(2584); + collapsed_macro!(2585); + collapsed_macro!(2586); + collapsed_macro!(2587); + collapsed_macro!(2588); + collapsed_macro!(2589); + collapsed_macro!(2590); + collapsed_macro!(2591); + collapsed_macro!(2592); + collapsed_macro!(2593); + collapsed_macro!(2594); + collapsed_macro!(2595); + collapsed_macro!(2596); + collapsed_macro!(2597); + collapsed_macro!(2598); + collapsed_macro!(2599); + collapsed_macro!(2600); + collapsed_macro!(2601); + collapsed_macro!(2602); + collapsed_macro!(2603); + collapsed_macro!(2604); + collapsed_macro!(2605); + collapsed_macro!(2606); + collapsed_macro!(2607); + collapsed_macro!(2608); + collapsed_macro!(2609); + collapsed_macro!(2610); + collapsed_macro!(2611); + collapsed_macro!(2612); + collapsed_macro!(2613); + collapsed_macro!(2614); + collapsed_macro!(2615); + collapsed_macro!(2616); + collapsed_macro!(2617); + collapsed_macro!(2618); + collapsed_macro!(2619); + collapsed_macro!(2620); + collapsed_macro!(2621); + collapsed_macro!(2622); + collapsed_macro!(2623); + collapsed_macro!(2624); + collapsed_macro!(2625); + collapsed_macro!(2626); + collapsed_macro!(2627); + collapsed_macro!(2628); + collapsed_macro!(2629); + collapsed_macro!(2630); + collapsed_macro!(2631); + collapsed_macro!(2632); + collapsed_macro!(2633); + collapsed_macro!(2634); + collapsed_macro!(2635); + collapsed_macro!(2636); + collapsed_macro!(2637); + collapsed_macro!(2638); + collapsed_macro!(2639); + collapsed_macro!(2640); + collapsed_macro!(2641); + collapsed_macro!(2642); + collapsed_macro!(2643); + collapsed_macro!(2644); + collapsed_macro!(2645); + collapsed_macro!(2646); + collapsed_macro!(2647); + collapsed_macro!(2648); + collapsed_macro!(2649); + collapsed_macro!(2650); + collapsed_macro!(2651); + collapsed_macro!(2652); + collapsed_macro!(2653); + collapsed_macro!(2654); + collapsed_macro!(2655); + collapsed_macro!(2656); + collapsed_macro!(2657); + collapsed_macro!(2658); + collapsed_macro!(2659); + collapsed_macro!(2660); + collapsed_macro!(2661); + collapsed_macro!(2662); + collapsed_macro!(2663); + collapsed_macro!(2664); + collapsed_macro!(2665); + collapsed_macro!(2666); + collapsed_macro!(2667); + collapsed_macro!(2668); + collapsed_macro!(2669); + collapsed_macro!(2670); + collapsed_macro!(2671); + collapsed_macro!(2672); + collapsed_macro!(2673); + collapsed_macro!(2674); + collapsed_macro!(2675); + collapsed_macro!(2676); + collapsed_macro!(2677); + collapsed_macro!(2678); + collapsed_macro!(2679); + collapsed_macro!(2680); + collapsed_macro!(2681); + collapsed_macro!(2682); + collapsed_macro!(2683); + collapsed_macro!(2684); + collapsed_macro!(2685); + collapsed_macro!(2686); + collapsed_macro!(2687); + collapsed_macro!(2688); + collapsed_macro!(2689); + collapsed_macro!(2690); + collapsed_macro!(2691); + collapsed_macro!(2692); + collapsed_macro!(2693); + collapsed_macro!(2694); + collapsed_macro!(2695); + collapsed_macro!(2696); + collapsed_macro!(2697); + collapsed_macro!(2698); + collapsed_macro!(2699); + collapsed_macro!(2700); + collapsed_macro!(2701); + collapsed_macro!(2702); + collapsed_macro!(2703); + collapsed_macro!(2704); + collapsed_macro!(2705); + collapsed_macro!(2706); + collapsed_macro!(2707); + collapsed_macro!(2708); + collapsed_macro!(2709); + collapsed_macro!(2710); + collapsed_macro!(2711); + collapsed_macro!(2712); + collapsed_macro!(2713); + collapsed_macro!(2714); + collapsed_macro!(2715); + collapsed_macro!(2716); + collapsed_macro!(2717); + collapsed_macro!(2718); + collapsed_macro!(2719); + collapsed_macro!(2720); + collapsed_macro!(2721); + collapsed_macro!(2722); + collapsed_macro!(2723); + collapsed_macro!(2724); + collapsed_macro!(2725); + collapsed_macro!(2726); + collapsed_macro!(2727); + collapsed_macro!(2728); + collapsed_macro!(2729); + collapsed_macro!(2730); + collapsed_macro!(2731); + collapsed_macro!(2732); + collapsed_macro!(2733); + collapsed_macro!(2734); + collapsed_macro!(2735); + collapsed_macro!(2736); + collapsed_macro!(2737); + collapsed_macro!(2738); + collapsed_macro!(2739); + collapsed_macro!(2740); + collapsed_macro!(2741); + collapsed_macro!(2742); + collapsed_macro!(2743); + collapsed_macro!(2744); + collapsed_macro!(2745); + collapsed_macro!(2746); + collapsed_macro!(2747); + collapsed_macro!(2748); + collapsed_macro!(2749); + collapsed_macro!(2750); + collapsed_macro!(2751); + collapsed_macro!(2752); + collapsed_macro!(2753); + collapsed_macro!(2754); + collapsed_macro!(2755); + collapsed_macro!(2756); + collapsed_macro!(2757); + collapsed_macro!(2758); + collapsed_macro!(2759); + collapsed_macro!(2760); + collapsed_macro!(2761); + collapsed_macro!(2762); + collapsed_macro!(2763); + collapsed_macro!(2764); + collapsed_macro!(2765); + collapsed_macro!(2766); + collapsed_macro!(2767); + collapsed_macro!(2768); + collapsed_macro!(2769); + collapsed_macro!(2770); + collapsed_macro!(2771); + collapsed_macro!(2772); + collapsed_macro!(2773); + collapsed_macro!(2774); + collapsed_macro!(2775); + collapsed_macro!(2776); + collapsed_macro!(2777); + collapsed_macro!(2778); + collapsed_macro!(2779); + collapsed_macro!(2780); + collapsed_macro!(2781); + collapsed_macro!(2782); + collapsed_macro!(2783); + collapsed_macro!(2784); + collapsed_macro!(2785); + collapsed_macro!(2786); + collapsed_macro!(2787); + collapsed_macro!(2788); + collapsed_macro!(2789); + collapsed_macro!(2790); + collapsed_macro!(2791); + collapsed_macro!(2792); + collapsed_macro!(2793); + collapsed_macro!(2794); + collapsed_macro!(2795); + collapsed_macro!(2796); + collapsed_macro!(2797); + collapsed_macro!(2798); + collapsed_macro!(2799); + collapsed_macro!(2800); + collapsed_macro!(2801); + collapsed_macro!(2802); + collapsed_macro!(2803); + collapsed_macro!(2804); + collapsed_macro!(2805); + collapsed_macro!(2806); + collapsed_macro!(2807); + collapsed_macro!(2808); + collapsed_macro!(2809); + collapsed_macro!(2810); + collapsed_macro!(2811); + collapsed_macro!(2812); + collapsed_macro!(2813); + collapsed_macro!(2814); + collapsed_macro!(2815); + collapsed_macro!(2816); + collapsed_macro!(2817); + collapsed_macro!(2818); + collapsed_macro!(2819); + collapsed_macro!(2820); + collapsed_macro!(2821); + collapsed_macro!(2822); + collapsed_macro!(2823); + collapsed_macro!(2824); + collapsed_macro!(2825); + collapsed_macro!(2826); + collapsed_macro!(2827); + collapsed_macro!(2828); + collapsed_macro!(2829); + collapsed_macro!(2830); + collapsed_macro!(2831); + collapsed_macro!(2832); + collapsed_macro!(2833); + collapsed_macro!(2834); + collapsed_macro!(2835); + collapsed_macro!(2836); + collapsed_macro!(2837); + collapsed_macro!(2838); + collapsed_macro!(2839); + collapsed_macro!(2840); + collapsed_macro!(2841); + collapsed_macro!(2842); + collapsed_macro!(2843); + collapsed_macro!(2844); + collapsed_macro!(2845); + collapsed_macro!(2846); + collapsed_macro!(2847); + collapsed_macro!(2848); + collapsed_macro!(2849); + collapsed_macro!(2850); + collapsed_macro!(2851); + collapsed_macro!(2852); + collapsed_macro!(2853); + collapsed_macro!(2854); + collapsed_macro!(2855); + collapsed_macro!(2856); + collapsed_macro!(2857); + collapsed_macro!(2858); + collapsed_macro!(2859); + collapsed_macro!(2860); + collapsed_macro!(2861); + collapsed_macro!(2862); + collapsed_macro!(2863); + collapsed_macro!(2864); + collapsed_macro!(2865); + collapsed_macro!(2866); + collapsed_macro!(2867); + collapsed_macro!(2868); + collapsed_macro!(2869); + collapsed_macro!(2870); + collapsed_macro!(2871); + collapsed_macro!(2872); + collapsed_macro!(2873); + collapsed_macro!(2874); + collapsed_macro!(2875); + collapsed_macro!(2876); + collapsed_macro!(2877); + collapsed_macro!(2878); + collapsed_macro!(2879); + collapsed_macro!(2880); + collapsed_macro!(2881); + collapsed_macro!(2882); + collapsed_macro!(2883); + collapsed_macro!(2884); + collapsed_macro!(2885); + collapsed_macro!(2886); + collapsed_macro!(2887); + collapsed_macro!(2888); + collapsed_macro!(2889); + collapsed_macro!(2890); + collapsed_macro!(2891); + collapsed_macro!(2892); + collapsed_macro!(2893); + collapsed_macro!(2894); + collapsed_macro!(2895); + collapsed_macro!(2896); + collapsed_macro!(2897); + collapsed_macro!(2898); + collapsed_macro!(2899); + collapsed_macro!(2900); + collapsed_macro!(2901); + collapsed_macro!(2902); + collapsed_macro!(2903); + collapsed_macro!(2904); + collapsed_macro!(2905); + collapsed_macro!(2906); + collapsed_macro!(2907); + collapsed_macro!(2908); + collapsed_macro!(2909); + collapsed_macro!(2910); + collapsed_macro!(2911); + collapsed_macro!(2912); + collapsed_macro!(2913); + collapsed_macro!(2914); + collapsed_macro!(2915); + collapsed_macro!(2916); + collapsed_macro!(2917); + collapsed_macro!(2918); + collapsed_macro!(2919); + collapsed_macro!(2920); + collapsed_macro!(2921); + collapsed_macro!(2922); + collapsed_macro!(2923); + collapsed_macro!(2924); + collapsed_macro!(2925); + collapsed_macro!(2926); + collapsed_macro!(2927); + collapsed_macro!(2928); + collapsed_macro!(2929); + collapsed_macro!(2930); + collapsed_macro!(2931); + collapsed_macro!(2932); + collapsed_macro!(2933); + collapsed_macro!(2934); + collapsed_macro!(2935); + collapsed_macro!(2936); + collapsed_macro!(2937); + collapsed_macro!(2938); + collapsed_macro!(2939); + collapsed_macro!(2940); + collapsed_macro!(2941); + collapsed_macro!(2942); + collapsed_macro!(2943); + collapsed_macro!(2944); + collapsed_macro!(2945); + collapsed_macro!(2946); + collapsed_macro!(2947); + collapsed_macro!(2948); + collapsed_macro!(2949); + collapsed_macro!(2950); + collapsed_macro!(2951); + collapsed_macro!(2952); + collapsed_macro!(2953); + collapsed_macro!(2954); + collapsed_macro!(2955); + collapsed_macro!(2956); + collapsed_macro!(2957); + collapsed_macro!(2958); + collapsed_macro!(2959); + collapsed_macro!(2960); + collapsed_macro!(2961); + collapsed_macro!(2962); + collapsed_macro!(2963); + collapsed_macro!(2964); + collapsed_macro!(2965); + collapsed_macro!(2966); + collapsed_macro!(2967); + collapsed_macro!(2968); + collapsed_macro!(2969); + collapsed_macro!(2970); + collapsed_macro!(2971); + collapsed_macro!(2972); + collapsed_macro!(2973); + collapsed_macro!(2974); + collapsed_macro!(2975); + collapsed_macro!(2976); + collapsed_macro!(2977); + collapsed_macro!(2978); + collapsed_macro!(2979); + collapsed_macro!(2980); + collapsed_macro!(2981); + collapsed_macro!(2982); + collapsed_macro!(2983); + collapsed_macro!(2984); + collapsed_macro!(2985); + collapsed_macro!(2986); + collapsed_macro!(2987); + collapsed_macro!(2988); + collapsed_macro!(2989); + collapsed_macro!(2990); + collapsed_macro!(2991); + collapsed_macro!(2992); + collapsed_macro!(2993); + collapsed_macro!(2994); + collapsed_macro!(2995); + collapsed_macro!(2996); + collapsed_macro!(2997); + collapsed_macro!(2998); + collapsed_macro!(2999); + collapsed_macro!(3000); + collapsed_macro!(3001); + collapsed_macro!(3002); + collapsed_macro!(3003); + collapsed_macro!(3004); + collapsed_macro!(3005); + collapsed_macro!(3006); + collapsed_macro!(3007); + collapsed_macro!(3008); + collapsed_macro!(3009); + collapsed_macro!(3010); + collapsed_macro!(3011); + collapsed_macro!(3012); + collapsed_macro!(3013); + collapsed_macro!(3014); + collapsed_macro!(3015); + collapsed_macro!(3016); + collapsed_macro!(3017); + collapsed_macro!(3018); + collapsed_macro!(3019); + collapsed_macro!(3020); + collapsed_macro!(3021); + collapsed_macro!(3022); + collapsed_macro!(3023); + collapsed_macro!(3024); + collapsed_macro!(3025); + collapsed_macro!(3026); + collapsed_macro!(3027); + collapsed_macro!(3028); + collapsed_macro!(3029); + collapsed_macro!(3030); + collapsed_macro!(3031); + collapsed_macro!(3032); + collapsed_macro!(3033); + collapsed_macro!(3034); + collapsed_macro!(3035); + collapsed_macro!(3036); + collapsed_macro!(3037); + collapsed_macro!(3038); + collapsed_macro!(3039); + collapsed_macro!(3040); + collapsed_macro!(3041); + collapsed_macro!(3042); + collapsed_macro!(3043); + collapsed_macro!(3044); + collapsed_macro!(3045); + collapsed_macro!(3046); + collapsed_macro!(3047); + collapsed_macro!(3048); + collapsed_macro!(3049); + collapsed_macro!(3050); + collapsed_macro!(3051); + collapsed_macro!(3052); + collapsed_macro!(3053); + collapsed_macro!(3054); + collapsed_macro!(3055); + collapsed_macro!(3056); + collapsed_macro!(3057); + collapsed_macro!(3058); + collapsed_macro!(3059); + collapsed_macro!(3060); + collapsed_macro!(3061); + collapsed_macro!(3062); + collapsed_macro!(3063); + collapsed_macro!(3064); + collapsed_macro!(3065); + collapsed_macro!(3066); + collapsed_macro!(3067); + collapsed_macro!(3068); + collapsed_macro!(3069); + collapsed_macro!(3070); + collapsed_macro!(3071); + collapsed_macro!(3072); + collapsed_macro!(3073); + collapsed_macro!(3074); + collapsed_macro!(3075); + collapsed_macro!(3076); + collapsed_macro!(3077); + collapsed_macro!(3078); + collapsed_macro!(3079); + collapsed_macro!(3080); + collapsed_macro!(3081); + collapsed_macro!(3082); + collapsed_macro!(3083); + collapsed_macro!(3084); + collapsed_macro!(3085); + collapsed_macro!(3086); + collapsed_macro!(3087); + collapsed_macro!(3088); + collapsed_macro!(3089); + collapsed_macro!(3090); + collapsed_macro!(3091); + collapsed_macro!(3092); + collapsed_macro!(3093); + collapsed_macro!(3094); + collapsed_macro!(3095); + collapsed_macro!(3096); + collapsed_macro!(3097); + collapsed_macro!(3098); + collapsed_macro!(3099); + collapsed_macro!(3100); + collapsed_macro!(3101); + collapsed_macro!(3102); + collapsed_macro!(3103); + collapsed_macro!(3104); + collapsed_macro!(3105); + collapsed_macro!(3106); + collapsed_macro!(3107); + collapsed_macro!(3108); + collapsed_macro!(3109); + collapsed_macro!(3110); + collapsed_macro!(3111); + collapsed_macro!(3112); + collapsed_macro!(3113); + collapsed_macro!(3114); + collapsed_macro!(3115); + collapsed_macro!(3116); + collapsed_macro!(3117); + collapsed_macro!(3118); + collapsed_macro!(3119); + collapsed_macro!(3120); + collapsed_macro!(3121); + collapsed_macro!(3122); + collapsed_macro!(3123); + collapsed_macro!(3124); + collapsed_macro!(3125); + collapsed_macro!(3126); + collapsed_macro!(3127); + collapsed_macro!(3128); + collapsed_macro!(3129); + collapsed_macro!(3130); + collapsed_macro!(3131); + collapsed_macro!(3132); + collapsed_macro!(3133); + collapsed_macro!(3134); + collapsed_macro!(3135); + collapsed_macro!(3136); + collapsed_macro!(3137); + collapsed_macro!(3138); + collapsed_macro!(3139); + collapsed_macro!(3140); + collapsed_macro!(3141); + collapsed_macro!(3142); + collapsed_macro!(3143); + collapsed_macro!(3144); + collapsed_macro!(3145); + collapsed_macro!(3146); + collapsed_macro!(3147); + collapsed_macro!(3148); + collapsed_macro!(3149); + collapsed_macro!(3150); + collapsed_macro!(3151); + collapsed_macro!(3152); + collapsed_macro!(3153); + collapsed_macro!(3154); + collapsed_macro!(3155); + collapsed_macro!(3156); + collapsed_macro!(3157); + collapsed_macro!(3158); + collapsed_macro!(3159); + collapsed_macro!(3160); + collapsed_macro!(3161); + collapsed_macro!(3162); + collapsed_macro!(3163); + collapsed_macro!(3164); + collapsed_macro!(3165); + collapsed_macro!(3166); + collapsed_macro!(3167); + collapsed_macro!(3168); + collapsed_macro!(3169); + collapsed_macro!(3170); + collapsed_macro!(3171); + collapsed_macro!(3172); + collapsed_macro!(3173); + collapsed_macro!(3174); + collapsed_macro!(3175); + collapsed_macro!(3176); + collapsed_macro!(3177); + collapsed_macro!(3178); + collapsed_macro!(3179); + collapsed_macro!(3180); + collapsed_macro!(3181); + collapsed_macro!(3182); + collapsed_macro!(3183); + collapsed_macro!(3184); + collapsed_macro!(3185); + collapsed_macro!(3186); + collapsed_macro!(3187); + collapsed_macro!(3188); + collapsed_macro!(3189); + collapsed_macro!(3190); + collapsed_macro!(3191); + collapsed_macro!(3192); + collapsed_macro!(3193); + collapsed_macro!(3194); + collapsed_macro!(3195); + collapsed_macro!(3196); + collapsed_macro!(3197); + collapsed_macro!(3198); + collapsed_macro!(3199); + collapsed_macro!(3200); + collapsed_macro!(3201); + collapsed_macro!(3202); + collapsed_macro!(3203); + collapsed_macro!(3204); + collapsed_macro!(3205); + collapsed_macro!(3206); + collapsed_macro!(3207); + collapsed_macro!(3208); + collapsed_macro!(3209); + collapsed_macro!(3210); + collapsed_macro!(3211); + collapsed_macro!(3212); + collapsed_macro!(3213); + collapsed_macro!(3214); + collapsed_macro!(3215); + collapsed_macro!(3216); + collapsed_macro!(3217); + collapsed_macro!(3218); + collapsed_macro!(3219); + collapsed_macro!(3220); + collapsed_macro!(3221); + collapsed_macro!(3222); + collapsed_macro!(3223); + collapsed_macro!(3224); + collapsed_macro!(3225); + collapsed_macro!(3226); + collapsed_macro!(3227); + collapsed_macro!(3228); + collapsed_macro!(3229); + collapsed_macro!(3230); + collapsed_macro!(3231); + collapsed_macro!(3232); + collapsed_macro!(3233); + collapsed_macro!(3234); + collapsed_macro!(3235); + collapsed_macro!(3236); + collapsed_macro!(3237); + collapsed_macro!(3238); + collapsed_macro!(3239); + collapsed_macro!(3240); + collapsed_macro!(3241); + collapsed_macro!(3242); + collapsed_macro!(3243); + collapsed_macro!(3244); + collapsed_macro!(3245); + collapsed_macro!(3246); + collapsed_macro!(3247); + collapsed_macro!(3248); + collapsed_macro!(3249); + collapsed_macro!(3250); + collapsed_macro!(3251); + collapsed_macro!(3252); + collapsed_macro!(3253); + collapsed_macro!(3254); + collapsed_macro!(3255); + collapsed_macro!(3256); + collapsed_macro!(3257); + collapsed_macro!(3258); + collapsed_macro!(3259); + collapsed_macro!(3260); + collapsed_macro!(3261); + collapsed_macro!(3262); + collapsed_macro!(3263); + collapsed_macro!(3264); + collapsed_macro!(3265); + collapsed_macro!(3266); + collapsed_macro!(3267); + collapsed_macro!(3268); + collapsed_macro!(3269); + collapsed_macro!(3270); + collapsed_macro!(3271); + collapsed_macro!(3272); + collapsed_macro!(3273); + collapsed_macro!(3274); + collapsed_macro!(3275); + collapsed_macro!(3276); + collapsed_macro!(3277); + collapsed_macro!(3278); + collapsed_macro!(3279); + collapsed_macro!(3280); + collapsed_macro!(3281); + collapsed_macro!(3282); + collapsed_macro!(3283); + collapsed_macro!(3284); + collapsed_macro!(3285); + collapsed_macro!(3286); + collapsed_macro!(3287); + collapsed_macro!(3288); + collapsed_macro!(3289); + collapsed_macro!(3290); + collapsed_macro!(3291); + collapsed_macro!(3292); + collapsed_macro!(3293); + collapsed_macro!(3294); + collapsed_macro!(3295); + collapsed_macro!(3296); + collapsed_macro!(3297); + collapsed_macro!(3298); + collapsed_macro!(3299); + collapsed_macro!(3300); + collapsed_macro!(3301); + collapsed_macro!(3302); + collapsed_macro!(3303); + collapsed_macro!(3304); + collapsed_macro!(3305); + collapsed_macro!(3306); + collapsed_macro!(3307); + collapsed_macro!(3308); + collapsed_macro!(3309); + collapsed_macro!(3310); + collapsed_macro!(3311); + collapsed_macro!(3312); + collapsed_macro!(3313); + collapsed_macro!(3314); + collapsed_macro!(3315); + collapsed_macro!(3316); + collapsed_macro!(3317); + collapsed_macro!(3318); + collapsed_macro!(3319); + collapsed_macro!(3320); + collapsed_macro!(3321); + collapsed_macro!(3322); + collapsed_macro!(3323); + collapsed_macro!(3324); + collapsed_macro!(3325); + collapsed_macro!(3326); + collapsed_macro!(3327); + collapsed_macro!(3328); + collapsed_macro!(3329); + collapsed_macro!(3330); + collapsed_macro!(3331); + collapsed_macro!(3332); + collapsed_macro!(3333); + collapsed_macro!(3334); + collapsed_macro!(3335); + collapsed_macro!(3336); + collapsed_macro!(3337); + collapsed_macro!(3338); + collapsed_macro!(3339); + collapsed_macro!(3340); + collapsed_macro!(3341); + collapsed_macro!(3342); + collapsed_macro!(3343); + collapsed_macro!(3344); + collapsed_macro!(3345); + collapsed_macro!(3346); + collapsed_macro!(3347); + collapsed_macro!(3348); + collapsed_macro!(3349); + collapsed_macro!(3350); + collapsed_macro!(3351); + collapsed_macro!(3352); + collapsed_macro!(3353); + collapsed_macro!(3354); + collapsed_macro!(3355); + collapsed_macro!(3356); + collapsed_macro!(3357); + collapsed_macro!(3358); + collapsed_macro!(3359); + collapsed_macro!(3360); + collapsed_macro!(3361); + collapsed_macro!(3362); + collapsed_macro!(3363); + collapsed_macro!(3364); + collapsed_macro!(3365); + collapsed_macro!(3366); + collapsed_macro!(3367); + collapsed_macro!(3368); + collapsed_macro!(3369); + collapsed_macro!(3370); + collapsed_macro!(3371); + collapsed_macro!(3372); + collapsed_macro!(3373); + collapsed_macro!(3374); + collapsed_macro!(3375); + collapsed_macro!(3376); + collapsed_macro!(3377); + collapsed_macro!(3378); + collapsed_macro!(3379); + collapsed_macro!(3380); + collapsed_macro!(3381); + collapsed_macro!(3382); + collapsed_macro!(3383); + collapsed_macro!(3384); + collapsed_macro!(3385); + collapsed_macro!(3386); + collapsed_macro!(3387); + collapsed_macro!(3388); + collapsed_macro!(3389); + collapsed_macro!(3390); + collapsed_macro!(3391); + collapsed_macro!(3392); + collapsed_macro!(3393); + collapsed_macro!(3394); + collapsed_macro!(3395); + collapsed_macro!(3396); + collapsed_macro!(3397); + collapsed_macro!(3398); + collapsed_macro!(3399); + collapsed_macro!(3400); + collapsed_macro!(3401); + collapsed_macro!(3402); + collapsed_macro!(3403); + collapsed_macro!(3404); + collapsed_macro!(3405); + collapsed_macro!(3406); + collapsed_macro!(3407); + collapsed_macro!(3408); + collapsed_macro!(3409); + collapsed_macro!(3410); + collapsed_macro!(3411); + collapsed_macro!(3412); + collapsed_macro!(3413); + collapsed_macro!(3414); + collapsed_macro!(3415); + collapsed_macro!(3416); + collapsed_macro!(3417); + collapsed_macro!(3418); + collapsed_macro!(3419); + collapsed_macro!(3420); + collapsed_macro!(3421); + collapsed_macro!(3422); + collapsed_macro!(3423); + collapsed_macro!(3424); + collapsed_macro!(3425); + collapsed_macro!(3426); + collapsed_macro!(3427); + collapsed_macro!(3428); + collapsed_macro!(3429); + collapsed_macro!(3430); + collapsed_macro!(3431); + collapsed_macro!(3432); + collapsed_macro!(3433); + collapsed_macro!(3434); + collapsed_macro!(3435); + collapsed_macro!(3436); + collapsed_macro!(3437); + collapsed_macro!(3438); + collapsed_macro!(3439); + collapsed_macro!(3440); + collapsed_macro!(3441); + collapsed_macro!(3442); + collapsed_macro!(3443); + collapsed_macro!(3444); + collapsed_macro!(3445); + collapsed_macro!(3446); + collapsed_macro!(3447); + collapsed_macro!(3448); + collapsed_macro!(3449); + collapsed_macro!(3450); + collapsed_macro!(3451); + collapsed_macro!(3452); + collapsed_macro!(3453); + collapsed_macro!(3454); + collapsed_macro!(3455); + collapsed_macro!(3456); + collapsed_macro!(3457); + collapsed_macro!(3458); + collapsed_macro!(3459); + collapsed_macro!(3460); + collapsed_macro!(3461); + collapsed_macro!(3462); + collapsed_macro!(3463); + collapsed_macro!(3464); + collapsed_macro!(3465); + collapsed_macro!(3466); + collapsed_macro!(3467); + collapsed_macro!(3468); + collapsed_macro!(3469); + collapsed_macro!(3470); + collapsed_macro!(3471); + collapsed_macro!(3472); + collapsed_macro!(3473); + collapsed_macro!(3474); + collapsed_macro!(3475); + collapsed_macro!(3476); + collapsed_macro!(3477); + collapsed_macro!(3478); + collapsed_macro!(3479); + collapsed_macro!(3480); + collapsed_macro!(3481); + collapsed_macro!(3482); + collapsed_macro!(3483); + collapsed_macro!(3484); + collapsed_macro!(3485); + collapsed_macro!(3486); + collapsed_macro!(3487); + collapsed_macro!(3488); + collapsed_macro!(3489); + collapsed_macro!(3490); + collapsed_macro!(3491); + collapsed_macro!(3492); + collapsed_macro!(3493); + collapsed_macro!(3494); + collapsed_macro!(3495); + collapsed_macro!(3496); + collapsed_macro!(3497); + collapsed_macro!(3498); + collapsed_macro!(3499); + collapsed_macro!(3500); + collapsed_macro!(3501); + collapsed_macro!(3502); + collapsed_macro!(3503); + collapsed_macro!(3504); + collapsed_macro!(3505); + collapsed_macro!(3506); + collapsed_macro!(3507); + collapsed_macro!(3508); + collapsed_macro!(3509); + collapsed_macro!(3510); + collapsed_macro!(3511); + collapsed_macro!(3512); + collapsed_macro!(3513); + collapsed_macro!(3514); + collapsed_macro!(3515); + collapsed_macro!(3516); + collapsed_macro!(3517); + collapsed_macro!(3518); + collapsed_macro!(3519); + collapsed_macro!(3520); + collapsed_macro!(3521); + collapsed_macro!(3522); + collapsed_macro!(3523); + collapsed_macro!(3524); + collapsed_macro!(3525); + collapsed_macro!(3526); + collapsed_macro!(3527); + collapsed_macro!(3528); + collapsed_macro!(3529); + collapsed_macro!(3530); + collapsed_macro!(3531); + collapsed_macro!(3532); + collapsed_macro!(3533); + collapsed_macro!(3534); + collapsed_macro!(3535); + collapsed_macro!(3536); + collapsed_macro!(3537); + collapsed_macro!(3538); + collapsed_macro!(3539); + collapsed_macro!(3540); + collapsed_macro!(3541); + collapsed_macro!(3542); + collapsed_macro!(3543); + collapsed_macro!(3544); + collapsed_macro!(3545); + collapsed_macro!(3546); + collapsed_macro!(3547); + collapsed_macro!(3548); + collapsed_macro!(3549); + collapsed_macro!(3550); + collapsed_macro!(3551); + collapsed_macro!(3552); + collapsed_macro!(3553); + collapsed_macro!(3554); + collapsed_macro!(3555); + collapsed_macro!(3556); + collapsed_macro!(3557); + collapsed_macro!(3558); + collapsed_macro!(3559); + collapsed_macro!(3560); + collapsed_macro!(3561); + collapsed_macro!(3562); + collapsed_macro!(3563); + collapsed_macro!(3564); + collapsed_macro!(3565); + collapsed_macro!(3566); + collapsed_macro!(3567); + collapsed_macro!(3568); + collapsed_macro!(3569); + collapsed_macro!(3570); + collapsed_macro!(3571); + collapsed_macro!(3572); + collapsed_macro!(3573); + collapsed_macro!(3574); + collapsed_macro!(3575); + collapsed_macro!(3576); + collapsed_macro!(3577); + collapsed_macro!(3578); + collapsed_macro!(3579); + collapsed_macro!(3580); + collapsed_macro!(3581); + collapsed_macro!(3582); + collapsed_macro!(3583); + collapsed_macro!(3584); + collapsed_macro!(3585); + collapsed_macro!(3586); + collapsed_macro!(3587); + collapsed_macro!(3588); + collapsed_macro!(3589); + collapsed_macro!(3590); + collapsed_macro!(3591); + collapsed_macro!(3592); + collapsed_macro!(3593); + collapsed_macro!(3594); + collapsed_macro!(3595); + collapsed_macro!(3596); + collapsed_macro!(3597); + collapsed_macro!(3598); + collapsed_macro!(3599); + collapsed_macro!(3600); + collapsed_macro!(3601); + collapsed_macro!(3602); + collapsed_macro!(3603); + collapsed_macro!(3604); + collapsed_macro!(3605); + collapsed_macro!(3606); + collapsed_macro!(3607); + collapsed_macro!(3608); + collapsed_macro!(3609); + collapsed_macro!(3610); + collapsed_macro!(3611); + collapsed_macro!(3612); + collapsed_macro!(3613); + collapsed_macro!(3614); + collapsed_macro!(3615); + collapsed_macro!(3616); + collapsed_macro!(3617); + collapsed_macro!(3618); + collapsed_macro!(3619); + collapsed_macro!(3620); + collapsed_macro!(3621); + collapsed_macro!(3622); + collapsed_macro!(3623); + collapsed_macro!(3624); + collapsed_macro!(3625); + collapsed_macro!(3626); + collapsed_macro!(3627); + collapsed_macro!(3628); + collapsed_macro!(3629); + collapsed_macro!(3630); + collapsed_macro!(3631); + collapsed_macro!(3632); + collapsed_macro!(3633); + collapsed_macro!(3634); + collapsed_macro!(3635); + collapsed_macro!(3636); + collapsed_macro!(3637); + collapsed_macro!(3638); + collapsed_macro!(3639); + collapsed_macro!(3640); + collapsed_macro!(3641); + collapsed_macro!(3642); + collapsed_macro!(3643); + collapsed_macro!(3644); + collapsed_macro!(3645); + collapsed_macro!(3646); + collapsed_macro!(3647); + collapsed_macro!(3648); + collapsed_macro!(3649); + collapsed_macro!(3650); + collapsed_macro!(3651); + collapsed_macro!(3652); + collapsed_macro!(3653); + collapsed_macro!(3654); + collapsed_macro!(3655); + collapsed_macro!(3656); + collapsed_macro!(3657); + collapsed_macro!(3658); + collapsed_macro!(3659); + collapsed_macro!(3660); + collapsed_macro!(3661); + collapsed_macro!(3662); + collapsed_macro!(3663); + collapsed_macro!(3664); + collapsed_macro!(3665); + collapsed_macro!(3666); + collapsed_macro!(3667); + collapsed_macro!(3668); + collapsed_macro!(3669); + collapsed_macro!(3670); + collapsed_macro!(3671); + collapsed_macro!(3672); + collapsed_macro!(3673); + collapsed_macro!(3674); + collapsed_macro!(3675); + collapsed_macro!(3676); + collapsed_macro!(3677); + collapsed_macro!(3678); + collapsed_macro!(3679); + collapsed_macro!(3680); + collapsed_macro!(3681); + collapsed_macro!(3682); + collapsed_macro!(3683); + collapsed_macro!(3684); + collapsed_macro!(3685); + collapsed_macro!(3686); + collapsed_macro!(3687); + collapsed_macro!(3688); + collapsed_macro!(3689); + collapsed_macro!(3690); + collapsed_macro!(3691); + collapsed_macro!(3692); + collapsed_macro!(3693); + collapsed_macro!(3694); + collapsed_macro!(3695); + collapsed_macro!(3696); + collapsed_macro!(3697); + collapsed_macro!(3698); + collapsed_macro!(3699); + collapsed_macro!(3700); + collapsed_macro!(3701); + collapsed_macro!(3702); + collapsed_macro!(3703); + collapsed_macro!(3704); + collapsed_macro!(3705); + collapsed_macro!(3706); + collapsed_macro!(3707); + collapsed_macro!(3708); + collapsed_macro!(3709); + collapsed_macro!(3710); + collapsed_macro!(3711); + collapsed_macro!(3712); + collapsed_macro!(3713); + collapsed_macro!(3714); + collapsed_macro!(3715); + collapsed_macro!(3716); + collapsed_macro!(3717); + collapsed_macro!(3718); + collapsed_macro!(3719); + collapsed_macro!(3720); + collapsed_macro!(3721); + collapsed_macro!(3722); + collapsed_macro!(3723); + collapsed_macro!(3724); + collapsed_macro!(3725); + collapsed_macro!(3726); + collapsed_macro!(3727); + collapsed_macro!(3728); + collapsed_macro!(3729); + collapsed_macro!(3730); + collapsed_macro!(3731); + collapsed_macro!(3732); + collapsed_macro!(3733); + collapsed_macro!(3734); + collapsed_macro!(3735); + collapsed_macro!(3736); + collapsed_macro!(3737); + collapsed_macro!(3738); + collapsed_macro!(3739); + collapsed_macro!(3740); + collapsed_macro!(3741); + collapsed_macro!(3742); + collapsed_macro!(3743); + collapsed_macro!(3744); + collapsed_macro!(3745); + collapsed_macro!(3746); + collapsed_macro!(3747); + collapsed_macro!(3748); + collapsed_macro!(3749); + collapsed_macro!(3750); + collapsed_macro!(3751); + collapsed_macro!(3752); + collapsed_macro!(3753); + collapsed_macro!(3754); + collapsed_macro!(3755); + collapsed_macro!(3756); + collapsed_macro!(3757); + collapsed_macro!(3758); + collapsed_macro!(3759); + collapsed_macro!(3760); + collapsed_macro!(3761); + collapsed_macro!(3762); + collapsed_macro!(3763); + collapsed_macro!(3764); + collapsed_macro!(3765); + collapsed_macro!(3766); + collapsed_macro!(3767); + collapsed_macro!(3768); + collapsed_macro!(3769); + collapsed_macro!(3770); + collapsed_macro!(3771); + collapsed_macro!(3772); + collapsed_macro!(3773); + collapsed_macro!(3774); + collapsed_macro!(3775); + collapsed_macro!(3776); + collapsed_macro!(3777); + collapsed_macro!(3778); + collapsed_macro!(3779); + collapsed_macro!(3780); + collapsed_macro!(3781); + collapsed_macro!(3782); + collapsed_macro!(3783); + collapsed_macro!(3784); + collapsed_macro!(3785); + collapsed_macro!(3786); + collapsed_macro!(3787); + collapsed_macro!(3788); + collapsed_macro!(3789); + collapsed_macro!(3790); + collapsed_macro!(3791); + collapsed_macro!(3792); + collapsed_macro!(3793); + collapsed_macro!(3794); + collapsed_macro!(3795); + collapsed_macro!(3796); + collapsed_macro!(3797); + collapsed_macro!(3798); + collapsed_macro!(3799); + collapsed_macro!(3800); + collapsed_macro!(3801); + collapsed_macro!(3802); + collapsed_macro!(3803); + collapsed_macro!(3804); + collapsed_macro!(3805); + collapsed_macro!(3806); + collapsed_macro!(3807); + collapsed_macro!(3808); + collapsed_macro!(3809); + collapsed_macro!(3810); + collapsed_macro!(3811); + collapsed_macro!(3812); + collapsed_macro!(3813); + collapsed_macro!(3814); + collapsed_macro!(3815); + collapsed_macro!(3816); + collapsed_macro!(3817); + collapsed_macro!(3818); + collapsed_macro!(3819); + collapsed_macro!(3820); + collapsed_macro!(3821); + collapsed_macro!(3822); + collapsed_macro!(3823); + collapsed_macro!(3824); + collapsed_macro!(3825); + collapsed_macro!(3826); + collapsed_macro!(3827); + collapsed_macro!(3828); + collapsed_macro!(3829); + collapsed_macro!(3830); + collapsed_macro!(3831); + collapsed_macro!(3832); + collapsed_macro!(3833); + collapsed_macro!(3834); + collapsed_macro!(3835); + collapsed_macro!(3836); + collapsed_macro!(3837); + collapsed_macro!(3838); + collapsed_macro!(3839); + collapsed_macro!(3840); + collapsed_macro!(3841); + collapsed_macro!(3842); + collapsed_macro!(3843); + collapsed_macro!(3844); + collapsed_macro!(3845); + collapsed_macro!(3846); + collapsed_macro!(3847); + collapsed_macro!(3848); + collapsed_macro!(3849); + collapsed_macro!(3850); + collapsed_macro!(3851); + collapsed_macro!(3852); + collapsed_macro!(3853); + collapsed_macro!(3854); + collapsed_macro!(3855); + collapsed_macro!(3856); + collapsed_macro!(3857); + collapsed_macro!(3858); + collapsed_macro!(3859); + collapsed_macro!(3860); + collapsed_macro!(3861); + collapsed_macro!(3862); + collapsed_macro!(3863); + collapsed_macro!(3864); + collapsed_macro!(3865); + collapsed_macro!(3866); + collapsed_macro!(3867); + collapsed_macro!(3868); + collapsed_macro!(3869); + collapsed_macro!(3870); + collapsed_macro!(3871); + collapsed_macro!(3872); + collapsed_macro!(3873); + collapsed_macro!(3874); + collapsed_macro!(3875); + collapsed_macro!(3876); + collapsed_macro!(3877); + collapsed_macro!(3878); + collapsed_macro!(3879); + collapsed_macro!(3880); + collapsed_macro!(3881); + collapsed_macro!(3882); + collapsed_macro!(3883); + collapsed_macro!(3884); + collapsed_macro!(3885); + collapsed_macro!(3886); + collapsed_macro!(3887); + collapsed_macro!(3888); + collapsed_macro!(3889); + collapsed_macro!(3890); + collapsed_macro!(3891); + collapsed_macro!(3892); + collapsed_macro!(3893); + collapsed_macro!(3894); + collapsed_macro!(3895); + collapsed_macro!(3896); + collapsed_macro!(3897); + collapsed_macro!(3898); + collapsed_macro!(3899); + collapsed_macro!(3900); + collapsed_macro!(3901); + collapsed_macro!(3902); + collapsed_macro!(3903); + collapsed_macro!(3904); + collapsed_macro!(3905); + collapsed_macro!(3906); + collapsed_macro!(3907); + collapsed_macro!(3908); + collapsed_macro!(3909); + collapsed_macro!(3910); + collapsed_macro!(3911); + collapsed_macro!(3912); + collapsed_macro!(3913); + collapsed_macro!(3914); + collapsed_macro!(3915); + collapsed_macro!(3916); + collapsed_macro!(3917); + collapsed_macro!(3918); + collapsed_macro!(3919); + collapsed_macro!(3920); + collapsed_macro!(3921); + collapsed_macro!(3922); + collapsed_macro!(3923); + collapsed_macro!(3924); + collapsed_macro!(3925); + collapsed_macro!(3926); + collapsed_macro!(3927); + collapsed_macro!(3928); + collapsed_macro!(3929); + collapsed_macro!(3930); + collapsed_macro!(3931); + collapsed_macro!(3932); + collapsed_macro!(3933); + collapsed_macro!(3934); + collapsed_macro!(3935); + collapsed_macro!(3936); + collapsed_macro!(3937); + collapsed_macro!(3938); + collapsed_macro!(3939); + collapsed_macro!(3940); + collapsed_macro!(3941); + collapsed_macro!(3942); + collapsed_macro!(3943); + collapsed_macro!(3944); + collapsed_macro!(3945); + collapsed_macro!(3946); + collapsed_macro!(3947); + collapsed_macro!(3948); + collapsed_macro!(3949); + collapsed_macro!(3950); + collapsed_macro!(3951); + collapsed_macro!(3952); + collapsed_macro!(3953); + collapsed_macro!(3954); + collapsed_macro!(3955); + collapsed_macro!(3956); + collapsed_macro!(3957); + collapsed_macro!(3958); + collapsed_macro!(3959); + collapsed_macro!(3960); + collapsed_macro!(3961); + collapsed_macro!(3962); + collapsed_macro!(3963); + collapsed_macro!(3964); + collapsed_macro!(3965); + collapsed_macro!(3966); + collapsed_macro!(3967); + collapsed_macro!(3968); + collapsed_macro!(3969); + collapsed_macro!(3970); + collapsed_macro!(3971); + collapsed_macro!(3972); + collapsed_macro!(3973); + collapsed_macro!(3974); + collapsed_macro!(3975); + collapsed_macro!(3976); + collapsed_macro!(3977); + collapsed_macro!(3978); + collapsed_macro!(3979); + collapsed_macro!(3980); + collapsed_macro!(3981); + collapsed_macro!(3982); + collapsed_macro!(3983); + collapsed_macro!(3984); + collapsed_macro!(3985); + collapsed_macro!(3986); + collapsed_macro!(3987); + collapsed_macro!(3988); + collapsed_macro!(3989); + collapsed_macro!(3990); + collapsed_macro!(3991); + collapsed_macro!(3992); + collapsed_macro!(3993); + collapsed_macro!(3994); + collapsed_macro!(3995); + collapsed_macro!(3996); + collapsed_macro!(3997); + collapsed_macro!(3998); + collapsed_macro!(3999); + collapsed_macro!(4000); + collapsed_macro!(4001); + collapsed_macro!(4002); + collapsed_macro!(4003); + collapsed_macro!(4004); + collapsed_macro!(4005); + collapsed_macro!(4006); + collapsed_macro!(4007); + collapsed_macro!(4008); + collapsed_macro!(4009); + collapsed_macro!(4010); + collapsed_macro!(4011); + collapsed_macro!(4012); + collapsed_macro!(4013); + collapsed_macro!(4014); + collapsed_macro!(4015); + collapsed_macro!(4016); + collapsed_macro!(4017); + collapsed_macro!(4018); + collapsed_macro!(4019); + collapsed_macro!(4020); + collapsed_macro!(4021); + collapsed_macro!(4022); + collapsed_macro!(4023); + collapsed_macro!(4024); + collapsed_macro!(4025); + collapsed_macro!(4026); + collapsed_macro!(4027); + collapsed_macro!(4028); + collapsed_macro!(4029); + collapsed_macro!(4030); + collapsed_macro!(4031); + collapsed_macro!(4032); + collapsed_macro!(4033); + collapsed_macro!(4034); + collapsed_macro!(4035); + collapsed_macro!(4036); + collapsed_macro!(4037); + collapsed_macro!(4038); + collapsed_macro!(4039); + collapsed_macro!(4040); + collapsed_macro!(4041); + collapsed_macro!(4042); + collapsed_macro!(4043); + collapsed_macro!(4044); + collapsed_macro!(4045); + collapsed_macro!(4046); + collapsed_macro!(4047); + collapsed_macro!(4048); + collapsed_macro!(4049); + collapsed_macro!(4050); + collapsed_macro!(4051); + collapsed_macro!(4052); + collapsed_macro!(4053); + collapsed_macro!(4054); + collapsed_macro!(4055); + collapsed_macro!(4056); + collapsed_macro!(4057); + collapsed_macro!(4058); + collapsed_macro!(4059); + collapsed_macro!(4060); + collapsed_macro!(4061); + collapsed_macro!(4062); + collapsed_macro!(4063); + collapsed_macro!(4064); + collapsed_macro!(4065); + collapsed_macro!(4066); + collapsed_macro!(4067); + collapsed_macro!(4068); + collapsed_macro!(4069); + collapsed_macro!(4070); + collapsed_macro!(4071); + collapsed_macro!(4072); + collapsed_macro!(4073); + collapsed_macro!(4074); + collapsed_macro!(4075); + collapsed_macro!(4076); + collapsed_macro!(4077); + collapsed_macro!(4078); + collapsed_macro!(4079); + collapsed_macro!(4080); + collapsed_macro!(4081); + collapsed_macro!(4082); + collapsed_macro!(4083); + collapsed_macro!(4084); + collapsed_macro!(4085); + collapsed_macro!(4086); + collapsed_macro!(4087); + collapsed_macro!(4088); + collapsed_macro!(4089); + collapsed_macro!(4090); + collapsed_macro!(4091); + collapsed_macro!(4092); + collapsed_macro!(4093); + collapsed_macro!(4094); + collapsed_macro!(4095); + collapsed_macro!(4096); + collapsed_macro!(4097); +} + +fn main() { + collapsed_debuginfo(); +} diff --git a/tests/ui/debuginfo/debuginfo-inline-callsite-location-macro-2.rs b/tests/ui/debuginfo/debuginfo-inline-callsite-location-macro-2.rs new file mode 100644 index 000000000000..3696ed37a204 --- /dev/null +++ b/tests/ui/debuginfo/debuginfo-inline-callsite-location-macro-2.rs @@ -0,0 +1,4122 @@ +//@ check-pass +//@ compile-flags: -Cdebuginfo=2 -Copt-level=0 -Zmir-enable-passes=+Inline +//@ ignore-msvc +// ignore-tidy-filelength + +#[derive(Default)] +struct Something {} + +macro_rules! simple_macro { + ($code:expr) => { + // Important to use a function here, so it can be inlined + // at the MIR stage. + Something::default() + } +} + +fn uncollapsed_debuginfo() { + // LLVM allows 12 bits for encoding discriminators, so 4096+1 calls to a + // MIR-inlined function will exhaust it. At that point we will start + // dropping debug info (and tracing::warn!). + simple_macro!(1); + simple_macro!(2); + simple_macro!(3); + simple_macro!(4); + simple_macro!(5); + simple_macro!(6); + simple_macro!(7); + simple_macro!(8); + simple_macro!(9); + simple_macro!(10); + simple_macro!(11); + simple_macro!(12); + simple_macro!(13); + simple_macro!(14); + simple_macro!(15); + simple_macro!(16); + simple_macro!(17); + simple_macro!(18); + simple_macro!(19); + simple_macro!(20); + simple_macro!(21); + simple_macro!(22); + simple_macro!(23); + simple_macro!(24); + simple_macro!(25); + simple_macro!(26); + simple_macro!(27); + simple_macro!(28); + simple_macro!(29); + simple_macro!(30); + simple_macro!(31); + simple_macro!(32); + simple_macro!(33); + simple_macro!(34); + simple_macro!(35); + simple_macro!(36); + simple_macro!(37); + simple_macro!(38); + simple_macro!(39); + simple_macro!(40); + simple_macro!(41); + simple_macro!(42); + simple_macro!(43); + simple_macro!(44); + simple_macro!(45); + simple_macro!(46); + simple_macro!(47); + simple_macro!(48); + simple_macro!(49); + simple_macro!(50); + simple_macro!(51); + simple_macro!(52); + simple_macro!(53); + simple_macro!(54); + simple_macro!(55); + simple_macro!(56); + simple_macro!(57); + simple_macro!(58); + simple_macro!(59); + simple_macro!(60); + simple_macro!(61); + simple_macro!(62); + simple_macro!(63); + simple_macro!(64); + simple_macro!(65); + simple_macro!(66); + simple_macro!(67); + simple_macro!(68); + simple_macro!(69); + simple_macro!(70); + simple_macro!(71); + simple_macro!(72); + simple_macro!(73); + simple_macro!(74); + simple_macro!(75); + simple_macro!(76); + simple_macro!(77); + simple_macro!(78); + simple_macro!(79); + simple_macro!(80); + simple_macro!(81); + simple_macro!(82); + simple_macro!(83); + simple_macro!(84); + simple_macro!(85); + simple_macro!(86); + simple_macro!(87); + simple_macro!(88); + simple_macro!(89); + simple_macro!(90); + simple_macro!(91); + simple_macro!(92); + simple_macro!(93); + simple_macro!(94); + simple_macro!(95); + simple_macro!(96); + simple_macro!(97); + simple_macro!(98); + simple_macro!(99); + simple_macro!(100); + simple_macro!(101); + simple_macro!(102); + simple_macro!(103); + simple_macro!(104); + simple_macro!(105); + simple_macro!(106); + simple_macro!(107); + simple_macro!(108); + simple_macro!(109); + simple_macro!(110); + simple_macro!(111); + simple_macro!(112); + simple_macro!(113); + simple_macro!(114); + simple_macro!(115); + simple_macro!(116); + simple_macro!(117); + simple_macro!(118); + simple_macro!(119); + simple_macro!(120); + simple_macro!(121); + simple_macro!(122); + simple_macro!(123); + simple_macro!(124); + simple_macro!(125); + simple_macro!(126); + simple_macro!(127); + simple_macro!(128); + simple_macro!(129); + simple_macro!(130); + simple_macro!(131); + simple_macro!(132); + simple_macro!(133); + simple_macro!(134); + simple_macro!(135); + simple_macro!(136); + simple_macro!(137); + simple_macro!(138); + simple_macro!(139); + simple_macro!(140); + simple_macro!(141); + simple_macro!(142); + simple_macro!(143); + simple_macro!(144); + simple_macro!(145); + simple_macro!(146); + simple_macro!(147); + simple_macro!(148); + simple_macro!(149); + simple_macro!(150); + simple_macro!(151); + simple_macro!(152); + simple_macro!(153); + simple_macro!(154); + simple_macro!(155); + simple_macro!(156); + simple_macro!(157); + simple_macro!(158); + simple_macro!(159); + simple_macro!(160); + simple_macro!(161); + simple_macro!(162); + simple_macro!(163); + simple_macro!(164); + simple_macro!(165); + simple_macro!(166); + simple_macro!(167); + simple_macro!(168); + simple_macro!(169); + simple_macro!(170); + simple_macro!(171); + simple_macro!(172); + simple_macro!(173); + simple_macro!(174); + simple_macro!(175); + simple_macro!(176); + simple_macro!(177); + simple_macro!(178); + simple_macro!(179); + simple_macro!(180); + simple_macro!(181); + simple_macro!(182); + simple_macro!(183); + simple_macro!(184); + simple_macro!(185); + simple_macro!(186); + simple_macro!(187); + simple_macro!(188); + simple_macro!(189); + simple_macro!(190); + simple_macro!(191); + simple_macro!(192); + simple_macro!(193); + simple_macro!(194); + simple_macro!(195); + simple_macro!(196); + simple_macro!(197); + simple_macro!(198); + simple_macro!(199); + simple_macro!(200); + simple_macro!(201); + simple_macro!(202); + simple_macro!(203); + simple_macro!(204); + simple_macro!(205); + simple_macro!(206); + simple_macro!(207); + simple_macro!(208); + simple_macro!(209); + simple_macro!(210); + simple_macro!(211); + simple_macro!(212); + simple_macro!(213); + simple_macro!(214); + simple_macro!(215); + simple_macro!(216); + simple_macro!(217); + simple_macro!(218); + simple_macro!(219); + simple_macro!(220); + simple_macro!(221); + simple_macro!(222); + simple_macro!(223); + simple_macro!(224); + simple_macro!(225); + simple_macro!(226); + simple_macro!(227); + simple_macro!(228); + simple_macro!(229); + simple_macro!(230); + simple_macro!(231); + simple_macro!(232); + simple_macro!(233); + simple_macro!(234); + simple_macro!(235); + simple_macro!(236); + simple_macro!(237); + simple_macro!(238); + simple_macro!(239); + simple_macro!(240); + simple_macro!(241); + simple_macro!(242); + simple_macro!(243); + simple_macro!(244); + simple_macro!(245); + simple_macro!(246); + simple_macro!(247); + simple_macro!(248); + simple_macro!(249); + simple_macro!(250); + simple_macro!(251); + simple_macro!(252); + simple_macro!(253); + simple_macro!(254); + simple_macro!(255); + simple_macro!(256); + simple_macro!(257); + simple_macro!(258); + simple_macro!(259); + simple_macro!(260); + simple_macro!(261); + simple_macro!(262); + simple_macro!(263); + simple_macro!(264); + simple_macro!(265); + simple_macro!(266); + simple_macro!(267); + simple_macro!(268); + simple_macro!(269); + simple_macro!(270); + simple_macro!(271); + simple_macro!(272); + simple_macro!(273); + simple_macro!(274); + simple_macro!(275); + simple_macro!(276); + simple_macro!(277); + simple_macro!(278); + simple_macro!(279); + simple_macro!(280); + simple_macro!(281); + simple_macro!(282); + simple_macro!(283); + simple_macro!(284); + simple_macro!(285); + simple_macro!(286); + simple_macro!(287); + simple_macro!(288); + simple_macro!(289); + simple_macro!(290); + simple_macro!(291); + simple_macro!(292); + simple_macro!(293); + simple_macro!(294); + simple_macro!(295); + simple_macro!(296); + simple_macro!(297); + simple_macro!(298); + simple_macro!(299); + simple_macro!(300); + simple_macro!(301); + simple_macro!(302); + simple_macro!(303); + simple_macro!(304); + simple_macro!(305); + simple_macro!(306); + simple_macro!(307); + simple_macro!(308); + simple_macro!(309); + simple_macro!(310); + simple_macro!(311); + simple_macro!(312); + simple_macro!(313); + simple_macro!(314); + simple_macro!(315); + simple_macro!(316); + simple_macro!(317); + simple_macro!(318); + simple_macro!(319); + simple_macro!(320); + simple_macro!(321); + simple_macro!(322); + simple_macro!(323); + simple_macro!(324); + simple_macro!(325); + simple_macro!(326); + simple_macro!(327); + simple_macro!(328); + simple_macro!(329); + simple_macro!(330); + simple_macro!(331); + simple_macro!(332); + simple_macro!(333); + simple_macro!(334); + simple_macro!(335); + simple_macro!(336); + simple_macro!(337); + simple_macro!(338); + simple_macro!(339); + simple_macro!(340); + simple_macro!(341); + simple_macro!(342); + simple_macro!(343); + simple_macro!(344); + simple_macro!(345); + simple_macro!(346); + simple_macro!(347); + simple_macro!(348); + simple_macro!(349); + simple_macro!(350); + simple_macro!(351); + simple_macro!(352); + simple_macro!(353); + simple_macro!(354); + simple_macro!(355); + simple_macro!(356); + simple_macro!(357); + simple_macro!(358); + simple_macro!(359); + simple_macro!(360); + simple_macro!(361); + simple_macro!(362); + simple_macro!(363); + simple_macro!(364); + simple_macro!(365); + simple_macro!(366); + simple_macro!(367); + simple_macro!(368); + simple_macro!(369); + simple_macro!(370); + simple_macro!(371); + simple_macro!(372); + simple_macro!(373); + simple_macro!(374); + simple_macro!(375); + simple_macro!(376); + simple_macro!(377); + simple_macro!(378); + simple_macro!(379); + simple_macro!(380); + simple_macro!(381); + simple_macro!(382); + simple_macro!(383); + simple_macro!(384); + simple_macro!(385); + simple_macro!(386); + simple_macro!(387); + simple_macro!(388); + simple_macro!(389); + simple_macro!(390); + simple_macro!(391); + simple_macro!(392); + simple_macro!(393); + simple_macro!(394); + simple_macro!(395); + simple_macro!(396); + simple_macro!(397); + simple_macro!(398); + simple_macro!(399); + simple_macro!(400); + simple_macro!(401); + simple_macro!(402); + simple_macro!(403); + simple_macro!(404); + simple_macro!(405); + simple_macro!(406); + simple_macro!(407); + simple_macro!(408); + simple_macro!(409); + simple_macro!(410); + simple_macro!(411); + simple_macro!(412); + simple_macro!(413); + simple_macro!(414); + simple_macro!(415); + simple_macro!(416); + simple_macro!(417); + simple_macro!(418); + simple_macro!(419); + simple_macro!(420); + simple_macro!(421); + simple_macro!(422); + simple_macro!(423); + simple_macro!(424); + simple_macro!(425); + simple_macro!(426); + simple_macro!(427); + simple_macro!(428); + simple_macro!(429); + simple_macro!(430); + simple_macro!(431); + simple_macro!(432); + simple_macro!(433); + simple_macro!(434); + simple_macro!(435); + simple_macro!(436); + simple_macro!(437); + simple_macro!(438); + simple_macro!(439); + simple_macro!(440); + simple_macro!(441); + simple_macro!(442); + simple_macro!(443); + simple_macro!(444); + simple_macro!(445); + simple_macro!(446); + simple_macro!(447); + simple_macro!(448); + simple_macro!(449); + simple_macro!(450); + simple_macro!(451); + simple_macro!(452); + simple_macro!(453); + simple_macro!(454); + simple_macro!(455); + simple_macro!(456); + simple_macro!(457); + simple_macro!(458); + simple_macro!(459); + simple_macro!(460); + simple_macro!(461); + simple_macro!(462); + simple_macro!(463); + simple_macro!(464); + simple_macro!(465); + simple_macro!(466); + simple_macro!(467); + simple_macro!(468); + simple_macro!(469); + simple_macro!(470); + simple_macro!(471); + simple_macro!(472); + simple_macro!(473); + simple_macro!(474); + simple_macro!(475); + simple_macro!(476); + simple_macro!(477); + simple_macro!(478); + simple_macro!(479); + simple_macro!(480); + simple_macro!(481); + simple_macro!(482); + simple_macro!(483); + simple_macro!(484); + simple_macro!(485); + simple_macro!(486); + simple_macro!(487); + simple_macro!(488); + simple_macro!(489); + simple_macro!(490); + simple_macro!(491); + simple_macro!(492); + simple_macro!(493); + simple_macro!(494); + simple_macro!(495); + simple_macro!(496); + simple_macro!(497); + simple_macro!(498); + simple_macro!(499); + simple_macro!(500); + simple_macro!(501); + simple_macro!(502); + simple_macro!(503); + simple_macro!(504); + simple_macro!(505); + simple_macro!(506); + simple_macro!(507); + simple_macro!(508); + simple_macro!(509); + simple_macro!(510); + simple_macro!(511); + simple_macro!(512); + simple_macro!(513); + simple_macro!(514); + simple_macro!(515); + simple_macro!(516); + simple_macro!(517); + simple_macro!(518); + simple_macro!(519); + simple_macro!(520); + simple_macro!(521); + simple_macro!(522); + simple_macro!(523); + simple_macro!(524); + simple_macro!(525); + simple_macro!(526); + simple_macro!(527); + simple_macro!(528); + simple_macro!(529); + simple_macro!(530); + simple_macro!(531); + simple_macro!(532); + simple_macro!(533); + simple_macro!(534); + simple_macro!(535); + simple_macro!(536); + simple_macro!(537); + simple_macro!(538); + simple_macro!(539); + simple_macro!(540); + simple_macro!(541); + simple_macro!(542); + simple_macro!(543); + simple_macro!(544); + simple_macro!(545); + simple_macro!(546); + simple_macro!(547); + simple_macro!(548); + simple_macro!(549); + simple_macro!(550); + simple_macro!(551); + simple_macro!(552); + simple_macro!(553); + simple_macro!(554); + simple_macro!(555); + simple_macro!(556); + simple_macro!(557); + simple_macro!(558); + simple_macro!(559); + simple_macro!(560); + simple_macro!(561); + simple_macro!(562); + simple_macro!(563); + simple_macro!(564); + simple_macro!(565); + simple_macro!(566); + simple_macro!(567); + simple_macro!(568); + simple_macro!(569); + simple_macro!(570); + simple_macro!(571); + simple_macro!(572); + simple_macro!(573); + simple_macro!(574); + simple_macro!(575); + simple_macro!(576); + simple_macro!(577); + simple_macro!(578); + simple_macro!(579); + simple_macro!(580); + simple_macro!(581); + simple_macro!(582); + simple_macro!(583); + simple_macro!(584); + simple_macro!(585); + simple_macro!(586); + simple_macro!(587); + simple_macro!(588); + simple_macro!(589); + simple_macro!(590); + simple_macro!(591); + simple_macro!(592); + simple_macro!(593); + simple_macro!(594); + simple_macro!(595); + simple_macro!(596); + simple_macro!(597); + simple_macro!(598); + simple_macro!(599); + simple_macro!(600); + simple_macro!(601); + simple_macro!(602); + simple_macro!(603); + simple_macro!(604); + simple_macro!(605); + simple_macro!(606); + simple_macro!(607); + simple_macro!(608); + simple_macro!(609); + simple_macro!(610); + simple_macro!(611); + simple_macro!(612); + simple_macro!(613); + simple_macro!(614); + simple_macro!(615); + simple_macro!(616); + simple_macro!(617); + simple_macro!(618); + simple_macro!(619); + simple_macro!(620); + simple_macro!(621); + simple_macro!(622); + simple_macro!(623); + simple_macro!(624); + simple_macro!(625); + simple_macro!(626); + simple_macro!(627); + simple_macro!(628); + simple_macro!(629); + simple_macro!(630); + simple_macro!(631); + simple_macro!(632); + simple_macro!(633); + simple_macro!(634); + simple_macro!(635); + simple_macro!(636); + simple_macro!(637); + simple_macro!(638); + simple_macro!(639); + simple_macro!(640); + simple_macro!(641); + simple_macro!(642); + simple_macro!(643); + simple_macro!(644); + simple_macro!(645); + simple_macro!(646); + simple_macro!(647); + simple_macro!(648); + simple_macro!(649); + simple_macro!(650); + simple_macro!(651); + simple_macro!(652); + simple_macro!(653); + simple_macro!(654); + simple_macro!(655); + simple_macro!(656); + simple_macro!(657); + simple_macro!(658); + simple_macro!(659); + simple_macro!(660); + simple_macro!(661); + simple_macro!(662); + simple_macro!(663); + simple_macro!(664); + simple_macro!(665); + simple_macro!(666); + simple_macro!(667); + simple_macro!(668); + simple_macro!(669); + simple_macro!(670); + simple_macro!(671); + simple_macro!(672); + simple_macro!(673); + simple_macro!(674); + simple_macro!(675); + simple_macro!(676); + simple_macro!(677); + simple_macro!(678); + simple_macro!(679); + simple_macro!(680); + simple_macro!(681); + simple_macro!(682); + simple_macro!(683); + simple_macro!(684); + simple_macro!(685); + simple_macro!(686); + simple_macro!(687); + simple_macro!(688); + simple_macro!(689); + simple_macro!(690); + simple_macro!(691); + simple_macro!(692); + simple_macro!(693); + simple_macro!(694); + simple_macro!(695); + simple_macro!(696); + simple_macro!(697); + simple_macro!(698); + simple_macro!(699); + simple_macro!(700); + simple_macro!(701); + simple_macro!(702); + simple_macro!(703); + simple_macro!(704); + simple_macro!(705); + simple_macro!(706); + simple_macro!(707); + simple_macro!(708); + simple_macro!(709); + simple_macro!(710); + simple_macro!(711); + simple_macro!(712); + simple_macro!(713); + simple_macro!(714); + simple_macro!(715); + simple_macro!(716); + simple_macro!(717); + simple_macro!(718); + simple_macro!(719); + simple_macro!(720); + simple_macro!(721); + simple_macro!(722); + simple_macro!(723); + simple_macro!(724); + simple_macro!(725); + simple_macro!(726); + simple_macro!(727); + simple_macro!(728); + simple_macro!(729); + simple_macro!(730); + simple_macro!(731); + simple_macro!(732); + simple_macro!(733); + simple_macro!(734); + simple_macro!(735); + simple_macro!(736); + simple_macro!(737); + simple_macro!(738); + simple_macro!(739); + simple_macro!(740); + simple_macro!(741); + simple_macro!(742); + simple_macro!(743); + simple_macro!(744); + simple_macro!(745); + simple_macro!(746); + simple_macro!(747); + simple_macro!(748); + simple_macro!(749); + simple_macro!(750); + simple_macro!(751); + simple_macro!(752); + simple_macro!(753); + simple_macro!(754); + simple_macro!(755); + simple_macro!(756); + simple_macro!(757); + simple_macro!(758); + simple_macro!(759); + simple_macro!(760); + simple_macro!(761); + simple_macro!(762); + simple_macro!(763); + simple_macro!(764); + simple_macro!(765); + simple_macro!(766); + simple_macro!(767); + simple_macro!(768); + simple_macro!(769); + simple_macro!(770); + simple_macro!(771); + simple_macro!(772); + simple_macro!(773); + simple_macro!(774); + simple_macro!(775); + simple_macro!(776); + simple_macro!(777); + simple_macro!(778); + simple_macro!(779); + simple_macro!(780); + simple_macro!(781); + simple_macro!(782); + simple_macro!(783); + simple_macro!(784); + simple_macro!(785); + simple_macro!(786); + simple_macro!(787); + simple_macro!(788); + simple_macro!(789); + simple_macro!(790); + simple_macro!(791); + simple_macro!(792); + simple_macro!(793); + simple_macro!(794); + simple_macro!(795); + simple_macro!(796); + simple_macro!(797); + simple_macro!(798); + simple_macro!(799); + simple_macro!(800); + simple_macro!(801); + simple_macro!(802); + simple_macro!(803); + simple_macro!(804); + simple_macro!(805); + simple_macro!(806); + simple_macro!(807); + simple_macro!(808); + simple_macro!(809); + simple_macro!(810); + simple_macro!(811); + simple_macro!(812); + simple_macro!(813); + simple_macro!(814); + simple_macro!(815); + simple_macro!(816); + simple_macro!(817); + simple_macro!(818); + simple_macro!(819); + simple_macro!(820); + simple_macro!(821); + simple_macro!(822); + simple_macro!(823); + simple_macro!(824); + simple_macro!(825); + simple_macro!(826); + simple_macro!(827); + simple_macro!(828); + simple_macro!(829); + simple_macro!(830); + simple_macro!(831); + simple_macro!(832); + simple_macro!(833); + simple_macro!(834); + simple_macro!(835); + simple_macro!(836); + simple_macro!(837); + simple_macro!(838); + simple_macro!(839); + simple_macro!(840); + simple_macro!(841); + simple_macro!(842); + simple_macro!(843); + simple_macro!(844); + simple_macro!(845); + simple_macro!(846); + simple_macro!(847); + simple_macro!(848); + simple_macro!(849); + simple_macro!(850); + simple_macro!(851); + simple_macro!(852); + simple_macro!(853); + simple_macro!(854); + simple_macro!(855); + simple_macro!(856); + simple_macro!(857); + simple_macro!(858); + simple_macro!(859); + simple_macro!(860); + simple_macro!(861); + simple_macro!(862); + simple_macro!(863); + simple_macro!(864); + simple_macro!(865); + simple_macro!(866); + simple_macro!(867); + simple_macro!(868); + simple_macro!(869); + simple_macro!(870); + simple_macro!(871); + simple_macro!(872); + simple_macro!(873); + simple_macro!(874); + simple_macro!(875); + simple_macro!(876); + simple_macro!(877); + simple_macro!(878); + simple_macro!(879); + simple_macro!(880); + simple_macro!(881); + simple_macro!(882); + simple_macro!(883); + simple_macro!(884); + simple_macro!(885); + simple_macro!(886); + simple_macro!(887); + simple_macro!(888); + simple_macro!(889); + simple_macro!(890); + simple_macro!(891); + simple_macro!(892); + simple_macro!(893); + simple_macro!(894); + simple_macro!(895); + simple_macro!(896); + simple_macro!(897); + simple_macro!(898); + simple_macro!(899); + simple_macro!(900); + simple_macro!(901); + simple_macro!(902); + simple_macro!(903); + simple_macro!(904); + simple_macro!(905); + simple_macro!(906); + simple_macro!(907); + simple_macro!(908); + simple_macro!(909); + simple_macro!(910); + simple_macro!(911); + simple_macro!(912); + simple_macro!(913); + simple_macro!(914); + simple_macro!(915); + simple_macro!(916); + simple_macro!(917); + simple_macro!(918); + simple_macro!(919); + simple_macro!(920); + simple_macro!(921); + simple_macro!(922); + simple_macro!(923); + simple_macro!(924); + simple_macro!(925); + simple_macro!(926); + simple_macro!(927); + simple_macro!(928); + simple_macro!(929); + simple_macro!(930); + simple_macro!(931); + simple_macro!(932); + simple_macro!(933); + simple_macro!(934); + simple_macro!(935); + simple_macro!(936); + simple_macro!(937); + simple_macro!(938); + simple_macro!(939); + simple_macro!(940); + simple_macro!(941); + simple_macro!(942); + simple_macro!(943); + simple_macro!(944); + simple_macro!(945); + simple_macro!(946); + simple_macro!(947); + simple_macro!(948); + simple_macro!(949); + simple_macro!(950); + simple_macro!(951); + simple_macro!(952); + simple_macro!(953); + simple_macro!(954); + simple_macro!(955); + simple_macro!(956); + simple_macro!(957); + simple_macro!(958); + simple_macro!(959); + simple_macro!(960); + simple_macro!(961); + simple_macro!(962); + simple_macro!(963); + simple_macro!(964); + simple_macro!(965); + simple_macro!(966); + simple_macro!(967); + simple_macro!(968); + simple_macro!(969); + simple_macro!(970); + simple_macro!(971); + simple_macro!(972); + simple_macro!(973); + simple_macro!(974); + simple_macro!(975); + simple_macro!(976); + simple_macro!(977); + simple_macro!(978); + simple_macro!(979); + simple_macro!(980); + simple_macro!(981); + simple_macro!(982); + simple_macro!(983); + simple_macro!(984); + simple_macro!(985); + simple_macro!(986); + simple_macro!(987); + simple_macro!(988); + simple_macro!(989); + simple_macro!(990); + simple_macro!(991); + simple_macro!(992); + simple_macro!(993); + simple_macro!(994); + simple_macro!(995); + simple_macro!(996); + simple_macro!(997); + simple_macro!(998); + simple_macro!(999); + simple_macro!(1000); + simple_macro!(1001); + simple_macro!(1002); + simple_macro!(1003); + simple_macro!(1004); + simple_macro!(1005); + simple_macro!(1006); + simple_macro!(1007); + simple_macro!(1008); + simple_macro!(1009); + simple_macro!(1010); + simple_macro!(1011); + simple_macro!(1012); + simple_macro!(1013); + simple_macro!(1014); + simple_macro!(1015); + simple_macro!(1016); + simple_macro!(1017); + simple_macro!(1018); + simple_macro!(1019); + simple_macro!(1020); + simple_macro!(1021); + simple_macro!(1022); + simple_macro!(1023); + simple_macro!(1024); + simple_macro!(1025); + simple_macro!(1026); + simple_macro!(1027); + simple_macro!(1028); + simple_macro!(1029); + simple_macro!(1030); + simple_macro!(1031); + simple_macro!(1032); + simple_macro!(1033); + simple_macro!(1034); + simple_macro!(1035); + simple_macro!(1036); + simple_macro!(1037); + simple_macro!(1038); + simple_macro!(1039); + simple_macro!(1040); + simple_macro!(1041); + simple_macro!(1042); + simple_macro!(1043); + simple_macro!(1044); + simple_macro!(1045); + simple_macro!(1046); + simple_macro!(1047); + simple_macro!(1048); + simple_macro!(1049); + simple_macro!(1050); + simple_macro!(1051); + simple_macro!(1052); + simple_macro!(1053); + simple_macro!(1054); + simple_macro!(1055); + simple_macro!(1056); + simple_macro!(1057); + simple_macro!(1058); + simple_macro!(1059); + simple_macro!(1060); + simple_macro!(1061); + simple_macro!(1062); + simple_macro!(1063); + simple_macro!(1064); + simple_macro!(1065); + simple_macro!(1066); + simple_macro!(1067); + simple_macro!(1068); + simple_macro!(1069); + simple_macro!(1070); + simple_macro!(1071); + simple_macro!(1072); + simple_macro!(1073); + simple_macro!(1074); + simple_macro!(1075); + simple_macro!(1076); + simple_macro!(1077); + simple_macro!(1078); + simple_macro!(1079); + simple_macro!(1080); + simple_macro!(1081); + simple_macro!(1082); + simple_macro!(1083); + simple_macro!(1084); + simple_macro!(1085); + simple_macro!(1086); + simple_macro!(1087); + simple_macro!(1088); + simple_macro!(1089); + simple_macro!(1090); + simple_macro!(1091); + simple_macro!(1092); + simple_macro!(1093); + simple_macro!(1094); + simple_macro!(1095); + simple_macro!(1096); + simple_macro!(1097); + simple_macro!(1098); + simple_macro!(1099); + simple_macro!(1100); + simple_macro!(1101); + simple_macro!(1102); + simple_macro!(1103); + simple_macro!(1104); + simple_macro!(1105); + simple_macro!(1106); + simple_macro!(1107); + simple_macro!(1108); + simple_macro!(1109); + simple_macro!(1110); + simple_macro!(1111); + simple_macro!(1112); + simple_macro!(1113); + simple_macro!(1114); + simple_macro!(1115); + simple_macro!(1116); + simple_macro!(1117); + simple_macro!(1118); + simple_macro!(1119); + simple_macro!(1120); + simple_macro!(1121); + simple_macro!(1122); + simple_macro!(1123); + simple_macro!(1124); + simple_macro!(1125); + simple_macro!(1126); + simple_macro!(1127); + simple_macro!(1128); + simple_macro!(1129); + simple_macro!(1130); + simple_macro!(1131); + simple_macro!(1132); + simple_macro!(1133); + simple_macro!(1134); + simple_macro!(1135); + simple_macro!(1136); + simple_macro!(1137); + simple_macro!(1138); + simple_macro!(1139); + simple_macro!(1140); + simple_macro!(1141); + simple_macro!(1142); + simple_macro!(1143); + simple_macro!(1144); + simple_macro!(1145); + simple_macro!(1146); + simple_macro!(1147); + simple_macro!(1148); + simple_macro!(1149); + simple_macro!(1150); + simple_macro!(1151); + simple_macro!(1152); + simple_macro!(1153); + simple_macro!(1154); + simple_macro!(1155); + simple_macro!(1156); + simple_macro!(1157); + simple_macro!(1158); + simple_macro!(1159); + simple_macro!(1160); + simple_macro!(1161); + simple_macro!(1162); + simple_macro!(1163); + simple_macro!(1164); + simple_macro!(1165); + simple_macro!(1166); + simple_macro!(1167); + simple_macro!(1168); + simple_macro!(1169); + simple_macro!(1170); + simple_macro!(1171); + simple_macro!(1172); + simple_macro!(1173); + simple_macro!(1174); + simple_macro!(1175); + simple_macro!(1176); + simple_macro!(1177); + simple_macro!(1178); + simple_macro!(1179); + simple_macro!(1180); + simple_macro!(1181); + simple_macro!(1182); + simple_macro!(1183); + simple_macro!(1184); + simple_macro!(1185); + simple_macro!(1186); + simple_macro!(1187); + simple_macro!(1188); + simple_macro!(1189); + simple_macro!(1190); + simple_macro!(1191); + simple_macro!(1192); + simple_macro!(1193); + simple_macro!(1194); + simple_macro!(1195); + simple_macro!(1196); + simple_macro!(1197); + simple_macro!(1198); + simple_macro!(1199); + simple_macro!(1200); + simple_macro!(1201); + simple_macro!(1202); + simple_macro!(1203); + simple_macro!(1204); + simple_macro!(1205); + simple_macro!(1206); + simple_macro!(1207); + simple_macro!(1208); + simple_macro!(1209); + simple_macro!(1210); + simple_macro!(1211); + simple_macro!(1212); + simple_macro!(1213); + simple_macro!(1214); + simple_macro!(1215); + simple_macro!(1216); + simple_macro!(1217); + simple_macro!(1218); + simple_macro!(1219); + simple_macro!(1220); + simple_macro!(1221); + simple_macro!(1222); + simple_macro!(1223); + simple_macro!(1224); + simple_macro!(1225); + simple_macro!(1226); + simple_macro!(1227); + simple_macro!(1228); + simple_macro!(1229); + simple_macro!(1230); + simple_macro!(1231); + simple_macro!(1232); + simple_macro!(1233); + simple_macro!(1234); + simple_macro!(1235); + simple_macro!(1236); + simple_macro!(1237); + simple_macro!(1238); + simple_macro!(1239); + simple_macro!(1240); + simple_macro!(1241); + simple_macro!(1242); + simple_macro!(1243); + simple_macro!(1244); + simple_macro!(1245); + simple_macro!(1246); + simple_macro!(1247); + simple_macro!(1248); + simple_macro!(1249); + simple_macro!(1250); + simple_macro!(1251); + simple_macro!(1252); + simple_macro!(1253); + simple_macro!(1254); + simple_macro!(1255); + simple_macro!(1256); + simple_macro!(1257); + simple_macro!(1258); + simple_macro!(1259); + simple_macro!(1260); + simple_macro!(1261); + simple_macro!(1262); + simple_macro!(1263); + simple_macro!(1264); + simple_macro!(1265); + simple_macro!(1266); + simple_macro!(1267); + simple_macro!(1268); + simple_macro!(1269); + simple_macro!(1270); + simple_macro!(1271); + simple_macro!(1272); + simple_macro!(1273); + simple_macro!(1274); + simple_macro!(1275); + simple_macro!(1276); + simple_macro!(1277); + simple_macro!(1278); + simple_macro!(1279); + simple_macro!(1280); + simple_macro!(1281); + simple_macro!(1282); + simple_macro!(1283); + simple_macro!(1284); + simple_macro!(1285); + simple_macro!(1286); + simple_macro!(1287); + simple_macro!(1288); + simple_macro!(1289); + simple_macro!(1290); + simple_macro!(1291); + simple_macro!(1292); + simple_macro!(1293); + simple_macro!(1294); + simple_macro!(1295); + simple_macro!(1296); + simple_macro!(1297); + simple_macro!(1298); + simple_macro!(1299); + simple_macro!(1300); + simple_macro!(1301); + simple_macro!(1302); + simple_macro!(1303); + simple_macro!(1304); + simple_macro!(1305); + simple_macro!(1306); + simple_macro!(1307); + simple_macro!(1308); + simple_macro!(1309); + simple_macro!(1310); + simple_macro!(1311); + simple_macro!(1312); + simple_macro!(1313); + simple_macro!(1314); + simple_macro!(1315); + simple_macro!(1316); + simple_macro!(1317); + simple_macro!(1318); + simple_macro!(1319); + simple_macro!(1320); + simple_macro!(1321); + simple_macro!(1322); + simple_macro!(1323); + simple_macro!(1324); + simple_macro!(1325); + simple_macro!(1326); + simple_macro!(1327); + simple_macro!(1328); + simple_macro!(1329); + simple_macro!(1330); + simple_macro!(1331); + simple_macro!(1332); + simple_macro!(1333); + simple_macro!(1334); + simple_macro!(1335); + simple_macro!(1336); + simple_macro!(1337); + simple_macro!(1338); + simple_macro!(1339); + simple_macro!(1340); + simple_macro!(1341); + simple_macro!(1342); + simple_macro!(1343); + simple_macro!(1344); + simple_macro!(1345); + simple_macro!(1346); + simple_macro!(1347); + simple_macro!(1348); + simple_macro!(1349); + simple_macro!(1350); + simple_macro!(1351); + simple_macro!(1352); + simple_macro!(1353); + simple_macro!(1354); + simple_macro!(1355); + simple_macro!(1356); + simple_macro!(1357); + simple_macro!(1358); + simple_macro!(1359); + simple_macro!(1360); + simple_macro!(1361); + simple_macro!(1362); + simple_macro!(1363); + simple_macro!(1364); + simple_macro!(1365); + simple_macro!(1366); + simple_macro!(1367); + simple_macro!(1368); + simple_macro!(1369); + simple_macro!(1370); + simple_macro!(1371); + simple_macro!(1372); + simple_macro!(1373); + simple_macro!(1374); + simple_macro!(1375); + simple_macro!(1376); + simple_macro!(1377); + simple_macro!(1378); + simple_macro!(1379); + simple_macro!(1380); + simple_macro!(1381); + simple_macro!(1382); + simple_macro!(1383); + simple_macro!(1384); + simple_macro!(1385); + simple_macro!(1386); + simple_macro!(1387); + simple_macro!(1388); + simple_macro!(1389); + simple_macro!(1390); + simple_macro!(1391); + simple_macro!(1392); + simple_macro!(1393); + simple_macro!(1394); + simple_macro!(1395); + simple_macro!(1396); + simple_macro!(1397); + simple_macro!(1398); + simple_macro!(1399); + simple_macro!(1400); + simple_macro!(1401); + simple_macro!(1402); + simple_macro!(1403); + simple_macro!(1404); + simple_macro!(1405); + simple_macro!(1406); + simple_macro!(1407); + simple_macro!(1408); + simple_macro!(1409); + simple_macro!(1410); + simple_macro!(1411); + simple_macro!(1412); + simple_macro!(1413); + simple_macro!(1414); + simple_macro!(1415); + simple_macro!(1416); + simple_macro!(1417); + simple_macro!(1418); + simple_macro!(1419); + simple_macro!(1420); + simple_macro!(1421); + simple_macro!(1422); + simple_macro!(1423); + simple_macro!(1424); + simple_macro!(1425); + simple_macro!(1426); + simple_macro!(1427); + simple_macro!(1428); + simple_macro!(1429); + simple_macro!(1430); + simple_macro!(1431); + simple_macro!(1432); + simple_macro!(1433); + simple_macro!(1434); + simple_macro!(1435); + simple_macro!(1436); + simple_macro!(1437); + simple_macro!(1438); + simple_macro!(1439); + simple_macro!(1440); + simple_macro!(1441); + simple_macro!(1442); + simple_macro!(1443); + simple_macro!(1444); + simple_macro!(1445); + simple_macro!(1446); + simple_macro!(1447); + simple_macro!(1448); + simple_macro!(1449); + simple_macro!(1450); + simple_macro!(1451); + simple_macro!(1452); + simple_macro!(1453); + simple_macro!(1454); + simple_macro!(1455); + simple_macro!(1456); + simple_macro!(1457); + simple_macro!(1458); + simple_macro!(1459); + simple_macro!(1460); + simple_macro!(1461); + simple_macro!(1462); + simple_macro!(1463); + simple_macro!(1464); + simple_macro!(1465); + simple_macro!(1466); + simple_macro!(1467); + simple_macro!(1468); + simple_macro!(1469); + simple_macro!(1470); + simple_macro!(1471); + simple_macro!(1472); + simple_macro!(1473); + simple_macro!(1474); + simple_macro!(1475); + simple_macro!(1476); + simple_macro!(1477); + simple_macro!(1478); + simple_macro!(1479); + simple_macro!(1480); + simple_macro!(1481); + simple_macro!(1482); + simple_macro!(1483); + simple_macro!(1484); + simple_macro!(1485); + simple_macro!(1486); + simple_macro!(1487); + simple_macro!(1488); + simple_macro!(1489); + simple_macro!(1490); + simple_macro!(1491); + simple_macro!(1492); + simple_macro!(1493); + simple_macro!(1494); + simple_macro!(1495); + simple_macro!(1496); + simple_macro!(1497); + simple_macro!(1498); + simple_macro!(1499); + simple_macro!(1500); + simple_macro!(1501); + simple_macro!(1502); + simple_macro!(1503); + simple_macro!(1504); + simple_macro!(1505); + simple_macro!(1506); + simple_macro!(1507); + simple_macro!(1508); + simple_macro!(1509); + simple_macro!(1510); + simple_macro!(1511); + simple_macro!(1512); + simple_macro!(1513); + simple_macro!(1514); + simple_macro!(1515); + simple_macro!(1516); + simple_macro!(1517); + simple_macro!(1518); + simple_macro!(1519); + simple_macro!(1520); + simple_macro!(1521); + simple_macro!(1522); + simple_macro!(1523); + simple_macro!(1524); + simple_macro!(1525); + simple_macro!(1526); + simple_macro!(1527); + simple_macro!(1528); + simple_macro!(1529); + simple_macro!(1530); + simple_macro!(1531); + simple_macro!(1532); + simple_macro!(1533); + simple_macro!(1534); + simple_macro!(1535); + simple_macro!(1536); + simple_macro!(1537); + simple_macro!(1538); + simple_macro!(1539); + simple_macro!(1540); + simple_macro!(1541); + simple_macro!(1542); + simple_macro!(1543); + simple_macro!(1544); + simple_macro!(1545); + simple_macro!(1546); + simple_macro!(1547); + simple_macro!(1548); + simple_macro!(1549); + simple_macro!(1550); + simple_macro!(1551); + simple_macro!(1552); + simple_macro!(1553); + simple_macro!(1554); + simple_macro!(1555); + simple_macro!(1556); + simple_macro!(1557); + simple_macro!(1558); + simple_macro!(1559); + simple_macro!(1560); + simple_macro!(1561); + simple_macro!(1562); + simple_macro!(1563); + simple_macro!(1564); + simple_macro!(1565); + simple_macro!(1566); + simple_macro!(1567); + simple_macro!(1568); + simple_macro!(1569); + simple_macro!(1570); + simple_macro!(1571); + simple_macro!(1572); + simple_macro!(1573); + simple_macro!(1574); + simple_macro!(1575); + simple_macro!(1576); + simple_macro!(1577); + simple_macro!(1578); + simple_macro!(1579); + simple_macro!(1580); + simple_macro!(1581); + simple_macro!(1582); + simple_macro!(1583); + simple_macro!(1584); + simple_macro!(1585); + simple_macro!(1586); + simple_macro!(1587); + simple_macro!(1588); + simple_macro!(1589); + simple_macro!(1590); + simple_macro!(1591); + simple_macro!(1592); + simple_macro!(1593); + simple_macro!(1594); + simple_macro!(1595); + simple_macro!(1596); + simple_macro!(1597); + simple_macro!(1598); + simple_macro!(1599); + simple_macro!(1600); + simple_macro!(1601); + simple_macro!(1602); + simple_macro!(1603); + simple_macro!(1604); + simple_macro!(1605); + simple_macro!(1606); + simple_macro!(1607); + simple_macro!(1608); + simple_macro!(1609); + simple_macro!(1610); + simple_macro!(1611); + simple_macro!(1612); + simple_macro!(1613); + simple_macro!(1614); + simple_macro!(1615); + simple_macro!(1616); + simple_macro!(1617); + simple_macro!(1618); + simple_macro!(1619); + simple_macro!(1620); + simple_macro!(1621); + simple_macro!(1622); + simple_macro!(1623); + simple_macro!(1624); + simple_macro!(1625); + simple_macro!(1626); + simple_macro!(1627); + simple_macro!(1628); + simple_macro!(1629); + simple_macro!(1630); + simple_macro!(1631); + simple_macro!(1632); + simple_macro!(1633); + simple_macro!(1634); + simple_macro!(1635); + simple_macro!(1636); + simple_macro!(1637); + simple_macro!(1638); + simple_macro!(1639); + simple_macro!(1640); + simple_macro!(1641); + simple_macro!(1642); + simple_macro!(1643); + simple_macro!(1644); + simple_macro!(1645); + simple_macro!(1646); + simple_macro!(1647); + simple_macro!(1648); + simple_macro!(1649); + simple_macro!(1650); + simple_macro!(1651); + simple_macro!(1652); + simple_macro!(1653); + simple_macro!(1654); + simple_macro!(1655); + simple_macro!(1656); + simple_macro!(1657); + simple_macro!(1658); + simple_macro!(1659); + simple_macro!(1660); + simple_macro!(1661); + simple_macro!(1662); + simple_macro!(1663); + simple_macro!(1664); + simple_macro!(1665); + simple_macro!(1666); + simple_macro!(1667); + simple_macro!(1668); + simple_macro!(1669); + simple_macro!(1670); + simple_macro!(1671); + simple_macro!(1672); + simple_macro!(1673); + simple_macro!(1674); + simple_macro!(1675); + simple_macro!(1676); + simple_macro!(1677); + simple_macro!(1678); + simple_macro!(1679); + simple_macro!(1680); + simple_macro!(1681); + simple_macro!(1682); + simple_macro!(1683); + simple_macro!(1684); + simple_macro!(1685); + simple_macro!(1686); + simple_macro!(1687); + simple_macro!(1688); + simple_macro!(1689); + simple_macro!(1690); + simple_macro!(1691); + simple_macro!(1692); + simple_macro!(1693); + simple_macro!(1694); + simple_macro!(1695); + simple_macro!(1696); + simple_macro!(1697); + simple_macro!(1698); + simple_macro!(1699); + simple_macro!(1700); + simple_macro!(1701); + simple_macro!(1702); + simple_macro!(1703); + simple_macro!(1704); + simple_macro!(1705); + simple_macro!(1706); + simple_macro!(1707); + simple_macro!(1708); + simple_macro!(1709); + simple_macro!(1710); + simple_macro!(1711); + simple_macro!(1712); + simple_macro!(1713); + simple_macro!(1714); + simple_macro!(1715); + simple_macro!(1716); + simple_macro!(1717); + simple_macro!(1718); + simple_macro!(1719); + simple_macro!(1720); + simple_macro!(1721); + simple_macro!(1722); + simple_macro!(1723); + simple_macro!(1724); + simple_macro!(1725); + simple_macro!(1726); + simple_macro!(1727); + simple_macro!(1728); + simple_macro!(1729); + simple_macro!(1730); + simple_macro!(1731); + simple_macro!(1732); + simple_macro!(1733); + simple_macro!(1734); + simple_macro!(1735); + simple_macro!(1736); + simple_macro!(1737); + simple_macro!(1738); + simple_macro!(1739); + simple_macro!(1740); + simple_macro!(1741); + simple_macro!(1742); + simple_macro!(1743); + simple_macro!(1744); + simple_macro!(1745); + simple_macro!(1746); + simple_macro!(1747); + simple_macro!(1748); + simple_macro!(1749); + simple_macro!(1750); + simple_macro!(1751); + simple_macro!(1752); + simple_macro!(1753); + simple_macro!(1754); + simple_macro!(1755); + simple_macro!(1756); + simple_macro!(1757); + simple_macro!(1758); + simple_macro!(1759); + simple_macro!(1760); + simple_macro!(1761); + simple_macro!(1762); + simple_macro!(1763); + simple_macro!(1764); + simple_macro!(1765); + simple_macro!(1766); + simple_macro!(1767); + simple_macro!(1768); + simple_macro!(1769); + simple_macro!(1770); + simple_macro!(1771); + simple_macro!(1772); + simple_macro!(1773); + simple_macro!(1774); + simple_macro!(1775); + simple_macro!(1776); + simple_macro!(1777); + simple_macro!(1778); + simple_macro!(1779); + simple_macro!(1780); + simple_macro!(1781); + simple_macro!(1782); + simple_macro!(1783); + simple_macro!(1784); + simple_macro!(1785); + simple_macro!(1786); + simple_macro!(1787); + simple_macro!(1788); + simple_macro!(1789); + simple_macro!(1790); + simple_macro!(1791); + simple_macro!(1792); + simple_macro!(1793); + simple_macro!(1794); + simple_macro!(1795); + simple_macro!(1796); + simple_macro!(1797); + simple_macro!(1798); + simple_macro!(1799); + simple_macro!(1800); + simple_macro!(1801); + simple_macro!(1802); + simple_macro!(1803); + simple_macro!(1804); + simple_macro!(1805); + simple_macro!(1806); + simple_macro!(1807); + simple_macro!(1808); + simple_macro!(1809); + simple_macro!(1810); + simple_macro!(1811); + simple_macro!(1812); + simple_macro!(1813); + simple_macro!(1814); + simple_macro!(1815); + simple_macro!(1816); + simple_macro!(1817); + simple_macro!(1818); + simple_macro!(1819); + simple_macro!(1820); + simple_macro!(1821); + simple_macro!(1822); + simple_macro!(1823); + simple_macro!(1824); + simple_macro!(1825); + simple_macro!(1826); + simple_macro!(1827); + simple_macro!(1828); + simple_macro!(1829); + simple_macro!(1830); + simple_macro!(1831); + simple_macro!(1832); + simple_macro!(1833); + simple_macro!(1834); + simple_macro!(1835); + simple_macro!(1836); + simple_macro!(1837); + simple_macro!(1838); + simple_macro!(1839); + simple_macro!(1840); + simple_macro!(1841); + simple_macro!(1842); + simple_macro!(1843); + simple_macro!(1844); + simple_macro!(1845); + simple_macro!(1846); + simple_macro!(1847); + simple_macro!(1848); + simple_macro!(1849); + simple_macro!(1850); + simple_macro!(1851); + simple_macro!(1852); + simple_macro!(1853); + simple_macro!(1854); + simple_macro!(1855); + simple_macro!(1856); + simple_macro!(1857); + simple_macro!(1858); + simple_macro!(1859); + simple_macro!(1860); + simple_macro!(1861); + simple_macro!(1862); + simple_macro!(1863); + simple_macro!(1864); + simple_macro!(1865); + simple_macro!(1866); + simple_macro!(1867); + simple_macro!(1868); + simple_macro!(1869); + simple_macro!(1870); + simple_macro!(1871); + simple_macro!(1872); + simple_macro!(1873); + simple_macro!(1874); + simple_macro!(1875); + simple_macro!(1876); + simple_macro!(1877); + simple_macro!(1878); + simple_macro!(1879); + simple_macro!(1880); + simple_macro!(1881); + simple_macro!(1882); + simple_macro!(1883); + simple_macro!(1884); + simple_macro!(1885); + simple_macro!(1886); + simple_macro!(1887); + simple_macro!(1888); + simple_macro!(1889); + simple_macro!(1890); + simple_macro!(1891); + simple_macro!(1892); + simple_macro!(1893); + simple_macro!(1894); + simple_macro!(1895); + simple_macro!(1896); + simple_macro!(1897); + simple_macro!(1898); + simple_macro!(1899); + simple_macro!(1900); + simple_macro!(1901); + simple_macro!(1902); + simple_macro!(1903); + simple_macro!(1904); + simple_macro!(1905); + simple_macro!(1906); + simple_macro!(1907); + simple_macro!(1908); + simple_macro!(1909); + simple_macro!(1910); + simple_macro!(1911); + simple_macro!(1912); + simple_macro!(1913); + simple_macro!(1914); + simple_macro!(1915); + simple_macro!(1916); + simple_macro!(1917); + simple_macro!(1918); + simple_macro!(1919); + simple_macro!(1920); + simple_macro!(1921); + simple_macro!(1922); + simple_macro!(1923); + simple_macro!(1924); + simple_macro!(1925); + simple_macro!(1926); + simple_macro!(1927); + simple_macro!(1928); + simple_macro!(1929); + simple_macro!(1930); + simple_macro!(1931); + simple_macro!(1932); + simple_macro!(1933); + simple_macro!(1934); + simple_macro!(1935); + simple_macro!(1936); + simple_macro!(1937); + simple_macro!(1938); + simple_macro!(1939); + simple_macro!(1940); + simple_macro!(1941); + simple_macro!(1942); + simple_macro!(1943); + simple_macro!(1944); + simple_macro!(1945); + simple_macro!(1946); + simple_macro!(1947); + simple_macro!(1948); + simple_macro!(1949); + simple_macro!(1950); + simple_macro!(1951); + simple_macro!(1952); + simple_macro!(1953); + simple_macro!(1954); + simple_macro!(1955); + simple_macro!(1956); + simple_macro!(1957); + simple_macro!(1958); + simple_macro!(1959); + simple_macro!(1960); + simple_macro!(1961); + simple_macro!(1962); + simple_macro!(1963); + simple_macro!(1964); + simple_macro!(1965); + simple_macro!(1966); + simple_macro!(1967); + simple_macro!(1968); + simple_macro!(1969); + simple_macro!(1970); + simple_macro!(1971); + simple_macro!(1972); + simple_macro!(1973); + simple_macro!(1974); + simple_macro!(1975); + simple_macro!(1976); + simple_macro!(1977); + simple_macro!(1978); + simple_macro!(1979); + simple_macro!(1980); + simple_macro!(1981); + simple_macro!(1982); + simple_macro!(1983); + simple_macro!(1984); + simple_macro!(1985); + simple_macro!(1986); + simple_macro!(1987); + simple_macro!(1988); + simple_macro!(1989); + simple_macro!(1990); + simple_macro!(1991); + simple_macro!(1992); + simple_macro!(1993); + simple_macro!(1994); + simple_macro!(1995); + simple_macro!(1996); + simple_macro!(1997); + simple_macro!(1998); + simple_macro!(1999); + simple_macro!(2000); + simple_macro!(2001); + simple_macro!(2002); + simple_macro!(2003); + simple_macro!(2004); + simple_macro!(2005); + simple_macro!(2006); + simple_macro!(2007); + simple_macro!(2008); + simple_macro!(2009); + simple_macro!(2010); + simple_macro!(2011); + simple_macro!(2012); + simple_macro!(2013); + simple_macro!(2014); + simple_macro!(2015); + simple_macro!(2016); + simple_macro!(2017); + simple_macro!(2018); + simple_macro!(2019); + simple_macro!(2020); + simple_macro!(2021); + simple_macro!(2022); + simple_macro!(2023); + simple_macro!(2024); + simple_macro!(2025); + simple_macro!(2026); + simple_macro!(2027); + simple_macro!(2028); + simple_macro!(2029); + simple_macro!(2030); + simple_macro!(2031); + simple_macro!(2032); + simple_macro!(2033); + simple_macro!(2034); + simple_macro!(2035); + simple_macro!(2036); + simple_macro!(2037); + simple_macro!(2038); + simple_macro!(2039); + simple_macro!(2040); + simple_macro!(2041); + simple_macro!(2042); + simple_macro!(2043); + simple_macro!(2044); + simple_macro!(2045); + simple_macro!(2046); + simple_macro!(2047); + simple_macro!(2048); + simple_macro!(2049); + simple_macro!(2050); + simple_macro!(2051); + simple_macro!(2052); + simple_macro!(2053); + simple_macro!(2054); + simple_macro!(2055); + simple_macro!(2056); + simple_macro!(2057); + simple_macro!(2058); + simple_macro!(2059); + simple_macro!(2060); + simple_macro!(2061); + simple_macro!(2062); + simple_macro!(2063); + simple_macro!(2064); + simple_macro!(2065); + simple_macro!(2066); + simple_macro!(2067); + simple_macro!(2068); + simple_macro!(2069); + simple_macro!(2070); + simple_macro!(2071); + simple_macro!(2072); + simple_macro!(2073); + simple_macro!(2074); + simple_macro!(2075); + simple_macro!(2076); + simple_macro!(2077); + simple_macro!(2078); + simple_macro!(2079); + simple_macro!(2080); + simple_macro!(2081); + simple_macro!(2082); + simple_macro!(2083); + simple_macro!(2084); + simple_macro!(2085); + simple_macro!(2086); + simple_macro!(2087); + simple_macro!(2088); + simple_macro!(2089); + simple_macro!(2090); + simple_macro!(2091); + simple_macro!(2092); + simple_macro!(2093); + simple_macro!(2094); + simple_macro!(2095); + simple_macro!(2096); + simple_macro!(2097); + simple_macro!(2098); + simple_macro!(2099); + simple_macro!(2100); + simple_macro!(2101); + simple_macro!(2102); + simple_macro!(2103); + simple_macro!(2104); + simple_macro!(2105); + simple_macro!(2106); + simple_macro!(2107); + simple_macro!(2108); + simple_macro!(2109); + simple_macro!(2110); + simple_macro!(2111); + simple_macro!(2112); + simple_macro!(2113); + simple_macro!(2114); + simple_macro!(2115); + simple_macro!(2116); + simple_macro!(2117); + simple_macro!(2118); + simple_macro!(2119); + simple_macro!(2120); + simple_macro!(2121); + simple_macro!(2122); + simple_macro!(2123); + simple_macro!(2124); + simple_macro!(2125); + simple_macro!(2126); + simple_macro!(2127); + simple_macro!(2128); + simple_macro!(2129); + simple_macro!(2130); + simple_macro!(2131); + simple_macro!(2132); + simple_macro!(2133); + simple_macro!(2134); + simple_macro!(2135); + simple_macro!(2136); + simple_macro!(2137); + simple_macro!(2138); + simple_macro!(2139); + simple_macro!(2140); + simple_macro!(2141); + simple_macro!(2142); + simple_macro!(2143); + simple_macro!(2144); + simple_macro!(2145); + simple_macro!(2146); + simple_macro!(2147); + simple_macro!(2148); + simple_macro!(2149); + simple_macro!(2150); + simple_macro!(2151); + simple_macro!(2152); + simple_macro!(2153); + simple_macro!(2154); + simple_macro!(2155); + simple_macro!(2156); + simple_macro!(2157); + simple_macro!(2158); + simple_macro!(2159); + simple_macro!(2160); + simple_macro!(2161); + simple_macro!(2162); + simple_macro!(2163); + simple_macro!(2164); + simple_macro!(2165); + simple_macro!(2166); + simple_macro!(2167); + simple_macro!(2168); + simple_macro!(2169); + simple_macro!(2170); + simple_macro!(2171); + simple_macro!(2172); + simple_macro!(2173); + simple_macro!(2174); + simple_macro!(2175); + simple_macro!(2176); + simple_macro!(2177); + simple_macro!(2178); + simple_macro!(2179); + simple_macro!(2180); + simple_macro!(2181); + simple_macro!(2182); + simple_macro!(2183); + simple_macro!(2184); + simple_macro!(2185); + simple_macro!(2186); + simple_macro!(2187); + simple_macro!(2188); + simple_macro!(2189); + simple_macro!(2190); + simple_macro!(2191); + simple_macro!(2192); + simple_macro!(2193); + simple_macro!(2194); + simple_macro!(2195); + simple_macro!(2196); + simple_macro!(2197); + simple_macro!(2198); + simple_macro!(2199); + simple_macro!(2200); + simple_macro!(2201); + simple_macro!(2202); + simple_macro!(2203); + simple_macro!(2204); + simple_macro!(2205); + simple_macro!(2206); + simple_macro!(2207); + simple_macro!(2208); + simple_macro!(2209); + simple_macro!(2210); + simple_macro!(2211); + simple_macro!(2212); + simple_macro!(2213); + simple_macro!(2214); + simple_macro!(2215); + simple_macro!(2216); + simple_macro!(2217); + simple_macro!(2218); + simple_macro!(2219); + simple_macro!(2220); + simple_macro!(2221); + simple_macro!(2222); + simple_macro!(2223); + simple_macro!(2224); + simple_macro!(2225); + simple_macro!(2226); + simple_macro!(2227); + simple_macro!(2228); + simple_macro!(2229); + simple_macro!(2230); + simple_macro!(2231); + simple_macro!(2232); + simple_macro!(2233); + simple_macro!(2234); + simple_macro!(2235); + simple_macro!(2236); + simple_macro!(2237); + simple_macro!(2238); + simple_macro!(2239); + simple_macro!(2240); + simple_macro!(2241); + simple_macro!(2242); + simple_macro!(2243); + simple_macro!(2244); + simple_macro!(2245); + simple_macro!(2246); + simple_macro!(2247); + simple_macro!(2248); + simple_macro!(2249); + simple_macro!(2250); + simple_macro!(2251); + simple_macro!(2252); + simple_macro!(2253); + simple_macro!(2254); + simple_macro!(2255); + simple_macro!(2256); + simple_macro!(2257); + simple_macro!(2258); + simple_macro!(2259); + simple_macro!(2260); + simple_macro!(2261); + simple_macro!(2262); + simple_macro!(2263); + simple_macro!(2264); + simple_macro!(2265); + simple_macro!(2266); + simple_macro!(2267); + simple_macro!(2268); + simple_macro!(2269); + simple_macro!(2270); + simple_macro!(2271); + simple_macro!(2272); + simple_macro!(2273); + simple_macro!(2274); + simple_macro!(2275); + simple_macro!(2276); + simple_macro!(2277); + simple_macro!(2278); + simple_macro!(2279); + simple_macro!(2280); + simple_macro!(2281); + simple_macro!(2282); + simple_macro!(2283); + simple_macro!(2284); + simple_macro!(2285); + simple_macro!(2286); + simple_macro!(2287); + simple_macro!(2288); + simple_macro!(2289); + simple_macro!(2290); + simple_macro!(2291); + simple_macro!(2292); + simple_macro!(2293); + simple_macro!(2294); + simple_macro!(2295); + simple_macro!(2296); + simple_macro!(2297); + simple_macro!(2298); + simple_macro!(2299); + simple_macro!(2300); + simple_macro!(2301); + simple_macro!(2302); + simple_macro!(2303); + simple_macro!(2304); + simple_macro!(2305); + simple_macro!(2306); + simple_macro!(2307); + simple_macro!(2308); + simple_macro!(2309); + simple_macro!(2310); + simple_macro!(2311); + simple_macro!(2312); + simple_macro!(2313); + simple_macro!(2314); + simple_macro!(2315); + simple_macro!(2316); + simple_macro!(2317); + simple_macro!(2318); + simple_macro!(2319); + simple_macro!(2320); + simple_macro!(2321); + simple_macro!(2322); + simple_macro!(2323); + simple_macro!(2324); + simple_macro!(2325); + simple_macro!(2326); + simple_macro!(2327); + simple_macro!(2328); + simple_macro!(2329); + simple_macro!(2330); + simple_macro!(2331); + simple_macro!(2332); + simple_macro!(2333); + simple_macro!(2334); + simple_macro!(2335); + simple_macro!(2336); + simple_macro!(2337); + simple_macro!(2338); + simple_macro!(2339); + simple_macro!(2340); + simple_macro!(2341); + simple_macro!(2342); + simple_macro!(2343); + simple_macro!(2344); + simple_macro!(2345); + simple_macro!(2346); + simple_macro!(2347); + simple_macro!(2348); + simple_macro!(2349); + simple_macro!(2350); + simple_macro!(2351); + simple_macro!(2352); + simple_macro!(2353); + simple_macro!(2354); + simple_macro!(2355); + simple_macro!(2356); + simple_macro!(2357); + simple_macro!(2358); + simple_macro!(2359); + simple_macro!(2360); + simple_macro!(2361); + simple_macro!(2362); + simple_macro!(2363); + simple_macro!(2364); + simple_macro!(2365); + simple_macro!(2366); + simple_macro!(2367); + simple_macro!(2368); + simple_macro!(2369); + simple_macro!(2370); + simple_macro!(2371); + simple_macro!(2372); + simple_macro!(2373); + simple_macro!(2374); + simple_macro!(2375); + simple_macro!(2376); + simple_macro!(2377); + simple_macro!(2378); + simple_macro!(2379); + simple_macro!(2380); + simple_macro!(2381); + simple_macro!(2382); + simple_macro!(2383); + simple_macro!(2384); + simple_macro!(2385); + simple_macro!(2386); + simple_macro!(2387); + simple_macro!(2388); + simple_macro!(2389); + simple_macro!(2390); + simple_macro!(2391); + simple_macro!(2392); + simple_macro!(2393); + simple_macro!(2394); + simple_macro!(2395); + simple_macro!(2396); + simple_macro!(2397); + simple_macro!(2398); + simple_macro!(2399); + simple_macro!(2400); + simple_macro!(2401); + simple_macro!(2402); + simple_macro!(2403); + simple_macro!(2404); + simple_macro!(2405); + simple_macro!(2406); + simple_macro!(2407); + simple_macro!(2408); + simple_macro!(2409); + simple_macro!(2410); + simple_macro!(2411); + simple_macro!(2412); + simple_macro!(2413); + simple_macro!(2414); + simple_macro!(2415); + simple_macro!(2416); + simple_macro!(2417); + simple_macro!(2418); + simple_macro!(2419); + simple_macro!(2420); + simple_macro!(2421); + simple_macro!(2422); + simple_macro!(2423); + simple_macro!(2424); + simple_macro!(2425); + simple_macro!(2426); + simple_macro!(2427); + simple_macro!(2428); + simple_macro!(2429); + simple_macro!(2430); + simple_macro!(2431); + simple_macro!(2432); + simple_macro!(2433); + simple_macro!(2434); + simple_macro!(2435); + simple_macro!(2436); + simple_macro!(2437); + simple_macro!(2438); + simple_macro!(2439); + simple_macro!(2440); + simple_macro!(2441); + simple_macro!(2442); + simple_macro!(2443); + simple_macro!(2444); + simple_macro!(2445); + simple_macro!(2446); + simple_macro!(2447); + simple_macro!(2448); + simple_macro!(2449); + simple_macro!(2450); + simple_macro!(2451); + simple_macro!(2452); + simple_macro!(2453); + simple_macro!(2454); + simple_macro!(2455); + simple_macro!(2456); + simple_macro!(2457); + simple_macro!(2458); + simple_macro!(2459); + simple_macro!(2460); + simple_macro!(2461); + simple_macro!(2462); + simple_macro!(2463); + simple_macro!(2464); + simple_macro!(2465); + simple_macro!(2466); + simple_macro!(2467); + simple_macro!(2468); + simple_macro!(2469); + simple_macro!(2470); + simple_macro!(2471); + simple_macro!(2472); + simple_macro!(2473); + simple_macro!(2474); + simple_macro!(2475); + simple_macro!(2476); + simple_macro!(2477); + simple_macro!(2478); + simple_macro!(2479); + simple_macro!(2480); + simple_macro!(2481); + simple_macro!(2482); + simple_macro!(2483); + simple_macro!(2484); + simple_macro!(2485); + simple_macro!(2486); + simple_macro!(2487); + simple_macro!(2488); + simple_macro!(2489); + simple_macro!(2490); + simple_macro!(2491); + simple_macro!(2492); + simple_macro!(2493); + simple_macro!(2494); + simple_macro!(2495); + simple_macro!(2496); + simple_macro!(2497); + simple_macro!(2498); + simple_macro!(2499); + simple_macro!(2500); + simple_macro!(2501); + simple_macro!(2502); + simple_macro!(2503); + simple_macro!(2504); + simple_macro!(2505); + simple_macro!(2506); + simple_macro!(2507); + simple_macro!(2508); + simple_macro!(2509); + simple_macro!(2510); + simple_macro!(2511); + simple_macro!(2512); + simple_macro!(2513); + simple_macro!(2514); + simple_macro!(2515); + simple_macro!(2516); + simple_macro!(2517); + simple_macro!(2518); + simple_macro!(2519); + simple_macro!(2520); + simple_macro!(2521); + simple_macro!(2522); + simple_macro!(2523); + simple_macro!(2524); + simple_macro!(2525); + simple_macro!(2526); + simple_macro!(2527); + simple_macro!(2528); + simple_macro!(2529); + simple_macro!(2530); + simple_macro!(2531); + simple_macro!(2532); + simple_macro!(2533); + simple_macro!(2534); + simple_macro!(2535); + simple_macro!(2536); + simple_macro!(2537); + simple_macro!(2538); + simple_macro!(2539); + simple_macro!(2540); + simple_macro!(2541); + simple_macro!(2542); + simple_macro!(2543); + simple_macro!(2544); + simple_macro!(2545); + simple_macro!(2546); + simple_macro!(2547); + simple_macro!(2548); + simple_macro!(2549); + simple_macro!(2550); + simple_macro!(2551); + simple_macro!(2552); + simple_macro!(2553); + simple_macro!(2554); + simple_macro!(2555); + simple_macro!(2556); + simple_macro!(2557); + simple_macro!(2558); + simple_macro!(2559); + simple_macro!(2560); + simple_macro!(2561); + simple_macro!(2562); + simple_macro!(2563); + simple_macro!(2564); + simple_macro!(2565); + simple_macro!(2566); + simple_macro!(2567); + simple_macro!(2568); + simple_macro!(2569); + simple_macro!(2570); + simple_macro!(2571); + simple_macro!(2572); + simple_macro!(2573); + simple_macro!(2574); + simple_macro!(2575); + simple_macro!(2576); + simple_macro!(2577); + simple_macro!(2578); + simple_macro!(2579); + simple_macro!(2580); + simple_macro!(2581); + simple_macro!(2582); + simple_macro!(2583); + simple_macro!(2584); + simple_macro!(2585); + simple_macro!(2586); + simple_macro!(2587); + simple_macro!(2588); + simple_macro!(2589); + simple_macro!(2590); + simple_macro!(2591); + simple_macro!(2592); + simple_macro!(2593); + simple_macro!(2594); + simple_macro!(2595); + simple_macro!(2596); + simple_macro!(2597); + simple_macro!(2598); + simple_macro!(2599); + simple_macro!(2600); + simple_macro!(2601); + simple_macro!(2602); + simple_macro!(2603); + simple_macro!(2604); + simple_macro!(2605); + simple_macro!(2606); + simple_macro!(2607); + simple_macro!(2608); + simple_macro!(2609); + simple_macro!(2610); + simple_macro!(2611); + simple_macro!(2612); + simple_macro!(2613); + simple_macro!(2614); + simple_macro!(2615); + simple_macro!(2616); + simple_macro!(2617); + simple_macro!(2618); + simple_macro!(2619); + simple_macro!(2620); + simple_macro!(2621); + simple_macro!(2622); + simple_macro!(2623); + simple_macro!(2624); + simple_macro!(2625); + simple_macro!(2626); + simple_macro!(2627); + simple_macro!(2628); + simple_macro!(2629); + simple_macro!(2630); + simple_macro!(2631); + simple_macro!(2632); + simple_macro!(2633); + simple_macro!(2634); + simple_macro!(2635); + simple_macro!(2636); + simple_macro!(2637); + simple_macro!(2638); + simple_macro!(2639); + simple_macro!(2640); + simple_macro!(2641); + simple_macro!(2642); + simple_macro!(2643); + simple_macro!(2644); + simple_macro!(2645); + simple_macro!(2646); + simple_macro!(2647); + simple_macro!(2648); + simple_macro!(2649); + simple_macro!(2650); + simple_macro!(2651); + simple_macro!(2652); + simple_macro!(2653); + simple_macro!(2654); + simple_macro!(2655); + simple_macro!(2656); + simple_macro!(2657); + simple_macro!(2658); + simple_macro!(2659); + simple_macro!(2660); + simple_macro!(2661); + simple_macro!(2662); + simple_macro!(2663); + simple_macro!(2664); + simple_macro!(2665); + simple_macro!(2666); + simple_macro!(2667); + simple_macro!(2668); + simple_macro!(2669); + simple_macro!(2670); + simple_macro!(2671); + simple_macro!(2672); + simple_macro!(2673); + simple_macro!(2674); + simple_macro!(2675); + simple_macro!(2676); + simple_macro!(2677); + simple_macro!(2678); + simple_macro!(2679); + simple_macro!(2680); + simple_macro!(2681); + simple_macro!(2682); + simple_macro!(2683); + simple_macro!(2684); + simple_macro!(2685); + simple_macro!(2686); + simple_macro!(2687); + simple_macro!(2688); + simple_macro!(2689); + simple_macro!(2690); + simple_macro!(2691); + simple_macro!(2692); + simple_macro!(2693); + simple_macro!(2694); + simple_macro!(2695); + simple_macro!(2696); + simple_macro!(2697); + simple_macro!(2698); + simple_macro!(2699); + simple_macro!(2700); + simple_macro!(2701); + simple_macro!(2702); + simple_macro!(2703); + simple_macro!(2704); + simple_macro!(2705); + simple_macro!(2706); + simple_macro!(2707); + simple_macro!(2708); + simple_macro!(2709); + simple_macro!(2710); + simple_macro!(2711); + simple_macro!(2712); + simple_macro!(2713); + simple_macro!(2714); + simple_macro!(2715); + simple_macro!(2716); + simple_macro!(2717); + simple_macro!(2718); + simple_macro!(2719); + simple_macro!(2720); + simple_macro!(2721); + simple_macro!(2722); + simple_macro!(2723); + simple_macro!(2724); + simple_macro!(2725); + simple_macro!(2726); + simple_macro!(2727); + simple_macro!(2728); + simple_macro!(2729); + simple_macro!(2730); + simple_macro!(2731); + simple_macro!(2732); + simple_macro!(2733); + simple_macro!(2734); + simple_macro!(2735); + simple_macro!(2736); + simple_macro!(2737); + simple_macro!(2738); + simple_macro!(2739); + simple_macro!(2740); + simple_macro!(2741); + simple_macro!(2742); + simple_macro!(2743); + simple_macro!(2744); + simple_macro!(2745); + simple_macro!(2746); + simple_macro!(2747); + simple_macro!(2748); + simple_macro!(2749); + simple_macro!(2750); + simple_macro!(2751); + simple_macro!(2752); + simple_macro!(2753); + simple_macro!(2754); + simple_macro!(2755); + simple_macro!(2756); + simple_macro!(2757); + simple_macro!(2758); + simple_macro!(2759); + simple_macro!(2760); + simple_macro!(2761); + simple_macro!(2762); + simple_macro!(2763); + simple_macro!(2764); + simple_macro!(2765); + simple_macro!(2766); + simple_macro!(2767); + simple_macro!(2768); + simple_macro!(2769); + simple_macro!(2770); + simple_macro!(2771); + simple_macro!(2772); + simple_macro!(2773); + simple_macro!(2774); + simple_macro!(2775); + simple_macro!(2776); + simple_macro!(2777); + simple_macro!(2778); + simple_macro!(2779); + simple_macro!(2780); + simple_macro!(2781); + simple_macro!(2782); + simple_macro!(2783); + simple_macro!(2784); + simple_macro!(2785); + simple_macro!(2786); + simple_macro!(2787); + simple_macro!(2788); + simple_macro!(2789); + simple_macro!(2790); + simple_macro!(2791); + simple_macro!(2792); + simple_macro!(2793); + simple_macro!(2794); + simple_macro!(2795); + simple_macro!(2796); + simple_macro!(2797); + simple_macro!(2798); + simple_macro!(2799); + simple_macro!(2800); + simple_macro!(2801); + simple_macro!(2802); + simple_macro!(2803); + simple_macro!(2804); + simple_macro!(2805); + simple_macro!(2806); + simple_macro!(2807); + simple_macro!(2808); + simple_macro!(2809); + simple_macro!(2810); + simple_macro!(2811); + simple_macro!(2812); + simple_macro!(2813); + simple_macro!(2814); + simple_macro!(2815); + simple_macro!(2816); + simple_macro!(2817); + simple_macro!(2818); + simple_macro!(2819); + simple_macro!(2820); + simple_macro!(2821); + simple_macro!(2822); + simple_macro!(2823); + simple_macro!(2824); + simple_macro!(2825); + simple_macro!(2826); + simple_macro!(2827); + simple_macro!(2828); + simple_macro!(2829); + simple_macro!(2830); + simple_macro!(2831); + simple_macro!(2832); + simple_macro!(2833); + simple_macro!(2834); + simple_macro!(2835); + simple_macro!(2836); + simple_macro!(2837); + simple_macro!(2838); + simple_macro!(2839); + simple_macro!(2840); + simple_macro!(2841); + simple_macro!(2842); + simple_macro!(2843); + simple_macro!(2844); + simple_macro!(2845); + simple_macro!(2846); + simple_macro!(2847); + simple_macro!(2848); + simple_macro!(2849); + simple_macro!(2850); + simple_macro!(2851); + simple_macro!(2852); + simple_macro!(2853); + simple_macro!(2854); + simple_macro!(2855); + simple_macro!(2856); + simple_macro!(2857); + simple_macro!(2858); + simple_macro!(2859); + simple_macro!(2860); + simple_macro!(2861); + simple_macro!(2862); + simple_macro!(2863); + simple_macro!(2864); + simple_macro!(2865); + simple_macro!(2866); + simple_macro!(2867); + simple_macro!(2868); + simple_macro!(2869); + simple_macro!(2870); + simple_macro!(2871); + simple_macro!(2872); + simple_macro!(2873); + simple_macro!(2874); + simple_macro!(2875); + simple_macro!(2876); + simple_macro!(2877); + simple_macro!(2878); + simple_macro!(2879); + simple_macro!(2880); + simple_macro!(2881); + simple_macro!(2882); + simple_macro!(2883); + simple_macro!(2884); + simple_macro!(2885); + simple_macro!(2886); + simple_macro!(2887); + simple_macro!(2888); + simple_macro!(2889); + simple_macro!(2890); + simple_macro!(2891); + simple_macro!(2892); + simple_macro!(2893); + simple_macro!(2894); + simple_macro!(2895); + simple_macro!(2896); + simple_macro!(2897); + simple_macro!(2898); + simple_macro!(2899); + simple_macro!(2900); + simple_macro!(2901); + simple_macro!(2902); + simple_macro!(2903); + simple_macro!(2904); + simple_macro!(2905); + simple_macro!(2906); + simple_macro!(2907); + simple_macro!(2908); + simple_macro!(2909); + simple_macro!(2910); + simple_macro!(2911); + simple_macro!(2912); + simple_macro!(2913); + simple_macro!(2914); + simple_macro!(2915); + simple_macro!(2916); + simple_macro!(2917); + simple_macro!(2918); + simple_macro!(2919); + simple_macro!(2920); + simple_macro!(2921); + simple_macro!(2922); + simple_macro!(2923); + simple_macro!(2924); + simple_macro!(2925); + simple_macro!(2926); + simple_macro!(2927); + simple_macro!(2928); + simple_macro!(2929); + simple_macro!(2930); + simple_macro!(2931); + simple_macro!(2932); + simple_macro!(2933); + simple_macro!(2934); + simple_macro!(2935); + simple_macro!(2936); + simple_macro!(2937); + simple_macro!(2938); + simple_macro!(2939); + simple_macro!(2940); + simple_macro!(2941); + simple_macro!(2942); + simple_macro!(2943); + simple_macro!(2944); + simple_macro!(2945); + simple_macro!(2946); + simple_macro!(2947); + simple_macro!(2948); + simple_macro!(2949); + simple_macro!(2950); + simple_macro!(2951); + simple_macro!(2952); + simple_macro!(2953); + simple_macro!(2954); + simple_macro!(2955); + simple_macro!(2956); + simple_macro!(2957); + simple_macro!(2958); + simple_macro!(2959); + simple_macro!(2960); + simple_macro!(2961); + simple_macro!(2962); + simple_macro!(2963); + simple_macro!(2964); + simple_macro!(2965); + simple_macro!(2966); + simple_macro!(2967); + simple_macro!(2968); + simple_macro!(2969); + simple_macro!(2970); + simple_macro!(2971); + simple_macro!(2972); + simple_macro!(2973); + simple_macro!(2974); + simple_macro!(2975); + simple_macro!(2976); + simple_macro!(2977); + simple_macro!(2978); + simple_macro!(2979); + simple_macro!(2980); + simple_macro!(2981); + simple_macro!(2982); + simple_macro!(2983); + simple_macro!(2984); + simple_macro!(2985); + simple_macro!(2986); + simple_macro!(2987); + simple_macro!(2988); + simple_macro!(2989); + simple_macro!(2990); + simple_macro!(2991); + simple_macro!(2992); + simple_macro!(2993); + simple_macro!(2994); + simple_macro!(2995); + simple_macro!(2996); + simple_macro!(2997); + simple_macro!(2998); + simple_macro!(2999); + simple_macro!(3000); + simple_macro!(3001); + simple_macro!(3002); + simple_macro!(3003); + simple_macro!(3004); + simple_macro!(3005); + simple_macro!(3006); + simple_macro!(3007); + simple_macro!(3008); + simple_macro!(3009); + simple_macro!(3010); + simple_macro!(3011); + simple_macro!(3012); + simple_macro!(3013); + simple_macro!(3014); + simple_macro!(3015); + simple_macro!(3016); + simple_macro!(3017); + simple_macro!(3018); + simple_macro!(3019); + simple_macro!(3020); + simple_macro!(3021); + simple_macro!(3022); + simple_macro!(3023); + simple_macro!(3024); + simple_macro!(3025); + simple_macro!(3026); + simple_macro!(3027); + simple_macro!(3028); + simple_macro!(3029); + simple_macro!(3030); + simple_macro!(3031); + simple_macro!(3032); + simple_macro!(3033); + simple_macro!(3034); + simple_macro!(3035); + simple_macro!(3036); + simple_macro!(3037); + simple_macro!(3038); + simple_macro!(3039); + simple_macro!(3040); + simple_macro!(3041); + simple_macro!(3042); + simple_macro!(3043); + simple_macro!(3044); + simple_macro!(3045); + simple_macro!(3046); + simple_macro!(3047); + simple_macro!(3048); + simple_macro!(3049); + simple_macro!(3050); + simple_macro!(3051); + simple_macro!(3052); + simple_macro!(3053); + simple_macro!(3054); + simple_macro!(3055); + simple_macro!(3056); + simple_macro!(3057); + simple_macro!(3058); + simple_macro!(3059); + simple_macro!(3060); + simple_macro!(3061); + simple_macro!(3062); + simple_macro!(3063); + simple_macro!(3064); + simple_macro!(3065); + simple_macro!(3066); + simple_macro!(3067); + simple_macro!(3068); + simple_macro!(3069); + simple_macro!(3070); + simple_macro!(3071); + simple_macro!(3072); + simple_macro!(3073); + simple_macro!(3074); + simple_macro!(3075); + simple_macro!(3076); + simple_macro!(3077); + simple_macro!(3078); + simple_macro!(3079); + simple_macro!(3080); + simple_macro!(3081); + simple_macro!(3082); + simple_macro!(3083); + simple_macro!(3084); + simple_macro!(3085); + simple_macro!(3086); + simple_macro!(3087); + simple_macro!(3088); + simple_macro!(3089); + simple_macro!(3090); + simple_macro!(3091); + simple_macro!(3092); + simple_macro!(3093); + simple_macro!(3094); + simple_macro!(3095); + simple_macro!(3096); + simple_macro!(3097); + simple_macro!(3098); + simple_macro!(3099); + simple_macro!(3100); + simple_macro!(3101); + simple_macro!(3102); + simple_macro!(3103); + simple_macro!(3104); + simple_macro!(3105); + simple_macro!(3106); + simple_macro!(3107); + simple_macro!(3108); + simple_macro!(3109); + simple_macro!(3110); + simple_macro!(3111); + simple_macro!(3112); + simple_macro!(3113); + simple_macro!(3114); + simple_macro!(3115); + simple_macro!(3116); + simple_macro!(3117); + simple_macro!(3118); + simple_macro!(3119); + simple_macro!(3120); + simple_macro!(3121); + simple_macro!(3122); + simple_macro!(3123); + simple_macro!(3124); + simple_macro!(3125); + simple_macro!(3126); + simple_macro!(3127); + simple_macro!(3128); + simple_macro!(3129); + simple_macro!(3130); + simple_macro!(3131); + simple_macro!(3132); + simple_macro!(3133); + simple_macro!(3134); + simple_macro!(3135); + simple_macro!(3136); + simple_macro!(3137); + simple_macro!(3138); + simple_macro!(3139); + simple_macro!(3140); + simple_macro!(3141); + simple_macro!(3142); + simple_macro!(3143); + simple_macro!(3144); + simple_macro!(3145); + simple_macro!(3146); + simple_macro!(3147); + simple_macro!(3148); + simple_macro!(3149); + simple_macro!(3150); + simple_macro!(3151); + simple_macro!(3152); + simple_macro!(3153); + simple_macro!(3154); + simple_macro!(3155); + simple_macro!(3156); + simple_macro!(3157); + simple_macro!(3158); + simple_macro!(3159); + simple_macro!(3160); + simple_macro!(3161); + simple_macro!(3162); + simple_macro!(3163); + simple_macro!(3164); + simple_macro!(3165); + simple_macro!(3166); + simple_macro!(3167); + simple_macro!(3168); + simple_macro!(3169); + simple_macro!(3170); + simple_macro!(3171); + simple_macro!(3172); + simple_macro!(3173); + simple_macro!(3174); + simple_macro!(3175); + simple_macro!(3176); + simple_macro!(3177); + simple_macro!(3178); + simple_macro!(3179); + simple_macro!(3180); + simple_macro!(3181); + simple_macro!(3182); + simple_macro!(3183); + simple_macro!(3184); + simple_macro!(3185); + simple_macro!(3186); + simple_macro!(3187); + simple_macro!(3188); + simple_macro!(3189); + simple_macro!(3190); + simple_macro!(3191); + simple_macro!(3192); + simple_macro!(3193); + simple_macro!(3194); + simple_macro!(3195); + simple_macro!(3196); + simple_macro!(3197); + simple_macro!(3198); + simple_macro!(3199); + simple_macro!(3200); + simple_macro!(3201); + simple_macro!(3202); + simple_macro!(3203); + simple_macro!(3204); + simple_macro!(3205); + simple_macro!(3206); + simple_macro!(3207); + simple_macro!(3208); + simple_macro!(3209); + simple_macro!(3210); + simple_macro!(3211); + simple_macro!(3212); + simple_macro!(3213); + simple_macro!(3214); + simple_macro!(3215); + simple_macro!(3216); + simple_macro!(3217); + simple_macro!(3218); + simple_macro!(3219); + simple_macro!(3220); + simple_macro!(3221); + simple_macro!(3222); + simple_macro!(3223); + simple_macro!(3224); + simple_macro!(3225); + simple_macro!(3226); + simple_macro!(3227); + simple_macro!(3228); + simple_macro!(3229); + simple_macro!(3230); + simple_macro!(3231); + simple_macro!(3232); + simple_macro!(3233); + simple_macro!(3234); + simple_macro!(3235); + simple_macro!(3236); + simple_macro!(3237); + simple_macro!(3238); + simple_macro!(3239); + simple_macro!(3240); + simple_macro!(3241); + simple_macro!(3242); + simple_macro!(3243); + simple_macro!(3244); + simple_macro!(3245); + simple_macro!(3246); + simple_macro!(3247); + simple_macro!(3248); + simple_macro!(3249); + simple_macro!(3250); + simple_macro!(3251); + simple_macro!(3252); + simple_macro!(3253); + simple_macro!(3254); + simple_macro!(3255); + simple_macro!(3256); + simple_macro!(3257); + simple_macro!(3258); + simple_macro!(3259); + simple_macro!(3260); + simple_macro!(3261); + simple_macro!(3262); + simple_macro!(3263); + simple_macro!(3264); + simple_macro!(3265); + simple_macro!(3266); + simple_macro!(3267); + simple_macro!(3268); + simple_macro!(3269); + simple_macro!(3270); + simple_macro!(3271); + simple_macro!(3272); + simple_macro!(3273); + simple_macro!(3274); + simple_macro!(3275); + simple_macro!(3276); + simple_macro!(3277); + simple_macro!(3278); + simple_macro!(3279); + simple_macro!(3280); + simple_macro!(3281); + simple_macro!(3282); + simple_macro!(3283); + simple_macro!(3284); + simple_macro!(3285); + simple_macro!(3286); + simple_macro!(3287); + simple_macro!(3288); + simple_macro!(3289); + simple_macro!(3290); + simple_macro!(3291); + simple_macro!(3292); + simple_macro!(3293); + simple_macro!(3294); + simple_macro!(3295); + simple_macro!(3296); + simple_macro!(3297); + simple_macro!(3298); + simple_macro!(3299); + simple_macro!(3300); + simple_macro!(3301); + simple_macro!(3302); + simple_macro!(3303); + simple_macro!(3304); + simple_macro!(3305); + simple_macro!(3306); + simple_macro!(3307); + simple_macro!(3308); + simple_macro!(3309); + simple_macro!(3310); + simple_macro!(3311); + simple_macro!(3312); + simple_macro!(3313); + simple_macro!(3314); + simple_macro!(3315); + simple_macro!(3316); + simple_macro!(3317); + simple_macro!(3318); + simple_macro!(3319); + simple_macro!(3320); + simple_macro!(3321); + simple_macro!(3322); + simple_macro!(3323); + simple_macro!(3324); + simple_macro!(3325); + simple_macro!(3326); + simple_macro!(3327); + simple_macro!(3328); + simple_macro!(3329); + simple_macro!(3330); + simple_macro!(3331); + simple_macro!(3332); + simple_macro!(3333); + simple_macro!(3334); + simple_macro!(3335); + simple_macro!(3336); + simple_macro!(3337); + simple_macro!(3338); + simple_macro!(3339); + simple_macro!(3340); + simple_macro!(3341); + simple_macro!(3342); + simple_macro!(3343); + simple_macro!(3344); + simple_macro!(3345); + simple_macro!(3346); + simple_macro!(3347); + simple_macro!(3348); + simple_macro!(3349); + simple_macro!(3350); + simple_macro!(3351); + simple_macro!(3352); + simple_macro!(3353); + simple_macro!(3354); + simple_macro!(3355); + simple_macro!(3356); + simple_macro!(3357); + simple_macro!(3358); + simple_macro!(3359); + simple_macro!(3360); + simple_macro!(3361); + simple_macro!(3362); + simple_macro!(3363); + simple_macro!(3364); + simple_macro!(3365); + simple_macro!(3366); + simple_macro!(3367); + simple_macro!(3368); + simple_macro!(3369); + simple_macro!(3370); + simple_macro!(3371); + simple_macro!(3372); + simple_macro!(3373); + simple_macro!(3374); + simple_macro!(3375); + simple_macro!(3376); + simple_macro!(3377); + simple_macro!(3378); + simple_macro!(3379); + simple_macro!(3380); + simple_macro!(3381); + simple_macro!(3382); + simple_macro!(3383); + simple_macro!(3384); + simple_macro!(3385); + simple_macro!(3386); + simple_macro!(3387); + simple_macro!(3388); + simple_macro!(3389); + simple_macro!(3390); + simple_macro!(3391); + simple_macro!(3392); + simple_macro!(3393); + simple_macro!(3394); + simple_macro!(3395); + simple_macro!(3396); + simple_macro!(3397); + simple_macro!(3398); + simple_macro!(3399); + simple_macro!(3400); + simple_macro!(3401); + simple_macro!(3402); + simple_macro!(3403); + simple_macro!(3404); + simple_macro!(3405); + simple_macro!(3406); + simple_macro!(3407); + simple_macro!(3408); + simple_macro!(3409); + simple_macro!(3410); + simple_macro!(3411); + simple_macro!(3412); + simple_macro!(3413); + simple_macro!(3414); + simple_macro!(3415); + simple_macro!(3416); + simple_macro!(3417); + simple_macro!(3418); + simple_macro!(3419); + simple_macro!(3420); + simple_macro!(3421); + simple_macro!(3422); + simple_macro!(3423); + simple_macro!(3424); + simple_macro!(3425); + simple_macro!(3426); + simple_macro!(3427); + simple_macro!(3428); + simple_macro!(3429); + simple_macro!(3430); + simple_macro!(3431); + simple_macro!(3432); + simple_macro!(3433); + simple_macro!(3434); + simple_macro!(3435); + simple_macro!(3436); + simple_macro!(3437); + simple_macro!(3438); + simple_macro!(3439); + simple_macro!(3440); + simple_macro!(3441); + simple_macro!(3442); + simple_macro!(3443); + simple_macro!(3444); + simple_macro!(3445); + simple_macro!(3446); + simple_macro!(3447); + simple_macro!(3448); + simple_macro!(3449); + simple_macro!(3450); + simple_macro!(3451); + simple_macro!(3452); + simple_macro!(3453); + simple_macro!(3454); + simple_macro!(3455); + simple_macro!(3456); + simple_macro!(3457); + simple_macro!(3458); + simple_macro!(3459); + simple_macro!(3460); + simple_macro!(3461); + simple_macro!(3462); + simple_macro!(3463); + simple_macro!(3464); + simple_macro!(3465); + simple_macro!(3466); + simple_macro!(3467); + simple_macro!(3468); + simple_macro!(3469); + simple_macro!(3470); + simple_macro!(3471); + simple_macro!(3472); + simple_macro!(3473); + simple_macro!(3474); + simple_macro!(3475); + simple_macro!(3476); + simple_macro!(3477); + simple_macro!(3478); + simple_macro!(3479); + simple_macro!(3480); + simple_macro!(3481); + simple_macro!(3482); + simple_macro!(3483); + simple_macro!(3484); + simple_macro!(3485); + simple_macro!(3486); + simple_macro!(3487); + simple_macro!(3488); + simple_macro!(3489); + simple_macro!(3490); + simple_macro!(3491); + simple_macro!(3492); + simple_macro!(3493); + simple_macro!(3494); + simple_macro!(3495); + simple_macro!(3496); + simple_macro!(3497); + simple_macro!(3498); + simple_macro!(3499); + simple_macro!(3500); + simple_macro!(3501); + simple_macro!(3502); + simple_macro!(3503); + simple_macro!(3504); + simple_macro!(3505); + simple_macro!(3506); + simple_macro!(3507); + simple_macro!(3508); + simple_macro!(3509); + simple_macro!(3510); + simple_macro!(3511); + simple_macro!(3512); + simple_macro!(3513); + simple_macro!(3514); + simple_macro!(3515); + simple_macro!(3516); + simple_macro!(3517); + simple_macro!(3518); + simple_macro!(3519); + simple_macro!(3520); + simple_macro!(3521); + simple_macro!(3522); + simple_macro!(3523); + simple_macro!(3524); + simple_macro!(3525); + simple_macro!(3526); + simple_macro!(3527); + simple_macro!(3528); + simple_macro!(3529); + simple_macro!(3530); + simple_macro!(3531); + simple_macro!(3532); + simple_macro!(3533); + simple_macro!(3534); + simple_macro!(3535); + simple_macro!(3536); + simple_macro!(3537); + simple_macro!(3538); + simple_macro!(3539); + simple_macro!(3540); + simple_macro!(3541); + simple_macro!(3542); + simple_macro!(3543); + simple_macro!(3544); + simple_macro!(3545); + simple_macro!(3546); + simple_macro!(3547); + simple_macro!(3548); + simple_macro!(3549); + simple_macro!(3550); + simple_macro!(3551); + simple_macro!(3552); + simple_macro!(3553); + simple_macro!(3554); + simple_macro!(3555); + simple_macro!(3556); + simple_macro!(3557); + simple_macro!(3558); + simple_macro!(3559); + simple_macro!(3560); + simple_macro!(3561); + simple_macro!(3562); + simple_macro!(3563); + simple_macro!(3564); + simple_macro!(3565); + simple_macro!(3566); + simple_macro!(3567); + simple_macro!(3568); + simple_macro!(3569); + simple_macro!(3570); + simple_macro!(3571); + simple_macro!(3572); + simple_macro!(3573); + simple_macro!(3574); + simple_macro!(3575); + simple_macro!(3576); + simple_macro!(3577); + simple_macro!(3578); + simple_macro!(3579); + simple_macro!(3580); + simple_macro!(3581); + simple_macro!(3582); + simple_macro!(3583); + simple_macro!(3584); + simple_macro!(3585); + simple_macro!(3586); + simple_macro!(3587); + simple_macro!(3588); + simple_macro!(3589); + simple_macro!(3590); + simple_macro!(3591); + simple_macro!(3592); + simple_macro!(3593); + simple_macro!(3594); + simple_macro!(3595); + simple_macro!(3596); + simple_macro!(3597); + simple_macro!(3598); + simple_macro!(3599); + simple_macro!(3600); + simple_macro!(3601); + simple_macro!(3602); + simple_macro!(3603); + simple_macro!(3604); + simple_macro!(3605); + simple_macro!(3606); + simple_macro!(3607); + simple_macro!(3608); + simple_macro!(3609); + simple_macro!(3610); + simple_macro!(3611); + simple_macro!(3612); + simple_macro!(3613); + simple_macro!(3614); + simple_macro!(3615); + simple_macro!(3616); + simple_macro!(3617); + simple_macro!(3618); + simple_macro!(3619); + simple_macro!(3620); + simple_macro!(3621); + simple_macro!(3622); + simple_macro!(3623); + simple_macro!(3624); + simple_macro!(3625); + simple_macro!(3626); + simple_macro!(3627); + simple_macro!(3628); + simple_macro!(3629); + simple_macro!(3630); + simple_macro!(3631); + simple_macro!(3632); + simple_macro!(3633); + simple_macro!(3634); + simple_macro!(3635); + simple_macro!(3636); + simple_macro!(3637); + simple_macro!(3638); + simple_macro!(3639); + simple_macro!(3640); + simple_macro!(3641); + simple_macro!(3642); + simple_macro!(3643); + simple_macro!(3644); + simple_macro!(3645); + simple_macro!(3646); + simple_macro!(3647); + simple_macro!(3648); + simple_macro!(3649); + simple_macro!(3650); + simple_macro!(3651); + simple_macro!(3652); + simple_macro!(3653); + simple_macro!(3654); + simple_macro!(3655); + simple_macro!(3656); + simple_macro!(3657); + simple_macro!(3658); + simple_macro!(3659); + simple_macro!(3660); + simple_macro!(3661); + simple_macro!(3662); + simple_macro!(3663); + simple_macro!(3664); + simple_macro!(3665); + simple_macro!(3666); + simple_macro!(3667); + simple_macro!(3668); + simple_macro!(3669); + simple_macro!(3670); + simple_macro!(3671); + simple_macro!(3672); + simple_macro!(3673); + simple_macro!(3674); + simple_macro!(3675); + simple_macro!(3676); + simple_macro!(3677); + simple_macro!(3678); + simple_macro!(3679); + simple_macro!(3680); + simple_macro!(3681); + simple_macro!(3682); + simple_macro!(3683); + simple_macro!(3684); + simple_macro!(3685); + simple_macro!(3686); + simple_macro!(3687); + simple_macro!(3688); + simple_macro!(3689); + simple_macro!(3690); + simple_macro!(3691); + simple_macro!(3692); + simple_macro!(3693); + simple_macro!(3694); + simple_macro!(3695); + simple_macro!(3696); + simple_macro!(3697); + simple_macro!(3698); + simple_macro!(3699); + simple_macro!(3700); + simple_macro!(3701); + simple_macro!(3702); + simple_macro!(3703); + simple_macro!(3704); + simple_macro!(3705); + simple_macro!(3706); + simple_macro!(3707); + simple_macro!(3708); + simple_macro!(3709); + simple_macro!(3710); + simple_macro!(3711); + simple_macro!(3712); + simple_macro!(3713); + simple_macro!(3714); + simple_macro!(3715); + simple_macro!(3716); + simple_macro!(3717); + simple_macro!(3718); + simple_macro!(3719); + simple_macro!(3720); + simple_macro!(3721); + simple_macro!(3722); + simple_macro!(3723); + simple_macro!(3724); + simple_macro!(3725); + simple_macro!(3726); + simple_macro!(3727); + simple_macro!(3728); + simple_macro!(3729); + simple_macro!(3730); + simple_macro!(3731); + simple_macro!(3732); + simple_macro!(3733); + simple_macro!(3734); + simple_macro!(3735); + simple_macro!(3736); + simple_macro!(3737); + simple_macro!(3738); + simple_macro!(3739); + simple_macro!(3740); + simple_macro!(3741); + simple_macro!(3742); + simple_macro!(3743); + simple_macro!(3744); + simple_macro!(3745); + simple_macro!(3746); + simple_macro!(3747); + simple_macro!(3748); + simple_macro!(3749); + simple_macro!(3750); + simple_macro!(3751); + simple_macro!(3752); + simple_macro!(3753); + simple_macro!(3754); + simple_macro!(3755); + simple_macro!(3756); + simple_macro!(3757); + simple_macro!(3758); + simple_macro!(3759); + simple_macro!(3760); + simple_macro!(3761); + simple_macro!(3762); + simple_macro!(3763); + simple_macro!(3764); + simple_macro!(3765); + simple_macro!(3766); + simple_macro!(3767); + simple_macro!(3768); + simple_macro!(3769); + simple_macro!(3770); + simple_macro!(3771); + simple_macro!(3772); + simple_macro!(3773); + simple_macro!(3774); + simple_macro!(3775); + simple_macro!(3776); + simple_macro!(3777); + simple_macro!(3778); + simple_macro!(3779); + simple_macro!(3780); + simple_macro!(3781); + simple_macro!(3782); + simple_macro!(3783); + simple_macro!(3784); + simple_macro!(3785); + simple_macro!(3786); + simple_macro!(3787); + simple_macro!(3788); + simple_macro!(3789); + simple_macro!(3790); + simple_macro!(3791); + simple_macro!(3792); + simple_macro!(3793); + simple_macro!(3794); + simple_macro!(3795); + simple_macro!(3796); + simple_macro!(3797); + simple_macro!(3798); + simple_macro!(3799); + simple_macro!(3800); + simple_macro!(3801); + simple_macro!(3802); + simple_macro!(3803); + simple_macro!(3804); + simple_macro!(3805); + simple_macro!(3806); + simple_macro!(3807); + simple_macro!(3808); + simple_macro!(3809); + simple_macro!(3810); + simple_macro!(3811); + simple_macro!(3812); + simple_macro!(3813); + simple_macro!(3814); + simple_macro!(3815); + simple_macro!(3816); + simple_macro!(3817); + simple_macro!(3818); + simple_macro!(3819); + simple_macro!(3820); + simple_macro!(3821); + simple_macro!(3822); + simple_macro!(3823); + simple_macro!(3824); + simple_macro!(3825); + simple_macro!(3826); + simple_macro!(3827); + simple_macro!(3828); + simple_macro!(3829); + simple_macro!(3830); + simple_macro!(3831); + simple_macro!(3832); + simple_macro!(3833); + simple_macro!(3834); + simple_macro!(3835); + simple_macro!(3836); + simple_macro!(3837); + simple_macro!(3838); + simple_macro!(3839); + simple_macro!(3840); + simple_macro!(3841); + simple_macro!(3842); + simple_macro!(3843); + simple_macro!(3844); + simple_macro!(3845); + simple_macro!(3846); + simple_macro!(3847); + simple_macro!(3848); + simple_macro!(3849); + simple_macro!(3850); + simple_macro!(3851); + simple_macro!(3852); + simple_macro!(3853); + simple_macro!(3854); + simple_macro!(3855); + simple_macro!(3856); + simple_macro!(3857); + simple_macro!(3858); + simple_macro!(3859); + simple_macro!(3860); + simple_macro!(3861); + simple_macro!(3862); + simple_macro!(3863); + simple_macro!(3864); + simple_macro!(3865); + simple_macro!(3866); + simple_macro!(3867); + simple_macro!(3868); + simple_macro!(3869); + simple_macro!(3870); + simple_macro!(3871); + simple_macro!(3872); + simple_macro!(3873); + simple_macro!(3874); + simple_macro!(3875); + simple_macro!(3876); + simple_macro!(3877); + simple_macro!(3878); + simple_macro!(3879); + simple_macro!(3880); + simple_macro!(3881); + simple_macro!(3882); + simple_macro!(3883); + simple_macro!(3884); + simple_macro!(3885); + simple_macro!(3886); + simple_macro!(3887); + simple_macro!(3888); + simple_macro!(3889); + simple_macro!(3890); + simple_macro!(3891); + simple_macro!(3892); + simple_macro!(3893); + simple_macro!(3894); + simple_macro!(3895); + simple_macro!(3896); + simple_macro!(3897); + simple_macro!(3898); + simple_macro!(3899); + simple_macro!(3900); + simple_macro!(3901); + simple_macro!(3902); + simple_macro!(3903); + simple_macro!(3904); + simple_macro!(3905); + simple_macro!(3906); + simple_macro!(3907); + simple_macro!(3908); + simple_macro!(3909); + simple_macro!(3910); + simple_macro!(3911); + simple_macro!(3912); + simple_macro!(3913); + simple_macro!(3914); + simple_macro!(3915); + simple_macro!(3916); + simple_macro!(3917); + simple_macro!(3918); + simple_macro!(3919); + simple_macro!(3920); + simple_macro!(3921); + simple_macro!(3922); + simple_macro!(3923); + simple_macro!(3924); + simple_macro!(3925); + simple_macro!(3926); + simple_macro!(3927); + simple_macro!(3928); + simple_macro!(3929); + simple_macro!(3930); + simple_macro!(3931); + simple_macro!(3932); + simple_macro!(3933); + simple_macro!(3934); + simple_macro!(3935); + simple_macro!(3936); + simple_macro!(3937); + simple_macro!(3938); + simple_macro!(3939); + simple_macro!(3940); + simple_macro!(3941); + simple_macro!(3942); + simple_macro!(3943); + simple_macro!(3944); + simple_macro!(3945); + simple_macro!(3946); + simple_macro!(3947); + simple_macro!(3948); + simple_macro!(3949); + simple_macro!(3950); + simple_macro!(3951); + simple_macro!(3952); + simple_macro!(3953); + simple_macro!(3954); + simple_macro!(3955); + simple_macro!(3956); + simple_macro!(3957); + simple_macro!(3958); + simple_macro!(3959); + simple_macro!(3960); + simple_macro!(3961); + simple_macro!(3962); + simple_macro!(3963); + simple_macro!(3964); + simple_macro!(3965); + simple_macro!(3966); + simple_macro!(3967); + simple_macro!(3968); + simple_macro!(3969); + simple_macro!(3970); + simple_macro!(3971); + simple_macro!(3972); + simple_macro!(3973); + simple_macro!(3974); + simple_macro!(3975); + simple_macro!(3976); + simple_macro!(3977); + simple_macro!(3978); + simple_macro!(3979); + simple_macro!(3980); + simple_macro!(3981); + simple_macro!(3982); + simple_macro!(3983); + simple_macro!(3984); + simple_macro!(3985); + simple_macro!(3986); + simple_macro!(3987); + simple_macro!(3988); + simple_macro!(3989); + simple_macro!(3990); + simple_macro!(3991); + simple_macro!(3992); + simple_macro!(3993); + simple_macro!(3994); + simple_macro!(3995); + simple_macro!(3996); + simple_macro!(3997); + simple_macro!(3998); + simple_macro!(3999); + simple_macro!(4000); + simple_macro!(4001); + simple_macro!(4002); + simple_macro!(4003); + simple_macro!(4004); + simple_macro!(4005); + simple_macro!(4006); + simple_macro!(4007); + simple_macro!(4008); + simple_macro!(4009); + simple_macro!(4010); + simple_macro!(4011); + simple_macro!(4012); + simple_macro!(4013); + simple_macro!(4014); + simple_macro!(4015); + simple_macro!(4016); + simple_macro!(4017); + simple_macro!(4018); + simple_macro!(4019); + simple_macro!(4020); + simple_macro!(4021); + simple_macro!(4022); + simple_macro!(4023); + simple_macro!(4024); + simple_macro!(4025); + simple_macro!(4026); + simple_macro!(4027); + simple_macro!(4028); + simple_macro!(4029); + simple_macro!(4030); + simple_macro!(4031); + simple_macro!(4032); + simple_macro!(4033); + simple_macro!(4034); + simple_macro!(4035); + simple_macro!(4036); + simple_macro!(4037); + simple_macro!(4038); + simple_macro!(4039); + simple_macro!(4040); + simple_macro!(4041); + simple_macro!(4042); + simple_macro!(4043); + simple_macro!(4044); + simple_macro!(4045); + simple_macro!(4046); + simple_macro!(4047); + simple_macro!(4048); + simple_macro!(4049); + simple_macro!(4050); + simple_macro!(4051); + simple_macro!(4052); + simple_macro!(4053); + simple_macro!(4054); + simple_macro!(4055); + simple_macro!(4056); + simple_macro!(4057); + simple_macro!(4058); + simple_macro!(4059); + simple_macro!(4060); + simple_macro!(4061); + simple_macro!(4062); + simple_macro!(4063); + simple_macro!(4064); + simple_macro!(4065); + simple_macro!(4066); + simple_macro!(4067); + simple_macro!(4068); + simple_macro!(4069); + simple_macro!(4070); + simple_macro!(4071); + simple_macro!(4072); + simple_macro!(4073); + simple_macro!(4074); + simple_macro!(4075); + simple_macro!(4076); + simple_macro!(4077); + simple_macro!(4078); + simple_macro!(4079); + simple_macro!(4080); + simple_macro!(4081); + simple_macro!(4082); + simple_macro!(4083); + simple_macro!(4084); + simple_macro!(4085); + simple_macro!(4086); + simple_macro!(4087); + simple_macro!(4088); + simple_macro!(4089); + simple_macro!(4090); + simple_macro!(4091); + simple_macro!(4092); + simple_macro!(4093); + simple_macro!(4094); + simple_macro!(4095); + simple_macro!(4096); + simple_macro!(4097); +} + +fn main() { + uncollapsed_debuginfo(); +} diff --git a/tests/ui/explore-issue-38412.rs b/tests/ui/explore-issue-38412.rs index e1295a96ba5f..2008b120faae 100644 --- a/tests/ui/explore-issue-38412.rs +++ b/tests/ui/explore-issue-38412.rs @@ -1,9 +1,9 @@ //@ aux-build:pub-and-stability.rs -// A big point of this test is that we *declare* `unstable_declared`, -// but do *not* declare `unstable_undeclared`. This way we can check -// that the compiler is letting in uses of declared feature-gated -// stuff but still rejecting uses of undeclared feature-gated stuff. +// A big point of this test is that we *enable* `unstable_declared`, +// but do *not* enable `unstable_undeclared`. This way we can check +// that the compiler is letting in uses of enabled feature-gated +// stuff but still rejecting uses of disabled feature-gated stuff. #![feature(unstable_declared)] extern crate pub_and_stability; diff --git a/tests/ui/feature-gates/feature-gate-large-assignments.rs b/tests/ui/feature-gates/feature-gate-large-assignments.rs index 7e9e574bfa08..c4125c557223 100644 --- a/tests/ui/feature-gates/feature-gate-large-assignments.rs +++ b/tests/ui/feature-gates/feature-gate-large-assignments.rs @@ -1,4 +1,4 @@ -// check that `move_size_limit is feature-gated +// check that `move_size_limit` is feature-gated #![move_size_limit = "42"] //~ ERROR the `#[move_size_limit]` attribute is an experimental feature diff --git a/tests/ui/feature-gates/feature-gate-link-arg-attribute.stderr b/tests/ui/feature-gates/feature-gate-link-arg-attribute.in_attr.stderr similarity index 91% rename from tests/ui/feature-gates/feature-gate-link-arg-attribute.stderr rename to tests/ui/feature-gates/feature-gate-link-arg-attribute.in_attr.stderr index 8cbad78478e1..3ea8c89bf3ae 100644 --- a/tests/ui/feature-gates/feature-gate-link-arg-attribute.stderr +++ b/tests/ui/feature-gates/feature-gate-link-arg-attribute.in_attr.stderr @@ -1,5 +1,5 @@ error[E0658]: link kind `link-arg` is unstable - --> $DIR/feature-gate-link-arg-attribute.rs:1:15 + --> $DIR/feature-gate-link-arg-attribute.rs:5:15 | LL | #[link(kind = "link-arg", name = "foo")] | ^^^^^^^^^^ diff --git a/tests/ui/feature-gates/feature-gate-link-arg-attribute.in_flag.stderr b/tests/ui/feature-gates/feature-gate-link-arg-attribute.in_flag.stderr new file mode 100644 index 000000000000..4d65db3c66d0 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-link-arg-attribute.in_flag.stderr @@ -0,0 +1,2 @@ +error: unknown linking modifier `link-arg`, expected one of: bundle, verbatim, whole-archive, as-needed + diff --git a/tests/ui/feature-gates/feature-gate-link-arg-attribute.rs b/tests/ui/feature-gates/feature-gate-link-arg-attribute.rs index 9036095fbc49..c12ff5b04dc3 100644 --- a/tests/ui/feature-gates/feature-gate-link-arg-attribute.rs +++ b/tests/ui/feature-gates/feature-gate-link-arg-attribute.rs @@ -1,5 +1,9 @@ +//@ revisions: in_attr in_flag +//@[in_flag] compile-flags: -l dylib:+link-arg=foo + +#[cfg(in_attr)] #[link(kind = "link-arg", name = "foo")] -//~^ ERROR link kind `link-arg` is unstable +//[in_attr]~^ ERROR link kind `link-arg` is unstable extern "C" {} fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-native_link_modifiers_as_needed.stderr b/tests/ui/feature-gates/feature-gate-native_link_modifiers_as_needed.in_attr.stderr similarity index 90% rename from tests/ui/feature-gates/feature-gate-native_link_modifiers_as_needed.stderr rename to tests/ui/feature-gates/feature-gate-native_link_modifiers_as_needed.in_attr.stderr index 216477828e73..11b7abc883e1 100644 --- a/tests/ui/feature-gates/feature-gate-native_link_modifiers_as_needed.stderr +++ b/tests/ui/feature-gates/feature-gate-native_link_modifiers_as_needed.in_attr.stderr @@ -1,5 +1,5 @@ error[E0658]: linking modifier `as-needed` is unstable - --> $DIR/feature-gate-native_link_modifiers_as_needed.rs:1:50 + --> $DIR/feature-gate-native_link_modifiers_as_needed.rs:5:50 | LL | #[link(name = "foo", kind = "dylib", modifiers = "+as-needed")] | ^^^^^^^^^^^^ diff --git a/tests/ui/feature-gates/feature-gate-native_link_modifiers_as_needed.in_flag.stderr b/tests/ui/feature-gates/feature-gate-native_link_modifiers_as_needed.in_flag.stderr new file mode 100644 index 000000000000..8f74e9d6f169 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-native_link_modifiers_as_needed.in_flag.stderr @@ -0,0 +1,2 @@ +error: linking modifier `as-needed` is unstable, the `-Z unstable-options` flag must also be passed to use it + diff --git a/tests/ui/feature-gates/feature-gate-native_link_modifiers_as_needed.rs b/tests/ui/feature-gates/feature-gate-native_link_modifiers_as_needed.rs index 132bc6ab04af..c2965e42f276 100644 --- a/tests/ui/feature-gates/feature-gate-native_link_modifiers_as_needed.rs +++ b/tests/ui/feature-gates/feature-gate-native_link_modifiers_as_needed.rs @@ -1,5 +1,9 @@ +//@ revisions: in_attr in_flag +//@[in_flag] compile-flags: -l dylib:+as-needed=foo + +#[cfg(in_attr)] #[link(name = "foo", kind = "dylib", modifiers = "+as-needed")] -//~^ ERROR: linking modifier `as-needed` is unstable +//[in_attr]~^ ERROR: linking modifier `as-needed` is unstable extern "C" {} fn main() {} diff --git a/tests/ui/impl-trait/in-trait/refine-captures.rs b/tests/ui/impl-trait/in-trait/refine-captures.rs new file mode 100644 index 000000000000..e7dffcb52aae --- /dev/null +++ b/tests/ui/impl-trait/in-trait/refine-captures.rs @@ -0,0 +1,36 @@ +#![feature(precise_capturing_in_traits)] + +trait LifetimeParam<'a> { + fn test() -> impl Sized; +} +// Refining via capturing fewer lifetimes than the trait definition. +impl<'a> LifetimeParam<'a> for i32 { + fn test() -> impl Sized + use<> {} + //~^ WARN impl trait in impl method captures fewer lifetimes than in trait +} +// If the lifetime is substituted, then we don't refine anything. +impl LifetimeParam<'static> for u32 { + fn test() -> impl Sized + use<> {} + // Ok +} + +trait TypeParam { + fn test() -> impl Sized; +} +// Indirectly capturing a lifetime param through a type param substitution. +impl<'a> TypeParam<&'a ()> for i32 { + fn test() -> impl Sized + use<> {} + //~^ WARN impl trait in impl method captures fewer lifetimes than in trait +} +// Two of them, but only one is captured... +impl<'a, 'b> TypeParam<(&'a (), &'b ())> for u32 { + fn test() -> impl Sized + use<'b> {} + //~^ WARN impl trait in impl method captures fewer lifetimes than in trait +} +// What if we don't capture a type param? That should be an error otherwise. +impl TypeParam for u64 { + fn test() -> impl Sized + use<> {} + //~^ ERROR `impl Trait` must mention all type parameters in scope in `use<...>` +} + +fn main() {} diff --git a/tests/ui/impl-trait/in-trait/refine-captures.stderr b/tests/ui/impl-trait/in-trait/refine-captures.stderr new file mode 100644 index 000000000000..ad2c2a11601d --- /dev/null +++ b/tests/ui/impl-trait/in-trait/refine-captures.stderr @@ -0,0 +1,52 @@ +warning: impl trait in impl method captures fewer lifetimes than in trait + --> $DIR/refine-captures.rs:8:31 + | +LL | fn test() -> impl Sized + use<> {} + | ^^^^^ + | + = note: add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate + = note: we are soliciting feedback, see issue #121718 for more information + = note: `#[warn(refining_impl_trait_internal)]` on by default +help: modify the `use<..>` bound to capture the same lifetimes that the trait does + | +LL | fn test() -> impl Sized + use<'a> {} + | ~~~~~~~ + +warning: impl trait in impl method captures fewer lifetimes than in trait + --> $DIR/refine-captures.rs:22:31 + | +LL | fn test() -> impl Sized + use<> {} + | ^^^^^ + | + = note: add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate + = note: we are soliciting feedback, see issue #121718 for more information +help: modify the `use<..>` bound to capture the same lifetimes that the trait does + | +LL | fn test() -> impl Sized + use<'a> {} + | ~~~~~~~ + +warning: impl trait in impl method captures fewer lifetimes than in trait + --> $DIR/refine-captures.rs:27:31 + | +LL | fn test() -> impl Sized + use<'b> {} + | ^^^^^^^ + | + = note: add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate + = note: we are soliciting feedback, see issue #121718 for more information +help: modify the `use<..>` bound to capture the same lifetimes that the trait does + | +LL | fn test() -> impl Sized + use<'a, 'b> {} + | ~~~~~~~~~~~ + +error: `impl Trait` must mention all type parameters in scope in `use<...>` + --> $DIR/refine-captures.rs:32:18 + | +LL | impl TypeParam for u64 { + | - type parameter is implicitly captured by this `impl Trait` +LL | fn test() -> impl Sized + use<> {} + | ^^^^^^^^^^^^^^^^^^ + | + = note: currently, all type parameters are required to be mentioned in the precise captures list + +error: aborting due to 1 previous error; 3 warnings emitted + diff --git a/tests/ui/moves/moved-value-on-as-ref-arg.fixed b/tests/ui/moves/moved-value-on-as-ref-arg.fixed index 292fa98a3f71..97bfe094ce54 100644 --- a/tests/ui/moves/moved-value-on-as-ref-arg.fixed +++ b/tests/ui/moves/moved-value-on-as-ref-arg.fixed @@ -18,8 +18,8 @@ impl AsMut for Bar { fn foo>(_: T) {} fn qux>(_: T) {} -fn bat>(_: T) {} -fn baz>(_: T) {} +fn bat>(_: T) {} +fn baz>(_: T) {} pub fn main() { let bar = Bar; diff --git a/tests/ui/moves/moved-value-on-as-ref-arg.rs b/tests/ui/moves/moved-value-on-as-ref-arg.rs index 632af9efcda3..fed41cf710d2 100644 --- a/tests/ui/moves/moved-value-on-as-ref-arg.rs +++ b/tests/ui/moves/moved-value-on-as-ref-arg.rs @@ -18,8 +18,8 @@ impl AsMut for Bar { fn foo>(_: T) {} fn qux>(_: T) {} -fn bat>(_: T) {} -fn baz>(_: T) {} +fn bat>(_: T) {} +fn baz>(_: T) {} pub fn main() { let bar = Bar; diff --git a/tests/ui/moves/region-var-in-moved-ty-issue-133118.rs b/tests/ui/moves/region-var-in-moved-ty-issue-133118.rs new file mode 100644 index 000000000000..a49370e315dd --- /dev/null +++ b/tests/ui/moves/region-var-in-moved-ty-issue-133118.rs @@ -0,0 +1,25 @@ +//! regression test for #133118 + +pub trait Alpha { + fn y(self) -> usize; +} + +pub trait Beta { + type Gamma; + fn gamma(&self) -> Self::Gamma; +} + +pub fn a(_x: T) -> usize { + todo!(); +} + +pub fn x(beta: &B) -> usize +where + for<'a> &'a B: Beta, + for<'a> <&'a B as Beta>::Gamma: Alpha, +{ + let g1 = beta.gamma(); + a(g1) + a(g1) //~ ERROR use of moved value: `g1` [E0382] +} + +pub fn main() {} diff --git a/tests/ui/moves/region-var-in-moved-ty-issue-133118.stderr b/tests/ui/moves/region-var-in-moved-ty-issue-133118.stderr new file mode 100644 index 000000000000..691625d042da --- /dev/null +++ b/tests/ui/moves/region-var-in-moved-ty-issue-133118.stderr @@ -0,0 +1,21 @@ +error[E0382]: use of moved value: `g1` + --> $DIR/region-var-in-moved-ty-issue-133118.rs:22:15 + | +LL | let g1 = beta.gamma(); + | -- move occurs because `g1` has type `<&B as Beta>::Gamma`, which does not implement the `Copy` trait +LL | a(g1) + a(g1) + | -- ^^ value used here after move + | | + | value moved here + | +note: consider changing this parameter type in function `a` to borrow instead if owning the value isn't necessary + --> $DIR/region-var-in-moved-ty-issue-133118.rs:12:24 + | +LL | pub fn a(_x: T) -> usize { + | - ^ this parameter takes ownership of the value + | | + | in this function + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/native-library-link-flags/modifiers-bad.blank.stderr b/tests/ui/native-library-link-flags/modifiers-bad.blank.stderr new file mode 100644 index 000000000000..ea36af0b4cfa --- /dev/null +++ b/tests/ui/native-library-link-flags/modifiers-bad.blank.stderr @@ -0,0 +1,2 @@ +error: invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed + diff --git a/tests/ui/native-library-link-flags/modifiers-bad.no-prefix.stderr b/tests/ui/native-library-link-flags/modifiers-bad.no-prefix.stderr new file mode 100644 index 000000000000..ea36af0b4cfa --- /dev/null +++ b/tests/ui/native-library-link-flags/modifiers-bad.no-prefix.stderr @@ -0,0 +1,2 @@ +error: invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed + diff --git a/tests/ui/native-library-link-flags/modifiers-bad.prefix-only.stderr b/tests/ui/native-library-link-flags/modifiers-bad.prefix-only.stderr new file mode 100644 index 000000000000..1e701374688f --- /dev/null +++ b/tests/ui/native-library-link-flags/modifiers-bad.prefix-only.stderr @@ -0,0 +1,2 @@ +error: unknown linking modifier ``, expected one of: bundle, verbatim, whole-archive, as-needed + diff --git a/tests/ui/native-library-link-flags/modifiers-bad.rs b/tests/ui/native-library-link-flags/modifiers-bad.rs new file mode 100644 index 000000000000..185201e0d842 --- /dev/null +++ b/tests/ui/native-library-link-flags/modifiers-bad.rs @@ -0,0 +1,11 @@ +//@ edition: 2021 +//@ revisions: blank no-prefix prefix-only unknown + +//@[blank] compile-flags: -l static:=foo +//@[no-prefix] compile-flags: -l static:bundle=foo +//@[prefix-only] compile-flags: -l static:+=foo +//@[unknown] compile-flags: -l static:+ferris=foo + +// Tests various illegal values for the "modifier" part of an `-l` flag. + +fn main() {} diff --git a/tests/ui/native-library-link-flags/modifiers-bad.unknown.stderr b/tests/ui/native-library-link-flags/modifiers-bad.unknown.stderr new file mode 100644 index 000000000000..75950ad9c64c --- /dev/null +++ b/tests/ui/native-library-link-flags/modifiers-bad.unknown.stderr @@ -0,0 +1,2 @@ +error: unknown linking modifier `ferris`, expected one of: bundle, verbatim, whole-archive, as-needed + diff --git a/tests/ui/parser/suggest-const-for-global-var.stderr b/tests/ui/parser/suggest-const-for-global-var.stderr index 235e621d8827..6ac7fe8f0921 100644 --- a/tests/ui/parser/suggest-const-for-global-var.stderr +++ b/tests/ui/parser/suggest-const-for-global-var.stderr @@ -2,7 +2,12 @@ error: expected item, found keyword `let` --> $DIR/suggest-const-for-global-var.rs:1:1 | LL | let X: i32 = 12; - | ^^^ consider using `const` or `static` instead of `let` for global variables + | ^^^ + | | + | `let` cannot be used for global variables + | help: consider using `static` or `const` instead of `let` + | + = note: for a full list of items that can appear in modules, see error: aborting due to 1 previous error diff --git a/tests/ui/parser/suggest-static-for-global-var-mut.rs b/tests/ui/parser/suggest-static-for-global-var-mut.rs new file mode 100644 index 000000000000..c63b09bb7a7f --- /dev/null +++ b/tests/ui/parser/suggest-static-for-global-var-mut.rs @@ -0,0 +1,5 @@ +let mut _data = vec![1,2,3]; +//~^ ERROR expected item, found keyword `let` + +fn main() { +} diff --git a/tests/ui/parser/suggest-static-for-global-var-mut.stderr b/tests/ui/parser/suggest-static-for-global-var-mut.stderr new file mode 100644 index 000000000000..4b00d1a24f31 --- /dev/null +++ b/tests/ui/parser/suggest-static-for-global-var-mut.stderr @@ -0,0 +1,11 @@ +error: expected item, found keyword `let` + --> $DIR/suggest-static-for-global-var-mut.rs:1:1 + | +LL | let mut _data = vec![1,2,3]; + | ^^^ `let` cannot be used for global variables + | + = help: consider using `static` and a `Mutex` instead of `let mut` + = note: for a full list of items that can appear in modules, see + +error: aborting due to 1 previous error + diff --git a/tests/ui/symbol-names/basic.rs b/tests/ui/symbol-names/basic.rs index dfcac21ccd6e..839dda2b3a3b 100644 --- a/tests/ui/symbol-names/basic.rs +++ b/tests/ui/symbol-names/basic.rs @@ -1,7 +1,7 @@ //@ build-fail //@ revisions: legacy v0 //@[legacy]compile-flags: -Z unstable-options -C symbol-mangling-version=legacy - //@[v0]compile-flags: -C symbol-mangling-version=v0 +//@[v0]compile-flags: -C symbol-mangling-version=v0 #![feature(rustc_attrs)] diff --git a/tests/ui/symbol-names/impl1.rs b/tests/ui/symbol-names/impl1.rs index fa4be88f68ff..9aefca47447f 100644 --- a/tests/ui/symbol-names/impl1.rs +++ b/tests/ui/symbol-names/impl1.rs @@ -1,7 +1,7 @@ //@ build-fail //@ revisions: legacy v0 //@[legacy]compile-flags: -Z unstable-options -C symbol-mangling-version=legacy - //@[v0]compile-flags: -C symbol-mangling-version=v0 +//@[v0]compile-flags: -C symbol-mangling-version=v0 //@[legacy]normalize-stderr-test: "h[\w]{16}E?\)" -> ")" #![feature(auto_traits, rustc_attrs)] diff --git a/tests/ui/symbol-names/issue-60925.rs b/tests/ui/symbol-names/issue-60925.rs index 9f1f007a0fac..ca0f21b7a781 100644 --- a/tests/ui/symbol-names/issue-60925.rs +++ b/tests/ui/symbol-names/issue-60925.rs @@ -1,7 +1,7 @@ //@ build-fail //@ revisions: legacy v0 //@[legacy]compile-flags: -Z unstable-options -C symbol-mangling-version=legacy - //@[v0]compile-flags: -C symbol-mangling-version=v0 +//@[v0]compile-flags: -C symbol-mangling-version=v0 #![feature(rustc_attrs)] diff --git a/triagebot.toml b/triagebot.toml index c5942fe27cdd..6154ffedc143 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -236,7 +236,21 @@ trigger_files = [ "compiler", # Tests + "tests/assembly", + "tests/auxiliary", + "tests/codegen", + "tests/codegen-units", + "tests/COMPILER_TESTS.md", + "tests/coverage", + "tests/coverage-run-rustdoc", + "tests/crashes", + "tests/debuginfo", + "tests/incremental", + "tests/mir-opt", + "tests/pretty", + "tests/run-make", "tests/ui", + "tests/ui-fulldeps", ] exclude_labels = [ "T-*", @@ -353,21 +367,22 @@ trigger_files = [ [autolabel."T-bootstrap"] trigger_files = [ - "x.py", - "x", - "x.ps1", + "Cargo.toml", + "configure", + "config.example.toml", "src/bootstrap", + "src/build_helper", "src/tools/rust-installer", "src/tools/x", - "configure", - "Cargo.toml", - "config.example.toml", "src/stage0", "src/tools/compiletest", "src/tools/tidy", "src/tools/rustdoc-gui-test", "src/tools/libcxx-version", "src/tools/rustc-perf-wrapper", + "x.py", + "x", + "x.ps1" ] [autolabel."T-infra"]