diff --git a/Cargo.lock b/Cargo.lock index 41c82c989becc..5ff455c57f056 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4640,6 +4640,7 @@ dependencies = [ "thin-vec", "tracing", "unicode-normalization", + "unicode-properties", "unicode-width 0.2.2", ] diff --git a/compiler/rustc_attr_parsing/src/parser.rs b/compiler/rustc_attr_parsing/src/parser.rs index a5461d9044b96..d5dda24009f34 100644 --- a/compiler/rustc_attr_parsing/src/parser.rs +++ b/compiler/rustc_attr_parsing/src/parser.rs @@ -727,10 +727,11 @@ impl<'a, 'sess> MetaItemListParserContext<'a, 'sess> { should_emit: ShouldEmit, allow_expr_metavar: AllowExprMetavar, ) -> PResult<'sess, MetaItemListParser> { - let mut parser = Parser::new(psess, tokens, None); - if let ShouldEmit::ErrorsAndLints { recovery } = should_emit { - parser = parser.recovery(recovery); - } + let recovery = match should_emit { + ShouldEmit::ErrorsAndLints { recovery } => recovery, + _ => Recovery::Forbidden, + }; + let mut parser = Parser::new(psess, tokens, None).recovery(recovery); let mut this = MetaItemListParserContext { parser: &mut parser, should_emit, allow_expr_metavar }; diff --git a/compiler/rustc_codegen_cranelift/patches/0027-sysroot_tests-128bit-atomic-operations.patch b/compiler/rustc_codegen_cranelift/patches/0027-sysroot_tests-128bit-atomic-operations.patch index 7194d8144ca69..6ec25732ab767 100644 --- a/compiler/rustc_codegen_cranelift/patches/0027-sysroot_tests-128bit-atomic-operations.patch +++ b/compiler/rustc_codegen_cranelift/patches/0027-sysroot_tests-128bit-atomic-operations.patch @@ -18,8 +18,8 @@ index 1e336bf..35e6f54 100644 // tidy-alphabetical-start #![cfg_attr(not(panic = "abort"), feature(reentrant_lock))] -#![cfg_attr(target_has_atomic = "128", feature(integer_atomics))] + #![feature(abort_immediate)] #![feature(array_ptr_get)] - #![feature(array_try_from_fn)] diff --git a/coretests/tests/atomic.rs b/coretests/tests/atomic.rs index b735957..ea728b6 100644 --- a/coretests/tests/atomic.rs diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs index 43179c1628f30..d0ea2e0ffb2c9 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs @@ -402,7 +402,7 @@ fn codegen_regular_intrinsic_call<'tcx>( fx.bcx.ins().trap(TrapCode::user(2).unwrap()); return Ok(()); } - sym::breakpoint => { + sym::breakpoint | sym::resumable_breakpoint => { intrinsic_args!(fx, args => (); intrinsic); fx.bcx.ins().debugtrap(); diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs index d7b31b372e09c..7ae29ca102e9a 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs @@ -222,7 +222,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc ); return IntrinsicResult::WroteIntoPlace; } - sym::breakpoint => { + sym::breakpoint | sym::resumable_breakpoint => { unimplemented!(); } sym::va_arg => { diff --git a/compiler/rustc_codegen_llvm/src/allocator.rs b/compiler/rustc_codegen_llvm/src/allocator.rs index ef77abd53527d..3550e62ff6e25 100644 --- a/compiler/rustc_codegen_llvm/src/allocator.rs +++ b/compiler/rustc_codegen_llvm/src/allocator.rs @@ -106,13 +106,13 @@ pub(crate) unsafe fn codegen( } } -fn create_wrapper_function( +fn create_wrapper_function<'ll>( tcx: TyCtxt<'_>, - cx: &SimpleCx<'_>, + cx: &SimpleCx<'ll>, from_name: &str, to_name: Option<&str>, - args: &[&Type], - output: Option<&Type>, + args: &[&'ll Type], + output: Option<&'ll Type>, no_return: bool, attrs: &CodegenFnAttrs, ) { diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index 56931aff992b6..bdbd43de07a53 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -212,7 +212,10 @@ pub(crate) fn sanitize_attrs<'ll, 'tcx>( /// Tell LLVM to emit or not emit the information necessary to unwind the stack for the function. #[inline] -pub(crate) fn uwtable_attr(llcx: &llvm::Context, use_sync_unwind: Option) -> &Attribute { +pub(crate) fn uwtable_attr<'ll>( + llcx: llvm::Context<'ll>, + use_sync_unwind: Option, +) -> &'ll Attribute { // NOTE: We should determine if we even need async unwind tables, as they // take have more overhead and if we can use sync unwind tables we // probably should. @@ -488,7 +491,7 @@ pub(crate) fn default_optimisation_attrs<'ll>( attrs } -fn create_alloc_family_attr(llcx: &llvm::Context) -> &llvm::Attribute { +fn create_alloc_family_attr<'ll>(llcx: llvm::Context<'ll>) -> &'ll llvm::Attribute { llvm::CreateAttrStringValue(llcx, "alloc-family", "__rust_alloc") } diff --git a/compiler/rustc_codegen_llvm/src/back/llvm_backend.rs b/compiler/rustc_codegen_llvm/src/back/llvm_backend.rs index c2fd8a79407f0..16465436e239e 100644 --- a/compiler/rustc_codegen_llvm/src/back/llvm_backend.rs +++ b/compiler/rustc_codegen_llvm/src/back/llvm_backend.rs @@ -442,7 +442,7 @@ impl CodegenBackend for LlvmCodegenBackend { } pub struct ModuleLlvm { - llcx_raw: ptr::NonNull, + llcx_raw: ptr::NonNull, llmod_raw: *const llvm::Module, // This field is `ManuallyDrop` because it is important that the `TargetMachine` @@ -461,12 +461,22 @@ pub struct ModuleLlvm { // `ModuleLlvm` owns the context and only allows borrowing LLVM objects tied to the context. unsafe impl Send for ModuleLlvm {} +/// Converts an unbranded pointer-to-context to a lifetime-branded [`llvm::Context`]. +/// +/// # Safety +/// - The pointer must be a valid LLVM context. +/// - If the context is passed to safe code, its caller-requested lifetime must be distinct +/// from that of any other context, and must not outlive the underlying context. +unsafe fn wrap_llcx<'ll>(llcx_raw: ptr::NonNull) -> llvm::Context<'ll> { + llvm::Context { llcx_raw, _invariant_ll: PhantomData } +} + /// Shared helper to call [`llvm::LLVMContextCreate`] and then configure /// [`llvm::LLVMContextSetDiscardValueNames`]. -fn create_context_and_set_fewer_names(fewer_names: bool) -> ptr::NonNull { +fn create_context_and_set_fewer_names(fewer_names: bool) -> ptr::NonNull { unsafe { let llcx_raw = llvm::LLVMContextCreate(); - llvm::LLVMContextSetDiscardValueNames(llcx_raw.as_ref(), fewer_names.to_llvm_bool()); + llvm::LLVMContextSetDiscardValueNames(wrap_llcx(llcx_raw), fewer_names.to_llvm_bool()); llcx_raw } } @@ -475,7 +485,7 @@ impl ModuleLlvm { pub(crate) fn new(tcx: TyCtxt<'_>, mod_name: &str) -> Self { unsafe { let llcx_raw = create_context_and_set_fewer_names(tcx.sess.fewer_names()); - let llmod_raw = context::create_module(tcx, llcx_raw.as_ref(), mod_name); + let llmod_raw = context::create_module(tcx, wrap_llcx(llcx_raw), mod_name); ModuleLlvm { llmod_raw, llcx_raw, @@ -488,7 +498,7 @@ impl ModuleLlvm { pub(crate) fn new_metadata(tcx: TyCtxt<'_>, mod_name: &str) -> Self { unsafe { let llcx_raw = create_context_and_set_fewer_names(tcx.sess.fewer_names()); - let llmod_raw = context::create_module(tcx, llcx_raw.as_ref(), mod_name); + let llmod_raw = context::create_module(tcx, wrap_llcx(llcx_raw), mod_name); ModuleLlvm { llmod_raw, llcx_raw, @@ -507,7 +517,7 @@ impl ModuleLlvm { ) -> Self { unsafe { let llcx_raw = create_context_and_set_fewer_names(cgcx.fewer_names); - let llmod_raw = back::lto::parse_module(llcx_raw.as_ref(), name, buffer, dcx); + let llmod_raw = back::lto::parse_module(wrap_llcx(llcx_raw), name, buffer, dcx); let tm = tm_factory(dcx, TargetMachineFactoryConfig::new(cgcx, name.to_str().unwrap())); ModuleLlvm { @@ -529,7 +539,7 @@ impl ModuleLlvm { inner_fn: impl for<'ll> FnOnce(ModuleRefs<'ll>) -> R, ) -> R { inner_fn(ModuleRefs { - llcx: unsafe { self.llcx_raw.as_ref() }, + llcx: unsafe { wrap_llcx(self.llcx_raw) }, llmod: unsafe { &*self.llmod_raw }, tm: self.tm.raw(), _ph: PhantomData, @@ -549,7 +559,7 @@ impl Drop for ModuleLlvm { /// Bundle of references provided by [`ModuleLlvm::with_module_refs`]. #[derive(Clone, Copy)] pub(crate) struct ModuleRefs<'ll> { - pub(crate) llcx: &'ll llvm::Context, + pub(crate) llcx: llvm::Context<'ll>, pub(crate) llmod: &'ll llvm::Module, pub(crate) tm: &'ll llvm::TargetMachine, /// Make sure `'ll` is invariant, even if no fields happen to require that. diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs index c99eb45438353..4ba4ca6e03b89 100644 --- a/compiler/rustc_codegen_llvm/src/back/lto.rs +++ b/compiler/rustc_codegen_llvm/src/back/lto.rs @@ -854,14 +854,14 @@ fn module_name_to_str(c_str: &CStr) -> &str { }) } -pub(crate) fn parse_module<'a>( - cx: &'a llvm::Context, +pub(crate) fn parse_module<'ll>( + llcx: llvm::Context<'ll>, name: &CStr, data: &[u8], dcx: DiagCtxtHandle<'_>, -) -> &'a llvm::Module { +) -> &'ll llvm::Module { unsafe { - llvm::LLVMRustParseBitcodeForLTO(cx, data.as_ptr(), data.len(), name.as_ptr()) + llvm::LLVMRustParseBitcodeForLTO(llcx, data.as_ptr(), data.len(), name.as_ptr()) .unwrap_or_else(|| write::llvm_err(dcx, LlvmError::ParseBitcode)) } } diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index 872c022373d45..b5219edf4efa2 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -326,8 +326,8 @@ struct DiagnosticHandlerCallbackData<'a> { shared_emitter: &'a SharedEmitter, } -pub(crate) struct DiagnosticHandlers<'a> { - llcx: &'a llvm::Context, +pub(crate) struct DiagnosticHandlers<'a, 'll> { + llcx: llvm::Context<'ll>, old_handler: Option>, /// Ownership of the box-allocated data that was installed (as a pointer) @@ -337,11 +337,11 @@ pub(crate) struct DiagnosticHandlers<'a> { diagnostic_handler_callback_data: *mut DiagnosticHandlerCallbackData<'a>, } -impl<'a> DiagnosticHandlers<'a> { +impl<'a, 'll> DiagnosticHandlers<'a, 'll> { pub(crate) fn new( cgcx: &'a CodegenContext, shared_emitter: &'a SharedEmitter, - llcx: &'a llvm::Context, + llcx: llvm::Context<'ll>, module: &ModuleCodegen, stage: CodegenDiagnosticsStage, ) -> Self { @@ -396,7 +396,7 @@ impl<'a> DiagnosticHandlers<'a> { } } -impl<'a> Drop for DiagnosticHandlers<'a> { +impl<'a, 'll> Drop for DiagnosticHandlers<'a, 'll> { fn drop(&mut self) { unsafe { llvm::LLVMRustContextSetDiagnosticHandler(self.llcx, self.old_handler); @@ -654,7 +654,7 @@ pub(crate) unsafe fn llvm_optimize<'ll>( None }; - fn handle_offload<'ll>(cx: &'ll SimpleCx<'_>, old_fn: &llvm::Value) { + fn handle_offload<'ll>(cx: &SimpleCx<'ll>, old_fn: &'ll llvm::Value) { let old_fn_ty = cx.get_type_of_global(old_fn); let old_param_types = cx.func_params_types(old_fn_ty); let old_param_count = old_param_types.len(); @@ -1205,10 +1205,10 @@ pub(crate) fn bitcode_section_name(cgcx: &CodegenContext) -> &'static CStr { } /// Embed the bitcode of an LLVM module for LTO in the LLVM module itself. -fn embed_bitcode( +fn embed_bitcode<'ll>( cgcx: &CodegenContext, - llcx: &llvm::Context, - llmod: &llvm::Module, + llcx: llvm::Context<'ll>, + llmod: &'ll llvm::Module, bitcode: &[u8], ) { // We're adding custom sections to the output object file, but we definitely @@ -1291,7 +1291,11 @@ fn embed_bitcode( // when using MSVC linker. We do this only for data, as linker can fix up // code references on its own. // See #26591, #27438 -fn create_msvc_imps(cgcx: &CodegenContext, llcx: &llvm::Context, llmod: &llvm::Module) { +fn create_msvc_imps<'ll>( + cgcx: &CodegenContext, + llcx: llvm::Context<'ll>, + llmod: &'ll llvm::Module, +) { if !cgcx.msvc_imps_needed { return; } diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 22b6e65e7973c..930463d251d7d 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -1,6 +1,6 @@ use std::borrow::{Borrow, Cow}; -use std::iter; use std::ops::Deref; +use std::{iter, ptr}; use rustc_ast::expand::typetree::FncTree; pub(crate) mod autodiff; @@ -42,7 +42,8 @@ use crate::type_of::LayoutLlvmExt; #[must_use] pub(crate) struct GenericBuilder<'a, 'll, CX: Borrow>> { - pub llbuilder: &'ll mut llvm::Builder<'ll>, + /// Owning pointer that corresponds to an `LLVMBuilderRef`. Disposed on drop. + llbuilder_raw: ptr::NonNull>, pub cx: &'a GenericCx<'ll, CX>, pub span: rustc_span::Span, } @@ -52,9 +53,7 @@ pub(crate) type Builder<'a, 'll, 'tcx> = GenericBuilder<'a, 'll, FullCx<'ll, 'tc impl<'a, 'll, CX: Borrow>> Drop for GenericBuilder<'a, 'll, CX> { fn drop(&mut self) { - unsafe { - llvm::LLVMDisposeBuilder(&mut *(self.llbuilder as *mut _)); - } + unsafe { llvm::LLVMDisposeBuilder(self.llbuilder_raw) }; } } @@ -77,7 +76,7 @@ impl<'a, 'll> SBuilder<'a, 'll> { let call = unsafe { llvm::LLVMBuildCallWithOperandBundles( - self.llbuilder, + self.llbuilder(), llty, llfn, args.as_ptr() as *const &llvm::Value, @@ -94,8 +93,8 @@ impl<'a, 'll> SBuilder<'a, 'll> { impl<'a, 'll, CX: Borrow>> GenericBuilder<'a, 'll, CX> { fn with_cx(scx: &'a GenericCx<'ll, CX>) -> Self { // Create a fresh builder from the simple context. - let llbuilder = unsafe { llvm::LLVMCreateBuilderForModule(scx.deref().borrow().llmod) }; - GenericBuilder { llbuilder, cx: scx, span: rustc_span::DUMMY_SP } + let llbuilder_raw = unsafe { llvm::LLVMCreateBuilderForModule(scx.deref().borrow().llmod) }; + GenericBuilder { llbuilder_raw, cx: scx, span: rustc_span::DUMMY_SP } } pub(crate) fn append_block( @@ -109,28 +108,36 @@ impl<'a, 'll, CX: Borrow>> GenericBuilder<'a, 'll, CX> { } } + /// Returns a reference to this builder's underlying [`llvm::Builder`], + /// tied to the lifetime of self. + pub(crate) fn llbuilder<'s>(&'s self) -> &'s llvm::Builder<'ll> { + // SAFETY: We own this builder, and the reference lifetime is tied to `&self` + // (not to 'll), so it won't be disposed by our Drop while the ref is live. + unsafe { self.llbuilder_raw.as_ref() } + } + pub(crate) fn trunc(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { - unsafe { llvm::LLVMBuildTrunc(self.llbuilder, val, dest_ty, UNNAMED) } + unsafe { llvm::LLVMBuildTrunc(self.llbuilder(), val, dest_ty, UNNAMED) } } pub(crate) fn bitcast(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { - unsafe { llvm::LLVMBuildBitCast(self.llbuilder, val, dest_ty, UNNAMED) } + unsafe { llvm::LLVMBuildBitCast(self.llbuilder(), val, dest_ty, UNNAMED) } } pub(crate) fn ret_void(&mut self) { - llvm::LLVMBuildRetVoid(self.llbuilder); + llvm::LLVMBuildRetVoid(self.llbuilder()); } pub(crate) fn ret(&mut self, v: &'ll Value) { unsafe { - llvm::LLVMBuildRet(self.llbuilder, v); + llvm::LLVMBuildRet(self.llbuilder(), v); } } pub(crate) fn build(cx: &'a GenericCx<'ll, CX>, llbb: &'ll BasicBlock) -> Self { let bx = Self::with_cx(cx); unsafe { - llvm::LLVMPositionBuilderAtEnd(bx.llbuilder, llbb); + llvm::LLVMPositionBuilderAtEnd(bx.llbuilder(), llbb); } bx } @@ -141,10 +148,10 @@ impl<'a, 'll, CX: Borrow>> GenericBuilder<'a, 'll, CX> { // handle this. pub(crate) fn direct_alloca(&mut self, ty: &'ll Type, align: Align, name: &str) -> &'ll Value { let val = unsafe { - let alloca = llvm::LLVMBuildAlloca(self.llbuilder, ty, UNNAMED); + let alloca = llvm::LLVMBuildAlloca(self.llbuilder(), ty, UNNAMED); llvm::LLVMSetAlignment(alloca, align.bytes() as c_uint); // Cast to default addrspace if necessary - llvm::LLVMBuildPointerCast(self.llbuilder, alloca, self.cx.type_ptr(), UNNAMED) + llvm::LLVMBuildPointerCast(self.llbuilder(), alloca, self.cx.type_ptr(), UNNAMED) }; if name != "" { let name = std::ffi::CString::new(name).unwrap(); @@ -161,7 +168,7 @@ impl<'a, 'll, CX: Borrow>> GenericBuilder<'a, 'll, CX> { ) -> &'ll Value { unsafe { llvm::LLVMBuildGEPWithNoWrapFlags( - self.llbuilder, + self.llbuilder(), ty, ptr, indices.as_ptr(), @@ -176,7 +183,7 @@ impl<'a, 'll, CX: Borrow>> GenericBuilder<'a, 'll, CX> { debug!("Store {:?} -> {:?}", val, ptr); assert_eq!(self.cx.type_kind(self.cx.val_ty(ptr)), TypeKind::Pointer); unsafe { - let store = llvm::LLVMBuildStore(self.llbuilder, val, ptr); + let store = llvm::LLVMBuildStore(self.llbuilder(), val, ptr); llvm::LLVMSetAlignment(store, align.bytes() as c_uint); store } @@ -184,7 +191,7 @@ impl<'a, 'll, CX: Borrow>> GenericBuilder<'a, 'll, CX> { pub(crate) fn load(&mut self, ty: &'ll Type, ptr: &'ll Value, align: Align) -> &'ll Value { unsafe { - let load = llvm::LLVMBuildLoad2(self.llbuilder, ty, ptr, UNNAMED); + let load = llvm::LLVMBuildLoad2(self.llbuilder(), ty, ptr, UNNAMED); llvm::LLVMSetAlignment(load, align.bytes() as c_uint); load } @@ -268,7 +275,7 @@ macro_rules! math_builder_methods { ($($name:ident($($arg:ident),*) => $llvm_capi:ident),+ $(,)?) => { $(fn $name(&mut self, $($arg: &'ll Value),*) -> &'ll Value { unsafe { - llvm::$llvm_capi(self.llbuilder, $($arg,)* UNNAMED) + llvm::$llvm_capi(self.llbuilder(), $($arg,)* UNNAMED) } })+ } @@ -278,7 +285,7 @@ macro_rules! set_math_builder_methods { ($($name:ident($($arg:ident),*) => ($llvm_capi:ident, $llvm_set_math:ident)),+ $(,)?) => { $(fn $name(&mut self, $($arg: &'ll Value),*) -> &'ll Value { unsafe { - let instr = llvm::$llvm_capi(self.llbuilder, $($arg,)* UNNAMED); + let instr = llvm::$llvm_capi(self.llbuilder(), $($arg,)* UNNAMED); llvm::$llvm_set_math(instr); instr } @@ -292,7 +299,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { fn build(cx: &'a CodegenCx<'ll, 'tcx>, llbb: &'ll BasicBlock) -> Self { let bx = Builder::with_cx(cx); unsafe { - llvm::LLVMPositionBuilderAtEnd(bx.llbuilder, llbb); + llvm::LLVMPositionBuilderAtEnd(bx.llbuilder(), llbb); } bx } @@ -302,7 +309,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } fn llbb(&self) -> &'ll BasicBlock { - unsafe { llvm::LLVMGetInsertBlock(self.llbuilder) } + unsafe { llvm::LLVMGetInsertBlock(self.llbuilder()) } } fn set_span(&mut self, span: rustc_span::Span) { @@ -325,24 +332,24 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } fn ret_void(&mut self) { - llvm::LLVMBuildRetVoid(self.llbuilder); + llvm::LLVMBuildRetVoid(self.llbuilder()); } fn ret(&mut self, v: &'ll Value) { unsafe { - llvm::LLVMBuildRet(self.llbuilder, v); + llvm::LLVMBuildRet(self.llbuilder(), v); } } fn br(&mut self, dest: &'ll BasicBlock) { unsafe { - llvm::LLVMBuildBr(self.llbuilder, dest); + llvm::LLVMBuildBr(self.llbuilder(), dest); } } fn br_with_attrs(&mut self, dest: &'ll BasicBlock, loop_hint_attrs: &[UnrollAttr]) { unsafe { - let val = llvm::LLVMBuildBr(self.llbuilder, dest); + let val = llvm::LLVMBuildBr(self.llbuilder(), dest); let mut nodes = Vec::new(); @@ -389,7 +396,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { else_llbb: &'ll BasicBlock, ) { unsafe { - llvm::LLVMBuildCondBr(self.llbuilder, cond, then_llbb, else_llbb); + llvm::LLVMBuildCondBr(self.llbuilder(), cond, then_llbb, else_llbb); } } @@ -400,7 +407,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { cases: impl ExactSizeIterator, ) { let switch = - unsafe { llvm::LLVMBuildSwitch(self.llbuilder, v, else_llbb, cases.len() as c_uint) }; + unsafe { llvm::LLVMBuildSwitch(self.llbuilder(), v, else_llbb, cases.len() as c_uint) }; for (on_val, dest) in cases { let on_val = self.const_uint_big(self.val_ty(v), on_val); unsafe { llvm::LLVMAddCase(switch, on_val, dest) } @@ -435,7 +442,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { md.push(weight(else_is_cold)); let switch = - unsafe { llvm::LLVMBuildSwitch(self.llbuilder, v, else_llbb, cases.len() as c_uint) }; + unsafe { llvm::LLVMBuildSwitch(self.llbuilder(), v, else_llbb, cases.len() as c_uint) }; for (on_val, dest, is_cold) in cases { let on_val = self.const_uint_big(self.val_ty(v), on_val); unsafe { llvm::LLVMAddCase(switch, on_val, dest) } @@ -492,7 +499,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { let invoke = unsafe { llvm::LLVMBuildInvokeWithOperandBundles( - self.llbuilder, + self.llbuilder(), llty, llfn, args.as_ptr(), @@ -512,7 +519,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { fn unreachable(&mut self) { unsafe { - llvm::LLVMBuildUnreachable(self.llbuilder); + llvm::LLVMBuildUnreachable(self.llbuilder()); } } @@ -550,7 +557,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { fn unchecked_suadd(&mut self, a: &'ll Value, b: &'ll Value) -> &'ll Value { unsafe { - let add = llvm::LLVMBuildAdd(self.llbuilder, a, b, UNNAMED); + let add = llvm::LLVMBuildAdd(self.llbuilder(), a, b, UNNAMED); if llvm::LLVMIsAInstruction(add).is_some() { llvm::LLVMSetNUW(add, TRUE); llvm::LLVMSetNSW(add, TRUE); @@ -560,7 +567,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } fn unchecked_susub(&mut self, a: &'ll Value, b: &'ll Value) -> &'ll Value { unsafe { - let sub = llvm::LLVMBuildSub(self.llbuilder, a, b, UNNAMED); + let sub = llvm::LLVMBuildSub(self.llbuilder(), a, b, UNNAMED); if llvm::LLVMIsAInstruction(sub).is_some() { llvm::LLVMSetNUW(sub, TRUE); llvm::LLVMSetNSW(sub, TRUE); @@ -570,7 +577,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } fn unchecked_sumul(&mut self, a: &'ll Value, b: &'ll Value) -> &'ll Value { unsafe { - let mul = llvm::LLVMBuildMul(self.llbuilder, a, b, UNNAMED); + let mul = llvm::LLVMBuildMul(self.llbuilder(), a, b, UNNAMED); if llvm::LLVMIsAInstruction(mul).is_some() { llvm::LLVMSetNUW(mul, TRUE); llvm::LLVMSetNSW(mul, TRUE); @@ -581,7 +588,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { fn or_disjoint(&mut self, a: &'ll Value, b: &'ll Value) -> &'ll Value { unsafe { - let or = llvm::LLVMBuildOr(self.llbuilder, a, b, UNNAMED); + let or = llvm::LLVMBuildOr(self.llbuilder(), a, b, UNNAMED); // If a and b are both values, then `or` is a value, rather than // an instruction, so we need to check before setting the flag. @@ -669,10 +676,10 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { bx.position_at_start(unsafe { llvm::LLVMGetFirstBasicBlock(self.llfn()) }); let ty = self.cx().type_array(self.cx().type_i8(), size.bytes()); unsafe { - let alloca = llvm::LLVMBuildAlloca(bx.llbuilder, ty, UNNAMED); + let alloca = llvm::LLVMBuildAlloca(bx.llbuilder(), ty, UNNAMED); llvm::LLVMSetAlignment(alloca, align.bytes() as c_uint); // Cast to default addrspace if necessary - llvm::LLVMBuildPointerCast(bx.llbuilder, alloca, self.cx().type_ptr(), UNNAMED) + llvm::LLVMBuildPointerCast(bx.llbuilder(), alloca, self.cx().type_ptr(), UNNAMED) } } @@ -682,7 +689,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { let scalable_vector_ty = layout.llvm_type(self.cx); unsafe { - let alloca = llvm::LLVMBuildAlloca(&bx.llbuilder, scalable_vector_ty, UNNAMED); + let alloca = llvm::LLVMBuildAlloca(bx.llbuilder(), scalable_vector_ty, UNNAMED); llvm::LLVMSetAlignment(alloca, layout.align.abi.bytes() as c_uint); alloca } @@ -690,7 +697,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { fn load(&mut self, ty: &'ll Type, ptr: &'ll Value, align: Align) -> &'ll Value { unsafe { - let load = llvm::LLVMBuildLoad2(self.llbuilder, ty, ptr, UNNAMED); + let load = llvm::LLVMBuildLoad2(self.llbuilder(), ty, ptr, UNNAMED); let align = align.min(self.cx().tcx.sess.target.max_reliable_alignment()); llvm::LLVMSetAlignment(load, align.bytes() as c_uint); load @@ -714,7 +721,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { size: Size, ) -> &'ll Value { unsafe { - let load = llvm::LLVMBuildLoad2(self.llbuilder, ty, ptr, UNNAMED); + let load = llvm::LLVMBuildLoad2(self.llbuilder(), ty, ptr, UNNAMED); // Set atomic ordering llvm::LLVMSetOrdering(load, AtomicOrdering::from_generic(order)); if volatile { @@ -883,7 +890,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { debug!("Store {:?} -> {:?} ({:?})", val, ptr, flags); assert_eq!(self.cx.type_kind(self.cx.val_ty(ptr)), TypeKind::Pointer); unsafe { - let store = llvm::LLVMBuildStore(self.llbuilder, val, ptr); + let store = llvm::LLVMBuildStore(self.llbuilder(), val, ptr); let align = align.min(self.cx().tcx.sess.target.max_reliable_alignment()); let align = align.bytes() as c_uint; llvm::LLVMSetAlignment(store, align); @@ -945,7 +952,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { debug!("Store {:?} -> {:?}", val, ptr); assert_eq!(self.cx.type_kind(self.cx.val_ty(ptr)), TypeKind::Pointer); unsafe { - let store = llvm::LLVMBuildStore(self.llbuilder, val, ptr); + let store = llvm::LLVMBuildStore(self.llbuilder(), val, ptr); // Set atomic ordering llvm::LLVMSetOrdering(store, AtomicOrdering::from_generic(order)); if volatile { @@ -959,7 +966,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { fn gep(&mut self, ty: &'ll Type, ptr: &'ll Value, indices: &[&'ll Value]) -> &'ll Value { unsafe { llvm::LLVMBuildGEPWithNoWrapFlags( - self.llbuilder, + self.llbuilder(), ty, ptr, indices.as_ptr(), @@ -978,7 +985,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { ) -> &'ll Value { unsafe { llvm::LLVMBuildGEPWithNoWrapFlags( - self.llbuilder, + self.llbuilder(), ty, ptr, indices.as_ptr(), @@ -997,7 +1004,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { ) -> &'ll Value { unsafe { llvm::LLVMBuildGEPWithNoWrapFlags( - self.llbuilder, + self.llbuilder(), ty, ptr, indices.as_ptr(), @@ -1010,7 +1017,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { /* Casts */ fn trunc(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { - unsafe { llvm::LLVMBuildTrunc(self.llbuilder, val, dest_ty, UNNAMED) } + unsafe { llvm::LLVMBuildTrunc(self.llbuilder(), val, dest_ty, UNNAMED) } } fn unchecked_utrunc(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { @@ -1038,7 +1045,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } fn sext(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { - unsafe { llvm::LLVMBuildSExt(self.llbuilder, val, dest_ty, UNNAMED) } + unsafe { llvm::LLVMBuildSExt(self.llbuilder(), val, dest_ty, UNNAMED) } } fn fptoui_sat(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { @@ -1078,7 +1085,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } } } - unsafe { llvm::LLVMBuildFPToUI(self.llbuilder, val, dest_ty, UNNAMED) } + unsafe { llvm::LLVMBuildFPToUI(self.llbuilder(), val, dest_ty, UNNAMED) } } fn fptosi(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { @@ -1097,56 +1104,62 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } } } - unsafe { llvm::LLVMBuildFPToSI(self.llbuilder, val, dest_ty, UNNAMED) } + unsafe { llvm::LLVMBuildFPToSI(self.llbuilder(), val, dest_ty, UNNAMED) } } fn uitofp(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { - unsafe { llvm::LLVMBuildUIToFP(self.llbuilder, val, dest_ty, UNNAMED) } + unsafe { llvm::LLVMBuildUIToFP(self.llbuilder(), val, dest_ty, UNNAMED) } } fn sitofp(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { - unsafe { llvm::LLVMBuildSIToFP(self.llbuilder, val, dest_ty, UNNAMED) } + unsafe { llvm::LLVMBuildSIToFP(self.llbuilder(), val, dest_ty, UNNAMED) } } fn fptrunc(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { - unsafe { llvm::LLVMBuildFPTrunc(self.llbuilder, val, dest_ty, UNNAMED) } + unsafe { llvm::LLVMBuildFPTrunc(self.llbuilder(), val, dest_ty, UNNAMED) } } fn fpext(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { - unsafe { llvm::LLVMBuildFPExt(self.llbuilder, val, dest_ty, UNNAMED) } + unsafe { llvm::LLVMBuildFPExt(self.llbuilder(), val, dest_ty, UNNAMED) } } fn ptrtoint(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { - unsafe { llvm::LLVMBuildPtrToInt(self.llbuilder, val, dest_ty, UNNAMED) } + unsafe { llvm::LLVMBuildPtrToInt(self.llbuilder(), val, dest_ty, UNNAMED) } } fn inttoptr(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { - unsafe { llvm::LLVMBuildIntToPtr(self.llbuilder, val, dest_ty, UNNAMED) } + unsafe { llvm::LLVMBuildIntToPtr(self.llbuilder(), val, dest_ty, UNNAMED) } } fn bitcast(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { - unsafe { llvm::LLVMBuildBitCast(self.llbuilder, val, dest_ty, UNNAMED) } + unsafe { llvm::LLVMBuildBitCast(self.llbuilder(), val, dest_ty, UNNAMED) } } fn intcast(&mut self, val: &'ll Value, dest_ty: &'ll Type, is_signed: bool) -> &'ll Value { unsafe { - llvm::LLVMBuildIntCast2(self.llbuilder, val, dest_ty, is_signed.to_llvm_bool(), UNNAMED) + llvm::LLVMBuildIntCast2( + self.llbuilder(), + val, + dest_ty, + is_signed.to_llvm_bool(), + UNNAMED, + ) } } fn pointercast(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { - unsafe { llvm::LLVMBuildPointerCast(self.llbuilder, val, dest_ty, UNNAMED) } + unsafe { llvm::LLVMBuildPointerCast(self.llbuilder(), val, dest_ty, UNNAMED) } } /* Comparisons */ fn icmp(&mut self, op: IntPredicate, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { let op = llvm::IntPredicate::from_generic(op); - unsafe { llvm::LLVMBuildICmp(self.llbuilder, op as c_uint, lhs, rhs, UNNAMED) } + unsafe { llvm::LLVMBuildICmp(self.llbuilder(), op as c_uint, lhs, rhs, UNNAMED) } } fn fcmp(&mut self, op: RealPredicate, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { let op = llvm::RealPredicate::from_generic(op); - unsafe { llvm::LLVMBuildFCmp(self.llbuilder, op as c_uint, lhs, rhs, UNNAMED) } + unsafe { llvm::LLVMBuildFCmp(self.llbuilder(), op as c_uint, lhs, rhs, UNNAMED) } } fn three_way_compare( @@ -1177,7 +1190,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { let is_volatile = flags.contains(MemFlags::VOLATILE); let memcpy = unsafe { llvm::LLVMRustBuildMemCpy( - self.llbuilder, + self.llbuilder(), dst, dst_align.bytes() as c_uint, src, @@ -1211,7 +1224,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { let is_volatile = flags.contains(MemFlags::VOLATILE); unsafe { llvm::LLVMRustBuildMemMove( - self.llbuilder, + self.llbuilder(), dst, dst_align.bytes() as c_uint, src, @@ -1234,7 +1247,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { let is_volatile = flags.contains(MemFlags::VOLATILE); unsafe { llvm::LLVMRustBuildMemSet( - self.llbuilder, + self.llbuilder(), ptr, align.bytes() as c_uint, fill_byte, @@ -1245,7 +1258,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } fn vscale(&mut self, ty: &'ll Type) -> &'ll Value { - unsafe { llvm::LLVMRustBuildVScale(self.llbuilder, ty) } + unsafe { llvm::LLVMRustBuildVScale(self.llbuilder(), ty) } } fn select( @@ -1254,15 +1267,15 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { then_val: &'ll Value, else_val: &'ll Value, ) -> &'ll Value { - unsafe { llvm::LLVMBuildSelect(self.llbuilder, cond, then_val, else_val, UNNAMED) } + unsafe { llvm::LLVMBuildSelect(self.llbuilder(), cond, then_val, else_val, UNNAMED) } } fn va_arg(&mut self, list: &'ll Value, ty: &'ll Type) -> &'ll Value { - unsafe { llvm::LLVMBuildVAArg(self.llbuilder, list, ty, UNNAMED) } + unsafe { llvm::LLVMBuildVAArg(self.llbuilder(), list, ty, UNNAMED) } } fn extract_element(&mut self, vec: &'ll Value, idx: &'ll Value) -> &'ll Value { - unsafe { llvm::LLVMBuildExtractElement(self.llbuilder, vec, idx, UNNAMED) } + unsafe { llvm::LLVMBuildExtractElement(self.llbuilder(), vec, idx, UNNAMED) } } fn vector_splat(&mut self, num_elts: usize, elt: &'ll Value) -> &'ll Value { @@ -1277,12 +1290,14 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { fn extract_value(&mut self, agg_val: &'ll Value, idx: u64) -> &'ll Value { assert_eq!(idx as c_uint as u64, idx); - unsafe { llvm::LLVMBuildExtractValue(self.llbuilder, agg_val, idx as c_uint, UNNAMED) } + unsafe { llvm::LLVMBuildExtractValue(self.llbuilder(), agg_val, idx as c_uint, UNNAMED) } } fn insert_value(&mut self, agg_val: &'ll Value, elt: &'ll Value, idx: u64) -> &'ll Value { assert_eq!(idx as c_uint as u64, idx); - unsafe { llvm::LLVMBuildInsertValue(self.llbuilder, agg_val, elt, idx as c_uint, UNNAMED) } + unsafe { + llvm::LLVMBuildInsertValue(self.llbuilder(), agg_val, elt, idx as c_uint, UNNAMED) + } } fn set_personality_fn(&mut self, personality: &'ll Value) { @@ -1312,14 +1327,14 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { exn = self.insert_value(exn, exn0, 0); exn = self.insert_value(exn, exn1, 1); unsafe { - llvm::LLVMBuildResume(self.llbuilder, exn); + llvm::LLVMBuildResume(self.llbuilder(), exn); } } fn cleanup_pad(&mut self, parent: Option<&'ll Value>, args: &[&'ll Value]) -> Funclet<'ll> { let ret = unsafe { llvm::LLVMBuildCleanupPad( - self.llbuilder, + self.llbuilder(), parent, args.as_ptr(), args.len() as c_uint, @@ -1331,7 +1346,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { fn cleanup_ret(&mut self, funclet: &Funclet<'ll>, unwind: Option<&'ll BasicBlock>) { unsafe { - llvm::LLVMBuildCleanupRet(self.llbuilder, funclet.cleanuppad(), unwind) + llvm::LLVMBuildCleanupRet(self.llbuilder(), funclet.cleanuppad(), unwind) .expect("LLVM does not have support for cleanupret"); } } @@ -1339,7 +1354,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { fn catch_pad(&mut self, parent: &'ll Value, args: &[&'ll Value]) -> Funclet<'ll> { let ret = unsafe { llvm::LLVMBuildCatchPad( - self.llbuilder, + self.llbuilder(), parent, args.as_ptr(), args.len() as c_uint, @@ -1357,7 +1372,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { ) -> &'ll Value { let ret = unsafe { llvm::LLVMBuildCatchSwitch( - self.llbuilder, + self.llbuilder(), parent, unwind, handlers.len() as c_uint, @@ -1389,7 +1404,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { ) -> (&'ll Value, &'ll Value) { unsafe { let value = llvm::LLVMBuildAtomicCmpXchg( - self.llbuilder, + self.llbuilder(), dst, cmp, src, @@ -1417,7 +1432,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { // currently support that (https://github.com/llvm/llvm-project/issues/120837). let mut res = unsafe { llvm::LLVMBuildAtomicRMW( - self.llbuilder, + self.llbuilder(), AtomicRmwBinOp::from_generic(op), dst, src, @@ -1442,7 +1457,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { }; unsafe { llvm::LLVMBuildFence( - self.llbuilder, + self.llbuilder(), AtomicOrdering::from_generic(order), single_threaded.to_llvm_bool(), UNNAMED, @@ -1507,7 +1522,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { let call = unsafe { llvm::LLVMBuildCallWithOperandBundles( - self.llbuilder, + self.llbuilder(), llty, llfn, args.as_ptr() as *const &llvm::Value, @@ -1555,7 +1570,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } fn zext(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { - unsafe { llvm::LLVMBuildZExt(self.llbuilder, val, dest_ty, UNNAMED) } + unsafe { llvm::LLVMBuildZExt(self.llbuilder(), val, dest_ty, UNNAMED) } } fn apply_attrs_to_cleanup_callsite(&mut self, llret: &'ll Value) { @@ -1635,7 +1650,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { impl<'a, 'll, CX: Borrow>> GenericBuilder<'a, 'll, CX> { fn position_at_start(&mut self, llbb: &'ll BasicBlock) { unsafe { - llvm::LLVMRustPositionBuilderAtStart(self.llbuilder, llbb); + llvm::LLVMRustPositionBuilderAtStart(self.llbuilder(), llbb); } } } @@ -1743,7 +1758,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { elt: &'ll Value, idx: &'ll Value, ) -> &'ll Value { - unsafe { llvm::LLVMBuildInsertElement(self.llbuilder, vec, elt, idx, UNNAMED) } + unsafe { llvm::LLVMBuildInsertElement(self.llbuilder(), vec, elt, idx, UNNAMED) } } pub(crate) fn shuffle_vector( @@ -1752,7 +1767,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { v2: &'ll Value, mask: &'ll Value, ) -> &'ll Value { - unsafe { llvm::LLVMBuildShuffleVector(self.llbuilder, v1, v2, mask, UNNAMED) } + unsafe { llvm::LLVMBuildShuffleVector(self.llbuilder(), v1, v2, mask, UNNAMED) } } pub(crate) fn vector_reduce_fadd(&mut self, acc: &'ll Value, src: &'ll Value) -> &'ll Value { @@ -1827,7 +1842,8 @@ impl<'a, 'll, CX: Borrow>> GenericBuilder<'a, 'll, CX> { funclet: &Funclet<'ll>, unwind: &'ll BasicBlock, ) -> &'ll Value { - let ret = unsafe { llvm::LLVMBuildCatchRet(self.llbuilder, funclet.cleanuppad(), unwind) }; + let ret = + unsafe { llvm::LLVMBuildCatchRet(self.llbuilder(), funclet.cleanuppad(), unwind) }; ret.expect("LLVM does not have support for catchret") } @@ -1873,7 +1889,7 @@ impl<'a, 'll, CX: Borrow>> GenericBuilder<'a, 'll, CX> { } pub(crate) fn va_arg(&mut self, list: &'ll Value, ty: &'ll Type) -> &'ll Value { - unsafe { llvm::LLVMBuildVAArg(self.llbuilder, list, ty, UNNAMED) } + unsafe { llvm::LLVMBuildVAArg(self.llbuilder(), list, ty, UNNAMED) } } } @@ -1913,7 +1929,7 @@ impl<'a, 'll, CX: Borrow>> GenericBuilder<'a, 'll, CX> { bbs: &[&'ll BasicBlock], ) -> &'ll Value { assert_eq!(vals.len(), bbs.len()); - let phi = unsafe { llvm::LLVMBuildPhi(self.llbuilder, ty, UNNAMED) }; + let phi = unsafe { llvm::LLVMBuildPhi(self.llbuilder(), ty, UNNAMED) }; unsafe { llvm::LLVMAddIncoming(phi, vals.as_ptr(), bbs.as_ptr(), vals.len() as c_uint); phi @@ -1938,7 +1954,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { // personality lives on the parent function anyway. self.set_personality_fn(pers_fn); unsafe { - llvm::LLVMBuildLandingPad(self.llbuilder, ty, None, num_clauses as c_uint, UNNAMED) + llvm::LLVMBuildLandingPad(self.llbuilder(), ty, None, num_clauses as c_uint, UNNAMED) } } @@ -1979,7 +1995,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { let callbr = unsafe { llvm::LLVMBuildCallBr( - self.llbuilder, + self.llbuilder(), llty, llfn, default_dest, diff --git a/compiler/rustc_codegen_llvm/src/builder/autodiff.rs b/compiler/rustc_codegen_llvm/src/builder/autodiff.rs index 3b1e36265b941..58b8cb1124d85 100644 --- a/compiler/rustc_codegen_llvm/src/builder/autodiff.rs +++ b/compiler/rustc_codegen_llvm/src/builder/autodiff.rs @@ -193,7 +193,7 @@ fn match_args_from_caller_to_enzyme<'ll, 'tcx>( // Now we multiply `4 * next_outer_arg` to get the stride. let mul = unsafe { llvm::LLVMBuildMul( - builder.llbuilder, + builder.llbuilder(), cx.get_const_int(cx.type_i64(), elem_bytes_size), next_outer_arg, UNNAMED, diff --git a/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs b/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs index d3bb8d7c3e6a4..de7b4688f1471 100644 --- a/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs +++ b/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs @@ -475,7 +475,7 @@ fn declare_offload_fn<'ll>( ) } -pub(crate) fn scalar_width<'ll>(cx: &'ll SimpleCx<'_>, ty: &'ll Type) -> u64 { +pub(crate) fn scalar_width<'ll>(cx: &SimpleCx<'ll>, ty: &'ll Type) -> u64 { match cx.type_kind(ty) { TypeKind::Half | TypeKind::Float @@ -560,7 +560,7 @@ pub(crate) fn gen_call_handling<'ll, 'tcx>( // Step 0) unsafe { - llvm::LLVMRustPositionBuilderPastAllocas(&builder.llbuilder, builder.llfn()); + llvm::LLVMRustPositionBuilderPastAllocas(builder.llbuilder(), builder.llfn()); } let ty = cx.type_array(cx.type_ptr(), num_args); @@ -594,7 +594,7 @@ pub(crate) fn gen_call_handling<'ll, 'tcx>( // Step 1) unsafe { - llvm::LLVMPositionBuilderAtEnd(&builder.llbuilder, bb); + llvm::LLVMPositionBuilderAtEnd(builder.llbuilder(), bb); } // Now we allocate once per function param, a copy to be passed to one of our maps. @@ -612,11 +612,11 @@ pub(crate) fn gen_call_handling<'ll, 'tcx>( let bb = builder.llbb(); unsafe { - llvm::LLVMRustPositionBuilderPastAllocas(builder.llbuilder, builder.llfn()); + llvm::LLVMRustPositionBuilderPastAllocas(builder.llbuilder(), builder.llfn()); } let addr = builder.direct_alloca(cx.type_i64(), Align::EIGHT, "addr"); unsafe { - llvm::LLVMPositionBuilderAtEnd(builder.llbuilder, bb); + llvm::LLVMPositionBuilderAtEnd(builder.llbuilder(), bb); } let cast = builder.bitcast(v, cx.type_ix(num_bits)); diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs index 6e8f005be9569..a7fdf9b2d8a76 100644 --- a/compiler/rustc_codegen_llvm/src/common.rs +++ b/compiler/rustc_codegen_llvm/src/common.rs @@ -469,12 +469,12 @@ pub(crate) fn val_ty(v: &Value) -> &Type { unsafe { llvm::LLVMTypeOf(v) } } -pub(crate) fn bytes_in_context<'ll>(llcx: &'ll llvm::Context, bytes: &[u8]) -> &'ll Value { +pub(crate) fn bytes_in_context<'ll>(llcx: llvm::Context<'ll>, bytes: &[u8]) -> &'ll Value { unsafe { llvm::LLVMConstStringInContext2(llcx, bytes.as_ptr(), bytes.len(), TRUE) } } pub(crate) fn null_terminate_bytes_in_context<'ll>( - llcx: &'ll llvm::Context, + llcx: llvm::Context<'ll>, bytes: &[u8], ) -> &'ll Value { unsafe { llvm::LLVMConstStringInContext2(llcx, bytes.as_ptr(), bytes.len(), FALSE) } @@ -486,7 +486,7 @@ pub(crate) fn named_struct<'ll>(ty: &'ll Type, elts: &[&'ll Value]) -> &'ll Valu } fn struct_in_context<'ll>( - llcx: &'ll llvm::Context, + llcx: llvm::Context<'ll>, elts: &[&'ll Value], packed: bool, ) -> &'ll Value { diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 1a323e550623b..8ef5ce26e1c2d 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -48,7 +48,7 @@ use crate::{attributes, common, coverageinfo, debuginfo, llvm_util}; /// moved around more freely. pub(crate) struct SCx<'ll> { pub llmod: &'ll llvm::Module, - pub llcx: &'ll llvm::Context, + pub llcx: llvm::Context<'ll>, pub isize_ty: &'ll Type, } @@ -184,7 +184,7 @@ fn to_llvm_tls_model(tls_model: TlsModel) -> llvm::ThreadLocalMode { pub(crate) unsafe fn create_module<'ll>( tcx: TyCtxt<'_>, - llcx: &'ll llvm::Context, + llcx: llvm::Context<'ll>, mod_name: &str, ) -> *const llvm::Module { let mod_name_cstr = SmallCStr::new(mod_name); @@ -194,7 +194,7 @@ pub(crate) unsafe fn create_module<'ll>( llmod_raw } -fn init_module<'ll, 'tcx>(tcx: TyCtxt<'tcx>, llcx: &'ll llvm::Context, llmod: &'ll llvm::Module) { +fn init_module<'ll, 'tcx>(tcx: TyCtxt<'tcx>, llcx: llvm::Context<'ll>, llmod: &'ll llvm::Module) { let sess = tcx.sess; let cx = SimpleCx::new(llmod, llcx, tcx.data_layout.pointer_size()); @@ -881,7 +881,7 @@ impl<'ll> SimpleCx<'ll> { impl<'ll> SimpleCx<'ll> { pub(crate) fn new( llmod: &'ll llvm::Module, - llcx: &'ll llvm::Context, + llcx: llvm::Context<'ll>, pointer_size: Size, ) -> Self { let isize_ty = llvm::LLVMIntTypeInContext(llcx, pointer_size.bits() as c_uint); diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index 99a54f1d74a62..eb923316cc649 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -121,7 +121,7 @@ impl<'ll, 'tcx> CodegenUnitDebugContext<'ll, 'tcx> { impl<'ll> Builder<'_, 'll, '_> { pub(crate) fn get_dbg_loc(&self) -> Option<&'ll DILocation> { - unsafe { llvm::LLVMGetCurrentDebugLocation2(self.llbuilder) } + unsafe { llvm::LLVMGetCurrentDebugLocation2(self.llbuilder()) } } } @@ -576,13 +576,13 @@ impl<'ll, 'tcx> DebugInfoBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { fn set_dbg_loc(&mut self, dbg_loc: &'ll DILocation) { unsafe { - llvm::LLVMSetCurrentDebugLocation2(self.llbuilder, dbg_loc); + llvm::LLVMSetCurrentDebugLocation2(self.llbuilder(), dbg_loc); } } fn clear_dbg_loc(&mut self) { unsafe { - llvm::LLVMSetCurrentDebugLocation2(self.llbuilder, ptr::null()); + llvm::LLVMSetCurrentDebugLocation2(self.llbuilder(), ptr::null()); } } diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index a08ebbb28fd20..212e2886fe019 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -242,7 +242,9 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { args[1].immediate(), args[2].immediate(), ), - sym::breakpoint => self.call_intrinsic("llvm.debugtrap", &[], &[]), + sym::breakpoint | sym::resumable_breakpoint => { + self.call_intrinsic("llvm.debugtrap", &[], &[]) + } sym::va_arg => { let target = &self.cx.tcx.sess.target; let stability = target.supports_c_variadic_definitions(); @@ -985,7 +987,7 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { let llret = unsafe { llvm::LLVMBuildCallWithOperandBundles( - self.llbuilder, + self.llbuilder(), fn_ty, fn_ptr, llargs.as_ptr(), diff --git a/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs index 8f6cc30e1166d..b0641b70d1189 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs @@ -3,8 +3,8 @@ use libc::{c_char, c_uchar, c_uint}; use super::MetadataKindId; -use super::ffi::{AttributeKind, BasicBlock, Context, Metadata, Module, Type, Value}; -use crate::llvm::{Bool, Builder}; +use super::ffi::{AttributeKind, BasicBlock, Metadata, Module, Type, Value}; +use crate::llvm::{Bool, Builder, Context}; // TypeTree types pub(crate) type CTypeTreeRef = *mut EnzymeTypeTree; @@ -108,7 +108,8 @@ pub(crate) mod Enzyme_AD { type EnzymeSetCLStringFn = unsafe extern "C" fn(*mut c_void, *const c_char); type EnzymeNewTypeTreeFn = unsafe extern "C" fn() -> CTypeTreeRef; - type EnzymeNewTypeTreeCTFn = unsafe extern "C" fn(CConcreteType, &Context) -> CTypeTreeRef; + type EnzymeNewTypeTreeCTFn = + for<'ll> unsafe extern "C" fn(CConcreteType, Context<'ll>) -> CTypeTreeRef; type EnzymeNewTypeTreeTRFn = unsafe extern "C" fn(CTypeTreeRef) -> CTypeTreeRef; type EnzymeFreeTypeTreeFn = unsafe extern "C" fn(CTypeTreeRef); type EnzymeMergeTypeTreeFn = unsafe extern "C" fn(CTypeTreeRef, CTypeTreeRef) -> bool; @@ -117,7 +118,7 @@ pub(crate) mod Enzyme_AD { type EnzymeTypeTreeShiftIndiciesEqFn = unsafe extern "C" fn(CTypeTreeRef, *const c_char, i64, i64, u64); type EnzymeTypeTreeInsertEqFn = - unsafe extern "C" fn(CTypeTreeRef, *const i64, usize, CConcreteType, &Context); + for<'ll> unsafe extern "C" fn(CTypeTreeRef, *const i64, usize, CConcreteType, Context<'ll>); type EnzymeTypeTreeToStringFn = unsafe extern "C" fn(CTypeTreeRef) -> *const c_char; type EnzymeTypeTreeToStringFreeFn = unsafe extern "C" fn(*const c_char); @@ -236,10 +237,10 @@ pub(crate) mod Enzyme_AD { unsafe { (self.EnzymeNewTypeTree)() } } - pub(crate) fn new_type_tree_ct( + pub(crate) fn new_type_tree_ct<'ll>( &self, t: CConcreteType, - ctx: &Context, + ctx: Context<'ll>, ) -> *mut EnzymeTypeTree { unsafe { (self.EnzymeNewTypeTreeCT)(t, ctx) } } @@ -283,13 +284,13 @@ pub(crate) mod Enzyme_AD { } } - pub(crate) fn tree_insert_eq( + pub(crate) fn tree_insert_eq<'ll>( &self, tree: CTypeTreeRef, indices: *const i64, len: usize, ct: CConcreteType, - ctx: &Context, + ctx: Context<'ll>, ) { unsafe { (self.EnzymeTypeTreeInsertEq)(tree, indices, len, ct, ctx) } } @@ -476,7 +477,7 @@ impl TypeTree { TypeTree { inner } } - pub(crate) fn from_type(t: CConcreteType, ctx: &Context) -> TypeTree { + pub(crate) fn from_type<'ll>(t: CConcreteType, ctx: Context<'ll>) -> TypeTree { let wrapper = EnzymeWrapper::get_instance(); let inner = wrapper.new_type_tree_ct(t, ctx); TypeTree { inner } @@ -510,7 +511,7 @@ impl TypeTree { self } - pub(crate) fn insert(&mut self, indices: &[i64], ct: CConcreteType, ctx: &Context) { + pub(crate) fn insert<'ll>(&mut self, indices: &[i64], ct: CConcreteType, ctx: Context<'ll>) { let wrapper = EnzymeWrapper::get_instance(); wrapper.tree_insert_eq(self.inner, indices.as_ptr(), indices.len(), ct, ctx); } diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index b109772eb501b..7e6c4869f0b26 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -700,9 +700,19 @@ struct InvariantOpaque<'a> { } // Opaque pointer types + +/// Corresponds to `LLVMContextRef`. +#[derive(Clone, Copy)] +#[repr(transparent)] +pub(crate) struct Context<'ll> { + pub(crate) llcx_raw: ptr::NonNull, + pub(crate) _invariant_ll: PhantomData &'ll ()>, +} + unsafe extern "C" { + /// Pointee of the raw pointer that is wrapped by a lifetime-branded [`Context`]. + pub(crate) type ContextRaw; pub(crate) type Module; - pub(crate) type Context; pub(crate) type Type; pub(crate) type Value; pub(crate) type ConstantInt; @@ -887,11 +897,11 @@ pub(crate) type GetSymbolsErrorCallback = unsafe extern "C" fn(*const c_char) -> unsafe extern "C" { // Create and destroy contexts. - pub(crate) fn LLVMContextCreate() -> ptr::NonNull; - pub(crate) fn LLVMContextDispose(C: ptr::NonNull); - pub(crate) fn LLVMContextSetDiscardValueNames(C: &Context, Discard: Bool); - pub(crate) fn LLVMGetMDKindIDInContext( - C: &Context, + pub(crate) fn LLVMContextCreate() -> ptr::NonNull; + pub(crate) fn LLVMContextDispose(C: ptr::NonNull); + pub(crate) fn LLVMContextSetDiscardValueNames<'ll>(C: Context<'ll>, Discard: Bool); + pub(crate) fn LLVMGetMDKindIDInContext<'ll>( + C: Context<'ll>, Name: *const c_uchar, // See "PTR_LEN_STR". SLen: c_uint, ) -> MetadataKindId; @@ -905,9 +915,9 @@ unsafe extern "C" { pub(crate) fn LLVMDisposeTargetMachine(T: ptr::NonNull); // Create modules. - pub(crate) fn LLVMModuleCreateWithNameInContext( + pub(crate) fn LLVMModuleCreateWithNameInContext<'ll>( ModuleID: *const c_char, - C: &Context, + C: Context<'ll>, ) -> *const Module; pub(crate) safe fn LLVMCloneModule(M: &Module) -> &Module; @@ -931,24 +941,24 @@ unsafe extern "C" { pub(crate) safe fn LLVMGetTypeKind(Ty: &Type) -> RawEnum; // Operations on integer types - pub(crate) fn LLVMInt1TypeInContext(C: &Context) -> &Type; - pub(crate) fn LLVMInt8TypeInContext(C: &Context) -> &Type; - pub(crate) fn LLVMInt16TypeInContext(C: &Context) -> &Type; - pub(crate) fn LLVMInt32TypeInContext(C: &Context) -> &Type; - pub(crate) fn LLVMInt64TypeInContext(C: &Context) -> &Type; - pub(crate) safe fn LLVMIntTypeInContext(C: &Context, NumBits: c_uint) -> &Type; + pub(crate) fn LLVMInt1TypeInContext<'ll>(C: Context<'ll>) -> &'ll Type; + pub(crate) fn LLVMInt8TypeInContext<'ll>(C: Context<'ll>) -> &'ll Type; + pub(crate) fn LLVMInt16TypeInContext<'ll>(C: Context<'ll>) -> &'ll Type; + pub(crate) fn LLVMInt32TypeInContext<'ll>(C: Context<'ll>) -> &'ll Type; + pub(crate) fn LLVMInt64TypeInContext<'ll>(C: Context<'ll>) -> &'ll Type; + pub(crate) safe fn LLVMIntTypeInContext<'ll>(C: Context<'ll>, NumBits: c_uint) -> &'ll Type; pub(crate) fn LLVMGetIntTypeWidth(IntegerTy: &Type) -> c_uint; // Operations on real types - pub(crate) fn LLVMHalfTypeInContext(C: &Context) -> &Type; - pub(crate) fn LLVMFloatTypeInContext(C: &Context) -> &Type; - pub(crate) fn LLVMDoubleTypeInContext(C: &Context) -> &Type; - pub(crate) fn LLVMFP128TypeInContext(C: &Context) -> &Type; + pub(crate) fn LLVMHalfTypeInContext<'ll>(C: Context<'ll>) -> &'ll Type; + pub(crate) fn LLVMFloatTypeInContext<'ll>(C: Context<'ll>) -> &'ll Type; + pub(crate) fn LLVMDoubleTypeInContext<'ll>(C: Context<'ll>) -> &'ll Type; + pub(crate) fn LLVMFP128TypeInContext<'ll>(C: Context<'ll>) -> &'ll Type; // Operations on non-IEEE real types - pub(crate) fn LLVMBFloatTypeInContext(C: &Context) -> &Type; - pub(crate) fn LLVMPPCFP128TypeInContext(C: &Context) -> &Type; + pub(crate) fn LLVMBFloatTypeInContext<'ll>(C: Context<'ll>) -> &'ll Type; + pub(crate) fn LLVMPPCFP128TypeInContext<'ll>(C: Context<'ll>) -> &'ll Type; // Operations on function types pub(crate) fn LLVMFunctionType<'a>( @@ -963,15 +973,18 @@ unsafe extern "C" { pub(crate) fn LLVMIsFunctionVarArg(FunctionTy: &Type) -> Bool; // Operations on struct types - pub(crate) fn LLVMStructTypeInContext<'a>( - C: &'a Context, - ElementTypes: *const &'a Type, + pub(crate) fn LLVMStructTypeInContext<'ll>( + C: Context<'ll>, + ElementTypes: *const &'ll Type, ElementCount: c_uint, Packed: Bool, - ) -> &'a Type; + ) -> &'ll Type; // Operations on array, pointer, and vector types (sequence types) - pub(crate) safe fn LLVMPointerTypeInContext(C: &Context, AddressSpace: c_uint) -> &Type; + pub(crate) safe fn LLVMPointerTypeInContext<'ll>( + C: Context<'ll>, + AddressSpace: c_uint, + ) -> &'ll Type; pub(crate) fn LLVMVectorType(ElementType: &Type, ElementCount: c_uint) -> &Type; pub(crate) fn LLVMScalableVectorType(ElementType: &Type, ElementCount: c_uint) -> &Type; @@ -979,7 +992,7 @@ unsafe extern "C" { pub(crate) fn LLVMGetVectorSize(VectorTy: &Type) -> c_uint; // Operations on other types - pub(crate) fn LLVMVoidTypeInContext(C: &Context) -> &Type; + pub(crate) fn LLVMVoidTypeInContext<'ll>(C: Context<'ll>) -> &'ll Type; // Operations on all values pub(crate) fn LLVMTypeOf(Val: &Value) -> &Type; @@ -1013,16 +1026,16 @@ unsafe extern "C" { pub(crate) fn LLVMGetPoison(Ty: &Type) -> &Value; // Operations on metadata - pub(crate) fn LLVMMDStringInContext2( - C: &Context, + pub(crate) fn LLVMMDStringInContext2<'ll>( + C: Context<'ll>, Str: *const c_uchar, // See "PTR_LEN_STR". SLen: size_t, - ) -> &Metadata; - pub(crate) fn LLVMMDNodeInContext2<'a>( - C: &'a Context, - Vals: *const &'a Metadata, + ) -> &'ll Metadata; + pub(crate) fn LLVMMDNodeInContext2<'ll>( + C: Context<'ll>, + Vals: *const &'ll Metadata, Count: size_t, - ) -> &'a Metadata; + ) -> &'ll Metadata; pub(crate) fn LLVMAddNamedMetadataOperand<'a>( M: &'a Module, Name: *const c_char, @@ -1046,18 +1059,18 @@ unsafe extern "C" { Length: u64, ) -> &'a Value; pub(crate) fn LLVMArrayType2(ElementType: &Type, ElementCount: u64) -> &Type; - pub(crate) fn LLVMConstStringInContext2( - C: &Context, + pub(crate) fn LLVMConstStringInContext2<'ll>( + C: Context<'ll>, Str: *const c_uchar, // See "PTR_LEN_STR". Length: size_t, DontNullTerminate: Bool, - ) -> &Value; - pub(crate) fn LLVMConstStructInContext<'a>( - C: &'a Context, - ConstantVals: *const &'a Value, + ) -> &'ll Value; + pub(crate) fn LLVMConstStructInContext<'ll>( + C: Context<'ll>, + ConstantVals: *const &'ll Value, Count: c_uint, Packed: Bool, - ) -> &'a Value; + ) -> &'ll Value; pub(crate) fn LLVMConstNamedStruct<'a>( StructTy: &'a Type, ConstantVals: *const &'a Value, @@ -1121,13 +1134,13 @@ unsafe extern "C" { pub(crate) fn LLVMGetNextGlobalAlias(GlobalAlias: &Value) -> Option<&Value>; // Operations on attributes - pub(crate) fn LLVMCreateStringAttribute( - C: &Context, + pub(crate) fn LLVMCreateStringAttribute<'ll>( + C: Context<'ll>, Name: *const c_uchar, // See "PTR_LEN_STR". NameLen: c_uint, Value: *const c_uchar, // See "PTR_LEN_STR". ValueLen: c_uint, - ) -> &Attribute; + ) -> &'ll Attribute; // Operations on functions pub(crate) fn LLVMSetFunctionCallConv(Fn: &Value, CC: c_uint); @@ -1169,11 +1182,11 @@ unsafe extern "C" { // Operations on basic blocks pub(crate) fn LLVMGetBasicBlockParent(BB: &BasicBlock) -> &Value; - pub(crate) fn LLVMAppendBasicBlockInContext<'a>( - C: &'a Context, - Fn: &'a Value, + pub(crate) fn LLVMAppendBasicBlockInContext<'ll>( + C: Context<'ll>, + Fn: &'ll Value, Name: *const c_char, - ) -> &'a BasicBlock; + ) -> &'ll BasicBlock; // Operations on instructions pub(crate) fn LLVMIsAInstruction(Val: &Value) -> Option<&Value>; @@ -1196,10 +1209,10 @@ unsafe extern "C" { ); // Instruction builders - pub(crate) fn LLVMCreateBuilderForModule(M: &Module) -> &mut Builder<'_>; + pub(crate) fn LLVMCreateBuilderForModule<'ll>(M: &'ll Module) -> ptr::NonNull>; pub(crate) fn LLVMPositionBuilderAtEnd<'a>(Builder: &Builder<'a>, Block: &'a BasicBlock); pub(crate) fn LLVMGetInsertBlock<'a>(Builder: &Builder<'a>) -> &'a BasicBlock; - pub(crate) fn LLVMDisposeBuilder<'a>(Builder: &'a mut Builder<'a>); + pub(crate) fn LLVMDisposeBuilder<'ll>(Builder: ptr::NonNull>); // Metadata pub(crate) fn LLVMSetCurrentDebugLocation2<'a>(Builder: &Builder<'a>, Loc: *const Metadata); @@ -1662,7 +1675,7 @@ unsafe extern "C" { pub(crate) fn LLVMIsMultithreaded() -> Bool; - pub(crate) fn LLVMStructCreateNamed(C: &Context, Name: *const c_char) -> &Type; + pub(crate) fn LLVMStructCreateNamed<'ll>(C: Context<'ll>, Name: *const c_char) -> &'ll Type; pub(crate) fn LLVMStructSetBody<'a>( StructTy: &'a Type, @@ -1674,7 +1687,7 @@ unsafe extern "C" { pub(crate) fn LLVMCountStructElementTypes(StructTy: &Type) -> c_uint; pub(crate) fn LLVMGetStructElementTypes<'a>(StructTy: &'a Type, Dest: *mut &'a Type); - pub(crate) safe fn LLVMMetadataAsValue<'a>(C: &'a Context, MD: &'a Metadata) -> &'a Value; + pub(crate) safe fn LLVMMetadataAsValue<'ll>(C: Context<'ll>, MD: &'ll Metadata) -> &'ll Value; pub(crate) safe fn LLVMSetUnnamedAddress(Global: &Value, UnnamedAddr: UnnamedAddr); @@ -1764,7 +1777,7 @@ unsafe extern "C" { ) -> &'ll Metadata; pub(crate) fn LLVMDIBuilderCreateDebugLocation<'ll>( - Ctx: &'ll Context, + Ctx: Context<'ll>, Line: c_uint, Column: c_uint, Scope: &'ll Metadata, @@ -2019,33 +2032,54 @@ unsafe extern "C" { ) -> Option<&Value>; // Operations on attributes - pub(crate) fn LLVMRustCreateAttrNoValue(C: &Context, attr: AttributeKind) -> &Attribute; - pub(crate) fn LLVMRustCreateAlignmentAttr(C: &Context, bytes: u64) -> &Attribute; - pub(crate) fn LLVMRustCreateDereferenceableAttr(C: &Context, bytes: u64) -> &Attribute; - pub(crate) fn LLVMRustCreateDereferenceableOrNullAttr(C: &Context, bytes: u64) -> &Attribute; - pub(crate) fn LLVMRustCreateByValAttr<'a>(C: &'a Context, ty: &'a Type) -> &'a Attribute; - pub(crate) fn LLVMRustCreateByRefAttr<'a>(C: &'a Context, ty: &'a Type) -> &'a Attribute; - pub(crate) fn LLVMRustCreateStructRetAttr<'a>(C: &'a Context, ty: &'a Type) -> &'a Attribute; - pub(crate) fn LLVMRustCreateElementTypeAttr<'a>(C: &'a Context, ty: &'a Type) -> &'a Attribute; - pub(crate) fn LLVMRustCreateUWTableAttr(C: &Context, async_: bool) -> &Attribute; - pub(crate) fn LLVMRustCreateAllocSizeAttr(C: &Context, size_arg: u32) -> &Attribute; - pub(crate) fn LLVMRustCreateAllocKindAttr(C: &Context, size_arg: u64) -> &Attribute; - pub(crate) fn LLVMRustCreateMemoryEffectsAttr( - C: &Context, + pub(crate) fn LLVMRustCreateAttrNoValue<'ll>( + C: Context<'ll>, + attr: AttributeKind, + ) -> &'ll Attribute; + pub(crate) fn LLVMRustCreateAlignmentAttr<'ll>(C: Context<'ll>, bytes: u64) -> &'ll Attribute; + pub(crate) fn LLVMRustCreateDereferenceableAttr<'ll>( + C: Context<'ll>, + bytes: u64, + ) -> &'ll Attribute; + pub(crate) fn LLVMRustCreateDereferenceableOrNullAttr<'ll>( + C: Context<'ll>, + bytes: u64, + ) -> &'ll Attribute; + pub(crate) fn LLVMRustCreateByValAttr<'ll>(C: Context<'ll>, ty: &'ll Type) -> &'ll Attribute; + pub(crate) fn LLVMRustCreateByRefAttr<'ll>(C: Context<'ll>, ty: &'ll Type) -> &'ll Attribute; + pub(crate) fn LLVMRustCreateStructRetAttr<'ll>( + C: Context<'ll>, + ty: &'ll Type, + ) -> &'ll Attribute; + pub(crate) fn LLVMRustCreateElementTypeAttr<'ll>( + C: Context<'ll>, + ty: &'ll Type, + ) -> &'ll Attribute; + pub(crate) fn LLVMRustCreateUWTableAttr<'ll>(C: Context<'ll>, async_: bool) -> &'ll Attribute; + pub(crate) fn LLVMRustCreateAllocSizeAttr<'ll>( + C: Context<'ll>, + size_arg: u32, + ) -> &'ll Attribute; + pub(crate) fn LLVMRustCreateAllocKindAttr<'ll>( + C: Context<'ll>, + size_arg: u64, + ) -> &'ll Attribute; + pub(crate) fn LLVMRustCreateMemoryEffectsAttr<'ll>( + C: Context<'ll>, effects: MemoryEffects, - ) -> &Attribute; + ) -> &'ll Attribute; /// ## Safety /// - Each of `LowerWords` and `UpperWords` must point to an array that is /// long enough to fully define an integer of size `NumBits`, i.e. each /// pointer must point to `NumBits.div_ceil(64)` elements or more. /// - The implementation will make its own copy of the pointed-to `u64` /// values, so the pointers only need to outlive this function call. - pub(crate) fn LLVMRustCreateRangeAttribute( - C: &Context, + pub(crate) fn LLVMRustCreateRangeAttribute<'ll>( + C: Context<'ll>, NumBits: c_uint, LowerWords: *const u64, UpperWords: *const u64, - ) -> &Attribute; + ) -> &'ll Attribute; // Operations on functions pub(crate) fn LLVMRustAddFunctionAttributes<'a>( @@ -2560,12 +2594,12 @@ unsafe extern "C" { Target: &TargetMachine, ) -> bool; pub(crate) fn LLVMRustFreeThinLTOData(Data: &'static mut ThinLTOData); - pub(crate) fn LLVMRustParseBitcodeForLTO( - Context: &Context, + pub(crate) fn LLVMRustParseBitcodeForLTO<'ll>( + Context: Context<'ll>, Data: *const u8, len: usize, Identifier: *const c_char, - ) -> Option<&Module>; + ) -> Option<&'ll Module>; pub(crate) fn LLVMRustLinkerNew(M: &Module) -> &mut Linker<'_>; pub(crate) fn LLVMRustLinkerAdd( @@ -2581,20 +2615,20 @@ unsafe extern "C" { ); /// Removes the currently-installed `DiagnosticHandler`, and returns an owning pointer to it. - pub(crate) fn LLVMRustContextTakeDiagnosticHandler( - Context: &Context, + pub(crate) fn LLVMRustContextTakeDiagnosticHandler<'ll>( + Context: Context<'ll>, ) -> Option>; /// Installs a diagnostic handler that was previously removed by /// [`LLVMRustContextTakeDiagnosticHandler`]. - pub(crate) fn LLVMRustContextSetDiagnosticHandler( - context: &Context, + pub(crate) fn LLVMRustContextSetDiagnosticHandler<'ll>( + context: Context<'ll>, diagnostic_handler: Option>, ); /// Installs a custom diagnostic handler. - pub(crate) fn LLVMRustContextConfigureDiagnosticHandler( - context: &Context, + pub(crate) fn LLVMRustContextConfigureDiagnosticHandler<'ll>( + context: Context<'ll>, diagnostic_handler_callback: DiagnosticHandlerCallback, diagnostic_handler_callback_data: *mut c_void, remark_all_passes: bool, diff --git a/compiler/rustc_codegen_llvm/src/llvm/mod.rs b/compiler/rustc_codegen_llvm/src/llvm/mod.rs index e189dc758d8e7..54b31bc450cfb 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/mod.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/mod.rs @@ -63,7 +63,7 @@ pub(crate) fn AddCallSiteAttributes<'ll>( } pub(crate) fn CreateAttrStringValue<'ll>( - llcx: &'ll Context, + llcx: Context<'ll>, attr: &str, value: &str, ) -> &'ll Attribute { @@ -78,7 +78,7 @@ pub(crate) fn CreateAttrStringValue<'ll>( } } pub(crate) fn CreateAttrStringValueFromCStr<'ll>( - llcx: &'ll Context, + llcx: Context<'ll>, attr: &std::ffi::CStr, value: &std::ffi::CStr, ) -> &'ll Attribute { @@ -95,7 +95,7 @@ pub(crate) fn CreateAttrStringValueFromCStr<'ll>( } } -pub(crate) fn CreateAttrString<'ll>(llcx: &'ll Context, attr: &str) -> &'ll Attribute { +pub(crate) fn CreateAttrString<'ll>(llcx: Context<'ll>, attr: &str) -> &'ll Attribute { unsafe { LLVMCreateStringAttribute( llcx, @@ -107,43 +107,53 @@ pub(crate) fn CreateAttrString<'ll>(llcx: &'ll Context, attr: &str) -> &'ll Attr } } -pub(crate) fn CreateAlignmentAttr(llcx: &Context, bytes: u64) -> &Attribute { +pub(crate) fn CreateAlignmentAttr<'ll>(llcx: Context<'ll>, bytes: u64) -> &'ll Attribute { unsafe { LLVMRustCreateAlignmentAttr(llcx, bytes) } } -pub(crate) fn CreateDereferenceableAttr(llcx: &Context, bytes: u64) -> &Attribute { +pub(crate) fn CreateDereferenceableAttr<'ll>(llcx: Context<'ll>, bytes: u64) -> &'ll Attribute { unsafe { LLVMRustCreateDereferenceableAttr(llcx, bytes) } } -pub(crate) fn CreateDereferenceableOrNullAttr(llcx: &Context, bytes: u64) -> &Attribute { +pub(crate) fn CreateDereferenceableOrNullAttr<'ll>( + llcx: Context<'ll>, + bytes: u64, +) -> &'ll Attribute { unsafe { LLVMRustCreateDereferenceableOrNullAttr(llcx, bytes) } } -pub(crate) fn CreateByValAttr<'ll>(llcx: &'ll Context, ty: &'ll Type) -> &'ll Attribute { +pub(crate) fn CreateByValAttr<'ll>(llcx: Context<'ll>, ty: &'ll Type) -> &'ll Attribute { unsafe { LLVMRustCreateByValAttr(llcx, ty) } } -pub(crate) fn CreateByRefAttr<'ll>(llcx: &'ll Context, ty: &'ll Type) -> &'ll Attribute { +pub(crate) fn CreateByRefAttr<'ll>(llcx: Context<'ll>, ty: &'ll Type) -> &'ll Attribute { unsafe { LLVMRustCreateByRefAttr(llcx, ty) } } -pub(crate) fn CreateStructRetAttr<'ll>(llcx: &'ll Context, ty: &'ll Type) -> &'ll Attribute { +pub(crate) fn CreateStructRetAttr<'ll>(llcx: Context<'ll>, ty: &'ll Type) -> &'ll Attribute { unsafe { LLVMRustCreateStructRetAttr(llcx, ty) } } -pub(crate) fn CreateUWTableAttr(llcx: &Context, async_: bool) -> &Attribute { +pub(crate) fn CreateUWTableAttr<'ll>(llcx: Context<'ll>, async_: bool) -> &'ll Attribute { unsafe { LLVMRustCreateUWTableAttr(llcx, async_) } } -pub(crate) fn CreateAllocSizeAttr(llcx: &Context, size_arg: u32) -> &Attribute { +pub(crate) fn CreateAllocSizeAttr<'ll>(llcx: Context<'ll>, size_arg: u32) -> &'ll Attribute { unsafe { LLVMRustCreateAllocSizeAttr(llcx, size_arg) } } -pub(crate) fn CreateAllocKindAttr(llcx: &Context, kind_arg: AllocKindFlags) -> &Attribute { +pub(crate) fn CreateAllocKindAttr<'ll>( + llcx: Context<'ll>, + kind_arg: AllocKindFlags, +) -> &'ll Attribute { unsafe { LLVMRustCreateAllocKindAttr(llcx, kind_arg.bits()) } } -pub(crate) fn CreateRangeAttr(llcx: &Context, size: Size, range: WrappingRange) -> &Attribute { +pub(crate) fn CreateRangeAttr<'ll>( + llcx: Context<'ll>, + size: Size, + range: WrappingRange, +) -> &'ll Attribute { let lower = range.start; // LLVM treats the upper bound as exclusive, but allows wrapping. let upper = range.end.wrapping_add(1); @@ -229,14 +239,14 @@ pub(crate) fn set_thread_local_mode(global: &Value, mode: ThreadLocalMode) { impl AttributeKind { /// Create an LLVM Attribute with no associated value. - pub(crate) fn create_attr(self, llcx: &Context) -> &Attribute { + pub(crate) fn create_attr<'ll>(self, llcx: Context<'ll>) -> &'ll Attribute { unsafe { LLVMRustCreateAttrNoValue(llcx, self) } } } impl MemoryEffects { /// Create an LLVM Attribute with these memory effects. - pub(crate) fn create_attr(self, llcx: &Context) -> &Attribute { + pub(crate) fn create_attr<'ll>(self, llcx: Context<'ll>) -> &'ll Attribute { unsafe { LLVMRustCreateMemoryEffectsAttr(llcx, self) } } } diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index ea91756b9068a..b67f6ca851177 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -444,19 +444,18 @@ fn update_target_reliable_float_cfg(target: &Target, cfg: &mut TargetConfig) { // `long double` is not IEEE binary128. See // . // - // This rules out anything that doesn't have `long double` = `binary128`; <= 32 bits - // (ld is `f64`), anything other than Linux (Windows and MacOS use `f64`), and `x86` - // (ld is 80-bit extended precision). - // + // This rules out anything that doesn't have `long double` = `binary128`: <= 32 bits + // (`long double` is `f64`) and anything other than Linux (Windows and MacOS use `f64`). + // x86-64 would also be a problem, except there's a special fix for linux-gnu. + // We have to reject musl anyway because it doesn't have the symbols for f128 math. + _ if target_pointer_width <= 32 => false, + _ if *target_os != Os::Linux => false, + _ if *target_env != Env::Gnu => false, // On big-endian powerpc the symbol selection is correct, despite __ibmf128 being // long double on the target, but the f128 symbols are not defined. - // - // musl does not implement the symbols required for f128 math at all. - _ if *target_env == Env::Musl => false, - (Arch::X86_64, _) => false, (Arch::PowerPC | Arch::PowerPC64, _) if *target_endian == Endian::Big => false, - (_, Os::Linux) if target_pointer_width == 64 => true, - _ => false, + // After applying all these exceptions, the rest should work. + _ => true, } && cfg.has_reliable_f128; } diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs index 4aa768019f696..2d64c63cf9ae4 100644 --- a/compiler/rustc_codegen_llvm/src/mono_item.rs +++ b/compiler/rustc_codegen_llvm/src/mono_item.rs @@ -131,7 +131,11 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { /// since for those we don't care about target architecture anyway. /// /// So, this function is for static aliases. See [`add_function_aliases`](Self::add_function_aliases) for the alternative. - fn add_static_aliases(&self, aliasee: &llvm::Value, aliases: &[(DefId, Linkage, Visibility)]) { + fn add_static_aliases( + &self, + aliasee: &'ll llvm::Value, + aliases: &[(DefId, Linkage, Visibility)], + ) { let ty = self.get_type_of_global(aliasee); for (alias, linkage, visibility) in aliases { diff --git a/compiler/rustc_codegen_llvm/src/type_.rs b/compiler/rustc_codegen_llvm/src/type_.rs index 31c43134dd3c1..2143f2b7aec37 100644 --- a/compiler/rustc_codegen_llvm/src/type_.rs +++ b/compiler/rustc_codegen_llvm/src/type_.rs @@ -149,7 +149,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { } impl<'ll, CX: Borrow>> GenericCx<'ll, CX> { - pub(crate) fn llcx(&self) -> &'ll llvm::Context { + pub(crate) fn llcx(&self) -> llvm::Context<'ll> { (**self).borrow().llcx } @@ -286,12 +286,12 @@ impl<'ll, CX: Borrow>> BaseTypeCodegenMethods for GenericCx<'ll, CX> { } } -pub(crate) fn llvm_type_ptr(llcx: &llvm::Context) -> &Type { +pub(crate) fn llvm_type_ptr<'ll>(llcx: llvm::Context<'ll>) -> &'ll Type { llvm_type_ptr_in_address_space(llcx, AddressSpace::ZERO) } pub(crate) fn llvm_type_ptr_in_address_space<'ll>( - llcx: &'ll llvm::Context, + llcx: llvm::Context<'ll>, addr_space: AddressSpace, ) -> &'ll Type { llvm::LLVMPointerTypeInContext(llcx, addr_space.0) diff --git a/compiler/rustc_codegen_llvm/src/typetree.rs b/compiler/rustc_codegen_llvm/src/typetree.rs index 9988ccfaee052..e781ffea99479 100644 --- a/compiler/rustc_codegen_llvm/src/typetree.rs +++ b/compiler/rustc_codegen_llvm/src/typetree.rs @@ -6,10 +6,10 @@ use crate::attributes; use crate::context::FullCx; use crate::llvm::{self, EnzymeWrapper, Value}; -fn to_enzyme_typetree( +fn to_enzyme_typetree<'ll>( rust_typetree: &RustTypeTree, _data_layout: &str, - llcx: &llvm::Context, + llcx: llvm::Context<'ll>, ) -> (llvm::TypeTree, Vec) { let mut enzyme_tt = llvm::TypeTree::new(); let extra_ints = process_typetree_recursive(&mut enzyme_tt, &rust_typetree, &[], llcx); @@ -24,11 +24,11 @@ fn to_enzyme_typetree( (enzyme_tt, int_vec) } -fn process_typetree_recursive( +fn process_typetree_recursive<'ll>( enzyme_tt: &mut llvm::TypeTree, rust_typetree: &RustTypeTree, parent_indices: &[i64], - llcx: &llvm::Context, + llcx: llvm::Context<'ll>, ) -> u32 { let mut extra_ints = 0; for rust_type in &rust_typetree.0 { diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index f30e3c235cbc1..0aa3e97568729 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -152,6 +152,7 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi | sym::ptr_guaranteed_cmp | sym::ptr_mask | sym::ptr_metadata + | sym::resumable_breakpoint | sym::return_address | sym::rotate_left | sym::rotate_right @@ -263,7 +264,7 @@ pub(crate) fn check_intrinsic_type( sym::abort_immediate => (0, 0, vec![], tcx.types.never), sym::amdgpu_dispatch_ptr => (0, 0, vec![], Ty::new_imm_ptr(tcx, tcx.types.unit)), sym::unreachable => (0, 0, vec![], tcx.types.never), - sym::breakpoint => (0, 0, vec![], tcx.types.unit), + sym::breakpoint | sym::resumable_breakpoint => (0, 0, vec![], tcx.types.unit), sym::codeview_annotation => (1, 0, vec![], tcx.types.unit), sym::size_of | sym::align_of | sym::variant_count => (1, 0, vec![], tcx.types.usize), sym::size_of_val | sym::align_of_val => { diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index 043b7ad59d0a8..0aa57e75889fa 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -143,6 +143,9 @@ pub enum TokenKind { /// A lifetime, e.g. `'a`. Lifetime { + // FIXME: this should be renamed to `invalid` as it also signals when + // there are emoji in the lifetime name, but avoid changing the name so + // we don't introduce incompatibilities with rust-analyzer. starts_with_number: bool, }, @@ -591,7 +594,7 @@ impl<'a> Cursor<'a> { let kind = RawStr { n_hashes: res.ok() }; Literal { kind, suffix_start } } - _ => self.ident_or_unknown_prefix(), + _ => self.ident_or_unknown_prefix(false), }, // Forced keyword identifier or identifier. @@ -601,7 +604,7 @@ impl<'a> Cursor<'a> { self.eat_identifier(); ForcedKeywordIdent } - _ => self.ident_or_unknown_prefix(), + _ => self.ident_or_unknown_prefix(false), }, // Byte literal, byte string literal, raw byte string literal or identifier. @@ -620,7 +623,7 @@ impl<'a> Cursor<'a> { // Identifier (this should be checked after other variant that can // start as identifier). - c if is_id_start(c) => self.ident_or_unknown_prefix(), + c if is_id_start(c) => self.ident_or_unknown_prefix(false), // Numeric literal. c @ '0'..='9' => { @@ -678,7 +681,7 @@ impl<'a> Cursor<'a> { Literal { kind, suffix_start } } // Identifier starting with an emoji. Only lexed for graceful error recovery. - c if !c.is_ascii() && c.is_emoji_char() => self.invalid_ident(), + c if is_emoji(c) => self.invalid_ident(), _ => Unknown, }; if matches!(self.frontmatter_allowed, FrontmatterAllowed::Yes) @@ -840,25 +843,22 @@ impl<'a> Cursor<'a> { Whitespace } - fn ident_or_unknown_prefix(&mut self) -> TokenKind { - debug_assert!(is_id_start(self.prev())); + fn ident_or_unknown_prefix(&mut self, already_invalid: bool) -> TokenKind { + debug_assert!(is_id_start(self.prev()) || already_invalid); // Start is already eaten, eat the rest of identifier. self.eat_while(is_id_continue); // Known prefixes must have been handled earlier. So if // we see a prefix here, it is definitely an unknown prefix. match self.first() { '#' | '"' | '\'' => UnknownPrefix, - c if !c.is_ascii() && c.is_emoji_char() => self.invalid_ident(), + c if is_emoji(c) => self.invalid_ident(), _ => Ident, } } fn invalid_ident(&mut self) -> TokenKind { // Start is already eaten, eat the rest of identifier. - self.eat_while(|c| { - const ZERO_WIDTH_JOINER: char = '\u{200d}'; - is_id_continue(c) || (!c.is_ascii() && c.is_emoji_char()) || c == ZERO_WIDTH_JOINER - }); + self.eat_while(|c| is_id_continue(c) || is_emoji(c)); // An invalid identifier followed by '#' or '"' or '\'' could be // interpreted as an invalid literal prefix. We don't bother doing that // because the treatment of invalid identifiers and invalid prefixes @@ -903,7 +903,7 @@ impl<'a> Cursor<'a> { let kind = mk_kind_raw(res.ok()); Literal { kind, suffix_start } } - _ => self.ident_or_unknown_prefix(), + _ => self.ident_or_unknown_prefix(false), } } @@ -983,6 +983,7 @@ impl<'a> Cursor<'a> { fn lifetime_or_char(&mut self) -> TokenKind { debug_assert!(self.prev() == '\''); + let mut invalid = false; let can_be_a_lifetime = if self.second() == '\'' { // It's surely not a lifetime. false @@ -990,7 +991,10 @@ impl<'a> Cursor<'a> { // 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_ascii_digit() + let c = self.first(); + invalid |= c.is_ascii_digit(); + invalid |= is_emoji(c); + is_id_start(c) || invalid }; if !can_be_a_lifetime { @@ -1020,7 +1024,7 @@ impl<'a> Cursor<'a> { // 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); + invalid |= matches!(self.ident_or_unknown_prefix(invalid), InvalidIdent); match self.first() { // Check if after skipping literal contents we've met a closing @@ -1032,7 +1036,7 @@ impl<'a> Cursor<'a> { Literal { kind, suffix_start: self.pos_within_token() } } '#' if !starts_with_number => UnknownPrefixLifetime, - _ => Lifetime { starts_with_number }, + _ => Lifetime { starts_with_number: invalid }, } } @@ -1285,3 +1289,7 @@ impl<'a> Cursor<'a> { self.eat_while(is_id_continue); } } + +fn is_emoji(c: char) -> bool { + !c.is_ascii() && c.is_emoji_char() +} diff --git a/compiler/rustc_parse/Cargo.toml b/compiler/rustc_parse/Cargo.toml index 9650742628f73..b54438384a215 100644 --- a/compiler/rustc_parse/Cargo.toml +++ b/compiler/rustc_parse/Cargo.toml @@ -21,6 +21,7 @@ rustc_span = { path = "../rustc_span" } thin-vec = "0.2.21" tracing = "0.1" unicode-normalization = "0.1.25" +unicode-properties = { version = "0.1.4", default-features = false, features = ["emoji"] } unicode-width = "0.2.2" # tidy-alphabetical-end diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 03d5634fc359c..13bda08fe8096 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -17,6 +17,7 @@ use rustc_session::parse::ParseSess; use rustc_span::edition::Edition; use rustc_span::{BytePos, Pos, Span, Symbol, sym}; use tracing::debug; +use unicode_properties::emoji::UnicodeEmoji; use crate::lexer::diagnostics::TokenTreeDiagInfo; use crate::lexer::unicode_chars::UNICODE_ARRAY; @@ -357,12 +358,36 @@ impl<'psess, 'src> Lexer<'psess, 'src> { // this is necessary. let lifetime_name = nfc_normalize(self.str_from(start)); self.last_lifetime = Some(self.mk_sp(start, start + BytePos(1))); + let span = self.mk_sp(start, self.pos); if starts_with_number { - let span = self.mk_sp(start, self.pos); - self.dcx() - .struct_err("lifetimes cannot start with a number") - .with_span(span) - .stash(span, StashKey::LifetimeIsChar); + let name = lifetime_name.as_str(); + // skip(1) to skip the `'` + let starts_with_number = matches!( + name.chars().skip(1).next(), + Some(c) if c.is_ascii_digit() + ); + if name.chars().any(|c| !c.is_ascii() && c.is_emoji_char()) { + self.psess + .bad_unicode_identifiers + .borrow_mut() + .entry(lifetime_name) + .or_default() + .push(span); + } + if starts_with_number { + let mut err = self.dcx() + .struct_err(format!( + "lifetimes cannot start with a number: `{name}`" + )) + .with_span(span); + if name.len() > 2 { + // Point at the first lifetime name character. + let start_span = self.mk_sp(start + BytePos(1), start + BytePos(2)); + err.span(start_span); + err.span_label(span, ""); + } + err.stash(span, StashKey::LifetimeIsChar); + } } token::Lifetime(lifetime_name, IdentKind::Normal) } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 95197e6c98a9f..c3e275971056d 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1754,6 +1754,7 @@ symbols! { residual, result, result_ffi_guarantees, + resumable_breakpoint, return_address, return_position_impl_trait_in_trait, return_type_notation, diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index d12543e6b35e2..64cf978a4b0e4 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -566,11 +566,19 @@ pub const fn prefetch_write_instruction(data: *const T) /// Executes a breakpoint trap, for inspection by a debugger. /// -/// This intrinsic does not have a stable counterpart. +/// The public version of this intrinsic is [`core::arch::breakpoint`]. #[rustc_intrinsic] #[rustc_nounwind] pub fn breakpoint(); +/// Executes a breakpoint trap, for inspection by a debugger. This is allowed to resume. +/// +/// The public version of this intrinsic is [`core::process::resumable_breakpoint`]. +#[rustc_intrinsic] +#[rustc_nounwind] +#[miri::intrinsic_fallback_is_spec] +pub const fn resumable_breakpoint() {} + /// A container for the string arguments passed to [`codeview_annotation`]. #[unstable(feature = "codeview_annotation", issue = "163964")] pub trait CodeViewAnnotationArgs { diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index d0cc0e3b31da7..99498252a127f 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -1231,6 +1231,66 @@ macro_rules! nonzero_integer { } } + /// Multiplies two non-zero integers together, panicking if + /// overflow occurs. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function always panics on overflow, regardless of whether + /// overflow checks are enabled. + /// + /// # Examples + /// + /// ``` + /// #![feature(nonzero_strict_ops)] + /// + /// # use std::num::NonZero; + /// # + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let three = NonZero::new(3", stringify!($Int), ")?;")] + #[doc = concat!("let nine = NonZero::new(9", stringify!($Int), ")?;")] + /// + /// assert_eq!(nine, three.strict_mul(three)); + /// # Some(()) + /// # } + /// ``` + /// + /// The following panics because of overflow: + /// + /// ```should_panic + /// #![feature(nonzero_strict_ops)] + /// + /// # use std::num::NonZero; + /// # + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let two = NonZero::new(2", stringify!($Int), ")?;")] + #[doc = concat!("let max = NonZero::new(", stringify!($Int), "::MAX)?;")] + /// + /// let _ = max.strict_mul(two); + /// # Some(()) + /// # } + /// ``` + #[unstable(feature = "nonzero_strict_ops", issue = "164850")] + #[rustc_const_unstable(feature = "const_nonzero_strict_ops", issue = "164850")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn strict_mul(self, other: Self) -> Self { + // SAFETY: + // - `$Int::strict_mul` panics on overflow; + // - `self` and `other` are nonzero; + // - the only way to get zero from a multiplication without + // overflow is for either operand to be zero. + // + // So the result cannot be zero. + unsafe { Self::new_unchecked(self.get().strict_mul(other.get())) } + } + /// Multiplies two non-zero integers together. #[doc = concat!("Return [`NonZero::<", stringify!($Int), ">::MAX`] on overflow.")] /// @@ -1344,6 +1404,65 @@ macro_rules! nonzero_integer { } } + /// Raises a non-zero value to an integer power, panicking if + /// overflow occurs. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function always panics on overflow, regardless of whether + /// overflow checks are enabled. + /// + /// # Examples + /// + /// ``` + /// #![feature(nonzero_strict_ops)] + /// + /// # use std::num::NonZero; + /// # + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let two = NonZero::new(2", stringify!($Int), ")?;")] + #[doc = concat!("let sixteen = NonZero::new(16", stringify!($Int), ")?;")] + /// + /// assert_eq!(sixteen, two.strict_pow(4)); + /// # Some(()) + /// # } + /// ``` + /// + /// The following panics because of overflow: + /// + /// ```should_panic + /// #![feature(nonzero_strict_ops)] + /// + /// # use std::num::NonZero; + /// # + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let half_max = NonZero::new(", stringify!($Int), "::MAX / 2)?;")] + /// + /// let _ = half_max.strict_pow(2); + /// # Some(()) + /// # } + /// ``` + #[unstable(feature = "nonzero_strict_ops", issue = "164850")] + #[rustc_const_unstable(feature = "const_nonzero_strict_ops", issue = "164850")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn strict_pow(self, exp: u32) -> Self { + // SAFETY: + // - `$Int::strict_pow` panics on overflow; + // - `self` is nonzero; + // - the only way to get zero from an exponentiation without + // overflow is for the base to be zero. + // + // So the result cannot be zero. + unsafe { Self::new_unchecked(self.get().strict_pow(exp)) } + } + /// Raise non-zero value to an integer power. #[doc = sign_dependent_expr!{ $signedness ? @@ -1824,6 +1943,65 @@ macro_rules! nonzero_integer_signedness_dependent_methods { } } + /// Adds an unsigned integer to a non-zero value, panicking + /// if overflow occurs. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function always panics on overflow, regardless of whether + /// overflow checks are enabled. + /// + /// # Examples + /// + /// ``` + /// #![feature(nonzero_strict_ops)] + /// + /// # use std::num::NonZero; + /// # + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let two = NonZero::new(2", stringify!($Int), ")?;")] + #[doc = concat!("let three = NonZero::new(3", stringify!($Int), ")?;")] + /// + /// assert_eq!(three, two.strict_add(1)); + /// # Some(()) + /// # } + /// ``` + /// + /// The following panics because of overflow: + /// + /// ```should_panic + /// #![feature(nonzero_strict_ops)] + /// + /// # use std::num::NonZero; + /// # + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let max = NonZero::new(", stringify!($Int), "::MAX)?;")] + /// + /// let _ = max.strict_add(1); + /// # Some(()) + /// # } + /// ``` + #[unstable(feature = "nonzero_strict_ops", issue = "164850")] + #[rustc_const_unstable(feature = "const_nonzero_strict_ops", issue = "164850")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn strict_add(self, other: $Int) -> Self { + // SAFETY: + // - `$Int::strict_add` panics on overflow; + // - `self` is nonzero; + // - the only way to get zero from an unsigned addition without + // overflow is for both addends to be zero. + // + // So the result cannot be zero. + unsafe { Self::new_unchecked(self.get().strict_add(other)) } + } + /// Adds an unsigned integer to a non-zero value. #[doc = concat!("Return [`NonZero::<", stringify!($Int), ">::MAX`] on overflow.")] /// @@ -2493,6 +2671,64 @@ macro_rules! nonzero_integer_signedness_dependent_methods { None } + /// Checked negation. Computes `-self`, panicking if `self == MIN`. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function always panics on overflow, regardless of whether + /// overflow checks are enabled. + /// + /// # Examples + /// + /// ``` + /// #![feature(nonzero_strict_ops)] + /// + /// # use std::num::NonZero; + /// # + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos_six = NonZero::new(6", stringify!($Int), ")?;")] + #[doc = concat!("let neg_six = NonZero::new(-6", stringify!($Int), ")?;")] + /// + /// assert_eq!(pos_six.strict_neg(), neg_six); + /// # Some(()) + /// # } + /// ``` + /// + /// The following panics because of overflow: + /// + /// ```should_panic + /// #![feature(nonzero_strict_ops)] + /// + /// # use std::num::NonZero; + /// # + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let min = NonZero::new(", stringify!($Int), "::MIN)?;")] + /// + /// let _ = min.strict_neg(); + /// # Some(()) + /// # } + /// ``` + #[unstable(feature = "nonzero_strict_ops", issue = "164850")] + #[rustc_const_unstable(feature = "const_nonzero_strict_ops", issue = "164850")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn strict_neg(self) -> Self { + // SAFETY: + // - `$Int::strict_neg` panics on overflow; + // - `self` is nonzero; + // - the only way to get zero from a negation without overflow + // is for the input to be zero. + // + // So the result cannot be zero. + unsafe { Self::new_unchecked(self.get().strict_neg()) } + } + /// Negates self, overflowing if this is equal to the minimum value. /// #[doc = concat!("See [`", stringify!($Int), "::overflowing_neg`]")] diff --git a/library/core/src/process.rs b/library/core/src/process.rs index d03e7cba04bef..12b2fdb46085d 100644 --- a/library/core/src/process.rs +++ b/library/core/src/process.rs @@ -99,6 +99,6 @@ pub const fn abort_immediate() -> ! { // actually want to stabilize both of them. #[unstable(feature = "breakpoint", issue = "133724")] #[inline(always)] -pub fn resumable_breakpoint() { - crate::intrinsics::breakpoint(); +pub const fn resumable_breakpoint() { + crate::intrinsics::resumable_breakpoint(); } diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs index bd53680408882..087b6bb2bc363 100644 --- a/library/coretests/tests/lib.rs +++ b/library/coretests/tests/lib.rs @@ -1,6 +1,7 @@ // tidy-alphabetical-start #![cfg_attr(not(panic = "abort"), feature(reentrant_lock))] #![cfg_attr(target_has_atomic = "128", feature(integer_atomics))] +#![feature(abort_immediate)] #![feature(array_ptr_get)] #![feature(array_try_from_fn)] #![feature(array_try_map)] @@ -10,6 +11,7 @@ #![feature(async_iterator)] #![feature(atomic_volatile)] #![feature(borrowed_buf_init)] +#![feature(breakpoint)] #![feature(byte_str)] #![feature(casefold)] #![feature(cfg_overflow_checks)] @@ -35,6 +37,7 @@ #![feature(const_eval_select)] #![feature(const_index)] #![feature(const_iter)] +#![feature(const_nonzero_strict_ops)] #![feature(const_ops)] #![feature(const_option_ops)] #![feature(const_ref_cell)] @@ -92,6 +95,7 @@ #![feature(min_specialization)] #![feature(next_index)] #![feature(non_exhaustive_omitted_patterns_lint)] +#![feature(nonzero_strict_ops)] #![feature(num_internals)] #![feature(numfmt)] #![feature(one_sided_range)] @@ -200,7 +204,6 @@ mod macros; mod manually_drop; mod mem; mod net; -mod nonzero; mod num; mod ops; mod option; @@ -208,6 +211,7 @@ mod panic; mod pattern; mod pin; mod pin_macro; +mod process; mod ptr; mod result; mod simd; diff --git a/library/coretests/tests/num/mod.rs b/library/coretests/tests/num/mod.rs index 46e5ee0213b04..919946fe4abcc 100644 --- a/library/coretests/tests/num/mod.rs +++ b/library/coretests/tests/num/mod.rs @@ -38,6 +38,7 @@ mod int_sqrt; mod midpoint; mod nan; mod niche_types; +mod nonzero; mod ops; mod wrapping; diff --git a/library/coretests/tests/nonzero.rs b/library/coretests/tests/num/nonzero.rs similarity index 99% rename from library/coretests/tests/nonzero.rs rename to library/coretests/tests/num/nonzero.rs index 37041e22d0dfd..388346fc8aca0 100644 --- a/library/coretests/tests/nonzero.rs +++ b/library/coretests/tests/num/nonzero.rs @@ -1,3 +1,6 @@ +mod int; +mod uint; + use core::num::{IntErrorKind, NonZero}; use core::option::Option::None; diff --git a/library/coretests/tests/num/nonzero/int.rs b/library/coretests/tests/num/nonzero/int.rs new file mode 100644 index 0000000000000..b46bfd3d585e6 --- /dev/null +++ b/library/coretests/tests/num/nonzero/int.rs @@ -0,0 +1,137 @@ +macro_rules! nonzero_int_module { + ($T:ident) => { + use core::num::NonZero; + const MIN: NonZero<$T> = NonZero::<$T>::MIN; + const MAX: NonZero<$T> = NonZero::<$T>::MAX; + + const fn nz(n: $T) -> NonZero<$T> { + NonZero::new(n).unwrap() + } + + test_runtime_and_compiletime! { + fn test_strict_neg() { + assert_eq_const_safe!(NonZero<$T>: nz(1).strict_neg(), nz(-1)); + assert_eq_const_safe!(NonZero<$T>: nz(-1).strict_neg(), nz(1)); + assert_eq_const_safe!(NonZero<$T>: nz(123).strict_neg(), nz(-123)); + assert_eq_const_safe!(NonZero<$T>: nz(-123).strict_neg(), nz(123)); + assert_eq_const_safe!(NonZero<$T>: nz($T::MAX - 2).strict_neg(), nz($T::MIN + 3)); + assert_eq_const_safe!(NonZero<$T>: nz($T::MAX - 1).strict_neg(), nz($T::MIN + 2)); + assert_eq_const_safe!(NonZero<$T>: MAX.strict_neg(), nz($T::MIN + 1)); + assert_eq_const_safe!(NonZero<$T>: nz($T::MIN + 2).strict_neg(), nz($T::MAX - 1)); + assert_eq_const_safe!(NonZero<$T>: nz($T::MIN + 1).strict_neg(), MAX); + } + + fn test_strict_mul() { + assert_eq_const_safe!(NonZero<$T>: nz(1).strict_mul(nz(1)), nz(1)); + assert_eq_const_safe!(NonZero<$T>: nz(-1).strict_mul(nz(1)), nz(-1)); + assert_eq_const_safe!(NonZero<$T>: nz(63).strict_mul(nz(-2)), nz(-126)); + assert_eq_const_safe!(NonZero<$T>: nz(-63).strict_mul(nz(-2)), nz(126)); + assert_eq_const_safe!(NonZero<$T>: MAX.strict_mul(nz(1)), MAX); + assert_eq_const_safe!(NonZero<$T>: nz(1).strict_mul(MAX), MAX); + assert_eq_const_safe!(NonZero<$T>: MIN.strict_mul(nz(1)), MIN); + assert_eq_const_safe!(NonZero<$T>: nz(1).strict_mul(MIN), MIN); + assert_eq_const_safe!(NonZero<$T>: MAX.strict_mul(nz(-1)), nz($T::MIN + 1)); + assert_eq_const_safe!(NonZero<$T>: nz(-1).strict_mul(MAX), nz($T::MIN + 1)); + assert_eq_const_safe!(NonZero<$T>: nz($T::MIN / 2).strict_mul(nz(2)), MIN); + assert_eq_const_safe!(NonZero<$T>: nz(2).strict_mul(nz($T::MIN / 2)), MIN); + assert_eq_const_safe!(NonZero<$T>: nz($T::MAX / 2).strict_mul(nz(2)), nz($T::MAX - 1)); + assert_eq_const_safe!(NonZero<$T>: nz(2).strict_mul(nz($T::MAX / 2)), nz($T::MAX - 1)); + } + + fn test_strict_pow() { + assert_eq_const_safe!(NonZero<$T>: nz(1).strict_pow(0), nz(1)); + assert_eq_const_safe!(NonZero<$T>: nz(1).strict_pow(1), nz(1)); + assert_eq_const_safe!(NonZero<$T>: nz(-1).strict_pow(0), nz(1)); + assert_eq_const_safe!(NonZero<$T>: nz(-1).strict_pow(1), nz(-1)); + assert_eq_const_safe!(NonZero<$T>: nz(3).strict_pow(0), nz(1)); + assert_eq_const_safe!(NonZero<$T>: nz(3).strict_pow(1), nz(3)); + assert_eq_const_safe!(NonZero<$T>: nz(3).strict_pow(2), nz(9)); + assert_eq_const_safe!(NonZero<$T>: nz(-3).strict_pow(0), nz(1)); + assert_eq_const_safe!(NonZero<$T>: nz(-3).strict_pow(1), nz(-3)); + assert_eq_const_safe!(NonZero<$T>: nz(-3).strict_pow(2), nz(9)); + assert_eq_const_safe!(NonZero<$T>: MAX.strict_pow(0), nz(1)); + assert_eq_const_safe!(NonZero<$T>: MAX.strict_pow(1), MAX); + assert_eq_const_safe!(NonZero<$T>: MIN.strict_pow(0), nz(1)); + assert_eq_const_safe!(NonZero<$T>: MIN.strict_pow(1), MIN); + } + } + + #[test] + #[should_panic = "attempt to negate with overflow"] + fn test_strict_neg_overflow() { + let _ = MIN.strict_neg(); + } + + #[test] + #[should_panic = "attempt to multiply with overflow"] + fn test_strict_mul_overflow_neg_min() { + let _ = MIN.strict_mul(nz(-1)); + } + + #[test] + #[should_panic = "attempt to multiply with overflow"] + fn test_strict_mul_overflow_neg_min_reverse() { + let _ = nz(-1).strict_mul(MIN); + } + + #[test] + #[should_panic = "attempt to multiply with overflow"] + fn test_strict_mul_overflow_limit() { + let _ = nz($T::MAX / 2 + 1).strict_mul(nz(2)); + } + + #[test] + #[should_panic = "attempt to multiply with overflow"] + fn test_strict_mul_overflow_large() { + let _ = MAX.strict_mul(nz(2)); + } + + #[test] + #[should_panic = "attempt to multiply with overflow"] + fn test_strict_mul_overflow_neg_large() { + let _ = MIN.strict_mul(nz(2)); + } + + #[test] + #[should_panic = "attempt to exponentiate with overflow"] + fn test_strict_pow_overflow_big_base() { + let _ = MAX.strict_pow(2); + } + + #[test] + #[should_panic = "attempt to exponentiate with overflow"] + fn test_strict_pow_overflow_big_exp() { + let _ = nz(2).strict_pow(256); + } + + #[test] + #[should_panic = "attempt to exponentiate with overflow"] + fn test_strict_pow_overflow_neg_base() { + let _ = MIN.strict_pow(2); + } + }; +} + +mod i8 { + nonzero_int_module!(i8); +} + +mod i16 { + nonzero_int_module!(i16); +} + +mod i32 { + nonzero_int_module!(i32); +} + +mod i64 { + nonzero_int_module!(i64); +} + +mod i128 { + nonzero_int_module!(i128); +} + +mod isize { + nonzero_int_module!(isize); +} diff --git a/library/coretests/tests/num/nonzero/uint.rs b/library/coretests/tests/num/nonzero/uint.rs new file mode 100644 index 0000000000000..f1b47927ec00e --- /dev/null +++ b/library/coretests/tests/num/nonzero/uint.rs @@ -0,0 +1,101 @@ +macro_rules! nonzero_uint_module { + ($T:ident) => { + use core::num::NonZero; + const MAX: NonZero<$T> = NonZero::<$T>::MAX; + + const fn nz(n: $T) -> NonZero<$T> { + NonZero::new(n).unwrap() + } + + test_runtime_and_compiletime! { + fn test_strict_add() { + assert_eq_const_safe!(NonZero<$T>: nz(1).strict_add(0), nz(1)); + assert_eq_const_safe!(NonZero<$T>: nz(1).strict_add(1), nz(2)); + assert_eq_const_safe!(NonZero<$T>: nz(57).strict_add(173), nz(230)); + assert_eq_const_safe!(NonZero<$T>: nz($T::MAX - 1).strict_add(1), MAX); + assert_eq_const_safe!(NonZero<$T>: nz(1).strict_add($T::MAX - 1), MAX); + assert_eq_const_safe!(NonZero<$T>: MAX.strict_add(0), MAX); + } + + fn test_strict_mul() { + assert_eq_const_safe!(NonZero<$T>: nz(1).strict_mul(nz(1)), nz(1)); + assert_eq_const_safe!(NonZero<$T>: MAX.strict_mul(nz(1)), MAX); + assert_eq_const_safe!(NonZero<$T>: nz(1).strict_mul(MAX), MAX); + assert_eq_const_safe!(NonZero<$T>: nz(123).strict_mul(nz(2)), nz(246)); + assert_eq_const_safe!(NonZero<$T>: nz(2).strict_mul(nz(123)), nz(246)); + assert_eq_const_safe!(NonZero<$T>: nz($T::MAX / 2).strict_mul(nz(2)), nz($T::MAX - 1)); + assert_eq_const_safe!(NonZero<$T>: nz(2).strict_mul(nz($T::MAX / 2)), nz($T::MAX - 1)); + } + + fn test_strict_pow() { + assert_eq_const_safe!(NonZero<$T>: nz(1).strict_pow(0), nz(1)); + assert_eq_const_safe!(NonZero<$T>: nz(1).strict_pow(1), nz(1)); + assert_eq_const_safe!(NonZero<$T>: nz(3).strict_pow(0), nz(1)); + assert_eq_const_safe!(NonZero<$T>: nz(3).strict_pow(1), nz(3)); + assert_eq_const_safe!(NonZero<$T>: nz(3).strict_pow(2), nz(9)); + assert_eq_const_safe!(NonZero<$T>: MAX.strict_pow(0), nz(1)); + assert_eq_const_safe!(NonZero<$T>: MAX.strict_pow(1), MAX); + } + } + + #[test] + #[should_panic = "attempt to add with overflow"] + fn test_strict_add_overflow_big_small() { + let _ = MAX.strict_add(1); + } + + #[test] + #[should_panic = "attempt to add with overflow"] + fn test_strict_add_overflow_small_big() { + let _ = nz(1).strict_add($T::MAX); + } + + #[test] + #[should_panic = "attempt to multiply with overflow"] + fn test_strict_mul_overflow_limit() { + let _ = nz($T::MAX / 2 + 1).strict_mul(nz(2)); + } + + #[test] + #[should_panic = "attempt to multiply with overflow"] + fn test_strict_mul_overflow_large() { + let _ = MAX.strict_mul(nz(2)); + } + + #[test] + #[should_panic = "attempt to exponentiate with overflow"] + fn test_strict_pow_overflow_big_base() { + let _ = MAX.strict_pow(2); + } + + #[test] + #[should_panic = "attempt to exponentiate with overflow"] + fn test_strict_pow_overflow_big_exp() { + let _ = nz(2).strict_pow(256); + } + }; +} + +mod u8 { + nonzero_uint_module!(u8); +} + +mod u16 { + nonzero_uint_module!(u16); +} + +mod u32 { + nonzero_uint_module!(u32); +} + +mod u64 { + nonzero_uint_module!(u64); +} + +mod u128 { + nonzero_uint_module!(u128); +} + +mod usize { + nonzero_uint_module!(usize); +} diff --git a/library/coretests/tests/process.rs b/library/coretests/tests/process.rs new file mode 100644 index 0000000000000..86cb594f0c62b --- /dev/null +++ b/library/coretests/tests/process.rs @@ -0,0 +1,12 @@ +use core::process; + +#[test] +fn const_breakpoint() { + // Ensure this continues in CTFE + const { process::resumable_breakpoint() }; + + // Miri should also continue, while native runtime will likely abort + if cfg!(miri) { + process::resumable_breakpoint(); + } +} diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index f839bdc870913..51767988ba313 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -2989,7 +2989,8 @@ impl<'a, K: 'a, V: 'a, A: Allocator> VacantEntry<'a, K, V, A> { /// let mut map: HashMap<&str, u32> = HashMap::new(); /// /// if let Entry::Vacant(o) = map.entry("poneyland") { - /// o.insert_entry(37); + /// let entry = o.insert_entry(37); + /// assert_eq!(entry.get(), &37); /// } /// assert_eq!(map["poneyland"], 37); /// ``` diff --git a/library/std/src/os/fd/owned.rs b/library/std/src/os/fd/owned.rs index dd6336748db2c..b292c720a11cd 100644 --- a/library/std/src/os/fd/owned.rs +++ b/library/std/src/os/fd/owned.rs @@ -94,11 +94,7 @@ impl BorrowedFd<'_> { /// Converts a `BorrowedFd` into a reference to a file-like type. /// #[cfg_attr(all(unix, not(miri)), doc = "```")] - #[cfg_attr( - // FIXME: https://github.com/rust-lang/miri/issues/5453 - any(not(unix), miri), - doc = "```ignore (needs unix; miri doesn't support metadata on stdio)" - )] + #[cfg_attr(not(unix), doc = "```ignore (needs unix)")] /// # #![feature(fd_view)] /// # use std::fs::File; /// # use std::io; diff --git a/library/std/src/process.rs b/library/std/src/process.rs index feed6e1ad55a0..7afda60d019ec 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -2642,6 +2642,9 @@ pub fn abort() -> ! { #[doc(inline)] #[unstable(feature = "abort_immediate", issue = "154601")] pub use core::process::abort_immediate; +#[doc(inline)] +#[unstable(feature = "breakpoint", issue = "133724")] +pub use core::process::resumable_breakpoint; /// Returns the OS-assigned process identifier associated with this process. /// diff --git a/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs b/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs index f449809911c90..9b9437740923c 100644 --- a/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs +++ b/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs @@ -267,7 +267,7 @@ impl<'a> Converter<'a> { rustc_lexer::TokenKind::Lifetime { starts_with_number } => { if *starts_with_number { - errors.push("Lifetime name cannot start with a number".into()); + errors.push("Lifetime name contains invalid characters".into()); } LIFETIME_IDENT } diff --git a/src/tools/rust-analyzer/crates/parser/test_data/lexer/err/lifetime_starts_with_a_number.rast b/src/tools/rust-analyzer/crates/parser/test_data/lexer/err/lifetime_starts_with_a_number.rast index e919bf2a4aef2..b2bf087e749f3 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/lexer/err/lifetime_starts_with_a_number.rast +++ b/src/tools/rust-analyzer/crates/parser/test_data/lexer/err/lifetime_starts_with_a_number.rast @@ -1,4 +1,4 @@ -LIFETIME_IDENT "'1" error: Lifetime name cannot start with a number +LIFETIME_IDENT "'1" error: Lifetime name contains invalid characters WHITESPACE "\n" -LIFETIME_IDENT "'1lifetime" error: Lifetime name cannot start with a number +LIFETIME_IDENT "'1lifetime" error: Lifetime name contains invalid characters WHITESPACE "\n" diff --git a/src/tools/rust-analyzer/crates/parser/test_data/lexer/err/lifetime_starts_with_a_number.txt b/src/tools/rust-analyzer/crates/parser/test_data/lexer/err/lifetime_starts_with_a_number.txt index e919bf2a4aef2..b2bf087e749f3 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/lexer/err/lifetime_starts_with_a_number.txt +++ b/src/tools/rust-analyzer/crates/parser/test_data/lexer/err/lifetime_starts_with_a_number.txt @@ -1,4 +1,4 @@ -LIFETIME_IDENT "'1" error: Lifetime name cannot start with a number +LIFETIME_IDENT "'1" error: Lifetime name contains invalid characters WHITESPACE "\n" -LIFETIME_IDENT "'1lifetime" error: Lifetime name cannot start with a number +LIFETIME_IDENT "'1lifetime" error: Lifetime name contains invalid characters WHITESPACE "\n" diff --git a/src/tools/rust-analyzer/crates/parser/test_data/lexer/err/unclosed_char_with_ferris.rast b/src/tools/rust-analyzer/crates/parser/test_data/lexer/err/unclosed_char_with_ferris.rast index 56f19cce0784e..6ace31f434ef2 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/lexer/err/unclosed_char_with_ferris.rast +++ b/src/tools/rust-analyzer/crates/parser/test_data/lexer/err/unclosed_char_with_ferris.rast @@ -1 +1 @@ -CHAR "'๐Ÿฆ€" error: Missing trailing `'` symbol to terminate the character literal +LIFETIME_IDENT "'๐Ÿฆ€" error: Lifetime name contains invalid characters diff --git a/tests/ui/borrowck/alias-liveness/alias-static-interface-lifetime-151861.rs b/tests/ui/borrowck/alias-liveness/alias-static-interface-lifetime-151861.rs new file mode 100644 index 0000000000000..b1e9a06ea395a --- /dev/null +++ b/tests/ui/borrowck/alias-liveness/alias-static-interface-lifetime-151861.rs @@ -0,0 +1,110 @@ +//@ check-pass +//@ known-bug: #151861 + +// This test exhibits UB by creating a dangling reference from a type where the +// lifetime on a trait bound isn't live. This happens because we don't currently +// consider lifetimes in trait bounds on aliases to be live. +// +// Ultimately, the *mechanism* of creating this dangling reference is likely +// unsound, but is only exposed because of the alias-liveness change in 1.75.0. + +trait Produce<'r> { + fn produce(self) -> &'r str; +} + +mod hidden { + pub struct Wrapper(pub std::ptr::NonNull); + + impl<'r> super::Produce<'r> for Wrapper { + fn produce(self) -> &'r str { + unsafe { + // This is almost certainly unsound: `Wrapper` is only ever + // built from a `&'r str` by the `construct` methods below, but + // this impl holds at every `'r`. + // This impl could be easily be called like: + // let d: &'static str = { + // let s = String::from(".."); + // Produce::<'static>::produce(hidden::Wrapper(NonNull::from(&*s))) + // }; + self.0.as_ref() + } + } + } +} + +/// The `'static` bound is left to the user to state as a where-clause. +trait Gat { + type Ty<'r>: Produce<'r>; + fn construct<'r>(r: &'r str) -> Self::Ty<'r>; +} + +/// The `'static` bound is an item bound on the associated type. +trait ItemBound<'r> { + type Ty: 'static + Produce<'r>; + fn construct(r: &'r str) -> Self::Ty; +} + +struct Def; + +impl Gat for Def { + type Ty<'r> = hidden::Wrapper; + fn construct<'r>(r: &'r str) -> Self::Ty<'r> { + hidden::Wrapper(r.into()) + } +} + +impl<'r> ItemBound<'r> for Def { + type Ty = hidden::Wrapper; + fn construct(r: &'r str) -> Self::Ty { + hidden::Wrapper(r.into()) + } +} + +// A generic is used in both cases so that `G::Ty` cannot be normalized. +fn item_bound ItemBound<'r>>() { + let a; + { + let s = String::from("huh"); + a = ::construct(&s); + } + let _unrelated = String::from("UB!"); + let dangling: &str = a.produce(); + println!("{dangling}"); +} + +fn where_clause() +where + for<'r> G::Ty<'r>: 'static, +{ + let a; + { + let s = String::from("huh"); + a = G::construct(&s); + } + let _unrelated = String::from("UB!"); + let dangling: &str = a.produce(); + println!("{dangling}"); +} + +/// The `'static` bound is on an opaque type rather than an associated type: a method returning +/// `impl Produce<'r> + 'static`. +fn rpit_produce<'r>(r: &'r str) -> impl 'static + Produce<'r> { + hidden::Wrapper(r.into()) +} + +fn rpit() { + let a; + { + let s = String::from("huh"); + a = rpit_produce(&s); + } + let _unrelated = String::from("UB!"); + let dangling: &str = a.produce(); + println!("{dangling}"); +} + +fn main() { + item_bound::(); + where_clause::(); + rpit(); +} diff --git a/tests/ui/borrowck/alias-liveness/closure-static-interface-lifetime-160979.nll.stderr b/tests/ui/borrowck/alias-liveness/closure-static-interface-lifetime-160979.nll.stderr new file mode 100644 index 0000000000000..c46dab96715a8 --- /dev/null +++ b/tests/ui/borrowck/alias-liveness/closure-static-interface-lifetime-160979.nll.stderr @@ -0,0 +1,22 @@ +error[E0597]: `s` does not live long enough + --> $DIR/closure-static-interface-lifetime-160979.rs:37:42 + | +LL | let s = String::from(""); + | - binding `s` declared here +LL | let cm = ClosureMaker { some_string: &s }; + | ^^ borrowed value does not live long enough +... +LL | let _leaked = leak_it(val); + | ------------ argument requires that `s` is borrowed for `'static` +LL | } + | - `s` dropped here while still borrowed + | +note: requirement that the value outlives `'static` introduced here + --> $DIR/closure-static-interface-lifetime-160979.rs:31:15 + | +LL | fn leak_it(val: T) -> &'static T { + | ^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/borrowck/alias-liveness/closure-static-interface-lifetime-160979.rs b/tests/ui/borrowck/alias-liveness/closure-static-interface-lifetime-160979.rs new file mode 100644 index 0000000000000..92f16d3fde206 --- /dev/null +++ b/tests/ui/borrowck/alias-liveness/closure-static-interface-lifetime-160979.rs @@ -0,0 +1,46 @@ +//@ ignore-compare-mode-polonius (explicit revisions) +//@ revisions: nll polonius +//@ [nll] compile-flags: -Zpolonius=off +//@ [polonius] compile-flags: -Zpolonius=next +//@ [polonius] check-pass +//@ [polonius] known-bug: #160979 + +// Lifetimes in the bounds of an opaque type must be considered live, even +// if they don't appear in the outlives bounds, because they can be "recreated" +// later through the trait's bounds. + +struct Lifetimed<'a> { + #[allow(dead_code)] + some_tuple: &'a (), +} +static LIFETIMED: Lifetimed<'static> = Lifetimed { some_tuple: &() }; + +struct ClosureMaker<'a> { + #[allow(dead_code)] + some_string: &'a str, +} + +impl<'a> ClosureMaker<'a> { + // The closure itself is `'static` (it captures nothing), but its return + // type mentions `'a`. + fn make_closure_simple(&self) -> impl Fn() -> &'a Lifetimed<'a> + 'static { + || &LIFETIMED + } +} + +fn leak_it(val: T) -> &'static T { + Box::leak(Box::new(val)) +} + +fn return_value_with_dangling_lifetime() { + let s = String::from(""); + let cm = ClosureMaker { some_string: &s }; + //[nll]~^ ERROR `s` does not live long enough + let val = cm.make_closure_simple()(); + // requires `&'a Lifetimed<'a>: 'static` + let _leaked = leak_it(val); +} + +fn main() { + return_value_with_dangling_lifetime(); +} diff --git a/tests/ui/borrowck/alias-liveness/higher-ranked-use-bound.rs b/tests/ui/borrowck/alias-liveness/higher-ranked-use-bound.rs new file mode 100644 index 0000000000000..e638d83357990 --- /dev/null +++ b/tests/ui/borrowck/alias-liveness/higher-ranked-use-bound.rs @@ -0,0 +1,16 @@ +//@ check-pass + +// This is like `higher-ranked-outlives-for-capture`, but represents a case that +// we can accept. Specifically, although `'o` is `use`d here, it is not named in +// any trait or projection bounds. + +trait Outlives<'a>: 'a {} +impl<'a, T: 'a> Outlives<'a> for T {} + +fn test<'o>(v: &'o Vec) -> impl use<'o> + for<'a> Outlives<'a> {} + +fn opaque_doesnt_use_temporary() { + let a = test(&vec![]); +} + +fn main() {} diff --git a/tests/ui/borrowck/alias-liveness/higher-ranked.rs b/tests/ui/borrowck/alias-liveness/higher-ranked.rs index 3af125299829b..a06a94c2919f2 100644 --- a/tests/ui/borrowck/alias-liveness/higher-ranked.rs +++ b/tests/ui/borrowck/alias-liveness/higher-ranked.rs @@ -1,4 +1,11 @@ //@ check-pass +//@ known-bug: #151861 + +// We once thought that we could accept this, but alas we cannot. Although in +// this case `Captures<'o>` doesn't do anything, the presence of a trait bound +// with a lifetime can result in unsoundness if the lifetime is not considered +// live. See `marker-trait-blanket-151861` and similar for examples of concrete +// unsoundness. trait Captures<'a> {} impl Captures<'_> for T {} @@ -6,7 +13,6 @@ impl Captures<'_> for T {} trait Outlives<'a>: 'a {} impl<'a, T: 'a> Outlives<'a> for T {} -// Test that we treat `for<'a> Opaque: 'a` as `Opaque: 'static` fn test<'o>(v: &'o Vec) -> impl Captures<'o> + for<'a> Outlives<'a> {} fn opaque_doesnt_use_temporary() { diff --git a/tests/ui/borrowck/alias-liveness/marker-trait-blanket-151861.nll.stderr b/tests/ui/borrowck/alias-liveness/marker-trait-blanket-151861.nll.stderr new file mode 100644 index 0000000000000..ee03541e4ec48 --- /dev/null +++ b/tests/ui/borrowck/alias-liveness/marker-trait-blanket-151861.nll.stderr @@ -0,0 +1,23 @@ +error[E0597]: `s` does not live long enough + --> $DIR/marker-trait-blanket-151861.rs:35:23 + | +LL | let s = String::from("hi"); + | - binding `s` declared here +LL | let r: &str = &s; + | ^^ borrowed value does not live long enough +LL | o = foo(r); +LL | } + | - `s` dropped here while still borrowed +LL | let out: &str = o.get(); +LL | requires_static(out); + | -------------------- argument requires that `s` is borrowed for `'static` + | +note: requirement that the value outlives `'static` introduced here + --> $DIR/marker-trait-blanket-151861.rs:29:23 + | +LL | fn requires_static(val: T) {} + | ^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/borrowck/alias-liveness/marker-trait-blanket-151861.rs b/tests/ui/borrowck/alias-liveness/marker-trait-blanket-151861.rs new file mode 100644 index 0000000000000..b5bb2e6ab2421 --- /dev/null +++ b/tests/ui/borrowck/alias-liveness/marker-trait-blanket-151861.rs @@ -0,0 +1,40 @@ +//@ ignore-compare-mode-polonius (explicit revisions) +//@ revisions: nll polonius +//@ [nll] compile-flags: -Zpolonius=off +//@ [polonius] compile-flags: -Zpolonius=next +//@ [polonius] check-pass +//@ [polonius] known-bug: #151861 + +// This shows that it is not sound to treat lifetimes within trait bounds of +// aliases as not live. Lifetimes within the trait bounds can be used to create +// shorter lifetimes than the data within (for example, here, when the inner +// data is `'static`). + +static STATIC: &str = "static"; + +trait Captures<'a> {} +impl Captures<'_> for T {} + +trait Yield<'a> { + fn get(&self) -> &'a str; +} +impl<'a, T: Captures<'a>> Yield<'a> for T { + fn get(&self) -> &'a str { + STATIC + } +} + +fn foo<'a>(_: &'a str) -> impl Sized + Captures<'a> + 'static {} + +fn requires_static(val: T) {} + +fn main() { + let o; + { + let s = String::from("hi"); + let r: &str = &s; //[nll]~ ERROR `s` does not live long enough + o = foo(r); + } + let out: &str = o.get(); + requires_static(out); +} diff --git a/tests/ui/borrowck/alias-liveness/projection-hide-one-bound-153215.nll.stderr b/tests/ui/borrowck/alias-liveness/projection-hide-one-bound-153215.nll.stderr new file mode 100644 index 0000000000000..72353261bb399 --- /dev/null +++ b/tests/ui/borrowck/alias-liveness/projection-hide-one-bound-153215.nll.stderr @@ -0,0 +1,31 @@ +error[E0597]: `x` does not live long enough + --> $DIR/projection-hide-one-bound-153215.rs:49:38 + | +LL | let x = [1, 2, 3]; + | - binding `x` declared here +LL | let short = Rc::new(RefCell::new(&x)); + | ^^ borrowed value does not live long enough +... +LL | let res: &'static [i32; 3] = *long.borrow(); + | ----------------- type annotation requires that `x` is borrowed for `'static` +LL | res +LL | } + | - `x` dropped here while still borrowed + +error[E0597]: `x` does not live long enough + --> $DIR/projection-hide-one-bound-153215.rs:78:38 + | +LL | let x = [1, 2, 3]; + | - binding `x` declared here +LL | let short = Rc::new(RefCell::new(&x)); + | ^^ borrowed value does not live long enough +... +LL | let res: &'static [i32; 3] = *long.borrow(); + | ----------------- type annotation requires that `x` is borrowed for `'static` +LL | res +LL | } + | - `x` dropped here while still borrowed + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/borrowck/alias-liveness/projection-hide-one-bound-153215.rs b/tests/ui/borrowck/alias-liveness/projection-hide-one-bound-153215.rs new file mode 100644 index 0000000000000..49c4e5d469b02 --- /dev/null +++ b/tests/ui/borrowck/alias-liveness/projection-hide-one-bound-153215.rs @@ -0,0 +1,88 @@ +//@ ignore-compare-mode-polonius (explicit revisions) +//@ edition: 2024 +//@ revisions: nll polonius +//@ [nll] compile-flags: -Zpolonius=off +//@ [polonius] compile-flags: -Zpolonius=next +//@ [polonius] check-pass +//@ [polonius] known-bug: #153215 + +// Data available through an associated type can end up in the hidden type of an +// opaque. We currently don't treat any generics as live, although we *should*. + +#![forbid(unsafe_code)] + +use std::cell::RefCell; +use std::rc::Rc; + +trait Swap: Sized { + fn swap(self, other: Self); +} + +impl Swap for Rc> { + fn swap(self, other: Self) { + >::swap(&self, &other); + } +} + +trait Tr { + type Assoc: Swap; + fn get(self) -> Self::Assoc; +} + +impl<'q> Tr for Rc> { + type Assoc = Rc>; + fn get(self) -> Self::Assoc { + self + } +} + +fn hide_one_bound<'a, S: Tr>(x: S) -> impl Swap + 'a +where + S::Assoc: 'a, +{ + x.get() +} + +fn dangle_one_bound() -> &'static [i32; 3] { + let long = Rc::new(RefCell::new(&[4, 5, 6] as &'static [i32; 3])); + let x = [1, 2, 3]; + let short = Rc::new(RefCell::new(&x)); + //[nll]~^ ERROR `x` does not live long enough + hide_one_bound(long.clone()).swap(hide_one_bound(short)); + let res: &'static [i32; 3] = *long.borrow(); + res +} + + trait TrItemBound<'a> { + type Assoc: Swap + 'a; + fn get(self) -> Self::Assoc; +} + +impl<'q, 'a> TrItemBound<'a> for Rc> +where + 'q: 'a, +{ + type Assoc = Rc>; + fn get(self) -> Self::Assoc { + self + } +} + +fn hide_item_bound<'a, S: TrItemBound<'a>>(x: S) -> impl Swap + 'a { + x.get() +} + +fn dangle_item_bound() -> &'static [i32; 3] { + let long = Rc::new(RefCell::new(&[4, 5, 6] as &'static [i32; 3])); + let x = [1, 2, 3]; + let short = Rc::new(RefCell::new(&x)); + //[nll]~^ ERROR `x` does not live long enough + hide_item_bound(long.clone()).swap(hide_item_bound(short)); + let res: &'static [i32; 3] = *long.borrow(); + res +} + +fn main() { + println!("{:?}", dangle_one_bound()); + println!("{:?}", dangle_item_bound()); +} diff --git a/tests/ui/borrowck/alias-liveness/projection-hide-unrelated-bounds-163886.nll.stderr b/tests/ui/borrowck/alias-liveness/projection-hide-unrelated-bounds-163886.nll.stderr new file mode 100644 index 0000000000000..026479d511233 --- /dev/null +++ b/tests/ui/borrowck/alias-liveness/projection-hide-unrelated-bounds-163886.nll.stderr @@ -0,0 +1,17 @@ +error[E0597]: `x` does not live long enough + --> $DIR/projection-hide-unrelated-bounds-163886.rs:50:38 + | +LL | let x = [1, 2, 3]; + | - binding `x` declared here +LL | let short = Rc::new(RefCell::new(&x)); + | ^^ borrowed value does not live long enough +... +LL | let res: &'static [i32; 3] = *long.borrow(); + | ----------------- type annotation requires that `x` is borrowed for `'static` +LL | res +LL | } + | - `x` dropped here while still borrowed + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/borrowck/alias-liveness/projection-hide-unrelated-bounds-163886.rs b/tests/ui/borrowck/alias-liveness/projection-hide-unrelated-bounds-163886.rs new file mode 100644 index 0000000000000..a837d278bf7d0 --- /dev/null +++ b/tests/ui/borrowck/alias-liveness/projection-hide-unrelated-bounds-163886.rs @@ -0,0 +1,59 @@ +//@ ignore-compare-mode-polonius (explicit revisions) +//@ edition: 2024 +//@ revisions: nll polonius +//@ [nll] compile-flags: -Zpolonius=off +//@ [polonius] compile-flags: -Zpolonius=next +//@ [polonius] check-pass +//@ [polonius] known-bug: #163886 + +// Similar to `projection-hide-one-bound-153215.rs`, but with two unrelated +// bounds. This used to properly error with Polonius Alpha, but has regressed +// since #156027. + +#![forbid(unsafe_code)] + +use std::cell::RefCell; +use std::rc::Rc; + +trait Swap: Sized { + fn swap(self, other: Self); +} + +impl Swap for Rc> { + fn swap(self, other: Self) { + >::swap(&self, &other); + } +} + +trait Tr { + type Assoc: Swap; + fn get(self) -> Self::Assoc; +} + +impl<'q> Tr for Rc> { + type Assoc = Rc>; + fn get(self) -> Self::Assoc { + self + } +} + +fn hide_unrelated_bounds<'a, 'b, S: Tr>(x: S) -> impl Swap + 'a + 'b +where + S::Assoc: 'a + 'b, +{ + x.get() +} + +fn dangle_unrelated_bounds() -> &'static [i32; 3] { + let long = Rc::new(RefCell::new(&[4, 5, 6] as &'static [i32; 3])); + let x = [1, 2, 3]; + let short = Rc::new(RefCell::new(&x)); + //[nll]~^ ERROR `x` does not live long enough + hide_unrelated_bounds(long.clone()).swap(hide_unrelated_bounds(short)); + let res: &'static [i32; 3] = *long.borrow(); + res +} + +fn main() { + println!("{:?}", dangle_unrelated_bounds()); +} diff --git a/tests/ui/borrowck/alias-liveness/rpit-shorten-through-impl-161038.nll.stderr b/tests/ui/borrowck/alias-liveness/rpit-shorten-through-impl-161038.nll.stderr new file mode 100644 index 0000000000000..cc160b516d4d9 --- /dev/null +++ b/tests/ui/borrowck/alias-liveness/rpit-shorten-through-impl-161038.nll.stderr @@ -0,0 +1,29 @@ +error[E0597]: `*x` does not live long enough + --> $DIR/rpit-shorten-through-impl-161038.rs:63:27 + | +LL | let x: Box = Box::new(Box::new(1)); + | - binding `x` declared here +LL | let r: &Payload = &*x; + | ^^^ borrowed value does not live long enough +LL | wrong = make_producer_alias(r).produce(); +LL | } + | - `*x` dropped here while still borrowed +LL | println!("{wrong}"); + | ----- borrow later used here + +error[E0597]: `*x` does not live long enough + --> $DIR/rpit-shorten-through-impl-161038.rs:73:27 + | +LL | let x: Box = Box::new(Box::new(1)); + | - binding `x` declared here +LL | let r: &Payload = &*x; + | ^^^ borrowed value does not live long enough +LL | wrong = make_producer_ref(r).produce(); +LL | } + | - `*x` dropped here while still borrowed +LL | println!("{wrong}"); + | ----- borrow later used here + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/borrowck/alias-liveness/rpit-shorten-through-impl-161038.rs b/tests/ui/borrowck/alias-liveness/rpit-shorten-through-impl-161038.rs new file mode 100644 index 0000000000000..1d05fe39fb2ec --- /dev/null +++ b/tests/ui/borrowck/alias-liveness/rpit-shorten-through-impl-161038.rs @@ -0,0 +1,82 @@ +//@ ignore-compare-mode-polonius (explicit revisions) +//@ edition: 2024 +//@ revisions: nll polonius +//@ [nll] compile-flags: -Zpolonius=off +//@ [polonius] compile-flags: -Zpolonius=next +//@ [polonius] check-pass +//@ [polonius] known-bug: #161038 + +// Two different variations of #161038: one with a trait with a method taking +// a reference and one taking an impl Trait. Fundamentally, both exploit the +// fact that we don't treat `'a` as live in `Produce<'a>` bound in the return +// type. + +#![forbid(unsafe_code)] + +type Payload = Box; + +trait Produce<'a> { + fn produce(self) -> &'a Payload; +} +impl<'a> Produce<'a> for &'a Payload { + fn produce(self) -> &'a Payload { + self + } +} + +trait OutlivesAlias<'a, 'b> { + fn shorten(x: impl Produce<'a> + 'a) -> impl Produce<'a> + 'b; +} +impl<'a: 'b, 'b> OutlivesAlias<'a, 'b> for () { + fn shorten(x: impl Produce<'a> + 'a) -> impl Produce<'a> + 'b { + x + } +} + +fn make_producer_alias<'a, 'b>(payload: &'a Payload) -> impl Produce<'a> + 'b + use<'a, 'b> +where + (): OutlivesAlias<'a, 'b>, +{ + <() as OutlivesAlias<'a, 'b>>::shorten(payload) +} + +trait OutlivesRef<'a, 'b> { + fn shorten(x: &'a Payload) -> impl Produce<'a> + 'b; +} +impl<'a: 'b, 'b> OutlivesRef<'a, 'b> for () { + fn shorten(x: &'a Payload) -> impl Produce<'a> + 'b { + x + } +} + +fn make_producer_ref<'a, 'b>(payload: &'a Payload) -> impl Produce<'a> + 'b + use<'a, 'b> +where + (): OutlivesRef<'a, 'b>, +{ + <() as OutlivesRef<'a, 'b>>::shorten(payload) +} + +fn through_alias_param() { + let wrong: &Payload; + { + let x: Box = Box::new(Box::new(1)); + let r: &Payload = &*x; //[nll]~ ERROR `*x` does not live long enough + wrong = make_producer_alias(r).produce(); + } + println!("{wrong}"); +} + +fn through_impl_header() { + let wrong: &Payload; + { + let x: Box = Box::new(Box::new(1)); + let r: &Payload = &*x; //[nll]~ ERROR `*x` does not live long enough + wrong = make_producer_ref(r).produce(); + } + println!("{wrong}"); +} + +fn main() { + through_alias_param(); + through_impl_header(); +} diff --git a/tests/ui/borrowck/alias-liveness/rpit-static-raw-ptr-160979.nll.stderr b/tests/ui/borrowck/alias-liveness/rpit-static-raw-ptr-160979.nll.stderr new file mode 100644 index 0000000000000..5ab6eabee2b6e --- /dev/null +++ b/tests/ui/borrowck/alias-liveness/rpit-static-raw-ptr-160979.nll.stderr @@ -0,0 +1,35 @@ +error[E0597]: `x` does not live long enough + --> $DIR/rpit-static-raw-ptr-160979.rs:40:49 + | +LL | let x: Box = Box::new(Box::new(1)); + | - binding `x` declared here +LL | let wrong: &'static Payload = make_producer(&x).produce(); + | ---------------- ^^ borrowed value does not live long enough + | | + | type annotation requires that `x` is borrowed for `'static` +... +LL | } + | - `x` dropped here while still borrowed + +error[E0505]: cannot move out of `x` because it is borrowed + --> $DIR/rpit-static-raw-ptr-160979.rs:42:10 + | +LL | let x: Box = Box::new(Box::new(1)); + | - binding `x` declared here +LL | let wrong: &'static Payload = make_producer(&x).produce(); + | ---------------- -- borrow of `x` occurs here + | | + | type annotation requires that `x` is borrowed for `'static` +LL | +LL | drop(x); + | ^ move out of `x` occurs here + | +help: consider cloning the value if the performance cost is acceptable + | +LL | let wrong: &'static Payload = make_producer(&x.clone()).produce(); + | ++++++++ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0505, E0597. +For more information about an error, try `rustc --explain E0505`. diff --git a/tests/ui/borrowck/alias-liveness/rpit-static-raw-ptr-160979.rs b/tests/ui/borrowck/alias-liveness/rpit-static-raw-ptr-160979.rs new file mode 100644 index 0000000000000..bc6cc70548e8f --- /dev/null +++ b/tests/ui/borrowck/alias-liveness/rpit-static-raw-ptr-160979.rs @@ -0,0 +1,45 @@ +//@ ignore-compare-mode-polonius (explicit revisions) +//@ revisions: nll polonius +//@ [nll] compile-flags: -Zpolonius=off +//@ [polonius] compile-flags: -Zpolonius=next +//@ [polonius] check-pass +//@ [polonius] known-bug: #160979 + +// This test exhibits UB by creating a dangling reference from a type where the +// lifetime on a trait bound isn't live. This happens because we don't currently +// consider lifetimes in trait bounds on aliases to be live. +// +// Ultimately, the *mechanism* of creating this dangling reference is likely +// unsound, but is only exposed because the lack of liveness on lifetimes in +// trait bounds on aliases. + + +type Payload = Box; + +trait Produce<'a> { + fn produce(self) -> &'a Payload; +} + +fn make_producer<'a>(payload: &'a Payload) -> impl Produce<'a> + 'static { + struct Producer { + ptr: *const Payload, + } + impl<'a> Produce<'a> for Producer { + fn produce(self) -> &'a Payload { + // This is almost certainly unsound: `Wrapper` is only ever + // built from a `&'a Payload`, but this impl holds at every `'r`. + unsafe { &*self.ptr } + } + } + + Producer { ptr: payload } +} + +fn main() { + let x: Box = Box::new(Box::new(1)); + let wrong: &'static Payload = make_producer(&x).produce(); + //[nll]~^ ERROR `x` does not live long enough + drop(x); + //[nll]~^ ERROR cannot move out of `x` because it is borrowed + println!("{wrong}"); +} diff --git a/tests/ui/borrowck/alias-liveness/rpit-static-use-bound.rs b/tests/ui/borrowck/alias-liveness/rpit-static-use-bound.rs new file mode 100644 index 0000000000000..7cd03e1d75305 --- /dev/null +++ b/tests/ui/borrowck/alias-liveness/rpit-static-use-bound.rs @@ -0,0 +1,19 @@ +//@ check-pass + +fn foo<'a>(x: &'a mut i32) -> impl Sized + use<'a> + 'static {} + +fn overlapping_mut() { + let i = &mut 1; + let x = foo(i); + let y = foo(i); +} + +fn live_past_borrow() { + let y; + { + let x = &mut 1; + y = foo(x); + } +} + +fn main() {} diff --git a/tests/ui/borrowck/alias-liveness/unrelated-bounds-liveness.rs b/tests/ui/borrowck/alias-liveness/unrelated-bounds-liveness.rs new file mode 100644 index 0000000000000..0db5007504ece --- /dev/null +++ b/tests/ui/borrowck/alias-liveness/unrelated-bounds-liveness.rs @@ -0,0 +1,231 @@ +//@ check-pass +//@ known-bug: #163886 +//@ edition: 2024 + +// This test shows that aliases can end up in the hidden type of an impl Trait, +// and that we currently don't properly consider generics live that *should* be. +// This affects both NLL and Polonius Alpha. + +#![forbid(unsafe_code)] + +use std::fmt::Debug; + +trait Tr { + type Assoc: Debug; + fn get(self) -> Self::Assoc; +} +impl<'q> Tr for &'q u8 { + type Assoc = &'q u8; + fn get(self) -> &'q u8 { + self + } +} + +fn make<'a, 'b, T: Tr>(t: T) -> impl Debug + 'a + 'b +where + T::Assoc: 'a + 'b, +{ + t.get() +} + +fn show(t: T, r: &Vec) { + println!("escaped = {t:?}, reused = {r:?}"); +} + +fn base() { + let escaped; + { + let v: Vec = vec![42]; + escaped = make(&v[0]); + } + let reused: Vec = vec![7]; + show(escaped, &reused); +} + +mod item_bounds { + use super::{Debug, show}; + + trait Tr<'a, 'b> { + type Assoc: Debug + 'a + 'b; + fn get(self) -> Self::Assoc; + } + + impl<'a, 'b, 'q: 'a + 'b> Tr<'a, 'b> for &'q u8 { + type Assoc = &'q u8; + fn get(self) -> &'q u8 { + self + } + } + + fn make<'a, 'b, T: Tr<'a, 'b>>(t: T) -> impl Debug + 'a + 'b { + t.get() + } + + pub fn run() { + let escaped; + { + let v: Vec = vec![42]; + escaped = make(&v[0]); + } + let reused: Vec = vec![7]; + show(escaped, &reused); + } +} + +mod lifetime_arg { + use super::{Debug, show}; + + mod trait_arg { + use super::Debug; + + pub trait Tr<'c> { + type Assoc: Debug; + fn get(self, x: &'c u8) -> Self::Assoc; + } + + impl<'c> Tr<'c> for () { + type Assoc = &'c u8; + fn get(self, x: &'c u8) -> &'c u8 { + x + } + } + + pub fn make<'a, 'b, 'c, T: Tr<'c>>(t: T, x: &'c u8) -> impl Debug + 'a + 'b + where + >::Assoc: 'a + 'b, + { + t.get(x) + } + } + + mod gat_arg { + use super::Debug; + + pub trait Tr { + type Assoc<'z>: Debug; + fn get<'z>(self, x: &'z u8) -> Self::Assoc<'z>; + } + + impl Tr for () { + type Assoc<'z> = &'z u8; + fn get<'z>(self, x: &'z u8) -> &'z u8 { + x + } + } + + pub fn make<'a, 'b, 'z, T: Tr>(t: T, x: &'z u8) -> impl Debug + 'a + 'b + where + T::Assoc<'z>: 'a + 'b, + { + t.get(x) + } + } + + pub fn on_the_trait() { + let escaped; + { + let v: Vec = vec![42]; + escaped = trait_arg::make((), &v[0]); + } + let reused: Vec = vec![7]; + show(escaped, &reused); + } + + pub fn on_the_gat() { + let escaped; + { + let v: Vec = vec![42]; + escaped = gat_arg::make((), &v[0]); + } + let reused: Vec = vec![7]; + show(escaped, &reused); + } +} + +mod nested { + use super::{Debug, Tr, show}; + + fn inner<'a, 'b, T: Tr>(t: T) -> impl Debug + 'a + 'b + where + T::Assoc: 'a + 'b, + { + t.get() + } + + fn outer<'a, 'b, T: Tr>(t: T) -> impl Debug + 'a + 'b + where + T::Assoc: 'a + 'b, + { + inner::<'a, 'b, T>(t) + } + + pub fn run() { + let escaped; + { + let v: Vec = vec![42]; + escaped = outer(&v[0]); + } + let reused: Vec = vec![7]; + show(escaped, &reused); + } +} + +mod rpitit { + use super::{Debug, Tr, show}; + + trait Make<'a, 'b> { + fn make(t: T) -> impl Debug + 'a + 'b + where + T::Assoc: 'a + 'b; + } + + impl<'a, 'b> Make<'a, 'b> for () { + fn make(t: T) -> impl Debug + 'a + 'b + where + T::Assoc: 'a + 'b, + { + t.get() + } + } + + pub fn run() { + let escaped; + { + let v: Vec = vec![42]; + escaped = <() as Make>::make(&v[0]); + } + let reused: Vec = vec![7]; + show(escaped, &reused); + } +} + +mod three_bounds { + use super::{Debug, Tr, show}; + + fn make<'a, 'b, 'c: 'a, T: Tr>(t: T) -> impl Debug + 'a + 'b + 'c + where + T::Assoc: 'a + 'b + 'c, + { + t.get() + } + + pub fn run() { + let escaped; + { + let v: Vec = vec![42]; + escaped = make(&v[0]); + } + let reused: Vec = vec![7]; + show(escaped, &reused); + } +} + +fn main() { + base(); + item_bounds::run(); + lifetime_arg::on_the_trait(); + lifetime_arg::on_the_gat(); + nested::run(); + rpitit::run(); + three_bounds::run(); +} diff --git a/tests/ui/lexer/emoji-in-lifetime.rs b/tests/ui/lexer/emoji-in-lifetime.rs new file mode 100644 index 0000000000000..e4a12f332ae70 --- /dev/null +++ b/tests/ui/lexer/emoji-in-lifetime.rs @@ -0,0 +1,16 @@ +// #141081 +fn bad_lifetime_name< + '๐Ÿ›๐Ÿ›๐Ÿ›family๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ,//~ ERROR: identifiers cannot contain emoji + '12, //~ ERROR: lifetimes cannot start with a number + 'a๐Ÿ›, //~ ERROR: identifiers cannot contain emoji + '1๐Ÿ›, //~ ERROR: identifiers cannot contain emoji + //~^ ERROR: lifetimes cannot start with a number + '1, //~ ERROR: lifetimes cannot start with a number + 'aโ€Œb // bare zero-width-joiners are accepted as XID_Continue +>() {} + +fn main() { + 'a๐Ÿ›: { // pointed at on the error from line 5 + todo!(); + }; +} diff --git a/tests/ui/lexer/emoji-in-lifetime.stderr b/tests/ui/lexer/emoji-in-lifetime.stderr new file mode 100644 index 0000000000000..7e205639a9a3c --- /dev/null +++ b/tests/ui/lexer/emoji-in-lifetime.stderr @@ -0,0 +1,41 @@ +error: identifiers cannot contain emoji: `'๐Ÿ›๐Ÿ›๐Ÿ›family๐Ÿ‘จ๐Ÿ‘ฉ๐Ÿ‘ง๐Ÿ‘ฆ` + --> $DIR/emoji-in-lifetime.rs:3:5 + | +LL | '๐Ÿ›๐Ÿ›๐Ÿ›family๐Ÿ‘จ๐Ÿ‘ฉ๐Ÿ‘ง๐Ÿ‘ฆ, + | ^^^^^^^^^^^^^^^^^^^^^ + +error: identifiers cannot contain emoji: `'a๐Ÿ›` + --> $DIR/emoji-in-lifetime.rs:5:5 + | +LL | 'a๐Ÿ›, + | ^^^^ +... +LL | 'a๐Ÿ›: { // pointed at on the error from line 5 + | ^^^^ + +error: identifiers cannot contain emoji: `'1๐Ÿ›` + --> $DIR/emoji-in-lifetime.rs:6:5 + | +LL | '1๐Ÿ›, + | ^^^^ + +error: lifetimes cannot start with a number: `'12` + --> $DIR/emoji-in-lifetime.rs:4:6 + | +LL | '12, + | -^- + +error: lifetimes cannot start with a number: `'1๐Ÿ›` + --> $DIR/emoji-in-lifetime.rs:6:6 + | +LL | '1๐Ÿ›, + | -^-- + +error: lifetimes cannot start with a number: `'1` + --> $DIR/emoji-in-lifetime.rs:8:5 + | +LL | '1, + | ^^ + +error: aborting due to 6 previous errors + diff --git a/tests/ui/lexer/lex-bad-str-literal-as-char-1.stderr b/tests/ui/lexer/lex-bad-str-literal-as-char-1.stderr index 81ee697802b9c..7503774cd686f 100644 --- a/tests/ui/lexer/lex-bad-str-literal-as-char-1.stderr +++ b/tests/ui/lexer/lex-bad-str-literal-as-char-1.stderr @@ -10,7 +10,7 @@ LL - println!('1 + 1'); LL + println!("1 + 1"); | -error: lifetimes cannot start with a number +error: lifetimes cannot start with a number: `'1` --> $DIR/lex-bad-str-literal-as-char-1.rs:3:14 | LL | println!('1 + 1'); diff --git a/tests/ui/parser/numeric-lifetime.stderr b/tests/ui/parser/numeric-lifetime.stderr index 7c1bcb7263171..46b06ae7dc3cb 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 cannot start with a number: `'1` --> $DIR/numeric-lifetime.rs:1:10 | LL | struct S<'1> { s: &'1 usize } | ^^ -error: lifetimes cannot start with a number +error: lifetimes cannot start with a number: `'1` --> $DIR/numeric-lifetime.rs:1:20 | LL | struct S<'1> { s: &'1 usize } diff --git a/tests/ui/tool-attributes/invalid-tool.rs b/tests/ui/tool-attributes/invalid-tool.rs index 51bf9bdf4b043..0b5504c0e205f 100644 --- a/tests/ui/tool-attributes/invalid-tool.rs +++ b/tests/ui/tool-attributes/invalid-tool.rs @@ -4,8 +4,6 @@ //~^ ERROR malformed `register_tool` attribute input #![register_tool(_)] //~^ ERROR expected identifier, found reserved identifier `_` -//~| ERROR expected identifier, found reserved identifier `_` -//~| ERROR expected identifier, found reserved identifier `_` //~| ERROR malformed `register_tool` attribute input // Special path keywords cannot be used. diff --git a/tests/ui/tool-attributes/invalid-tool.stderr b/tests/ui/tool-attributes/invalid-tool.stderr index 5d7742c45d248..b0ee674b4086d 100644 --- a/tests/ui/tool-attributes/invalid-tool.stderr +++ b/tests/ui/tool-attributes/invalid-tool.stderr @@ -1,17 +1,3 @@ -error: expected identifier, found reserved identifier `_` - --> $DIR/invalid-tool.rs:5:18 - | -LL | #![register_tool(_)] - | ^ expected identifier, found reserved identifier - -error: expected identifier, found reserved identifier `_` - --> $DIR/invalid-tool.rs:5:18 - | -LL | #![register_tool(_)] - | ^ expected identifier, found reserved identifier - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - error[E0565]: malformed `register_tool` attribute input --> $DIR/invalid-tool.rs:3:4 | @@ -31,8 +17,6 @@ error: expected identifier, found reserved identifier `_` | LL | #![register_tool(_)] | ^ expected identifier, found reserved identifier - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0565]: malformed `register_tool` attribute input --> $DIR/invalid-tool.rs:5:4 @@ -49,7 +33,7 @@ LL + #![register_tool(tool1, tool2, ...)] | error[E0565]: malformed `register_tool` attribute input - --> $DIR/invalid-tool.rs:12:4 + --> $DIR/invalid-tool.rs:10:4 | LL | #![register_tool(crate)] | ^^^^^^^^^^^^^^-----^ @@ -63,7 +47,7 @@ LL + #![register_tool(tool1, tool2, ...)] | error[E0565]: malformed `register_tool` attribute input - --> $DIR/invalid-tool.rs:14:4 + --> $DIR/invalid-tool.rs:12:4 | LL | #![register_tool(self)] | ^^^^^^^^^^^^^^----^ @@ -77,7 +61,7 @@ LL + #![register_tool(tool1, tool2, ...)] | error[E0565]: malformed `register_tool` attribute input - --> $DIR/invalid-tool.rs:16:4 + --> $DIR/invalid-tool.rs:14:4 | LL | #![register_tool(Self)] | ^^^^^^^^^^^^^^----^ @@ -91,7 +75,7 @@ LL + #![register_tool(tool1, tool2, ...)] | error[E0565]: malformed `register_tool` attribute input - --> $DIR/invalid-tool.rs:18:4 + --> $DIR/invalid-tool.rs:16:4 | LL | #![register_tool(super)] | ^^^^^^^^^^^^^^-----^ @@ -104,6 +88,6 @@ LL - #![register_tool(super)] LL + #![register_tool(tool1, tool2, ...)] | -error: aborting due to 9 previous errors +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0565`.