diff options
104 files changed, 911 insertions, 398 deletions
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 1ec1f0cb110..004b945eada 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -2589,7 +2589,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { DefKind::InlineConst => substs.as_inline_const().parent_substs(), other => bug!("unexpected item {:?}", other), }; - let parent_substs = tcx.mk_substs(parent_substs.iter()); + let parent_substs = tcx.intern_substs(parent_substs); assert_eq!(typeck_root_substs.len(), parent_substs.len()); if let Err(_) = self.eq_substs( diff --git a/compiler/rustc_codegen_cranelift/src/codegen_i128.rs b/compiler/rustc_codegen_cranelift/src/codegen_i128.rs index 638b2d573b5..b4a2537b5ea 100644 --- a/compiler/rustc_codegen_cranelift/src/codegen_i128.rs +++ b/compiler/rustc_codegen_cranelift/src/codegen_i128.rs @@ -56,7 +56,7 @@ pub(crate) fn maybe_codegen<'tcx>( Some(fx.easy_call("__multi3", &[lhs, rhs], val_ty)) } } else { - let out_ty = fx.tcx.mk_tup([lhs.layout().ty, fx.tcx.types.bool].iter()); + let out_ty = fx.tcx.intern_tup(&[lhs.layout().ty, fx.tcx.types.bool]); let oflow = CPlace::new_stack_slot(fx, fx.layout_of(fx.tcx.types.i32)); let lhs = lhs.load_scalar(fx); let rhs = rhs.load_scalar(fx); @@ -78,7 +78,7 @@ pub(crate) fn maybe_codegen<'tcx>( } BinOp::Add | BinOp::Sub | BinOp::Mul => { assert!(checked); - let out_ty = fx.tcx.mk_tup([lhs.layout().ty, fx.tcx.types.bool].iter()); + let out_ty = fx.tcx.intern_tup(&[lhs.layout().ty, fx.tcx.types.bool]); let out_place = CPlace::new_stack_slot(fx, fx.layout_of(out_ty)); let (param_types, args) = if fx.tcx.sess.target.is_like_windows { let (lhs_ptr, lhs_extra) = lhs.force_stack(fx); diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs index d2ae6978ca2..cbac2e66765 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs @@ -191,7 +191,7 @@ fn llvm_add_sub<'tcx>( // carry0 | carry1 -> carry or borrow respectively let cb_out = fx.bcx.ins().bor(cb0, cb1); - let layout = fx.layout_of(fx.tcx.mk_tup([fx.tcx.types.u8, fx.tcx.types.u64].iter())); + let layout = fx.layout_of(fx.tcx.intern_tup(&[fx.tcx.types.u8, fx.tcx.types.u64])); let val = CValue::by_val_pair(cb_out, c, layout); ret.write_cvalue(fx, val); } diff --git a/compiler/rustc_codegen_cranelift/src/main_shim.rs b/compiler/rustc_codegen_cranelift/src/main_shim.rs index 3e3b6857134..26327107df4 100644 --- a/compiler/rustc_codegen_cranelift/src/main_shim.rs +++ b/compiler/rustc_codegen_cranelift/src/main_shim.rs @@ -119,7 +119,7 @@ pub(crate) fn maybe_create_entry_wrapper( tcx, ParamEnv::reveal_all(), report.def_id, - tcx.mk_substs([GenericArg::from(main_ret_ty)].iter()), + tcx.intern_substs(&[GenericArg::from(main_ret_ty)]), ) .unwrap() .unwrap() diff --git a/compiler/rustc_codegen_cranelift/src/num.rs b/compiler/rustc_codegen_cranelift/src/num.rs index afacbec6445..05905a7bcdf 100644 --- a/compiler/rustc_codegen_cranelift/src/num.rs +++ b/compiler/rustc_codegen_cranelift/src/num.rs @@ -289,7 +289,7 @@ pub(crate) fn codegen_checked_int_binop<'tcx>( _ => bug!("binop {:?} on checked int/uint lhs: {:?} rhs: {:?}", bin_op, in_lhs, in_rhs), }; - let out_layout = fx.layout_of(fx.tcx.mk_tup([in_lhs.layout().ty, fx.tcx.types.bool].iter())); + let out_layout = fx.layout_of(fx.tcx.intern_tup(&[in_lhs.layout().ty, fx.tcx.types.bool])); CValue::by_val_pair(res, has_overflow, out_layout) } diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index 7a4ec494c8e..651d644ebb6 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -62,7 +62,7 @@ pub fn sanitize_attrs<'ll>( ) -> SmallVec<[&'ll Attribute; 4]> { let mut attrs = SmallVec::new(); let enabled = cx.tcx.sess.opts.unstable_opts.sanitizer - no_sanitize; - if enabled.contains(SanitizerSet::ADDRESS) { + if enabled.contains(SanitizerSet::ADDRESS) || enabled.contains(SanitizerSet::KERNELADDRESS) { attrs.push(llvm::AttributeKind::SanitizeAddress.create_attr(cx.llcx)); } if enabled.contains(SanitizerSet::MEMORY) { diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index fb160669436..40f0594b40d 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -442,6 +442,10 @@ pub(crate) unsafe fn llvm_optimize( sanitize_thread: config.sanitizer.contains(SanitizerSet::THREAD), sanitize_hwaddress: config.sanitizer.contains(SanitizerSet::HWADDRESS), sanitize_hwaddress_recover: config.sanitizer_recover.contains(SanitizerSet::HWADDRESS), + sanitize_kernel_address: config.sanitizer.contains(SanitizerSet::KERNELADDRESS), + sanitize_kernel_address_recover: config + .sanitizer_recover + .contains(SanitizerSet::KERNELADDRESS), }) } else { None diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs index ace15cfb024..3dc0ac03312 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs @@ -27,8 +27,6 @@ use rustc_middle::ty::Instance; use std::cell::RefCell; use std::ffi::CString; -use std::iter; - pub mod mapgen; const UNUSED_FUNCTION_COUNTER_ID: CounterValueReference = CounterValueReference::START; @@ -201,7 +199,7 @@ fn declare_unused_fn<'tcx>(cx: &CodegenCx<'_, 'tcx>, def_id: DefId) -> Instance< tcx.symbol_name(instance).name, cx.fn_abi_of_fn_ptr( ty::Binder::dummy(tcx.mk_fn_sig( - iter::once(tcx.mk_unit()), + [tcx.mk_unit()], tcx.mk_unit(), false, hir::Unsafety::Unsafe, diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index b0295481ca5..39afb4af6f6 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -22,7 +22,6 @@ use rustc_target::abi::{self, Align, HasDataLayout, Primitive}; use rustc_target::spec::{HasTargetSpec, PanicStrategy}; use std::cmp::Ordering; -use std::iter; fn get_simple_intrinsic<'ll>( cx: &CodegenCx<'ll, '_>, @@ -798,7 +797,7 @@ fn get_rust_try_fn<'ll, 'tcx>( let i8p = tcx.mk_mut_ptr(tcx.types.i8); // `unsafe fn(*mut i8) -> ()` let try_fn_ty = tcx.mk_fn_ptr(ty::Binder::dummy(tcx.mk_fn_sig( - iter::once(i8p), + [i8p], tcx.mk_unit(), false, hir::Unsafety::Unsafe, @@ -806,7 +805,7 @@ fn get_rust_try_fn<'ll, 'tcx>( ))); // `unsafe fn(*mut i8, *mut i8) -> ()` let catch_fn_ty = tcx.mk_fn_ptr(ty::Binder::dummy(tcx.mk_fn_sig( - [i8p, i8p].iter().cloned(), + [i8p, i8p], tcx.mk_unit(), false, hir::Unsafety::Unsafe, @@ -814,7 +813,7 @@ fn get_rust_try_fn<'ll, 'tcx>( ))); // `unsafe fn(unsafe fn(*mut i8) -> (), *mut i8, unsafe fn(*mut i8, *mut i8) -> ()) -> i32` let rust_fn_sig = ty::Binder::dummy(cx.tcx.mk_fn_sig( - [try_fn_ty, i8p, catch_fn_ty].into_iter(), + [try_fn_ty, i8p, catch_fn_ty], tcx.types.i32, false, hir::Unsafety::Unsafe, diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 8b4861962b2..7aab666fc5e 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -482,6 +482,8 @@ pub struct SanitizerOptions { pub sanitize_thread: bool, pub sanitize_hwaddress: bool, pub sanitize_hwaddress_recover: bool, + pub sanitize_kernel_address: bool, + pub sanitize_kernel_address_recover: bool, } /// LLVMRelocMode diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 3ebbb2cbdfb..7d5c0048626 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -295,7 +295,8 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs { if let Some(list) = attr.meta_item_list() { for item in list.iter() { if item.has_name(sym::address) { - codegen_fn_attrs.no_sanitize |= SanitizerSet::ADDRESS; + codegen_fn_attrs.no_sanitize |= + SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS; } else if item.has_name(sym::cfi) { codegen_fn_attrs.no_sanitize |= SanitizerSet::CFI; } else if item.has_name(sym::kcfi) { diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs b/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs index ec5707505c8..f6a3937870e 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs @@ -96,7 +96,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let loc_ty = self .tcx .type_of(self.tcx.require_lang_item(LangItem::PanicLocation, None)) - .subst(*self.tcx, self.tcx.mk_substs([self.tcx.lifetimes.re_erased.into()].iter())); + .subst(*self.tcx, self.tcx.intern_substs(&[self.tcx.lifetimes.re_erased.into()])); let loc_layout = self.layout_of(loc_ty).unwrap(); let location = self.allocate(loc_layout, MemoryKind::CallerLocation).unwrap(); diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 4b3c0c055ad..8c39feca88a 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -471,6 +471,8 @@ pub enum StashKey { /// When an invalid lifetime e.g. `'2` should be reinterpreted /// as a char literal in the parser LifetimeIsChar, + /// When an invalid lifetime e.g. `'🐱` contains emoji. + LifetimeContainsEmoji, /// Maybe there was a typo where a comma was forgotten before /// FRU syntax MaybeFruTypo, diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 7122ccdcd2e..6d8f7e4a0f6 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -474,7 +474,7 @@ declare_features! ( /// Allows using the `non_exhaustive_omitted_patterns` lint. (active, non_exhaustive_omitted_patterns_lint, "1.57.0", Some(89554), None), /// Allows `for<T>` binders in where-clauses - (incomplete, non_lifetime_binders, "CURRENT_RUSTC_VERSION", Some(1), None), + (incomplete, non_lifetime_binders, "CURRENT_RUSTC_VERSION", Some(108185), None), /// Allows making `dyn Trait` well-formed even if `Trait` is not object safe. /// In that case, `dyn Trait: Trait` does not hold. Moreover, coercions and /// casts in safe Rust to `dyn Trait` for such a `Trait` is also forbidden. diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index abc33e84139..2ff47237b1b 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -252,6 +252,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // (*) -- not late-bound, won't change } + Some(rbv::ResolvedArg::Error(_)) => { + bug!("only ty/ct should resolve as ResolvedArg::Error") + } + None => { self.re_infer(def, lifetime.ident.span).unwrap_or_else(|| { debug!(?lifetime, "unelided lifetime in signature"); @@ -1608,7 +1612,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .collect::<SmallVec<[_; 8]>>(); v.sort_by(|a, b| a.skip_binder().stable_cmp(tcx, &b.skip_binder())); v.dedup(); - let existential_predicates = tcx.mk_poly_existential_predicates(v.into_iter()); + let existential_predicates = tcx.intern_poly_existential_predicates(&v); // Use explicitly-specified region bound. let region_bound = if !lifetime.is_elided() { @@ -2689,6 +2693,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let index = generics.param_def_id_to_index[&def_id.to_def_id()]; tcx.mk_ty_param(index, tcx.hir().ty_param_name(def_id)) } + Some(rbv::ResolvedArg::Error(guar)) => tcx.ty_error_with_guaranteed(guar), arg => bug!("unexpected bound var resolution for {hir_id:?}: {arg:?}"), } } @@ -2893,22 +2898,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { hir::TyKind::BareFn(bf) => { require_c_abi_if_c_variadic(tcx, bf.decl, bf.abi, ast_ty.span); - let fn_ptr_ty = tcx.mk_fn_ptr(self.ty_of_fn( + tcx.mk_fn_ptr(self.ty_of_fn( ast_ty.hir_id, bf.unsafety, bf.abi, bf.decl, None, Some(ast_ty), - )); - - if let Some(guar) = - deny_non_region_late_bound(tcx, bf.generic_params, "function pointer") - { - tcx.ty_error_with_guaranteed(guar) - } else { - fn_ptr_ty - } + )) } hir::TyKind::TraitObject(bounds, lifetime, repr) => { self.maybe_lint_bare_trait(ast_ty, in_path); @@ -2917,21 +2914,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { TraitObjectSyntax::DynStar => ty::DynStar, }; - let object_ty = self.conv_object_ty_poly_trait_ref( - ast_ty.span, - bounds, - lifetime, - borrowed, - repr, - ); - - if let Some(guar) = bounds.iter().find_map(|trait_ref| { - deny_non_region_late_bound(tcx, trait_ref.bound_generic_params, "trait object") - }) { - tcx.ty_error_with_guaranteed(guar) - } else { - object_ty - } + self.conv_object_ty_poly_trait_ref(ast_ty.span, bounds, lifetime, borrowed, repr) } hir::TyKind::Path(hir::QPath::Resolved(maybe_qself, path)) => { debug!(?maybe_qself, ?path); @@ -3109,7 +3092,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { debug!(?output_ty); - let fn_ty = tcx.mk_fn_sig(input_tys.into_iter(), output_ty, decl.c_variadic, unsafety, abi); + let fn_ty = tcx.mk_fn_sig(input_tys, output_ty, decl.c_variadic, unsafety, abi); let bare_fn_ty = ty::Binder::bind_with_vars(fn_ty, bound_vars); if !self.allow_ty_infer() && !(visitor.0.is_empty() && infer_replacements.is_empty()) { @@ -3392,24 +3375,3 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } } } - -fn deny_non_region_late_bound( - tcx: TyCtxt<'_>, - params: &[hir::GenericParam<'_>], - where_: &str, -) -> Option<ErrorGuaranteed> { - params.iter().find_map(|bad_param| { - let what = match bad_param.kind { - hir::GenericParamKind::Type { .. } => "type", - hir::GenericParamKind::Const { .. } => "const", - hir::GenericParamKind::Lifetime { .. } => return None, - }; - - let mut diag = tcx.sess.struct_span_err( - bad_param.span, - format!("late-bound {what} parameter not allowed on {where_} types"), - ); - - Some(if tcx.features().non_lifetime_binders { diag.emit() } else { diag.delay_as_bug() }) - }) -} diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index a07a46da21f..a9fcc8e6250 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -1936,7 +1936,7 @@ pub(super) fn check_type_bounds<'tcx>( .into() } }); - let bound_vars = tcx.mk_bound_variable_kinds(bound_vars.into_iter()); + let bound_vars = tcx.intern_bound_variable_kinds(&bound_vars); let impl_ty_substs = tcx.intern_substs(&substs); let container_id = impl_ty.container_id(tcx); diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 82562ac75e1..4720fea8ef4 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -15,8 +15,6 @@ use rustc_middle::ty::{self, TyCtxt}; use rustc_span::symbol::{kw, sym, Symbol}; use rustc_target::spec::abi::Abi; -use std::iter; - fn equate_intrinsic_type<'tcx>( tcx: TyCtxt<'tcx>, it: &hir::ForeignItem<'_>, @@ -139,14 +137,10 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { let intrinsic_name = tcx.item_name(intrinsic_id); let name_str = intrinsic_name.as_str(); - let bound_vars = tcx.mk_bound_variable_kinds( - [ - ty::BoundVariableKind::Region(ty::BrAnon(0, None)), - ty::BoundVariableKind::Region(ty::BrEnv), - ] - .iter() - .copied(), - ); + let bound_vars = tcx.intern_bound_variable_kinds(&[ + ty::BoundVariableKind::Region(ty::BrAnon(0, None)), + ty::BoundVariableKind::Region(ty::BrEnv), + ]); let mk_va_list_ty = |mutbl| { tcx.lang_items().va_list().map(|did| { let region = tcx.mk_re_late_bound( @@ -378,21 +372,21 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { ( 1, vec![tcx.mk_imm_ref(tcx.mk_re_late_bound(ty::INNERMOST, br), param(0))], - tcx.mk_projection(discriminant_def_id, tcx.mk_substs([param(0).into()].iter())), + tcx.mk_projection(discriminant_def_id, tcx.intern_substs(&[param(0).into()])), ) } kw::Try => { let mut_u8 = tcx.mk_mut_ptr(tcx.types.u8); let try_fn_ty = ty::Binder::dummy(tcx.mk_fn_sig( - iter::once(mut_u8), + [mut_u8], tcx.mk_unit(), false, hir::Unsafety::Normal, Abi::Rust, )); let catch_fn_ty = ty::Binder::dummy(tcx.mk_fn_sig( - [mut_u8, mut_u8].iter().cloned(), + [mut_u8, mut_u8], tcx.mk_unit(), false, hir::Unsafety::Normal, @@ -447,7 +441,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { }; (n_tps, 0, inputs, output, unsafety) }; - let sig = tcx.mk_fn_sig(inputs.into_iter(), output, false, unsafety, Abi::RustIntrinsic); + let sig = tcx.mk_fn_sig(inputs, output, false, unsafety, Abi::RustIntrinsic); let sig = ty::Binder::bind_with_vars(sig, bound_vars); equate_intrinsic_type(tcx, it, n_tps, n_lts, sig) } @@ -545,13 +539,7 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) } }; - let sig = tcx.mk_fn_sig( - inputs.into_iter(), - output, - false, - hir::Unsafety::Unsafe, - Abi::PlatformIntrinsic, - ); + let sig = tcx.mk_fn_sig(inputs, output, false, hir::Unsafety::Unsafe, Abi::PlatformIntrinsic); let sig = ty::Binder::dummy(sig); equate_intrinsic_type(tcx, it, n_tps, 0, sig) } diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index 7bcaeadbcf6..127d4fa908b 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -398,7 +398,12 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option<S Some(rbv::ResolvedArg::StaticLifetime | rbv::ResolvedArg::EarlyBound(..)) => {} Some(rbv::ResolvedArg::LateBound(debruijn, _, _)) if debruijn < self.outer_index => {} - Some(rbv::ResolvedArg::LateBound(..) | rbv::ResolvedArg::Free(..)) | None => { + Some( + rbv::ResolvedArg::LateBound(..) + | rbv::ResolvedArg::Free(..) + | rbv::ResolvedArg::Error(_), + ) + | None => { self.has_late_bound_regions = Some(lt.ident.span); } } diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 8a110bfc2f7..c0c90e47a75 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -50,7 +50,7 @@ impl RegionExt for ResolvedArg { fn id(&self) -> Option<DefId> { match *self { - ResolvedArg::StaticLifetime => None, + ResolvedArg::StaticLifetime | ResolvedArg::Error(_) => None, ResolvedArg::EarlyBound(id) | ResolvedArg::LateBound(_, _, id) @@ -336,7 +336,57 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { } } } + + fn visit_poly_trait_ref_inner( + &mut self, + trait_ref: &'tcx hir::PolyTraitRef<'tcx>, + non_lifetime_binder_allowed: NonLifetimeBinderAllowed, + ) { + debug!("visit_poly_trait_ref(trait_ref={:?})", trait_ref); + + let (mut binders, scope_type) = self.poly_trait_ref_binder_info(); + + let initial_bound_vars = binders.len() as u32; + let mut bound_vars: FxIndexMap<LocalDefId, ResolvedArg> = FxIndexMap::default(); + let binders_iter = + trait_ref.bound_generic_params.iter().enumerate().map(|(late_bound_idx, param)| { + let pair = ResolvedArg::late(initial_bound_vars + late_bound_idx as u32, param); + let r = late_arg_as_bound_arg(self.tcx, &pair.1, param); + bound_vars.insert(pair.0, pair.1); + r + }); + binders.extend(binders_iter); + + if let NonLifetimeBinderAllowed::Deny(where_) = non_lifetime_binder_allowed { + deny_non_region_late_bound(self.tcx, &mut bound_vars, where_); + } + + debug!(?binders); + self.record_late_bound_vars(trait_ref.trait_ref.hir_ref_id, binders); + + // Always introduce a scope here, even if this is in a where clause and + // we introduced the binders around the bounded Ty. In that case, we + // just reuse the concatenation functionality also present in nested trait + // refs. + let scope = Scope::Binder { + hir_id: trait_ref.trait_ref.hir_ref_id, + bound_vars, + s: self.scope, + scope_type, + where_bound_origin: None, + }; + self.with(scope, |this| { + walk_list!(this, visit_generic_param, trait_ref.bound_generic_params); + this.visit_trait_ref(&trait_ref.trait_ref); + }); + } +} + +enum NonLifetimeBinderAllowed { + Deny(&'static str), + Allow, } + impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { type NestedFilter = nested_filter::OnlyBodies; @@ -400,7 +450,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { } } - let (bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) = + let (mut bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) = bound_generic_params .iter() .enumerate() @@ -411,6 +461,8 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { }) .unzip(); + deny_non_region_late_bound(self.tcx, &mut bound_vars, "closures"); + self.record_late_bound_vars(e.hir_id, binders); let scope = Scope::Binder { hir_id: e.hir_id, @@ -567,7 +619,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) { match ty.kind { hir::TyKind::BareFn(c) => { - let (bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) = c + let (mut bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) = c .generic_params .iter() .enumerate() @@ -577,6 +629,9 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { (pair, r) }) .unzip(); + + deny_non_region_late_bound(self.tcx, &mut bound_vars, "function pointer types"); + self.record_late_bound_vars(ty.hir_id, binders); let scope = Scope::Binder { hir_id: ty.hir_id, @@ -596,7 +651,10 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { let scope = Scope::TraitRefBoundary { s: self.scope }; self.with(scope, |this| { for bound in bounds { - this.visit_poly_trait_ref(bound); + this.visit_poly_trait_ref_inner( + bound, + NonLifetimeBinderAllowed::Deny("trait object types"), + ); } }); match lifetime.res { @@ -967,39 +1025,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { } fn visit_poly_trait_ref(&mut self, trait_ref: &'tcx hir::PolyTraitRef<'tcx>) { - debug!("visit_poly_trait_ref(trait_ref={:?})", trait_ref); - - let (mut binders, scope_type) = self.poly_trait_ref_binder_info(); - - let initial_bound_vars = binders.len() as u32; - let mut bound_vars: FxIndexMap<LocalDefId, ResolvedArg> = FxIndexMap::default(); - let binders_iter = - trait_ref.bound_generic_params.iter().enumerate().map(|(late_bound_idx, param)| { - let pair = ResolvedArg::late(initial_bound_vars + late_bound_idx as u32, param); - let r = late_arg_as_bound_arg(self.tcx, &pair.1, param); - bound_vars.insert(pair.0, pair.1); - r - }); - binders.extend(binders_iter); - - debug!(?binders); - self.record_late_bound_vars(trait_ref.trait_ref.hir_ref_id, binders); - - // Always introduce a scope here, even if this is in a where clause and - // we introduced the binders around the bounded Ty. In that case, we - // just reuse the concatenation functionality also present in nested trait - // refs. - let scope = Scope::Binder { - hir_id: trait_ref.trait_ref.hir_ref_id, - bound_vars, - s: self.scope, - scope_type, - where_bound_origin: None, - }; - self.with(scope, |this| { - walk_list!(this, visit_generic_param, trait_ref.bound_generic_params); - this.visit_trait_ref(&trait_ref.trait_ref); - }); + self.visit_poly_trait_ref_inner(trait_ref, NonLifetimeBinderAllowed::Allow); } } @@ -1364,7 +1390,9 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { return; } - span_bug!(self.tcx.hir().span(hir_id), "could not resolve {param_def_id:?}",); + self.tcx + .sess + .delay_span_bug(self.tcx.hir().span(hir_id), "could not resolve {param_def_id:?}"); } #[instrument(level = "debug", skip(self))] @@ -1915,3 +1943,37 @@ fn is_late_bound_map( } } } + +pub fn deny_non_region_late_bound( + tcx: TyCtxt<'_>, + bound_vars: &mut FxIndexMap<LocalDefId, ResolvedArg>, + where_: &str, +) { + let mut first = true; + + for (var, arg) in bound_vars { + let Node::GenericParam(param) = tcx.hir().get_by_def_id(*var) else { + bug!(); + }; + + let what = match param.kind { + hir::GenericParamKind::Type { .. } => "type", + hir::GenericParamKind::Const { .. } => "const", + hir::GenericParamKind::Lifetime { .. } => continue, + }; + + let mut diag = tcx.sess.struct_span_err( + param.span, + format!("late-bound {what} parameter not allowed on {where_}"), + ); + + let guar = if tcx.features().non_lifetime_binders && first { + diag.emit() + } else { + diag.delay_as_bug() + }; + + first = false; + *arg = ResolvedArg::Error(guar); + } +} diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 6111046a519..11240cf22e4 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -113,7 +113,6 @@ use rustc_target::spec::abi::Abi; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _; use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode}; -use std::iter; use std::ops::Not; use astconv::AstConv; @@ -348,7 +347,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { } let se_ty = tcx.mk_fn_ptr(expected_return_type.map_bound(|expected_return_type| { - tcx.mk_fn_sig(iter::empty(), expected_return_type, false, hir::Unsafety::Normal, Abi::Rust) + tcx.mk_fn_sig([], expected_return_type, false, hir::Unsafety::Normal, Abi::Rust) })); require_same_types( @@ -434,7 +433,7 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) { } let se_ty = tcx.mk_fn_ptr(ty::Binder::dummy(tcx.mk_fn_sig( - [tcx.types.isize, tcx.mk_imm_ptr(tcx.mk_imm_ptr(tcx.types.u8))].iter().cloned(), + [tcx.types.isize, tcx.mk_imm_ptr(tcx.mk_imm_ptr(tcx.types.u8))], tcx.types.isize, false, hir::Unsafety::Normal, diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs index 3feb23d3481..bf8259ff70f 100644 --- a/compiler/rustc_hir_typeck/src/check.rs +++ b/compiler/rustc_hir_typeck/src/check.rs @@ -264,7 +264,7 @@ fn check_lang_start_fn<'tcx>( let fn_generic = generics.param_at(0, tcx); let generic_ty = tcx.mk_ty_param(fn_generic.index, fn_generic.name); let expected_fn_sig = - tcx.mk_fn_sig([].iter(), &generic_ty, false, hir::Unsafety::Normal, Abi::Rust); + tcx.mk_fn_sig([], generic_ty, false, hir::Unsafety::Normal, Abi::Rust); let expected_ty = tcx.mk_fn_ptr(Binder::dummy(expected_fn_sig)); // we emit the same error to suggest changing the arg no matter what's wrong with the arg diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index b1268c5f792..cf296a7bf65 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -126,7 +126,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // the `closures` table. let sig = bound_sig.map_bound(|sig| { self.tcx.mk_fn_sig( - iter::once(self.tcx.intern_tup(sig.inputs())), + [self.tcx.intern_tup(sig.inputs())], sig.output(), sig.c_variadic, sig.unsafety, @@ -326,7 +326,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { debug!(?ret_param_ty); let sig = projection.rebind(self.tcx.mk_fn_sig( - input_tys.iter(), + input_tys, ret_param_ty, false, hir::Unsafety::Normal, diff --git a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs index 3f61a1a83e5..14e3ba83b10 100644 --- a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs +++ b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs @@ -312,7 +312,7 @@ pub fn resolve_interior<'a, 'tcx>( // Extract type components to build the witness type. let type_list = fcx.tcx.mk_type_list(type_causes.iter().map(|cause| cause.ty)); - let bound_vars = fcx.tcx.mk_bound_variable_kinds(bound_vars.iter()); + let bound_vars = fcx.tcx.intern_bound_variable_kinds(&bound_vars); let witness = fcx.tcx.mk_generator_witness(ty::Binder::bind_with_vars(type_list, bound_vars.clone())); diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index e12a575d5ac..7c8abb4186f 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -301,7 +301,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Build a tuple (U0..Un) of the final upvar types U0..Un // and unify the upvar tuple type in the closure with it: - let final_tupled_upvars_type = self.tcx.mk_tup(final_upvar_tys.iter()); + let final_tupled_upvars_type = self.tcx.intern_tup(&final_upvar_tys); self.demand_suptype(span, substs.tupled_upvars_ty(), final_tupled_upvars_type); let fake_reads = delegate @@ -315,8 +315,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.typeck_results.borrow_mut().closure_size_eval.insert( closure_def_id, ClosureSizeProfileData { - before_feature_tys: self.tcx.mk_tup(before_feature_tys.into_iter()), - after_feature_tys: self.tcx.mk_tup(after_feature_tys.into_iter()), + before_feature_tys: self.tcx.intern_tup(&before_feature_tys), + after_feature_tys: self.tcx.intern_tup(&after_feature_tys), }, ); } diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs index 4fe6c6618f6..fec04af2313 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs @@ -134,7 +134,8 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> { rbv::ResolvedArg::StaticLifetime | rbv::ResolvedArg::Free(_, _) | rbv::ResolvedArg::EarlyBound(_) - | rbv::ResolvedArg::LateBound(_, _, _), + | rbv::ResolvedArg::LateBound(_, _, _) + | rbv::ResolvedArg::Error(_), ) | None, _, @@ -211,7 +212,8 @@ impl<'tcx> Visitor<'tcx> for TyPathVisitor<'tcx> { rbv::ResolvedArg::StaticLifetime | rbv::ResolvedArg::EarlyBound(_) | rbv::ResolvedArg::LateBound(_, _, _) - | rbv::ResolvedArg::Free(_, _), + | rbv::ResolvedArg::Free(_, _) + | rbv::ResolvedArg::Error(_), ) | None, _, diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index 6e815863d06..e6f04fe0aaa 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -95,7 +95,7 @@ pub enum TokenKind { Literal { kind: LiteralKind, suffix_start: u32 }, /// "'a" - Lifetime { starts_with_number: bool }, + Lifetime { starts_with_number: bool, contains_emoji: bool }, // One-char tokens: /// ";" @@ -630,7 +630,13 @@ impl Cursor<'_> { // If the first symbol is valid for identifier, it can be a lifetime. // Also check if it's a number for a better error reporting (so '0 will // be reported as invalid lifetime and not as unterminated char literal). - is_id_start(self.first()) || self.first().is_digit(10) + // We also have to account for potential `'🐱` emojis to avoid reporting + // it as an unterminated char literal. + is_id_start(self.first()) + || self.first().is_digit(10) + // FIXME(#108019): `unic-emoji-char` seems to have data tables only up to Unicode + // 5.0, but Unicode is already newer than this. + || unic_emoji_char::is_emoji(self.first()) }; if !can_be_a_lifetime { @@ -643,16 +649,33 @@ impl Cursor<'_> { return Literal { kind, suffix_start }; } - // Either a lifetime or a character literal with - // length greater than 1. + // Either a lifetime or a character literal. let starts_with_number = self.first().is_digit(10); + let mut contains_emoji = false; - // Skip the literal contents. - // First symbol can be a number (which isn't a valid identifier start), - // so skip it without any checks. - self.bump(); - self.eat_while(is_id_continue); + // FIXME(#108019): `unic-emoji-char` seems to have data tables only up to Unicode + // 5.0, but Unicode is already newer than this. + if unic_emoji_char::is_emoji(self.first()) { + contains_emoji = true; + } else { + // Skip the literal contents. + // First symbol can be a number (which isn't a valid identifier start), + // so skip it without any checks. + self.bump(); + } + self.eat_while(|c| { + if is_id_continue(c) { + true + // FIXME(#108019): `unic-emoji-char` seems to have data tables only up to Unicode + // 5.0, but Unicode is already newer than this. + } else if unic_emoji_char::is_emoji(c) { + contains_emoji = true; + true + } else { + false + } + }); // Check if after skipping literal contents we've met a closing // single quote (which means that user attempted to create a @@ -662,7 +685,7 @@ impl Cursor<'_> { let kind = Char { terminated: true }; Literal { kind, suffix_start: self.pos_within_token() } } else { - Lifetime { starts_with_number } + Lifetime { starts_with_number, contains_emoji } } } diff --git a/compiler/rustc_lexer/src/tests.rs b/compiler/rustc_lexer/src/tests.rs index e4c1787f2cc..670d64fb983 100644 --- a/compiler/rustc_lexer/src/tests.rs +++ b/compiler/rustc_lexer/src/tests.rs @@ -235,7 +235,7 @@ fn lifetime() { check_lexing( "'abc", expect![[r#" - Token { kind: Lifetime { starts_with_number: false }, len: 4 } + Token { kind: Lifetime { starts_with_number: false, contains_emoji: false }, len: 4 } "#]], ); } diff --git a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs index 65a686857e5..ccf95992a6e 100644 --- a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs +++ b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs @@ -78,7 +78,7 @@ impl<'tcx> LateLintPass<'tcx> for DerefIntoDynSupertrait { }); cx.emit_spanned_lint(DEREF_INTO_DYN_SUPERTRAIT, cx.tcx.def_span(item.owner_id.def_id), SupertraitAsDerefTarget { t, - target_principal: target_principal.to_string(), + target_principal, label, }); } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 2e447b900e1..94a43ab0c46 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -8,7 +8,7 @@ use rustc_errors::{ }; use rustc_hir::def_id::DefId; use rustc_macros::{LintDiagnostic, Subdiagnostic}; -use rustc_middle::ty::{Predicate, Ty, TyCtxt}; +use rustc_middle::ty::{PolyExistentialTraitRef, Predicate, Ty, TyCtxt}; use rustc_session::parse::ParseSess; use rustc_span::{edition::Edition, sym, symbol::Ident, Span, Symbol}; @@ -556,8 +556,7 @@ pub struct BuiltinUnexpectedCliConfigValue { #[diag(lint_supertrait_as_deref_target)] pub struct SupertraitAsDerefTarget<'a> { pub t: Ty<'a>, - pub target_principal: String, - // pub target_principal: Binder<'a, ExistentialTraitRef<'b>>, + pub target_principal: PolyExistentialTraitRef<'a>, #[subdiagnostic] pub label: Option<SupertraitAsDerefTargetLabel>, } diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index fbc1d8ef310..0a42265a6ba 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -594,6 +594,8 @@ struct LLVMRustSanitizerOptions { bool SanitizeThread; bool SanitizeHWAddress; bool SanitizeHWAddressRecover; + bool SanitizeKernelAddress; + bool SanitizeKernelAddressRecover; }; extern "C" LLVMRustResult @@ -765,15 +767,17 @@ LLVMRustOptimize( ); } - if (SanitizerOptions->SanitizeAddress) { + if (SanitizerOptions->SanitizeAddress || SanitizerOptions->SanitizeKernelAddress) { OptimizerLastEPCallbacks.push_back( [SanitizerOptions](ModulePassManager &MPM, OptimizationLevel Level) { + auto CompileKernel = SanitizerOptions->SanitizeKernelAddress; #if LLVM_VERSION_LT(15, 0) MPM.addPass(RequireAnalysisPass<ASanGlobalsMetadataAnalysis, Module>()); #endif AddressSanitizerOptions opts = AddressSanitizerOptions{ - /*CompileKernel=*/false, - SanitizerOptions->SanitizeAddressRecover, + CompileKernel, + SanitizerOptions->SanitizeAddressRecover + || SanitizerOptions->SanitizeKernelAddressRecover, /*UseAfterScope=*/true, AsanDetectStackUseAfterReturnMode::Runtime, }; diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index ffb52d167b1..d823989bb02 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -502,7 +502,7 @@ impl<'tcx> Collector<'tcx> { .subst_identity() .fn_sig(self.tcx) .inputs() - .map_bound(|slice| self.tcx.mk_type_list(slice.iter())), + .map_bound(|slice| self.tcx.intern_type_list(slice)), ); argument_types diff --git a/compiler/rustc_middle/src/middle/resolve_bound_vars.rs b/compiler/rustc_middle/src/middle/resolve_bound_vars.rs index b96d07e7dc8..c59704fc023 100644 --- a/compiler/rustc_middle/src/middle/resolve_bound_vars.rs +++ b/compiler/rustc_middle/src/middle/resolve_bound_vars.rs @@ -3,6 +3,7 @@ use crate::ty; use rustc_data_structures::fx::FxHashMap; +use rustc_errors::ErrorGuaranteed; use rustc_hir::def_id::DefId; use rustc_hir::{ItemLocalId, OwnerId}; use rustc_macros::HashStable; @@ -13,6 +14,7 @@ pub enum ResolvedArg { EarlyBound(/* decl */ DefId), LateBound(ty::DebruijnIndex, /* late-bound index */ u32, /* decl */ DefId), Free(DefId, /* lifetime decl */ DefId), + Error(ErrorGuaranteed), } /// A set containing, at most, one known element. diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index f955b312b23..46184cddd51 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -2525,14 +2525,12 @@ impl<'tcx> ConstantKind<'tcx> { } let hir_id = tcx.hir().local_def_id_to_hir_id(def.did); - let parent_substs = if let Some(parent_hir_id) = tcx.hir().opt_parent_id(hir_id) { - if let Some(parent_did) = parent_hir_id.as_owner() { - InternalSubsts::identity_for_item(tcx, parent_did.to_def_id()) - } else { - tcx.mk_substs(Vec::<GenericArg<'tcx>>::new().into_iter()) - } + let parent_substs = if let Some(parent_hir_id) = tcx.hir().opt_parent_id(hir_id) + && let Some(parent_did) = parent_hir_id.as_owner() + { + InternalSubsts::identity_for_item(tcx, parent_did.to_def_id()) } else { - tcx.mk_substs(Vec::<GenericArg<'tcx>>::new().into_iter()) + tcx.intern_substs(&[]) }; debug!(?parent_substs); diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 08e2ef0cada..884ae7f5da2 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -149,6 +149,9 @@ impl<'tcx> Const<'tcx> { ty::ConstKind::Bound(debruijn, ty::BoundVar::from_u32(index)), ty, )), + Some(rbv::ResolvedArg::Error(guar)) => { + Some(tcx.const_error_with_guaranteed(ty, guar)) + } arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", expr.hir_id), } } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 117f3decd1a..e2f32cdca3c 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -67,7 +67,7 @@ use rustc_target::abi::{Layout, LayoutS, TargetDataLayout, VariantIdx}; use rustc_target::spec::abi; use rustc_type_ir::sty::TyKind::*; use rustc_type_ir::WithCachedTypeInfo; -use rustc_type_ir::{DynKind, InternAs, InternIteratorElement, Interner, TypeFlags}; +use rustc_type_ir::{CollectAndApply, DynKind, Interner, TypeFlags}; use std::any::Any; use std::borrow::Borrow; @@ -1190,7 +1190,7 @@ impl<'tcx> TyCtxt<'tcx> { self.mk_imm_ref( self.lifetimes.re_static, self.type_of(self.require_lang_item(LangItem::PanicLocation, None)) - .subst(self, self.mk_substs([self.lifetimes.re_static.into()].iter())), + .subst(self, self.intern_substs(&[self.lifetimes.re_static.into()])), ) } @@ -1660,11 +1660,11 @@ impl<'tcx> TyCtxt<'tcx> { unsafety: hir::Unsafety, ) -> PolyFnSig<'tcx> { sig.map_bound(|s| { - let params_iter = match s.inputs()[0].kind() { - ty::Tuple(params) => params.into_iter(), + let params = match s.inputs()[0].kind() { + ty::Tuple(params) => *params, _ => bug!(), }; - self.mk_fn_sig(params_iter, s.output(), s.c_variadic, unsafety, abi::Abi::Rust) + self.mk_fn_sig(params, s.output(), s.c_variadic, unsafety, abi::Abi::Rust) }) } @@ -1835,8 +1835,12 @@ impl<'tcx> TyCtxt<'tcx> { if ts.is_empty() { self.types.unit } else { self.mk_ty(Tuple(self.intern_type_list(&ts))) } } - pub fn mk_tup<I: InternAs<Ty<'tcx>, Ty<'tcx>>>(self, iter: I) -> I::Output { - iter.intern_with(|ts| self.intern_tup(ts)) + pub fn mk_tup<I, T>(self, iter: I) -> T::Output + where + I: Iterator<Item = T>, + T: CollectAndApply<Ty<'tcx>, Ty<'tcx>>, + { + T::collect_and_apply(iter, |ts| self.intern_tup(ts)) } #[inline] @@ -2157,11 +2161,12 @@ impl<'tcx> TyCtxt<'tcx> { } } - pub fn mk_const_list<I: InternAs<ty::Const<'tcx>, &'tcx List<ty::Const<'tcx>>>>( - self, - iter: I, - ) -> I::Output { - iter.intern_with(|xs| self.intern_const_list(xs)) + pub fn mk_const_list<I, T>(self, iter: I) -> T::Output + where + I: Iterator<Item = T>, + T: CollectAndApply<ty::Const<'tcx>, &'tcx List<ty::Const<'tcx>>>, + { + T::collect_and_apply(iter, |xs| self.intern_const_list(xs)) } pub fn intern_const_list(self, cs: &[ty::Const<'tcx>]) -> &'tcx List<ty::Const<'tcx>> { @@ -2210,18 +2215,24 @@ impl<'tcx> TyCtxt<'tcx> { if ts.is_empty() { List::empty() } else { self._intern_bound_variable_kinds(ts) } } - pub fn mk_fn_sig<I>( + // Unlike various other `mk_*` functions, this one uses `I: IntoIterator` + // instead of `I: Iterator`. Unlike those other functions, this one doesn't + // have a `intern_fn_sig` variant that can be used for cases where `I` is + // something like a `Vec`. That's because of the need to combine `inputs` + // and `output`. + pub fn mk_fn_sig<I, T>( self, inputs: I, output: I::Item, c_variadic: bool, unsafety: hir::Unsafety, abi: abi::Abi, - ) -> <I::Item as InternIteratorElement<Ty<'tcx>, ty::FnSig<'tcx>>>::Output + ) -> T::Output where - I: Iterator<Item: InternIteratorElement<Ty<'tcx>, ty::FnSig<'tcx>>>, + I: IntoIterator<Item = T>, + T: CollectAndApply<Ty<'tcx>, ty::FnSig<'tcx>>, { - inputs.chain(iter::once(output)).intern_with(|xs| ty::FnSig { + T::collect_and_apply(inputs.into_iter().chain(iter::once(output)), |xs| ty::FnSig { inputs_and_output: self.intern_type_list(xs), c_variadic, unsafety, @@ -2229,38 +2240,47 @@ impl<'tcx> TyCtxt<'tcx> { }) } - pub fn mk_poly_existential_predicates< - I: InternAs<PolyExistentialPredicate<'tcx>, &'tcx List<PolyExistentialPredicate<'tcx>>>, - >( - self, - iter: I, - ) -> I::Output { - iter.intern_with(|xs| self.intern_poly_existential_predicates(xs)) + pub fn mk_poly_existential_predicates<I, T>(self, iter: I) -> T::Output + where + I: Iterator<Item = T>, + T: CollectAndApply< + PolyExistentialPredicate<'tcx>, + &'tcx List<PolyExistentialPredicate<'tcx>>, + >, + { + T::collect_and_apply(iter, |xs| self.intern_poly_existential_predicates(xs)) } - pub fn mk_predicates<I: InternAs<Predicate<'tcx>, &'tcx List<Predicate<'tcx>>>>( - self, - iter: I, - ) -> I::Output { - iter.intern_with(|xs| self.intern_predicates(xs)) + pub fn mk_predicates<I, T>(self, iter: I) -> T::Output + where + I: Iterator<Item = T>, + T: CollectAndApply<Predicate<'tcx>, &'tcx List<Predicate<'tcx>>>, + { + T::collect_and_apply(iter, |xs| self.intern_predicates(xs)) } - pub fn mk_type_list<I: InternAs<Ty<'tcx>, &'tcx List<Ty<'tcx>>>>(self, iter: I) -> I::Output { - iter.intern_with(|xs| self.intern_type_list(xs)) + pub fn mk_type_list<I, T>(self, iter: I) -> T::Output + where + I: Iterator<Item = T>, + T: CollectAndApply<Ty<'tcx>, &'tcx List<Ty<'tcx>>>, + { + T::collect_and_apply(iter, |xs| self.intern_type_list(xs)) } - pub fn mk_substs<I: InternAs<GenericArg<'tcx>, &'tcx List<GenericArg<'tcx>>>>( - self, - iter: I, - ) -> I::Output { - iter.intern_with(|xs| self.intern_substs(xs)) + pub fn mk_substs<I, T>(self, iter: I) -> T::Output + where + I: Iterator<Item = T>, + T: CollectAndApply<GenericArg<'tcx>, &'tcx List<GenericArg<'tcx>>>, + { + T::collect_and_apply(iter, |xs| self.intern_substs(xs)) } - pub fn mk_place_elems<I: InternAs<PlaceElem<'tcx>, &'tcx List<PlaceElem<'tcx>>>>( - self, - iter: I, - ) -> I::Output { - iter.intern_with(|xs| self.intern_place_elems(xs)) + pub fn mk_place_elems<I, T>(self, iter: I) -> T::Output + where + I: Iterator<Item = T>, + T: CollectAndApply<PlaceElem<'tcx>, &'tcx List<PlaceElem<'tcx>>>, + { + T::collect_and_apply(iter, |xs| self.intern_place_elems(xs)) } pub fn mk_substs_trait( @@ -2289,13 +2309,12 @@ impl<'tcx> TyCtxt<'tcx> { ty::AliasTy { def_id, substs, _use_mk_alias_ty_instead: () } } - pub fn mk_bound_variable_kinds< - I: InternAs<ty::BoundVariableKind, &'tcx List<ty::BoundVariableKind>>, - >( - self, - iter: I, - ) -> I::Output { - iter.intern_with(|xs| self.intern_bound_variable_kinds(xs)) + pub fn mk_bound_variable_kinds<I, T>(self, iter: I) -> T::Output + where + I: Iterator<Item = T>, + T: CollectAndApply<ty::BoundVariableKind, &'tcx List<ty::BoundVariableKind>>, + { + T::collect_and_apply(iter, |xs| self.intern_bound_variable_kinds(xs)) } /// Emit a lint at `span` from a lint struct (some type that implements `DecorateLint`, @@ -2380,13 +2399,13 @@ impl<'tcx> TyCtxt<'tcx> { } pub fn late_bound_vars(self, id: HirId) -> &'tcx List<ty::BoundVariableKind> { - self.mk_bound_variable_kinds( - self.late_bound_vars_map(id.owner) + self.intern_bound_variable_kinds( + &self + .late_bound_vars_map(id.owner) .and_then(|map| map.get(&id.local_id).cloned()) .unwrap_or_else(|| { bug!("No bound vars found for {}", self.hir().node_to_string(id)) - }) - .iter(), + }), ) } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 1d76f435e26..3d0f9a5053c 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -686,7 +686,7 @@ where Increase this counter if you tried to implement this but failed to do it without duplicating a lot of code from other places in the compiler: 2 - tcx.mk_tup(&[ + tcx.intern_tup(&[ tcx.mk_array(tcx.types.usize, 3), tcx.mk_array(Option<fn()>), ]) diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 322afeb2d34..2ba25e8bfad 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -673,7 +673,7 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>( for (a_arg, b_arg) in aa.iter().zip(ba.iter()) { related_args.push(r.consts(a_arg, b_arg)?); } - let related_args = tcx.mk_const_list(related_args.iter()); + let related_args = tcx.intern_const_list(&related_args); Expr::FunctionCall(func, related_args) } _ => return Err(TypeError::ConstMismatch(expected_found(r, a, b))), diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index d8dbd04f438..573105fd8c0 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -419,7 +419,7 @@ impl<'tcx> ir::TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<ty::PolyExistential impl<'tcx> ir::TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<ty::Const<'tcx>> { fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { - ty::util::fold_list(self, folder, |tcx, v| tcx.mk_const_list(v.iter())) + ty::util::fold_list(self, folder, |tcx, v| tcx.intern_const_list(v)) } } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 8d2712b6c87..f8d17433cf7 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -933,6 +933,12 @@ impl<'tcx> PolyExistentialTraitRef<'tcx> { } } +impl rustc_errors::IntoDiagnosticArg for PolyExistentialTraitRef<'_> { + fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { + self.to_string().into_diagnostic_arg() + } +} + #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)] #[derive(HashStable)] pub enum BoundVariableKind { diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs index 3b7ceb3adcc..74c35ef0fc2 100644 --- a/compiler/rustc_mir_build/src/thir/cx/mod.rs +++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs @@ -133,9 +133,9 @@ impl<'tcx> Cx<'tcx> { bug!("closure expr does not have closure type: {:?}", closure_ty); }; - let bound_vars = self.tcx.mk_bound_variable_kinds(std::iter::once( - ty::BoundVariableKind::Region(ty::BrEnv), - )); + let bound_vars = self + .tcx + .intern_bound_variable_kinds(&[ty::BoundVariableKind::Region(ty::BrEnv)]); let br = ty::BoundRegion { var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind: ty::BrEnv, diff --git a/compiler/rustc_mir_transform/src/instcombine.rs b/compiler/rustc_mir_transform/src/instcombine.rs index 1079377fbac..0534e688703 100644 --- a/compiler/rustc_mir_transform/src/instcombine.rs +++ b/compiler/rustc_mir_transform/src/instcombine.rs @@ -110,11 +110,7 @@ impl<'tcx> InstCombineContext<'tcx, '_> { fn combine_ref_deref(&self, source_info: &SourceInfo, rvalue: &mut Rvalue<'tcx>) { if let Rvalue::Ref(_, _, place) = rvalue { if let Some((base, ProjectionElem::Deref)) = place.as_ref().last_projection() { - if let ty::Ref(_, _, Mutability::Not) = - base.ty(self.local_decls, self.tcx).ty.kind() - { - // The dereferenced place must have type `&_`, so that we don't copy `&mut _`. - } else { + if rvalue.ty(self.local_decls, self.tcx) != base.ty(self.local_decls, self.tcx).ty { return; } diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index 7f388b065ad..682ad081f5c 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -597,7 +597,7 @@ fn build_call_shim<'tcx>( let untuple_args = sig.inputs(); // Create substitutions for the `Self` and `Args` generic parameters of the shim body. - let arg_tup = tcx.mk_tup(untuple_args.iter()); + let arg_tup = tcx.intern_tup(untuple_args); (Some([ty.into(), arg_tup.into()]), Some(untuple_args)) } else { diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index bd998ed91d9..37449aaabed 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -200,16 +200,21 @@ impl<'a> StringReader<'a> { }; token::Literal(token::Lit { kind, symbol, suffix }) } - rustc_lexer::TokenKind::Lifetime { starts_with_number } => { + rustc_lexer::TokenKind::Lifetime { starts_with_number, contains_emoji } => { // Include the leading `'` in the real identifier, for macro // expansion purposes. See #12512 for the gory details of why // this is necessary. let lifetime_name = self.str_from(start); if starts_with_number { let span = self.mk_sp(start, self.pos); - let mut diag = self.sess.struct_err("lifetimes cannot start with a number"); + let mut diag = self.sess.struct_err("lifetimes or labels cannot start with a number"); diag.set_span(span); diag.stash(span, StashKey::LifetimeIsChar); + } else if contains_emoji { + let span = self.mk_sp(start, self.pos); + let mut diag = self.sess.struct_err("lifetimes or labels cannot contain emojis"); + diag.set_span(span); + diag.stash(span, StashKey::LifetimeContainsEmoji); } let ident = Symbol::intern(lifetime_name); token::Lifetime(ident) diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index 57217fb681a..53e04bcc132 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -19,7 +19,6 @@ use rustc_data_structures::sync::Lock; use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed, FatalError}; use rustc_session::Session; use rustc_span::{Span, DUMMY_SP}; -use std::borrow::Borrow; use std::cell::Cell; use std::collections::hash_map::Entry; use std::fmt::Debug; @@ -364,25 +363,13 @@ where let (result, dep_node_index) = execute_job::<Q, Qcx>(qcx, key.clone(), dep_node, job.id); if Q::FEEDABLE { - // We may have put a value inside the cache from inside the execution. - // Verify that it has the same hash as what we have now, to ensure consistency. + // We should not compute queries that also got a value via feeding. + // This can't happen, as query feeding adds the very dependencies to the fed query + // as its feeding query had. So if the fed query is red, so is its feeder, which will + // get evaluated first, and re-feed the query. if let Some((cached_result, _)) = cache.lookup(&key) { - let hasher = Q::HASH_RESULT.expect("feedable forbids no_hash"); - - let old_hash = qcx.dep_context().with_stable_hashing_context(|mut hcx| { - hasher(&mut hcx, cached_result.borrow()) - }); - let new_hash = qcx - .dep_context() - .with_stable_hashing_context(|mut hcx| hasher(&mut hcx, &result)); - debug_assert_eq!( - old_hash, - new_hash, - "Computed query value for {:?}({:?}) is inconsistent with fed value,\ncomputed={:#?}\nfed={:#?}", - Q::DEP_KIND, - key, - result, - cached_result, + panic!( + "fed query later has its value computed. The already cached value: {cached_result:?}" ); } } diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 4da6acad2c0..295e93f6103 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1022,7 +1022,13 @@ fn default_configuration(sess: &Session) -> CrateConfig { let panic_strategy = sess.panic_strategy(); ret.insert((sym::panic, Some(panic_strategy.desc_symbol()))); - for s in sess.opts.unstable_opts.sanitizer { + for mut s in sess.opts.unstable_opts.sanitizer { + // KASAN should use the same attribute name as ASAN, as it's still ASAN + // under the hood + if s == SanitizerSet::KERNELADDRESS { + s = SanitizerSet::ADDRESS; + } + let symbol = Symbol::intern(&s.to_string()); ret.insert((sym::sanitize, Some(symbol))); } diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index c784582012a..0d5818bd39c 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -370,7 +370,7 @@ mod desc { pub const parse_opt_panic_strategy: &str = parse_panic_strategy; pub const parse_oom_strategy: &str = "either `panic` or `abort`"; pub const parse_relro_level: &str = "one of: `full`, `partial`, or `off`"; - pub const parse_sanitizers: &str = "comma separated list of sanitizers: `address`, `cfi`, `hwaddress`, `kcfi`, `leak`, `memory`, `memtag`, `shadow-call-stack`, or `thread`"; + pub const parse_sanitizers: &str = "comma separated list of sanitizers: `address`, `cfi`, `hwaddress`, `kcfi`, `kernel-address`, `leak`, `memory`, `memtag`, `shadow-call-stack`, or `thread`"; pub const parse_sanitizer_memory_track_origins: &str = "0, 1, or 2"; pub const parse_cfguard: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc), `checks`, or `nochecks`"; @@ -684,6 +684,7 @@ mod parse { "address" => SanitizerSet::ADDRESS, "cfi" => SanitizerSet::CFI, "kcfi" => SanitizerSet::KCFI, + "kernel-address" => SanitizerSet::KERNELADDRESS, "leak" => SanitizerSet::LEAK, "memory" => SanitizerSet::MEMORY, "memtag" => SanitizerSet::MEMTAG, diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index e608b9fe0b3..3dc09854b3c 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -954,10 +954,10 @@ impl Session { /// Checks if LLVM lifetime markers should be emitted. pub fn emit_lifetime_markers(&self) -> bool { self.opts.optimize != config::OptLevel::No - // AddressSanitizer uses lifetimes to detect use after scope bugs. + // AddressSanitizer and KernelAddressSanitizer uses lifetimes to detect use after scope bugs. // MemorySanitizer uses lifetimes to detect use of uninitialized stack variables. // HWAddressSanitizer will use lifetimes to detect use after scope bugs in the future. - || self.opts.unstable_opts.sanitizer.intersects(SanitizerSet::ADDRESS | SanitizerSet::MEMORY | SanitizerSet::HWADDRESS) + || self.opts.unstable_opts.sanitizer.intersects(SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS | SanitizerSet::MEMORY | SanitizerSet::HWADDRESS) } pub fn is_proc_macro_attr(&self, attr: &Attribute) -> bool { diff --git a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs index 949ef04dd4d..59a2227cd36 100644 --- a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs +++ b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs @@ -781,8 +781,8 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio let output = transform_ty(tcx, fn_sig.skip_binder().output(), options); ty = tcx.mk_fn_ptr(ty::Binder::bind_with_vars( tcx.mk_fn_sig( - parameters.iter(), - &output, + parameters, + output, fn_sig.c_variadic(), fn_sig.unsafety(), fn_sig.abi(), @@ -813,21 +813,18 @@ fn transform_substs<'tcx>( substs: SubstsRef<'tcx>, options: TransformTyOptions, ) -> SubstsRef<'tcx> { - let substs: Vec<GenericArg<'tcx>> = substs - .iter() - .map(|subst| { - if let GenericArgKind::Type(ty) = subst.unpack() { - if is_c_void_ty(tcx, ty) { - tcx.mk_unit().into() - } else { - transform_ty(tcx, ty, options).into() - } + let substs = substs.iter().map(|subst| { + if let GenericArgKind::Type(ty) = subst.unpack() { + if is_c_void_ty(tcx, ty) { + tcx.mk_unit().into() } else { - subst + transform_ty(tcx, ty, options).into() } - }) - .collect(); - tcx.mk_substs(substs.iter()) + } else { + subst + } + }); + tcx.mk_substs(substs) } /// Returns a type metadata identifier for the specified FnAbi using the Itanium C++ ABI with vendor diff --git a/compiler/rustc_target/src/spec/aarch64_apple_ios.rs b/compiler/rustc_target/src/spec/aarch64_apple_ios.rs index b5f9eb1259d..e9edfd2877b 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_ios.rs +++ b/compiler/rustc_target/src/spec/aarch64_apple_ios.rs @@ -1,8 +1,11 @@ use super::apple_base::{ios_llvm_target, opts, Arch}; -use crate::spec::{FramePointer, Target, TargetOptions}; +use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions}; pub fn target() -> Target { let arch = Arch::Arm64; + let mut base = opts("ios", arch); + base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::THREAD; + Target { // Clang automatically chooses a more specific target based on // IPHONEOS_DEPLOYMENT_TARGET. @@ -28,7 +31,7 @@ pub fn target() -> Target { darwinpcs\0\ -Os\0" .into(), - ..opts("ios", arch) + ..base }, } } diff --git a/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs b/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs index 3374755e2dd..6e2d62b6e08 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs +++ b/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs @@ -1,8 +1,11 @@ use super::apple_base::{ios_sim_llvm_target, opts, Arch}; -use crate::spec::{FramePointer, Target, TargetOptions}; +use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions}; pub fn target() -> Target { let arch = Arch::Arm64_sim; + let mut base = opts("ios", arch); + base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::THREAD; + Target { // Clang automatically chooses a more specific target based on // IPHONEOS_DEPLOYMENT_TARGET. @@ -28,7 +31,7 @@ pub fn target() -> Target { darwinpcs\0\ -Os\0" .into(), - ..opts("ios", arch) + ..base }, } } diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_none.rs b/compiler/rustc_target/src/spec/aarch64_unknown_none.rs index 30fbe6f3c15..be27302f7f5 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_none.rs +++ b/compiler/rustc_target/src/spec/aarch64_unknown_none.rs @@ -15,7 +15,7 @@ pub fn target() -> Target { linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes), linker: Some("rust-lld".into()), features: "+v8a,+strict-align,+neon,+fp-armv8".into(), - supported_sanitizers: SanitizerSet::KCFI, + supported_sanitizers: SanitizerSet::KCFI | SanitizerSet::KERNELADDRESS, relocation_model: RelocModel::Static, disable_redzone: true, max_atomic_width: Some(128), diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index ef60956a617..0d86a3032a6 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -812,6 +812,7 @@ bitflags::bitflags! { const MEMTAG = 1 << 6; const SHADOWCALLSTACK = 1 << 7; const KCFI = 1 << 8; + const KERNELADDRESS = 1 << 9; } } @@ -824,6 +825,7 @@ impl SanitizerSet { SanitizerSet::ADDRESS => "address", SanitizerSet::CFI => "cfi", SanitizerSet::KCFI => "kcfi", + SanitizerSet::KERNELADDRESS => "kernel-address", SanitizerSet::LEAK => "leak", SanitizerSet::MEMORY => "memory", SanitizerSet::MEMTAG => "memtag", @@ -866,6 +868,7 @@ impl IntoIterator for SanitizerSet { SanitizerSet::SHADOWCALLSTACK, SanitizerSet::THREAD, SanitizerSet::HWADDRESS, + SanitizerSet::KERNELADDRESS, ] .iter() .copied() @@ -2341,6 +2344,7 @@ impl Target { Some("address") => SanitizerSet::ADDRESS, Some("cfi") => SanitizerSet::CFI, Some("kcfi") => SanitizerSet::KCFI, + Some("kernel-address") => SanitizerSet::KERNELADDRESS, Some("leak") => SanitizerSet::LEAK, Some("memory") => SanitizerSet::MEMORY, Some("memtag") => SanitizerSet::MEMTAG, diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs b/compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs index 409b0b26961..ab3c14e3fe7 100644 --- a/compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs +++ b/compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs @@ -1,6 +1,8 @@ use crate::spec::{Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy}; use crate::spec::{RelocModel, Target, TargetOptions}; +use super::SanitizerSet; + pub fn target() -> Target { Target { data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(), @@ -20,6 +22,7 @@ pub fn target() -> Target { code_model: Some(CodeModel::Medium), emit_debug_gdb_scripts: false, eh_frame_header: false, + supported_sanitizers: SanitizerSet::KERNELADDRESS, ..Default::default() }, } diff --git a/compiler/rustc_target/src/spec/riscv64imac_unknown_none_elf.rs b/compiler/rustc_target/src/spec/riscv64imac_unknown_none_elf.rs index 87aba9171b4..0f1821c9985 100644 --- a/compiler/rustc_target/src/spec/riscv64imac_unknown_none_elf.rs +++ b/compiler/rustc_target/src/spec/riscv64imac_unknown_none_elf.rs @@ -1,5 +1,5 @@ use crate::spec::{Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy}; -use crate::spec::{RelocModel, Target, TargetOptions}; +use crate::spec::{RelocModel, SanitizerSet, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -19,6 +19,7 @@ pub fn target() -> Target { code_model: Some(CodeModel::Medium), emit_debug_gdb_scripts: false, eh_frame_header: false, + supported_sanitizers: SanitizerSet::KERNELADDRESS, ..Default::default() }, } diff --git a/compiler/rustc_target/src/spec/x86_64_apple_ios.rs b/compiler/rustc_target/src/spec/x86_64_apple_ios.rs index fbd3ebd4d04..1dcb47056a4 100644 --- a/compiler/rustc_target/src/spec/x86_64_apple_ios.rs +++ b/compiler/rustc_target/src/spec/x86_64_apple_ios.rs @@ -1,8 +1,11 @@ use super::apple_base::{ios_sim_llvm_target, opts, Arch}; -use crate::spec::{StackProbeType, Target, TargetOptions}; +use crate::spec::{SanitizerSet, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { let arch = Arch::X86_64_sim; + let mut base = opts("ios", arch); + base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::THREAD; + Target { llvm_target: ios_sim_llvm_target(arch).into(), pointer_width: 64, @@ -12,7 +15,7 @@ pub fn target() -> Target { options: TargetOptions { max_atomic_width: Some(64), stack_probes: StackProbeType::X86, - ..opts("ios", arch) + ..base }, } } diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_none.rs b/compiler/rustc_target/src/spec/x86_64_unknown_none.rs index 32060c35c11..43c5ce78ce3 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_none.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_none.rs @@ -20,7 +20,7 @@ pub fn target() -> Target { features: "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2,+soft-float" .into(), - supported_sanitizers: SanitizerSet::KCFI, + supported_sanitizers: SanitizerSet::KCFI | SanitizerSet::KERNELADDRESS, disable_redzone: true, panic_strategy: PanicStrategy::Abort, code_model: Some(CodeModel::Kernel), diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index 0921fb5756d..d12e5f797fb 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -359,7 +359,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { let b_last_ty = b_tys.last().unwrap(); // Substitute just the tail field of B., and require that they're equal. - let unsized_a_ty = tcx.mk_tup(a_rest_tys.iter().chain([b_last_ty])); + let unsized_a_ty = tcx.mk_tup(a_rest_tys.iter().chain([b_last_ty]).copied()); let mut nested_goals = ecx.infcx.eq(goal.param_env, unsized_a_ty, b_ty)?; // Similar to ADTs, require that the rest of the fields are equal. diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs index b6847b976be..3662463178f 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs @@ -191,10 +191,10 @@ pub(crate) fn extract_tupled_inputs_and_output_from_callable<'tcx>( ty::FnDef(def_id, substs) => Ok(Some( tcx.fn_sig(def_id) .subst(tcx, substs) - .map_bound(|sig| (tcx.mk_tup(sig.inputs().iter()), sig.output())), + .map_bound(|sig| (tcx.intern_tup(sig.inputs()), sig.output())), )), ty::FnPtr(sig) => { - Ok(Some(sig.map_bound(|sig| (tcx.mk_tup(sig.inputs().iter()), sig.output())))) + Ok(Some(sig.map_bound(|sig| (tcx.intern_tup(sig.inputs()), sig.output())))) } ty::Closure(_, substs) => { let closure_substs = substs.as_closure(); diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index a0c67f480d0..91b463800a8 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -2012,7 +2012,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let sig = match inputs.kind() { ty::Tuple(inputs) if infcx.tcx.is_fn_trait(trait_ref.def_id()) => { infcx.tcx.mk_fn_sig( - inputs.iter(), + *inputs, infcx.next_ty_var(TypeVariableOrigin { span: DUMMY_SP, kind: TypeVariableOriginKind::MiscVariable, @@ -2023,7 +2023,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ) } _ => infcx.tcx.mk_fn_sig( - std::iter::once(inputs), + [inputs], infcx.next_ty_var(TypeVariableOrigin { span: DUMMY_SP, kind: TypeVariableOriginKind::MiscVariable, diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index c2388f9fa1b..9b3249e58e8 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1923,7 +1923,7 @@ fn confirm_builtin_candidate<'cx, 'tcx>( ) -> Progress<'tcx> { let tcx = selcx.tcx(); let self_ty = obligation.predicate.self_ty(); - let substs = tcx.mk_substs([self_ty.into()].iter()); + let substs = tcx.intern_substs(&[self_ty.into()]); let lang_items = tcx.lang_items(); let item_def_id = obligation.predicate.def_id; let trait_def_id = tcx.trait_of_item(item_def_id).unwrap(); diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 1309df18e15..e4a832e4728 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -564,10 +564,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .into() } }); - let bound_vars = tcx.mk_bound_variable_kinds(bound_vars.into_iter()); + let bound_vars = tcx.intern_bound_variable_kinds(&bound_vars); let assoc_ty_substs = tcx.intern_substs(&substs); - - let bound_vars = tcx.mk_bound_variable_kinds(bound_vars.into_iter()); let bound = bound.map_bound(|b| b.kind().skip_binder()).subst(tcx, assoc_ty_substs); tcx.mk_predicate(ty::Binder::bind_with_vars(bound, bound_vars)) diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index 8b32c0119e0..41924dc2a6d 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -141,8 +141,8 @@ fn fn_sig_for_fn_abi<'tcx>( ty::Binder::bind_with_vars( tcx.mk_fn_sig( - [env_ty, resume_ty].iter(), - &ret_ty, + [env_ty, resume_ty], + ret_ty, false, hir::Unsafety::Normal, rustc_target::spec::abi::Abi::Rust, diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs index a9fbad55dac..852156c24f4 100644 --- a/compiler/rustc_ty_utils/src/consts.rs +++ b/compiler/rustc_ty_utils/src/consts.rs @@ -144,7 +144,7 @@ fn recurse_build<'tcx>( for &id in args.iter() { new_args.push(recurse_build(tcx, body, id, root_span)?); } - let new_args = tcx.mk_const_list(new_args.iter()); + let new_args = tcx.intern_const_list(&new_args); tcx.mk_const(Expr::FunctionCall(fun, new_args), node.ty) } &ExprKind::Binary { op, lhs, rhs } if check_binop(op) => { diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index cb28731681b..5a991e03dee 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -69,38 +69,37 @@ pub trait Interner: Sized { type PlaceholderRegion: Clone + Debug + Hash + Ord; } -pub trait InternAs<T: ?Sized, R> { +/// Imagine you have a function `F: FnOnce(&[T]) -> R`, plus an iterator `iter` +/// that produces `T` items. You could combine them with +/// `f(&iter.collect::<Vec<_>>())`, but this requires allocating memory for the +/// `Vec`. +/// +/// This trait allows for faster implementations, intended for cases where the +/// number of items produced by the iterator is small. There is a blanket impl +/// for `T` items, but there is also a fallible impl for `Result<T, E>` items. +pub trait CollectAndApply<T, R>: Sized { type Output; - fn intern_with<F>(self, f: F) -> Self::Output + + /// Produce a result of type `Self::Output` from `iter`. The result will + /// typically be produced by applying `f` on the elements produced by + /// `iter`, though this may not happen in some impls, e.g. if an error + /// occured during iteration. + fn collect_and_apply<I, F>(iter: I, f: F) -> Self::Output where + I: Iterator<Item = Self>, F: FnOnce(&[T]) -> R; } -impl<I, T, R, E> InternAs<T, R> for I -where - E: InternIteratorElement<T, R>, - I: Iterator<Item = E>, -{ - type Output = E::Output; - fn intern_with<F>(self, f: F) -> Self::Output +/// The blanket impl that always collects all elements and applies `f`. +impl<T, R> CollectAndApply<T, R> for T { + type Output = R; + + /// Equivalent to `f(&iter.collect::<Vec<_>>())`. + fn collect_and_apply<I, F>(mut iter: I, f: F) -> R where + I: Iterator<Item = T>, F: FnOnce(&[T]) -> R, { - E::intern_with(self, f) - } -} - -pub trait InternIteratorElement<T, R>: Sized { - type Output; - fn intern_with<I: Iterator<Item = Self>, F: FnOnce(&[T]) -> R>(iter: I, f: F) -> Self::Output; -} - -impl<T, R> InternIteratorElement<T, R> for T { - type Output = R; - fn intern_with<I: Iterator<Item = Self>, F: FnOnce(&[T]) -> R>( - mut iter: I, - f: F, - ) -> Self::Output { // This code is hot enough that it's worth specializing for the most // common length lists, to avoid the overhead of `SmallVec` creation. // Lengths 0, 1, and 2 typically account for ~95% of cases. If @@ -127,23 +126,17 @@ impl<T, R> InternIteratorElement<T, R> for T { } } -impl<'a, T, R> InternIteratorElement<T, R> for &'a T -where - T: Clone + 'a, -{ - type Output = R; - fn intern_with<I: Iterator<Item = Self>, F: FnOnce(&[T]) -> R>(iter: I, f: F) -> Self::Output { - // This code isn't hot. - f(&iter.cloned().collect::<SmallVec<[_; 8]>>()) - } -} - -impl<T, R, E> InternIteratorElement<T, R> for Result<T, E> { +/// A fallible impl that will fail, without calling `f`, if there are any +/// errors during collection. +impl<T, R, E> CollectAndApply<T, R> for Result<T, E> { type Output = Result<R, E>; - fn intern_with<I: Iterator<Item = Self>, F: FnOnce(&[T]) -> R>( - mut iter: I, - f: F, - ) -> Self::Output { + + /// Equivalent to `Ok(f(&iter.collect::<Result<Vec<_>>>()?))`. + fn collect_and_apply<I, F>(mut iter: I, f: F) -> Result<R, E> + where + I: Iterator<Item = Result<T, E>>, + F: FnOnce(&[T]) -> R, + { // This code is hot enough that it's worth specializing for the most // common length lists, to avoid the overhead of `SmallVec` creation. // Lengths 0, 1, and 2 typically account for ~95% of cases. If diff --git a/library/std/src/sync/lazy_lock.rs b/library/std/src/sync/lazy_lock.rs index 4a15305301d..7e85d6a063a 100644 --- a/library/std/src/sync/lazy_lock.rs +++ b/library/std/src/sync/lazy_lock.rs @@ -1,8 +1,21 @@ -use crate::cell::Cell; +use crate::cell::UnsafeCell; use crate::fmt; +use crate::mem::ManuallyDrop; use crate::ops::Deref; use crate::panic::{RefUnwindSafe, UnwindSafe}; -use crate::sync::OnceLock; +use crate::sync::Once; + +use super::once::ExclusiveState; + +// We use the state of a Once as discriminant value. Upon creation, the state is +// "incomplete" and `f` contains the initialization closure. In the first call to +// `call_once`, `f` is taken and run. If it succeeds, `value` is set and the state +// is changed to "complete". If it panics, the Once is poisoned, so none of the +// two fields is initialized. +union Data<T, F> { + value: ManuallyDrop<T>, + f: ManuallyDrop<F>, +} /// A value which is initialized on the first access. /// @@ -43,16 +56,17 @@ use crate::sync::OnceLock; /// ``` #[unstable(feature = "once_cell", issue = "74465")] pub struct LazyLock<T, F = fn() -> T> { - cell: OnceLock<T>, - init: Cell<Option<F>>, + once: Once, + data: UnsafeCell<Data<T, F>>, } + impl<T, F: FnOnce() -> T> LazyLock<T, F> { /// Creates a new lazy value with the given initializing /// function. #[inline] #[unstable(feature = "once_cell", issue = "74465")] pub const fn new(f: F) -> LazyLock<T, F> { - LazyLock { cell: OnceLock::new(), init: Cell::new(Some(f)) } + LazyLock { once: Once::new(), data: UnsafeCell::new(Data { f: ManuallyDrop::new(f) }) } } /// Forces the evaluation of this lazy value and @@ -74,10 +88,50 @@ impl<T, F: FnOnce() -> T> LazyLock<T, F> { #[inline] #[unstable(feature = "once_cell", issue = "74465")] pub fn force(this: &LazyLock<T, F>) -> &T { - this.cell.get_or_init(|| match this.init.take() { - Some(f) => f(), - None => panic!("Lazy instance has previously been poisoned"), - }) + this.once.call_once(|| { + // SAFETY: `call_once` only runs this closure once, ever. + let data = unsafe { &mut *this.data.get() }; + let f = unsafe { ManuallyDrop::take(&mut data.f) }; + let value = f(); + data.value = ManuallyDrop::new(value); + }); + + // SAFETY: + // There are four possible scenarios: + // * the closure was called and initialized `value`. + // * the closure was called and panicked, so this point is never reached. + // * the closure was not called, but a previous call initialized `value`. + // * the closure was not called because the Once is poisoned, so this point + // is never reached. + // So `value` has definitely been initialized and will not be modified again. + unsafe { &*(*this.data.get()).value } + } +} + +impl<T, F> LazyLock<T, F> { + /// Get the inner value if it has already been initialized. + fn get(&self) -> Option<&T> { + if self.once.is_completed() { + // SAFETY: + // The closure has been run successfully, so `value` has been initialized + // and will not be modified again. + Some(unsafe { &*(*self.data.get()).value }) + } else { + None + } + } +} + +#[unstable(feature = "once_cell", issue = "74465")] +impl<T, F> Drop for LazyLock<T, F> { + fn drop(&mut self) { + match self.once.state() { + ExclusiveState::Incomplete => unsafe { ManuallyDrop::drop(&mut self.data.get_mut().f) }, + ExclusiveState::Complete => unsafe { + ManuallyDrop::drop(&mut self.data.get_mut().value) + }, + ExclusiveState::Poisoned => {} + } } } @@ -103,23 +157,23 @@ impl<T: Default> Default for LazyLock<T> { #[unstable(feature = "once_cell", issue = "74465")] impl<T: fmt::Debug, F> fmt::Debug for LazyLock<T, F> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Lazy").field("cell", &self.cell).finish_non_exhaustive() + match self.get() { + Some(v) => f.debug_tuple("LazyLock").field(v).finish(), + None => f.write_str("LazyLock(Uninit)"), + } } } // We never create a `&F` from a `&LazyLock<T, F>` so it is fine // to not impl `Sync` for `F` -// we do create a `&mut Option<F>` in `force`, but this is -// properly synchronized, so it only happens once -// so it also does not contribute to this impl. #[unstable(feature = "once_cell", issue = "74465")] -unsafe impl<T, F: Send> Sync for LazyLock<T, F> where OnceLock<T>: Sync {} +unsafe impl<T: Sync + Send, F: Send> Sync for LazyLock<T, F> {} // auto-derived `Send` impl is OK. #[unstable(feature = "once_cell", issue = "74465")] -impl<T, F: UnwindSafe> RefUnwindSafe for LazyLock<T, F> where OnceLock<T>: RefUnwindSafe {} +impl<T: RefUnwindSafe + UnwindSafe, F: UnwindSafe> RefUnwindSafe for LazyLock<T, F> {} #[unstable(feature = "once_cell", issue = "74465")] -impl<T, F: UnwindSafe> UnwindSafe for LazyLock<T, F> where OnceLock<T>: UnwindSafe {} +impl<T: UnwindSafe, F: UnwindSafe> UnwindSafe for LazyLock<T, F> {} #[cfg(test)] mod tests; diff --git a/library/std/src/sync/mod.rs b/library/std/src/sync/mod.rs index ba20bab87a4..4edc956173b 100644 --- a/library/std/src/sync/mod.rs +++ b/library/std/src/sync/mod.rs @@ -186,7 +186,7 @@ mod condvar; mod lazy_lock; mod mpmc; mod mutex; -mod once; +pub(crate) mod once; mod once_lock; mod poison; mod remutex; diff --git a/library/std/src/sync/once.rs b/library/std/src/sync/once.rs index 0f25417d6b5..1b17c31089f 100644 --- a/library/std/src/sync/once.rs +++ b/library/std/src/sync/once.rs @@ -43,6 +43,12 @@ pub struct OnceState { pub(crate) inner: sys::OnceState, } +pub(crate) enum ExclusiveState { + Incomplete, + Poisoned, + Complete, +} + /// Initialization value for static [`Once`] values. /// /// # Examples @@ -248,6 +254,16 @@ impl Once { pub fn is_completed(&self) -> bool { self.inner.is_completed() } + + /// Returns the current state of the `Once` instance. + /// + /// Since this takes a mutable reference, no initialization can currently + /// be running, so the state must be either "incomplete", "poisoned" or + /// "complete". + #[inline] + pub(crate) fn state(&mut self) -> ExclusiveState { + self.inner.state() + } } #[stable(feature = "std_debug", since = "1.16.0")] diff --git a/library/std/src/sys/unsupported/once.rs b/library/std/src/sys/unsupported/once.rs index b4bb4975f41..11fde1888ba 100644 --- a/library/std/src/sys/unsupported/once.rs +++ b/library/std/src/sys/unsupported/once.rs @@ -1,5 +1,6 @@ use crate::cell::Cell; use crate::sync as public; +use crate::sync::once::ExclusiveState; pub struct Once { state: Cell<State>, @@ -44,6 +45,16 @@ impl Once { self.state.get() == State::Complete } + #[inline] + pub(crate) fn state(&mut self) -> ExclusiveState { + match self.state.get() { + State::Incomplete => ExclusiveState::Incomplete, + State::Poisoned => ExclusiveState::Poisoned, + State::Complete => ExclusiveState::Complete, + _ => unreachable!("invalid Once state"), + } + } + #[cold] #[track_caller] pub fn call(&self, ignore_poisoning: bool, f: &mut impl FnMut(&public::OnceState)) { diff --git a/library/std/src/sys_common/once/futex.rs b/library/std/src/sys_common/once/futex.rs index 5c7e6c01371..42db5fad4b4 100644 --- a/library/std/src/sys_common/once/futex.rs +++ b/library/std/src/sys_common/once/futex.rs @@ -4,6 +4,7 @@ use crate::sync::atomic::{ AtomicU32, Ordering::{Acquire, Relaxed, Release}, }; +use crate::sync::once::ExclusiveState; use crate::sys::futex::{futex_wait, futex_wake_all}; // On some platforms, the OS is very nice and handles the waiter queue for us. @@ -78,6 +79,16 @@ impl Once { self.state.load(Acquire) == COMPLETE } + #[inline] + pub(crate) fn state(&mut self) -> ExclusiveState { + match *self.state.get_mut() { + INCOMPLETE => ExclusiveState::Incomplete, + POISONED => ExclusiveState::Poisoned, + COMPLETE => ExclusiveState::Complete, + _ => unreachable!("invalid Once state"), + } + } + // This uses FnMut to match the API of the generic implementation. As this // implementation is quite light-weight, it is generic over the closure and // so avoids the cost of dynamic dispatch. diff --git a/library/std/src/sys_common/once/queue.rs b/library/std/src/sys_common/once/queue.rs index d953a674592..def0bcd6fac 100644 --- a/library/std/src/sys_common/once/queue.rs +++ b/library/std/src/sys_common/once/queue.rs @@ -60,6 +60,7 @@ use crate::fmt; use crate::ptr; use crate::sync as public; use crate::sync::atomic::{AtomicBool, AtomicPtr, Ordering}; +use crate::sync::once::ExclusiveState; use crate::thread::{self, Thread}; type Masked = (); @@ -121,6 +122,16 @@ impl Once { self.state_and_queue.load(Ordering::Acquire).addr() == COMPLETE } + #[inline] + pub(crate) fn state(&mut self) -> ExclusiveState { + match self.state_and_queue.get_mut().addr() { + INCOMPLETE => ExclusiveState::Incomplete, + POISONED => ExclusiveState::Poisoned, + COMPLETE => ExclusiveState::Complete, + _ => unreachable!("invalid Once state"), + } + } + // This is a non-generic function to reduce the monomorphization cost of // using `call_once` (this isn't exactly a trivial or small implementation). // diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 97a1102e3c5..e7d7215166b 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -533,7 +533,12 @@ fn copy_sanitizers( let dst = libdir.join(&runtime.name); builder.copy(&runtime.path, &dst); - if target == "x86_64-apple-darwin" || target == "aarch64-apple-darwin" { + if target == "x86_64-apple-darwin" + || target == "aarch64-apple-darwin" + || target == "aarch64-apple-ios" + || target == "aarch64-apple-ios-sim" + || target == "x86_64-apple-ios" + { // Update the library’s install name to reflect that it has been renamed. apple_darwin_update_library_name(&dst, &format!("@rpath/{}", &runtime.name)); // Upon renaming the install name, the code signature of the file will invalidate, diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 9235de75ec6..d6e63fb937e 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -483,7 +483,7 @@ impl Step for Llvm { cfg.define("LLVM_VERSION_SUFFIX", suffix); } - configure_cmake(builder, target, &mut cfg, true, ldflags); + configure_cmake(builder, target, &mut cfg, true, ldflags, &[]); configure_llvm(builder, target, &mut cfg); for (key, val) in &builder.config.llvm_build_config { @@ -574,6 +574,7 @@ fn configure_cmake( cfg: &mut cmake::Config, use_compiler_launcher: bool, mut ldflags: LdFlags, + extra_compiler_flags: &[&str], ) { // Do not print installation messages for up-to-date files. // LLVM and LLD builds can produce a lot of those and hit CI limits on log size. @@ -714,6 +715,9 @@ fn configure_cmake( if builder.config.llvm_clang_cl.is_some() { cflags.push(&format!(" --target={}", target)); } + for flag in extra_compiler_flags { + cflags.push(&format!(" {}", flag)); + } cfg.define("CMAKE_C_FLAGS", cflags); let mut cxxflags: OsString = builder.cflags(target, GitRepo::Llvm, CLang::Cxx).join(" ").into(); if let Some(ref s) = builder.config.llvm_cxxflags { @@ -723,6 +727,9 @@ fn configure_cmake( if builder.config.llvm_clang_cl.is_some() { cxxflags.push(&format!(" --target={}", target)); } + for flag in extra_compiler_flags { + cxxflags.push(&format!(" {}", flag)); + } cfg.define("CMAKE_CXX_FLAGS", cxxflags); if let Some(ar) = builder.ar(target) { if ar.is_absolute() { @@ -864,7 +871,7 @@ impl Step for Lld { } } - configure_cmake(builder, target, &mut cfg, true, ldflags); + configure_cmake(builder, target, &mut cfg, true, ldflags, &[]); configure_llvm(builder, target, &mut cfg); // Re-use the same flags as llvm to control the level of debug information @@ -1028,7 +1035,16 @@ impl Step for Sanitizers { // Unfortunately sccache currently lacks support to build them successfully. // Disable compiler launcher on Darwin targets to avoid potential issues. let use_compiler_launcher = !self.target.contains("apple-darwin"); - configure_cmake(builder, self.target, &mut cfg, use_compiler_launcher, LdFlags::default()); + let extra_compiler_flags: &[&str] = + if self.target.contains("apple") { &["-fembed-bitcode=off"] } else { &[] }; + configure_cmake( + builder, + self.target, + &mut cfg, + use_compiler_launcher, + LdFlags::default(), + extra_compiler_flags, + ); t!(fs::create_dir_all(&out_dir)); cfg.out_dir(out_dir); @@ -1084,12 +1100,15 @@ fn supported_sanitizers( match &*target.triple { "aarch64-apple-darwin" => darwin_libs("osx", &["asan", "lsan", "tsan"]), + "aarch64-apple-ios" => darwin_libs("ios", &["asan", "tsan"]), + "aarch64-apple-ios-sim" => darwin_libs("iossim", &["asan", "tsan"]), "aarch64-unknown-fuchsia" => common_libs("fuchsia", "aarch64", &["asan"]), "aarch64-unknown-linux-gnu" => { common_libs("linux", "aarch64", &["asan", "lsan", "msan", "tsan", "hwasan"]) } "x86_64-apple-darwin" => darwin_libs("osx", &["asan", "lsan", "tsan"]), "x86_64-unknown-fuchsia" => common_libs("fuchsia", "x86_64", &["asan"]), + "x86_64-apple-ios" => darwin_libs("iossim", &["asan", "tsan"]), "x86_64-unknown-freebsd" => common_libs("freebsd", "x86_64", &["asan", "msan", "tsan"]), "x86_64-unknown-netbsd" => { common_libs("netbsd", "x86_64", &["asan", "lsan", "msan", "tsan"]) diff --git a/src/doc/unstable-book/src/compiler-flags/sanitizer.md b/src/doc/unstable-book/src/compiler-flags/sanitizer.md index 70c3a445b86..262cef3454a 100644 --- a/src/doc/unstable-book/src/compiler-flags/sanitizer.md +++ b/src/doc/unstable-book/src/compiler-flags/sanitizer.md @@ -531,6 +531,24 @@ LLVM KCFI is supported on the following targets: See the [Clang KernelControlFlowIntegrity documentation][clang-kcfi] for more details. +# KernelAddressSanitizer + +KernelAddressSanitizer (KASAN) is a freestanding version of AddressSanitizer +which is suitable for detecting memory errors in programs which do not have a +runtime environment, such as operating system kernels. KernelAddressSanitizer +requires manual implementation of the underlying functions used for tracking +KernelAddressSanitizer state. + +KernelAddressSanitizer is supported on the following targets: + +* `aarch64-unknown-none` +* `riscv64gc-unknown-none-elf` +* `riscv64imac-unknown-none-elf` +* `x86_64-unknown-none` + +See the [Linux Kernel's KernelAddressSanitizer documentation][linux-kasan] for +more details. + # LeakSanitizer LeakSanitizer is run-time memory leak detector. @@ -714,6 +732,7 @@ Sanitizers produce symbolized stacktraces when llvm-symbolizer binary is in `PAT * [AddressSanitizer in Clang][clang-asan] * [ControlFlowIntegrity in Clang][clang-cfi] * [HWAddressSanitizer in Clang][clang-hwasan] +* [Linux Kernel's KernelAddressSanitizer documentation][linux-kasan] * [LeakSanitizer in Clang][clang-lsan] * [MemorySanitizer in Clang][clang-msan] * [MemTagSanitizer in LLVM][llvm-memtag] @@ -727,4 +746,5 @@ Sanitizers produce symbolized stacktraces when llvm-symbolizer binary is in `PAT [clang-msan]: https://clang.llvm.org/docs/MemorySanitizer.html [clang-scs]: https://clang.llvm.org/docs/ShadowCallStack.html [clang-tsan]: https://clang.llvm.org/docs/ThreadSanitizer.html +[linux-kasan]: https://www.kernel.org/doc/html/latest/dev-tools/kasan.html [llvm-memtag]: https://llvm.org/docs/MemTagSanitizer.html 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 82d3b830d4f..8ddbacc3d7a 100644 --- a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs +++ b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs @@ -173,7 +173,7 @@ fn is_contains_sig(cx: &LateContext<'_>, call_id: HirId, iter_expr: &Expr<'_>) - && let Some(iter_item) = cx.tcx .associated_items(iter_trait) .find_by_name_and_kind(cx.tcx, Ident::with_dummy_span(Symbol::intern("Item")), AssocKind::Type, iter_trait) - && let substs = cx.tcx.mk_substs([GenericArg::from(typeck.expr_ty_adjusted(iter_expr))].into_iter()) + && let substs = cx.tcx.intern_substs(&[GenericArg::from(typeck.expr_ty_adjusted(iter_expr))]) && let proj_ty = cx.tcx.mk_projection(iter_item.def_id, substs) && let Ok(item_ty) = cx.tcx.try_normalize_erasing_regions(cx.param_env, proj_ty) { diff --git a/src/tools/clippy/clippy_lints/src/redundant_slicing.rs b/src/tools/clippy/clippy_lints/src/redundant_slicing.rs index 245a02ea26e..398329e455b 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_slicing.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_slicing.rs @@ -11,8 +11,6 @@ use rustc_middle::ty::adjustment::{Adjust, AutoBorrow, AutoBorrowMutability}; use rustc_middle::ty::subst::GenericArg; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use std::iter; - declare_clippy_lint! { /// ### What it does /// Checks for redundant slicing expressions which use the full range, and @@ -136,7 +134,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.tcx.mk_projection(target_id, cx.tcx.mk_substs(iter::once(GenericArg::from(indexed_ty)))), + cx.tcx.mk_projection(target_id, cx.tcx.intern_substs(&[GenericArg::from(indexed_ty)])), ) { if deref_ty == expr_ty { let snip = snippet_with_context(cx, indexed.span, ctxt, "..", &mut app).0; diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index e11ebca6ea9..d9b39927ca4 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -935,6 +935,7 @@ pub fn make_test_description<R: Read>( let has_asan = util::ASAN_SUPPORTED_TARGETS.contains(&&*config.target); let has_cfi = util::CFI_SUPPORTED_TARGETS.contains(&&*config.target); let has_kcfi = util::KCFI_SUPPORTED_TARGETS.contains(&&*config.target); + let has_kasan = util::KASAN_SUPPORTED_TARGETS.contains(&&*config.target); let has_lsan = util::LSAN_SUPPORTED_TARGETS.contains(&&*config.target); let has_msan = util::MSAN_SUPPORTED_TARGETS.contains(&&*config.target); let has_tsan = util::TSAN_SUPPORTED_TARGETS.contains(&&*config.target); @@ -1010,6 +1011,7 @@ pub fn make_test_description<R: Read>( reason!(!has_asan && config.parse_name_directive(ln, "needs-sanitizer-address")); reason!(!has_cfi && config.parse_name_directive(ln, "needs-sanitizer-cfi")); reason!(!has_kcfi && config.parse_name_directive(ln, "needs-sanitizer-kcfi")); + reason!(!has_kasan && config.parse_name_directive(ln, "needs-sanitizer-kasan")); reason!(!has_lsan && config.parse_name_directive(ln, "needs-sanitizer-leak")); reason!(!has_msan && config.parse_name_directive(ln, "needs-sanitizer-memory")); reason!(!has_tsan && config.parse_name_directive(ln, "needs-sanitizer-thread")); diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs index 67f49bb6397..5f6a27e5366 100644 --- a/src/tools/compiletest/src/util.rs +++ b/src/tools/compiletest/src/util.rs @@ -11,6 +11,8 @@ mod tests; pub const ASAN_SUPPORTED_TARGETS: &[&str] = &[ "aarch64-apple-darwin", + "aarch64-apple-ios", + "aarch64-apple-ios-sim", "aarch64-unknown-fuchsia", "aarch64-linux-android", "aarch64-unknown-linux-gnu", @@ -19,6 +21,7 @@ pub const ASAN_SUPPORTED_TARGETS: &[&str] = &[ "i686-linux-android", "i686-unknown-linux-gnu", "x86_64-apple-darwin", + "x86_64-apple-ios", "x86_64-unknown-fuchsia", "x86_64-linux-android", "x86_64-unknown-freebsd", @@ -45,6 +48,13 @@ pub const CFI_SUPPORTED_TARGETS: &[&str] = &[ pub const KCFI_SUPPORTED_TARGETS: &[&str] = &["aarch64-linux-none", "x86_64-linux-none"]; +pub const KASAN_SUPPORTED_TARGETS: &[&str] = &[ + "aarch64-unknown-none", + "riscv64gc-unknown-none-elf", + "riscv64imac-unknown-none-elf", + "x86_64-unknown-none", +]; + pub const LSAN_SUPPORTED_TARGETS: &[&str] = &[ // FIXME: currently broken, see #88132 // "aarch64-apple-darwin", @@ -63,8 +73,11 @@ pub const MSAN_SUPPORTED_TARGETS: &[&str] = &[ pub const TSAN_SUPPORTED_TARGETS: &[&str] = &[ "aarch64-apple-darwin", + "aarch64-apple-ios", + "aarch64-apple-ios-sim", "aarch64-unknown-linux-gnu", "x86_64-apple-darwin", + "x86_64-apple-ios", "x86_64-unknown-freebsd", "x86_64-unknown-linux-gnu", "s390x-unknown-linux-gnu", diff --git a/src/tools/miri/src/eval.rs b/src/tools/miri/src/eval.rs index d61e17cbf9a..ebb71b57ae3 100644 --- a/src/tools/miri/src/eval.rs +++ b/src/tools/miri/src/eval.rs @@ -363,7 +363,7 @@ pub fn create_ecx<'mir, 'tcx: 'mir>( tcx, ty::ParamEnv::reveal_all(), start_id, - tcx.mk_substs(::std::iter::once(ty::subst::GenericArg::from(main_ret_ty))), + tcx.intern_substs(&[ty::subst::GenericArg::from(main_ret_ty)]), ) .unwrap() .unwrap(); diff --git a/tests/codegen/sanitizer-kasan-emits-instrumentation.rs b/tests/codegen/sanitizer-kasan-emits-instrumentation.rs new file mode 100644 index 00000000000..d6e3f2719df --- /dev/null +++ b/tests/codegen/sanitizer-kasan-emits-instrumentation.rs @@ -0,0 +1,47 @@ +// Verifies that `-Zsanitizer=kernel-address` emits sanitizer instrumentation. + +// compile-flags: -Zsanitizer=kernel-address +// revisions: aarch64 riscv64imac riscv64gc x86_64 +//[aarch64] compile-flags: --target aarch64-unknown-none +//[aarch64] needs-llvm-components: aarch64 +//[riscv64imac] compile-flags: --target riscv64imac-unknown-none-elf +//[riscv64imac] needs-llvm-components: riscv +//[riscv64imac] min-llvm-version: 16 +//[riscv64gc] compile-flags: --target riscv64gc-unknown-none-elf +//[riscv64gc] needs-llvm-components: riscv +//[riscv64gc] min-llvm-version: 16 +//[x86_64] compile-flags: --target x86_64-unknown-none +//[x86_64] needs-llvm-components: x86 + +#![crate_type = "rlib"] +#![feature(no_core, no_sanitize, lang_items)] +#![no_core] + +#[lang = "sized"] +trait Sized {} + +#[lang = "copy"] +trait Copy {} + +impl Copy for u8 {} + +// CHECK-LABEL: ; sanitizer_kasan_emits_instrumentation::unsanitized +// CHECK-NEXT: ; Function Attrs: +// CHECK-NOT: sanitize_address +// CHECK: start: +// CHECK-NOT: call void @__asan_report_load +// CHECK: } +#[no_sanitize(address)] +pub fn unsanitized(b: &mut u8) -> u8 { + *b +} + +// CHECK-LABEL: ; sanitizer_kasan_emits_instrumentation::sanitized +// CHECK-NEXT: ; Function Attrs: +// CHECK: sanitize_address +// CHECK: start: +// CHECK: call void @__asan_report_load +// CHECK: } +pub fn sanitized(b: &mut u8) -> u8 { + *b +} diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff index 5ebaacd4ba9..1f5c533815d 100644 --- a/tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff +++ b/tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff @@ -86,8 +86,6 @@ bb6: { _10 = ((_7 as Some).0: usize); // scope 3 at $DIR/funky_arms.rs:+13:17: +13:26 - StorageLive(_11); // scope 3 at $DIR/funky_arms.rs:+15:43: +15:46 - _11 = &mut (*_1); // scope 3 at $DIR/funky_arms.rs:+15:43: +15:46 StorageLive(_13); // scope 3 at $DIR/funky_arms.rs:+15:53: +15:57 _13 = _6; // scope 3 at $DIR/funky_arms.rs:+15:53: +15:57 StorageLive(_14); // scope 3 at $DIR/funky_arms.rs:+15:59: +15:79 @@ -95,7 +93,7 @@ _15 = _10 as u32 (IntToInt); // scope 3 at $DIR/funky_arms.rs:+15:59: +15:75 _14 = Add(move _15, const 1_u32); // scope 3 at $DIR/funky_arms.rs:+15:59: +15:79 StorageDead(_15); // scope 3 at $DIR/funky_arms.rs:+15:78: +15:79 - _0 = float_to_exponential_common_exact::<T>(move _11, _2, move _13, move _14, _3) -> bb7; // scope 3 at $DIR/funky_arms.rs:+15:9: +15:87 + _0 = float_to_exponential_common_exact::<T>(_1, _2, move _13, move _14, _3) -> bb7; // scope 3 at $DIR/funky_arms.rs:+15:9: +15:87 // mir::Constant // + span: $DIR/funky_arms.rs:26:9: 26:42 // + literal: Const { ty: for<'a, 'b, 'c> fn(&'a mut Formatter<'b>, &'c T, Sign, u32, bool) -> Result<(), std::fmt::Error> {float_to_exponential_common_exact::<T>}, val: Value(<ZST>) } @@ -104,16 +102,13 @@ bb7: { StorageDead(_14); // scope 3 at $DIR/funky_arms.rs:+15:86: +15:87 StorageDead(_13); // scope 3 at $DIR/funky_arms.rs:+15:86: +15:87 - StorageDead(_11); // scope 3 at $DIR/funky_arms.rs:+15:86: +15:87 goto -> bb10; // scope 2 at $DIR/funky_arms.rs:+13:5: +18:6 } bb8: { - StorageLive(_18); // scope 2 at $DIR/funky_arms.rs:+17:46: +17:49 - _18 = &mut (*_1); // scope 2 at $DIR/funky_arms.rs:+17:46: +17:49 StorageLive(_20); // scope 2 at $DIR/funky_arms.rs:+17:56: +17:60 _20 = _6; // scope 2 at $DIR/funky_arms.rs:+17:56: +17:60 - _0 = float_to_exponential_common_shortest::<T>(move _18, _2, move _20, _3) -> bb9; // scope 2 at $DIR/funky_arms.rs:+17:9: +17:68 + _0 = float_to_exponential_common_shortest::<T>(_1, _2, move _20, _3) -> bb9; // scope 2 at $DIR/funky_arms.rs:+17:9: +17:68 // mir::Constant // + span: $DIR/funky_arms.rs:28:9: 28:45 // + literal: Const { ty: for<'a, 'b, 'c> fn(&'a mut Formatter<'b>, &'c T, Sign, bool) -> Result<(), std::fmt::Error> {float_to_exponential_common_shortest::<T>}, val: Value(<ZST>) } @@ -121,7 +116,6 @@ bb9: { StorageDead(_20); // scope 2 at $DIR/funky_arms.rs:+17:67: +17:68 - StorageDead(_18); // scope 2 at $DIR/funky_arms.rs:+17:67: +17:68 goto -> bb10; // scope 2 at $DIR/funky_arms.rs:+13:5: +18:6 } diff --git a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.a.Inline.after.mir b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.a.Inline.after.mir index dc0c3235043..6441a9668de 100644 --- a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.a.Inline.after.mir +++ b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.a.Inline.after.mir @@ -8,7 +8,6 @@ fn a(_1: &mut [T]) -> &mut [T] { let mut _4: &mut [T]; // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 scope 1 (inlined <[T] as AsMut<[T]>>::as_mut) { // at $DIR/issue_58867_inline_as_ref_as_mut.rs:3:7: 3:15 debug self => _4; // in scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL - let mut _5: &mut [T]; // in scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL } bb0: { @@ -16,10 +15,7 @@ fn a(_1: &mut [T]) -> &mut [T] { StorageLive(_3); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 StorageLive(_4); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 _4 = &mut (*_1); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 - StorageLive(_5); // scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL - _5 = &mut (*_4); // scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL - _3 = &mut (*_5); // scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL - StorageDead(_5); // scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL + _3 = _4; // scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL _2 = &mut (*_3); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 StorageDead(_4); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:14: +1:15 _0 = &mut (*_2); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 diff --git a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir index b6aff30149f..21570a88a6b 100644 --- a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir +++ b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir @@ -8,10 +8,8 @@ fn b(_1: &mut Box<T>) -> &mut T { let mut _4: &mut std::boxed::Box<T>; // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 scope 1 (inlined <Box<T> as AsMut<T>>::as_mut) { // at $DIR/issue_58867_inline_as_ref_as_mut.rs:8:7: 8:15 debug self => _4; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL - let mut _5: &mut T; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL - let mut _6: &mut T; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL - let mut _7: std::boxed::Box<T>; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL - let mut _8: *const T; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL + let mut _5: std::boxed::Box<T>; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL + let mut _6: *const T; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL } bb0: { @@ -19,15 +17,9 @@ fn b(_1: &mut Box<T>) -> &mut T { StorageLive(_3); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 StorageLive(_4); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 _4 = &mut (*_1); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 - StorageLive(_5); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL - StorageLive(_6); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL - _7 = deref_copy (*_4); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL - _8 = (((_7.0: std::ptr::Unique<T>).0: std::ptr::NonNull<T>).0: *const T); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL - _6 = &mut (*_8); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL - _5 = &mut (*_6); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL - _3 = &mut (*_5); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL - StorageDead(_6); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL - StorageDead(_5); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL + _5 = deref_copy (*_4); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL + _6 = (((_5.0: std::ptr::Unique<T>).0: std::ptr::NonNull<T>).0: *const T); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL + _3 = &mut (*_6); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL _2 = &mut (*_3); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 StorageDead(_4); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:14: +1:15 _0 = &mut (*_2); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 diff --git a/tests/ui/bounds-lifetime.stderr b/tests/ui/bounds-lifetime.stderr index a3427e21cde..f0bfe784ccc 100644 --- a/tests/ui/bounds-lifetime.stderr +++ b/tests/ui/bounds-lifetime.stderr @@ -22,7 +22,7 @@ error[E0658]: only lifetime parameters can be used in this context LL | type D = for<'a, T> fn(); | ^ | - = note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information + = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable error[E0658]: only lifetime parameters can be used in this context @@ -31,7 +31,7 @@ error[E0658]: only lifetime parameters can be used in this context LL | type E = dyn for<T> Fn(); | ^ | - = note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information + = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable error: aborting due to 5 previous errors diff --git a/tests/ui/closures/binder/const-bound.rs b/tests/ui/closures/binder/const-bound.rs new file mode 100644 index 00000000000..b1c79db1375 --- /dev/null +++ b/tests/ui/closures/binder/const-bound.rs @@ -0,0 +1,7 @@ +#![feature(closure_lifetime_binder, non_lifetime_binders)] +//~^ WARN is incomplete and may not be safe to use + +fn main() { + for<const N: i32> || -> () {}; + //~^ ERROR late-bound const parameter not allowed on closures +} diff --git a/tests/ui/closures/binder/const-bound.stderr b/tests/ui/closures/binder/const-bound.stderr new file mode 100644 index 00000000000..c016465c101 --- /dev/null +++ b/tests/ui/closures/binder/const-bound.stderr @@ -0,0 +1,17 @@ +warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/const-bound.rs:1:37 + | +LL | #![feature(closure_lifetime_binder, non_lifetime_binders)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information + = note: `#[warn(incomplete_features)]` on by default + +error: late-bound const parameter not allowed on closures + --> $DIR/const-bound.rs:5:9 + | +LL | for<const N: i32> || -> () {}; + | ^^^^^^^^^^^^ + +error: aborting due to previous error; 1 warning emitted + diff --git a/tests/ui/closures/binder/disallow-const.stderr b/tests/ui/closures/binder/disallow-const.stderr index 9f4deaa774d..59f299315f8 100644 --- a/tests/ui/closures/binder/disallow-const.stderr +++ b/tests/ui/closures/binder/disallow-const.stderr @@ -4,7 +4,7 @@ error[E0658]: only lifetime parameters can be used in this context LL | for<const N: i32> || -> () {}; | ^ | - = note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information + = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable error: aborting due to previous error diff --git a/tests/ui/closures/binder/disallow-ty.stderr b/tests/ui/closures/binder/disallow-ty.stderr index 22882ca2ba6..3370e21bd71 100644 --- a/tests/ui/closures/binder/disallow-ty.stderr +++ b/tests/ui/closures/binder/disallow-ty.stderr @@ -4,7 +4,7 @@ error[E0658]: only lifetime parameters can be used in this context LL | for<T> || -> () {}; | ^ | - = note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information + = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable error: aborting due to previous error diff --git a/tests/ui/closures/binder/type-bound-2.rs b/tests/ui/closures/binder/type-bound-2.rs new file mode 100644 index 00000000000..f4edcdaa9ca --- /dev/null +++ b/tests/ui/closures/binder/type-bound-2.rs @@ -0,0 +1,7 @@ +#![feature(closure_lifetime_binder, non_lifetime_binders)] +//~^ WARN is incomplete and may not be safe to use + +fn main() { + for<T> || -> () {}; + //~^ ERROR late-bound type parameter not allowed on closures +} diff --git a/tests/ui/closures/binder/type-bound-2.stderr b/tests/ui/closures/binder/type-bound-2.stderr new file mode 100644 index 00000000000..14b2dbf0395 --- /dev/null +++ b/tests/ui/closures/binder/type-bound-2.stderr @@ -0,0 +1,17 @@ +warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/type-bound-2.rs:1:37 + | +LL | #![feature(closure_lifetime_binder, non_lifetime_binders)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information + = note: `#[warn(incomplete_features)]` on by default + +error: late-bound type parameter not allowed on closures + --> $DIR/type-bound-2.rs:5:9 + | +LL | for<T> || -> () {}; + | ^ + +error: aborting due to previous error; 1 warning emitted + diff --git a/tests/ui/closures/binder/type-bound.rs b/tests/ui/closures/binder/type-bound.rs new file mode 100644 index 00000000000..59a3353f496 --- /dev/null +++ b/tests/ui/closures/binder/type-bound.rs @@ -0,0 +1,7 @@ +#![feature(closure_lifetime_binder, non_lifetime_binders)] +//~^ WARN is incomplete and may not be safe to use + +fn main() { + for<T> || -> T {}; + //~^ ERROR late-bound type parameter not allowed on closures +} diff --git a/tests/ui/closures/binder/type-bound.stderr b/tests/ui/closures/binder/type-bound.stderr new file mode 100644 index 00000000000..ef00a2dffce --- /dev/null +++ b/tests/ui/closures/binder/type-bound.stderr @@ -0,0 +1,17 @@ +warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/type-bound.rs:1:37 + | +LL | #![feature(closure_lifetime_binder, non_lifetime_binders)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information + = note: `#[warn(incomplete_features)]` on by default + +error: late-bound type parameter not allowed on closures + --> $DIR/type-bound.rs:5:9 + | +LL | for<T> || -> T {}; + | ^ + +error: aborting due to previous error; 1 warning emitted + diff --git a/tests/ui/conditional-compilation/cfg-generic-params.stderr b/tests/ui/conditional-compilation/cfg-generic-params.stderr index 69b0f741156..f733c09c22e 100644 --- a/tests/ui/conditional-compilation/cfg-generic-params.stderr +++ b/tests/ui/conditional-compilation/cfg-generic-params.stderr @@ -34,7 +34,7 @@ error[E0658]: only lifetime parameters can be used in this context LL | type FnBad = for<#[cfg(no)] 'a, #[cfg(yes)] T> fn(); | ^ | - = note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information + = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable error[E0658]: only lifetime parameters can be used in this context @@ -43,7 +43,7 @@ error[E0658]: only lifetime parameters can be used in this context LL | type PolyBad = dyn for<#[cfg(no)] 'a, #[cfg(yes)] T> Copy; | ^ | - = note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information + = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable error[E0658]: only lifetime parameters can be used in this context @@ -52,7 +52,7 @@ error[E0658]: only lifetime parameters can be used in this context LL | struct WhereBad where for<#[cfg(no)] 'a, #[cfg(yes)] T> u8: Copy; | ^ | - = note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information + = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable error: aborting due to 8 previous errors diff --git a/tests/ui/feature-gates/feature-gate-non_lifetime_binders.stderr b/tests/ui/feature-gates/feature-gate-non_lifetime_binders.stderr index 75645e32401..01c8ee30c5f 100644 --- a/tests/ui/feature-gates/feature-gate-non_lifetime_binders.stderr +++ b/tests/ui/feature-gates/feature-gate-non_lifetime_binders.stderr @@ -4,7 +4,7 @@ error[E0658]: only lifetime parameters can be used in this context LL | fn foo() where for<T> T:, {} | ^ | - = note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information + = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable error: aborting due to previous error diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-wrong-kind.stderr b/tests/ui/higher-rank-trait-bounds/hrtb-wrong-kind.stderr index d605c9e0df7..765ea9f7854 100644 --- a/tests/ui/higher-rank-trait-bounds/hrtb-wrong-kind.stderr +++ b/tests/ui/higher-rank-trait-bounds/hrtb-wrong-kind.stderr @@ -4,7 +4,7 @@ error[E0658]: only lifetime parameters can be used in this context LL | fn a() where for<T> T: Copy {} | ^ | - = note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information + = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable error[E0658]: only lifetime parameters can be used in this context @@ -13,7 +13,7 @@ error[E0658]: only lifetime parameters can be used in this context LL | fn b() where for<const C: usize> [(); C]: Copy {} | ^ | - = note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information + = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable error: aborting due to 2 previous errors diff --git a/tests/ui/lexer/issue-108019-bad-emoji-recovery.rs b/tests/ui/lexer/issue-108019-bad-emoji-recovery.rs new file mode 100644 index 00000000000..f0f86224560 --- /dev/null +++ b/tests/ui/lexer/issue-108019-bad-emoji-recovery.rs @@ -0,0 +1,45 @@ +#![allow(unused_labels)] + +// FIXME(#108019): outdated Unicode table +// fn foo() { +// '🥺 loop { +// break +// } +// } + +fn bar() { + '🐱 loop { + //~^ ERROR labeled expression must be followed by `:` + //~| ERROR lifetimes or labels cannot contain emojis + break + } +} + +fn qux() { + 'a🐱 loop { + //~^ ERROR labeled expression must be followed by `:` + //~| ERROR lifetimes or labels cannot contain emojis + break + } +} + +fn quux() { + '1🐱 loop { + //~^ ERROR labeled expression must be followed by `:` + //~| ERROR lifetimes or labels cannot start with a number + break + } +} + +fn x<'🐱>() -> &'🐱 () { + //~^ ERROR lifetimes or labels cannot contain emojis + //~| ERROR lifetimes or labels cannot contain emojis + &() +} + +fn y() { + 'a🐱: loop {} + //~^ ERROR lifetimes or labels cannot contain emojis +} + +fn main() {} diff --git a/tests/ui/lexer/issue-108019-bad-emoji-recovery.stderr b/tests/ui/lexer/issue-108019-bad-emoji-recovery.stderr new file mode 100644 index 00000000000..be77ffdea34 --- /dev/null +++ b/tests/ui/lexer/issue-108019-bad-emoji-recovery.stderr @@ -0,0 +1,86 @@ +error: labeled expression must be followed by `:` + --> $DIR/issue-108019-bad-emoji-recovery.rs:11:5 + | +LL | '🐱 loop { + | ^--- help: add `:` after the label + | | + | _____the label + | | +LL | | +LL | | +LL | | break +LL | | } + | |_____^ + | + = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them + +error: labeled expression must be followed by `:` + --> $DIR/issue-108019-bad-emoji-recovery.rs:19:5 + | +LL | 'a🐱 loop { + | ^---- help: add `:` after the label + | | + | _____the label + | | +LL | | +LL | | +LL | | break +LL | | } + | |_____^ + | + = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them + +error: labeled expression must be followed by `:` + --> $DIR/issue-108019-bad-emoji-recovery.rs:27:5 + | +LL | '1🐱 loop { + | ^---- help: add `:` after the label + | | + | _____the label + | | +LL | | +LL | | +LL | | break +LL | | } + | |_____^ + | + = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them + +error: lifetimes or labels cannot contain emojis + --> $DIR/issue-108019-bad-emoji-recovery.rs:11:5 + | +LL | '🐱 loop { + | ^^^ + +error: lifetimes or labels cannot contain emojis + --> $DIR/issue-108019-bad-emoji-recovery.rs:19:5 + | +LL | 'a🐱 loop { + | ^^^^ + +error: lifetimes or labels cannot start with a number + --> $DIR/issue-108019-bad-emoji-recovery.rs:27:5 + | +LL | '1🐱 loop { + | ^^^^ + +error: lifetimes or labels cannot contain emojis + --> $DIR/issue-108019-bad-emoji-recovery.rs:34:6 + | +LL | fn x<'🐱>() -> &'🐱 () { + | ^^^ + +error: lifetimes or labels cannot contain emojis + --> $DIR/issue-108019-bad-emoji-recovery.rs:34:16 + | +LL | fn x<'🐱>() -> &'🐱 () { + | ^^^ + +error: lifetimes or labels cannot contain emojis + --> $DIR/issue-108019-bad-emoji-recovery.rs:41:5 + | +LL | 'a🐱: loop {} + | ^^^^ + +error: aborting due to 9 previous errors + diff --git a/tests/ui/lint/issue-108155.rs b/tests/ui/lint/issue-108155.rs new file mode 100644 index 00000000000..4ae0cbd92ff --- /dev/null +++ b/tests/ui/lint/issue-108155.rs @@ -0,0 +1,15 @@ +// check-pass +// check that `deref_into_dyn_supertrait` doesn't cause ICE by eagerly converting +// a cancelled lint + +#![allow(deref_into_dyn_supertrait)] + +trait Trait {} +impl std::ops::Deref for dyn Trait + Send + Sync { + type Target = dyn Trait; + fn deref(&self) -> &Self::Target { + self + } +} + +fn main() {} diff --git a/tests/ui/parser/numeric-lifetime.rs b/tests/ui/parser/numeric-lifetime.rs index 2d82354c62c..a082a8a44df 100644 --- a/tests/ui/parser/numeric-lifetime.rs +++ b/tests/ui/parser/numeric-lifetime.rs @@ -1,6 +1,6 @@ struct S<'1> { s: &'1 usize } -//~^ ERROR lifetimes cannot start with a number -//~| ERROR lifetimes cannot start with a number +//~^ ERROR lifetimes or labels cannot start with a number +//~| ERROR lifetimes or labels cannot start with a number fn main() { // verify that the parse error doesn't stop type checking let x: usize = ""; diff --git a/tests/ui/parser/numeric-lifetime.stderr b/tests/ui/parser/numeric-lifetime.stderr index 7c1bcb72631..66e35dca923 100644 --- a/tests/ui/parser/numeric-lifetime.stderr +++ b/tests/ui/parser/numeric-lifetime.stderr @@ -6,13 +6,13 @@ LL | let x: usize = ""; | | | expected due to this -error: lifetimes cannot start with a number +error: lifetimes or labels cannot start with a number --> $DIR/numeric-lifetime.rs:1:10 | LL | struct S<'1> { s: &'1 usize } | ^^ -error: lifetimes cannot start with a number +error: lifetimes or labels cannot start with a number --> $DIR/numeric-lifetime.rs:1:20 | LL | struct S<'1> { s: &'1 usize } diff --git a/tests/ui/sanitize/cfg-kasan.rs b/tests/ui/sanitize/cfg-kasan.rs new file mode 100644 index 00000000000..d721011f3ee --- /dev/null +++ b/tests/ui/sanitize/cfg-kasan.rs @@ -0,0 +1,28 @@ +// Verifies that when compiling with -Zsanitizer=kernel-address, +// the `#[cfg(sanitize = "address")]` attribute is configured. + +// check-pass +// compile-flags: -Zsanitizer=kernel-address --cfg kernel_address +// revisions: aarch64 riscv64imac riscv64gc x86_64 +//[aarch64] compile-flags: --target aarch64-unknown-none +//[aarch64] needs-llvm-components: aarch64 +//[riscv64imac] compile-flags: --target riscv64imac-unknown-none-elf +//[riscv64imac] needs-llvm-components: riscv +//[riscv64imac] min-llvm-version: 16 +//[riscv64gc] compile-flags: --target riscv64gc-unknown-none-elf +//[riscv64gc] needs-llvm-components: riscv +//[riscv64gc] min-llvm-version: 16 +//[x86_64] compile-flags: --target x86_64-unknown-none +//[x86_64] needs-llvm-components: x86 + +#![crate_type = "rlib"] +#![feature(cfg_sanitize, no_core, lang_items)] +#![no_core] + +#[lang = "sized"] +trait Sized {} + +const _: fn() -> () = main; + +#[cfg(all(sanitize = "address", kernel_address))] +fn main() {} diff --git a/tests/ui/traits/non_lifetime_binders/basic.stderr b/tests/ui/traits/non_lifetime_binders/basic.stderr index fddc5d9fc25..0fd16c5d0ee 100644 --- a/tests/ui/traits/non_lifetime_binders/basic.stderr +++ b/tests/ui/traits/non_lifetime_binders/basic.stderr @@ -4,7 +4,7 @@ warning: the feature `non_lifetime_binders` is incomplete and may not be safe to LL | #![feature(non_lifetime_binders)] | ^^^^^^^^^^^^^^^^^^^^ | - = note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information + = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information = note: `#[warn(incomplete_features)]` on by default warning: 1 warning emitted diff --git a/tests/ui/traits/non_lifetime_binders/fail.stderr b/tests/ui/traits/non_lifetime_binders/fail.stderr index ba5953193a4..c3f4fd6a88e 100644 --- a/tests/ui/traits/non_lifetime_binders/fail.stderr +++ b/tests/ui/traits/non_lifetime_binders/fail.stderr @@ -4,7 +4,7 @@ warning: the feature `non_lifetime_binders` is incomplete and may not be safe to LL | #![feature(non_lifetime_binders)] | ^^^^^^^^^^^^^^^^^^^^ | - = note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information + = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information = note: `#[warn(incomplete_features)]` on by default error[E0277]: the trait bound `T: Trait` is not satisfied diff --git a/tests/ui/traits/non_lifetime_binders/on-dyn.stderr b/tests/ui/traits/non_lifetime_binders/on-dyn.stderr index 44071107de4..95656f99976 100644 --- a/tests/ui/traits/non_lifetime_binders/on-dyn.stderr +++ b/tests/ui/traits/non_lifetime_binders/on-dyn.stderr @@ -4,7 +4,7 @@ warning: the feature `non_lifetime_binders` is incomplete and may not be safe to LL | #![feature(non_lifetime_binders)] | ^^^^^^^^^^^^^^^^^^^^ | - = note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information + = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information = note: `#[warn(incomplete_features)]` on by default error: late-bound type parameter not allowed on trait object types diff --git a/tests/ui/traits/non_lifetime_binders/on-ptr.stderr b/tests/ui/traits/non_lifetime_binders/on-ptr.stderr index bb7dccaf07d..3b17f7697b2 100644 --- a/tests/ui/traits/non_lifetime_binders/on-ptr.stderr +++ b/tests/ui/traits/non_lifetime_binders/on-ptr.stderr @@ -4,7 +4,7 @@ warning: the feature `non_lifetime_binders` is incomplete and may not be safe to LL | #![feature(non_lifetime_binders)] | ^^^^^^^^^^^^^^^^^^^^ | - = note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information + = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information = note: `#[warn(incomplete_features)]` on by default error: late-bound type parameter not allowed on function pointer types |
