diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 450a93ee8481e..96e4b822b041d 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -1753,6 +1753,9 @@ pub struct AddressSpace(pub u32); impl AddressSpace { /// LLVM's `0` address space. pub const ZERO: Self = AddressSpace(0); + /// The address space for workgroup memory on nvptx and amdgpu. + /// See e.g. the `gpu_launch_sized_workgroup_mem` intrinsic for details. + pub const GPU_WORKGROUP: Self = AddressSpace(3); } /// How many scalable vectors are in a `BackendRepr::ScalableVector`? diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index f0b292d3179da..4e1b46d568099 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -1052,7 +1052,7 @@ impl<'hir> LoweringContext<'_, 'hir> { binder: &ClosureBinder, capture_clause: CaptureBy, closure_id: NodeId, - mut constness: Const, + constness: Const, movability: Movability, decl: &FnDecl, body: &Expr, @@ -1062,18 +1062,11 @@ impl<'hir> LoweringContext<'_, 'hir> { let closure_def_id = self.local_def_id(closure_id); let (binder_clause, generic_params) = self.lower_closure_binder(binder); - if let Const::Yes(span) = constness { - if !self.is_in_const_context { - self.dcx().span_err(span, "cannot use `const` closures outside of const contexts"); - constness = Const::No; - } - } - let (body_id, closure_kind) = self.with_new_scopes(fn_decl_span, move |this| { let mut coroutine_kind = find_attr!(attrs, Coroutine(_) => hir::CoroutineKind::Coroutine(Movability::Movable)); // FIXME(contracts): Support contracts on closures? - let body_id = this.lower_fn_body(decl, None, constness, |this| { + let body_id = this.lower_fn_body(decl, None, |this| { this.coroutine_kind = coroutine_kind; let e = this.lower_expr_mut(body); coroutine_kind = this.coroutine_kind; diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 2195581eccec3..571da622c9557 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1,4 +1,3 @@ -use std::mem; use rustc_abi::ExternAbi; use rustc_ast::visit::AssocCtxt; @@ -378,7 +377,6 @@ impl<'hir> LoweringContext<'_, 'hir> { body.as_deref(), attrs, contract.as_deref(), - header.constness, ); let itctx = ImplTraitContext::Universal; @@ -1068,7 +1066,6 @@ impl<'hir> LoweringContext<'_, 'hir> { Some(body), attrs, contract.as_deref(), - sig.header.constness, ); let (generics, sig) = self.lower_method_sig( generics, @@ -1262,7 +1259,6 @@ impl<'hir> LoweringContext<'_, 'hir> { body.as_deref(), attrs, contract.as_deref(), - sig.header.constness, ); let (generics, sig) = self.lower_method_sig( generics, @@ -1391,13 +1387,11 @@ impl<'hir> LoweringContext<'_, 'hir> { f: impl FnOnce(&mut Self) -> (&'hir [hir::Param<'hir>], hir::Expr<'hir>), ) -> hir::BodyId { let prev_coroutine_kind = self.coroutine_kind.take(); - let prev_is_in_const_context = mem::take(&mut self.is_in_const_context); let task_context = self.task_context.take(); let (parameters, result) = f(self); let body_id = self.record_body(parameters, result); self.task_context = task_context; self.coroutine_kind = prev_coroutine_kind; - self.is_in_const_context = prev_is_in_const_context; body_id } @@ -1416,13 +1410,9 @@ impl<'hir> LoweringContext<'_, 'hir> { &mut self, decl: &FnDecl, contract: Option<&FnContract>, - constness: Const, body: impl FnOnce(&mut Self) -> hir::Expr<'hir>, ) -> hir::BodyId { self.lower_body(|this| { - if let Const::Yes(_) = constness { - this.is_in_const_context = true; - } let params = this.arena.alloc_from_iter(decl.inputs.iter().map(|x| this.lower_param(x))); @@ -1440,9 +1430,8 @@ impl<'hir> LoweringContext<'_, 'hir> { decl: &FnDecl, body: &Block, contract: Option<&FnContract>, - constness: Const, ) -> hir::BodyId { - self.lower_fn_body(decl, contract, constness, |this| this.lower_block_expr(body)) + self.lower_fn_body(decl, contract, |this| this.lower_block_expr(body)) } pub(super) fn lower_const_body(&mut self, span: Span, expr: Option<&Expr>) -> hir::BodyId { @@ -1450,10 +1439,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ( &[], match expr { - Some(expr) => { - this.is_in_const_context = true; - this.lower_expr_mut(expr) - } + Some(expr) => this.lower_expr_mut(expr), None => this.expr_err(span, this.dcx().span_delayed_bug(span, "no block")), }, ) @@ -1472,13 +1458,12 @@ impl<'hir> LoweringContext<'_, 'hir> { body: Option<&Block>, attrs: &'hir [hir::Attribute], contract: Option<&FnContract>, - constness: Const, ) -> hir::BodyId { let Some(body) = body else { // Functions without a body are an error, except if this is an intrinsic. For those we // create a fake body so that the entire rest of the compiler doesn't have to deal with // this as a special case. - return self.lower_fn_body(decl, contract, constness, |this| { + return self.lower_fn_body(decl, contract, |this| { if find_attr!(attrs, RustcIntrinsic) || this.tcx.is_sdylib_interface_build() { let span = this.lower_span(span); let empty_block = hir::Block { @@ -1503,7 +1488,7 @@ impl<'hir> LoweringContext<'_, 'hir> { }; let Some(coroutine_kind) = coroutine_kind else { // Typical case: not a coroutine. - return self.lower_fn_body_block(decl, body, contract, constness); + return self.lower_fn_body_block(decl, body, contract); }; // FIXME(contracts): Support contracts on async fn. self.lower_body(|this| { diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 5188fb8d6aada..5e9674b7a0422 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -124,7 +124,6 @@ struct LoweringContext<'a, 'hir> { loop_scope: Option, is_in_loop_condition: bool, is_in_dyn_type: bool, - is_in_const_context: bool, current_hir_id_owner: hir::OwnerId, item_local_id_counter: hir::ItemLocalId, @@ -193,7 +192,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { loop_scope: None, is_in_loop_condition: false, is_in_dyn_type: false, - is_in_const_context: false, coroutine_kind: None, task_context: None, current_item: None, diff --git a/compiler/rustc_codegen_llvm/src/declare.rs b/compiler/rustc_codegen_llvm/src/declare.rs index d7b8a304e9591..419d38f95e595 100644 --- a/compiler/rustc_codegen_llvm/src/declare.rs +++ b/compiler/rustc_codegen_llvm/src/declare.rs @@ -14,6 +14,7 @@ use std::borrow::Borrow; use itertools::Itertools; +use rustc_abi::AddressSpace; use rustc_codegen_ssa::traits::{MiscCodegenMethods, TypeMembershipCodegenMethods}; use rustc_data_structures::fx::FxIndexSet; use rustc_middle::ty::{Instance, Ty}; @@ -104,6 +105,28 @@ impl<'ll, CX: Borrow>> GenericCx<'ll, CX> { ) } } + + /// Declare a global value in a specific address space. + /// + /// If there’s a value with the same name already declared, the function will + /// return its Value instead. + pub(crate) fn declare_global_in_addrspace( + &self, + name: &str, + ty: &'ll Type, + addr_space: AddressSpace, + ) -> &'ll Value { + debug!("declare_global(name={name:?}, addrspace={addr_space:?})"); + unsafe { + llvm::LLVMRustGetOrInsertGlobalInAddrspace( + (**self).borrow().llmod, + name.as_c_char_ptr(), + name.len(), + ty, + addr_space.0, + ) + } + } } impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 48ba8d400f7b5..94bd4a6ef76ef 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -3,8 +3,8 @@ use std::ffi::c_uint; use std::{assert_matches, iter, ptr}; use rustc_abi::{ - Align, BackendRepr, Float, HasDataLayout, Integer, NumScalableVectors, Primitive, Size, - WrappingRange, + AddressSpace, Align, BackendRepr, Float, HasDataLayout, Integer, NumScalableVectors, Primitive, + Size, WrappingRange, }; use rustc_codegen_ssa::base::{compare_simd_types, wants_msvc_seh, wants_wasm_eh}; use rustc_codegen_ssa::common::{IntPredicate, TypeKind}; @@ -178,6 +178,7 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { span: Span, ) -> Result<(), ty::Instance<'tcx>> { let tcx = self.tcx; + let llvm_version = crate::llvm_util::get_version(); let name = tcx.item_name(instance.def_id()); let fn_args = instance.args; @@ -194,7 +195,7 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { | sym::maximum_number_nsz_f64 | sym::maximum_number_nsz_f128 // Need at least LLVM 22 for `min/maximumnum` to not crash LLVM. - if crate::llvm_util::get_version() >= (22, 0, 0) => + if llvm_version >= (22, 0, 0) => { let intrinsic_name = if name.as_str().starts_with("min") { "llvm.minimumnum" @@ -420,7 +421,7 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { } // FIXME move into the branch below when LLVM 22 is the lowest version we support. - sym::carryless_mul if crate::llvm_util::get_version() >= (22, 0, 0) => { + sym::carryless_mul if llvm_version >= (22, 0, 0) => { let ty = args[0].layout.ty; if !ty.is_integral() { tcx.dcx().emit_err(InvalidMonomorphization::BasicIntegerType { @@ -620,6 +621,46 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { return Ok(()); } + sym::gpu_launch_sized_workgroup_mem => { + // Generate an anonymous global per call, with these properties: + // 1. The global is in the address space for workgroup memory + // 2. It is an `external` global + // 3. It is correctly aligned for the pointee `T` + // All instances of extern addrspace(gpu_workgroup) globals are merged in the LLVM backend. + // The name is irrelevant. + // See https://docs.nvidia.com/cuda/cuda-c-programming-guide/#shared + let name = if llvm_version < (23, 0, 0) && tcx.sess.target.arch == Arch::Nvptx64 { + // The auto-assigned name for extern shared globals in the nvptx backend does + // not compile in ptxas. Workaround this issue by assigning a name. + // Fixed in LLVM 23. + "gpu_launch_sized_workgroup_mem" + } else { + "" + }; + let global = self.declare_global_in_addrspace( + name, + self.type_array(self.type_i8(), 0), + AddressSpace::GPU_WORKGROUP, + ); + let ty::RawPtr(inner_ty, _) = result.layout.ty.kind() else { unreachable!() }; + // The alignment of the global is used to specify the *minimum* alignment that + // must be obeyed by the GPU runtime. + // When multiple of these global variables are used by a kernel, the maximum alignment is taken. + // See https://github.com/llvm/llvm-project/blob/a271d07488a85ce677674bbe8101b10efff58c95/llvm/lib/Target/AMDGPU/AMDGPULowerModuleLDSPass.cpp#L821 + let alignment = self.align_of(*inner_ty).bytes() as u32; + unsafe { + // FIXME Workaround the above issue by taking maximum alignment if the global existed + if tcx.sess.target.arch == Arch::Nvptx64 { + if alignment > llvm::LLVMGetAlignment(global) { + llvm::LLVMSetAlignment(global, alignment); + } + } else { + llvm::LLVMSetAlignment(global, alignment); + } + } + self.cx().const_pointercast(global, self.type_ptr()) + } + sym::amdgpu_dispatch_ptr => { let val = self.call_intrinsic("llvm.amdgcn.dispatch.ptr", &[], &[]); // Relying on `LLVMBuildPointerCast` to produce an addrspacecast diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 525d1dbe9d0d3..3e373c42eca34 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -2003,6 +2003,13 @@ unsafe extern "C" { NameLen: size_t, T: &'a Type, ) -> &'a Value; + pub(crate) fn LLVMRustGetOrInsertGlobalInAddrspace<'a>( + M: &'a Module, + Name: *const c_char, + NameLen: size_t, + T: &'a Type, + AddressSpace: c_uint, + ) -> &'a Value; pub(crate) fn LLVMRustGetNamedValue( M: &Module, Name: *const c_char, diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs index fd0c7c656ac21..f4a5e8baa2a5f 100644 --- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs +++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs @@ -111,6 +111,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { sym::abort | sym::unreachable | sym::cold_path + | sym::gpu_launch_sized_workgroup_mem | sym::breakpoint | sym::amdgpu_dispatch_ptr | sym::assert_zero_valid diff --git a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs index 0b5065f12f805..57fd230ec4685 100644 --- a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs @@ -16,7 +16,13 @@ fn constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Constness { // Foreign functions cannot be evaluated at compile-time. Constness::NotConst } - Node::Expr(e) if let ExprKind::Closure(c) = e.kind => c.constness, + Node::Expr(e) if let ExprKind::Closure(c) = e.kind => { + if let Constness::Const = c.constness && tcx.hir_body_const_context(tcx.local_parent(def_id)).is_none() { + tcx.dcx().span_err(tcx.def_span(def_id), "cannot use `const` closures outside of const contexts"); + return Constness::NotConst; + } + c.constness + }, // FIXME(fee1-dead): extract this one out and rename this query to `fn_constness` so we don't need `is_const_fn` anymore. Node::Item(i) if let ItemKind::Impl(impl_) = i.kind => impl_.constness, Node::Item(Item { kind: ItemKind::Fn { sig, .. }, .. }) => sig.header.constness, diff --git a/compiler/rustc_hir_analysis/src/check/always_applicable.rs b/compiler/rustc_hir_analysis/src/check/always_applicable.rs index bdef0b57d6914..dbf5465ee18b3 100644 --- a/compiler/rustc_hir_analysis/src/check/always_applicable.rs +++ b/compiler/rustc_hir_analysis/src/check/always_applicable.rs @@ -11,7 +11,7 @@ use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt}; use rustc_infer::traits::{ObligationCause, ObligationCauseCode}; use rustc_middle::span_bug; use rustc_middle::ty::util::CheckRegions; -use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, TypingMode}; +use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt, TypingMode}; use rustc_trait_selection::regions::InferCtxtRegionExt; use rustc_trait_selection::traits::{self, ObligationCtxt}; @@ -65,6 +65,8 @@ pub(crate) fn check_drop_impl( adt_to_impl_args, )?; + ensure_all_fields_are_const_destruct(tcx, drop_impl_did, adt_def.did())?; + ensure_impl_predicates_are_implied_by_item_defn( tcx, drop_impl_did, @@ -173,6 +175,64 @@ fn ensure_impl_params_and_item_params_correspond<'tcx>( Err(err.emit()) } +fn ensure_all_fields_are_const_destruct<'tcx>( + tcx: TyCtxt<'tcx>, + impl_def_id: LocalDefId, + adt_def_id: DefId, +) -> Result<(), ErrorGuaranteed> { + if !tcx.is_conditionally_const(impl_def_id) { + return Ok(()); + } + let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis()); + let ocx = ObligationCtxt::new_with_diagnostics(&infcx); + + let impl_span = tcx.def_span(impl_def_id.to_def_id()); + let env = + ty::EarlyBinder::bind(tcx.param_env(impl_def_id)).instantiate_identity().skip_norm_wip(); + let args = ty::GenericArgs::identity_for_item(tcx, impl_def_id); + let destruct_trait = tcx.lang_items().destruct_trait().unwrap(); + for field in tcx.adt_def(adt_def_id).all_fields() { + let field_ty = field.ty(tcx, args); + let cause = traits::ObligationCause::new( + tcx.def_span(field.did), + impl_def_id, + ObligationCauseCode::Misc, + ); + ocx.register_obligation(traits::Obligation::new( + tcx, + cause, + env, + ty::ClauseKind::HostEffect(ty::HostEffectPredicate { + trait_ref: ty::TraitRef::new(tcx, destruct_trait, [field_ty]), + constness: ty::BoundConstness::Maybe, + }), + )); + } + ocx.evaluate_obligations_error_on_ambiguity() + .into_iter() + .map(|error| { + let ty::ClauseKind::HostEffect(eff) = + error.root_obligation.predicate.expect_clause().kind().no_bound_vars().unwrap() + else { + unreachable!() + }; + let field_ty = eff.trait_ref.self_ty(); + let diag = struct_span_code_err!( + tcx.dcx(), + error.root_obligation.cause.span, + E0367, + "`{field_ty}` does not implement `[const] Destruct`", + ) + .with_span_note(impl_span, "required for this `Drop` impl"); + if field_ty.has_param() { + // FIXME: suggest adding `[const] Destruct` by teaching + // `suggest_restricting_param_bound` about const traits. + } + Err(diag.emit()) + }) + .collect() +} + /// Confirms that all predicates defined on the `Drop` impl (`drop_impl_def_id`) are able to be /// proven from within `adt_def_id`'s environment. I.e. all the predicates on the impl are /// implied by the ADT being well formed. diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 4b0225e858818..7d606439cedc3 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -130,6 +130,7 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi | sym::forget | sym::frem_algebraic | sym::fsub_algebraic + | sym::gpu_launch_sized_workgroup_mem | sym::is_val_statically_known | sym::log2f16 | sym::log2f32 @@ -297,6 +298,7 @@ pub(crate) fn check_intrinsic_type( sym::field_offset => (1, 0, vec![], tcx.types.usize), sym::rustc_peek => (1, 0, vec![param(0)], param(0)), sym::caller_location => (0, 0, vec![], tcx.caller_location_ty()), + sym::gpu_launch_sized_workgroup_mem => (1, 0, vec![], Ty::new_mut_ptr(tcx, param(0))), sym::assert_inhabited | sym::assert_zero_valid | sym::assert_mem_uninitialized_valid => { (1, 0, vec![], tcx.types.unit) } diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index c310e580af559..91bb1c9733630 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -299,10 +299,12 @@ extern "C" LLVMValueRef LLVMRustGetOrInsertFunction(LLVMModuleRef M, .getCallee()); } -extern "C" LLVMValueRef LLVMRustGetOrInsertGlobal(LLVMModuleRef M, - const char *Name, - size_t NameLen, - LLVMTypeRef Ty) { +// Get the global variable with the given name if it exists or create a new +// external global. +extern "C" LLVMValueRef +LLVMRustGetOrInsertGlobalInAddrspace(LLVMModuleRef M, const char *Name, + size_t NameLen, LLVMTypeRef Ty, + unsigned int AddressSpace) { Module *Mod = unwrap(M); auto NameRef = StringRef(Name, NameLen); @@ -313,10 +315,24 @@ extern "C" LLVMValueRef LLVMRustGetOrInsertGlobal(LLVMModuleRef M, GlobalVariable *GV = Mod->getGlobalVariable(NameRef, true); if (!GV) GV = new GlobalVariable(*Mod, unwrap(Ty), false, - GlobalValue::ExternalLinkage, nullptr, NameRef); + GlobalValue::ExternalLinkage, nullptr, NameRef, + nullptr, GlobalValue::NotThreadLocal, AddressSpace); return wrap(GV); } +// Get the global variable with the given name if it exists or create a new +// external global. +extern "C" LLVMValueRef LLVMRustGetOrInsertGlobal(LLVMModuleRef M, + const char *Name, + size_t NameLen, + LLVMTypeRef Ty) { + Module *Mod = unwrap(M); + unsigned int AddressSpace = + Mod->getDataLayout().getDefaultGlobalsAddressSpace(); + return LLVMRustGetOrInsertGlobalInAddrspace(M, Name, NameLen, Ty, + AddressSpace); +} + // Must match the layout of `rustc_codegen_llvm::llvm::ffi::AttributeKind`. enum class LLVMRustAttributeKind { AlwaysInline = 0, diff --git a/compiler/rustc_middle/src/hir/map.rs b/compiler/rustc_middle/src/hir/map.rs index d63034ed1d2bb..68357212bebe8 100644 --- a/compiler/rustc_middle/src/hir/map.rs +++ b/compiler/rustc_middle/src/hir/map.rs @@ -319,17 +319,7 @@ impl<'tcx> TyCtxt<'tcx> { BodyOwnerKind::Fn if self.is_constructor(def_id) => return None, // Const closures use their parent's const context BodyOwnerKind::Closure if self.is_const_fn(def_id) => { - return Some( - self.hir_body_const_context(self.local_parent(local_def_id)).unwrap_or_else( - || { - assert!( - self.dcx().has_errors().is_some(), - "`const` closure with no enclosing const context", - ); - ConstContext::ConstFn - }, - ), - ); + return self.hir_body_const_context(self.local_parent(local_def_id)); } BodyOwnerKind::Fn if self.is_const_fn(def_id) => ConstContext::ConstFn, BodyOwnerKind::Fn | BodyOwnerKind::Closure | BodyOwnerKind::GlobalAsm => return None, diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index a92ed9cd3ae83..cbec647bdc95e 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1281,6 +1281,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { suggestions.extend( BUILTIN_ATTRIBUTES .iter() + // These trace attributes are compiler-generated and have + // deliberately invalid names. + .filter(|attr| { + !matches!(attr.name, sym::cfg_trace | sym::cfg_attr_trace) + }) .map(|attr| TypoSuggestion::typo_from_name(attr.name, res)), ); } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index e7574eaed5b27..4cacdbd3408a5 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1033,6 +1033,7 @@ symbols! { global_asm, global_registration, globs, + gpu_launch_sized_workgroup_mem, gt, guard, guard_patterns, diff --git a/library/core/src/intrinsics/gpu.rs b/library/core/src/intrinsics/gpu.rs index 9e7624841d0c6..43cb7251c3c88 100644 --- a/library/core/src/intrinsics/gpu.rs +++ b/library/core/src/intrinsics/gpu.rs @@ -5,6 +5,51 @@ #![unstable(feature = "gpu_intrinsics", issue = "none")] +/// Returns the pointer to workgroup memory allocated at launch-time on GPUs. +/// +/// Workgroup memory is a memory region that is shared between all threads in +/// the same workgroup. It is faster to access than other memory but pointers do not +/// work outside the workgroup where they were obtained. +/// Workgroup memory can be allocated statically or after compilation, when +/// launching a gpu-kernel. `gpu_launch_sized_workgroup_mem` returns the pointer to +/// the memory that is allocated at launch-time. +/// The size of this memory can differ between launches of a gpu-kernel, depending on +/// what is specified at launch-time. +/// However, the alignment is fixed by the kernel itself, at compile-time. +/// +/// The returned pointer is the start of the workgroup memory region that is +/// allocated at launch-time. +/// All calls to `gpu_launch_sized_workgroup_mem` in a workgroup, independent of the +/// generic type, return the same address, so alias the same memory. +/// The returned pointer is aligned by at least the alignment of `T`. +/// +/// If `gpu_launch_sized_workgroup_mem` is invoked multiple times with different +/// types that have different alignment, then you may only rely on the resulting +/// pointer having the alignment of `T` after a call to `gpu_launch_sized_workgroup_mem::` +/// has occurred in the current program execution. +/// +/// # Safety +/// +/// The pointer is safe to dereference from the start (the returned pointer) up to the +/// size of workgroup memory that was specified when launching the current gpu-kernel. +/// This allocated size is not related in any way to `T`. +/// +/// The user must take care of synchronizing access to workgroup memory between +/// threads in a workgroup. The usual data race requirements apply. +/// +/// # Other APIs +/// +/// CUDA and HIP call this dynamic shared memory, shared between threads in a block. +/// OpenCL and SYCL call this local memory, shared between threads in a work-group. +/// GLSL calls this shared memory, shared between invocations in a work group. +/// DirectX calls this groupshared memory, shared between threads in a thread-group. +#[must_use = "returns a pointer that does nothing unless used"] +#[rustc_intrinsic] +#[rustc_nounwind] +#[unstable(feature = "gpu_launch_sized_workgroup_mem", issue = "135513")] +#[cfg(any(target_arch = "amdgpu", target_arch = "nvptx64"))] +pub fn gpu_launch_sized_workgroup_mem() -> *mut T; + /// Returns a pointer to the HSA kernel dispatch packet. /// /// A `gpu-kernel` on amdgpu is always launched through a kernel dispatch packet. diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs index d144ffa222097..4e2f71b94ce2d 100644 --- a/src/tools/tidy/src/style.rs +++ b/src/tools/tidy/src/style.rs @@ -222,6 +222,10 @@ fn should_ignore(line: &str) -> bool { || static_regex!( "\\s*//@ \\!?(count|files|has|has-dir|hasraw|matches|matchesraw|snapshot)\\s.*" ).is_match(line) + // Matching for FileCheck checks + || static_regex!( + "\\s*// [a-zA-Z0-9-_]*:\\s.*" + ).is_match(line) } /// Returns `true` if `line` is allowed to be longer than the normal limit. diff --git a/tests/codegen-llvm/gpu-launch-sized-workgroup-memory.rs b/tests/codegen-llvm/gpu-launch-sized-workgroup-memory.rs new file mode 100644 index 0000000000000..4764160fd0b59 --- /dev/null +++ b/tests/codegen-llvm/gpu-launch-sized-workgroup-memory.rs @@ -0,0 +1,41 @@ +// Checks that the GPU intrinsic to get launch-sized workgroup memory works +// and correctly aligns the `external addrspace(...) global`s over multiple calls. + +//@ revisions: amdgpu nvptx-pre-llvm-23 nvptx-post-llvm-23 +//@ compile-flags: --crate-type=rlib -Copt-level=1 +// +//@ [amdgpu] compile-flags: --target amdgcn-amd-amdhsa -Ctarget-cpu=gfx900 +//@ [amdgpu] needs-llvm-components: amdgpu + +//@ [nvptx-pre-llvm-23] compile-flags: --target nvptx64-nvidia-cuda +//@ [nvptx-pre-llvm-23] needs-llvm-components: nvptx +//@ [nvptx-pre-llvm-23] max-llvm-major-version: 22 +//@ [nvptx-post-llvm-23] compile-flags: --target nvptx64-nvidia-cuda +//@ [nvptx-post-llvm-23] needs-llvm-components: nvptx +//@ [nvptx-post-llvm-23] min-llvm-version: 23 +//@ add-minicore +#![feature(intrinsics, no_core, rustc_attrs)] +#![no_core] + +extern crate minicore; + +#[rustc_intrinsic] +#[rustc_nounwind] +fn gpu_launch_sized_workgroup_mem() -> *mut T; + +// amdgpu-DAG: @[[SMALL:[^ ]+]] = external addrspace(3) global [0 x i8], align 4 +// amdgpu-DAG: @[[BIG:[^ ]+]] = external addrspace(3) global [0 x i8], align 8 +// amdgpu: ret { ptr, ptr } { ptr addrspacecast (ptr addrspace(3) @[[SMALL]] to ptr), ptr addrspacecast (ptr addrspace(3) @[[BIG]] to ptr) } + +// nvptx-pre-llvm-23: @[[BIG:[^ ]+]] = external addrspace(3) global [0 x i8], align 8 +// nvptx-pre-llvm-23: ret { ptr, ptr } { ptr addrspacecast (ptr addrspace(3) @[[BIG]] to ptr), ptr addrspacecast (ptr addrspace(3) @[[BIG]] to ptr) } + +// nvptx-post-llvm-23-DAG: @[[SMALL:[^ ]+]] = external addrspace(3) global [0 x i8], align 4 +// nvptx-post-llvm-23-DAG: @[[BIG:[^ ]+]] = external addrspace(3) global [0 x i8], align 8 +// nvptx-post-llvm-23: ret { ptr, ptr } { ptr addrspacecast (ptr addrspace(3) @[[SMALL]] to ptr), ptr addrspacecast (ptr addrspace(3) @[[BIG]] to ptr) } +#[unsafe(no_mangle)] +pub fn fun() -> (*mut i32, *mut f64) { + let small = gpu_launch_sized_workgroup_mem::(); + let big = gpu_launch_sized_workgroup_mem::(); // Increase alignment to 8 + (small, big) +} diff --git a/tests/ui/consts/const-closure-in-trait-impl.rs b/tests/ui/consts/const-closure-in-trait-impl.rs new file mode 100644 index 0000000000000..29722dd37c1e0 --- /dev/null +++ b/tests/ui/consts/const-closure-in-trait-impl.rs @@ -0,0 +1,25 @@ +//@ check-pass + +#![feature(const_closures, const_destruct, const_trait_impl)] + +use std::marker::Destruct; +use std::num::NonZero; + +const trait T { + fn a(&mut self, f: impl [const] Fn() + [const] Destruct); + fn b(&mut self); +} + +struct S; + +impl const T for S { + fn a(&mut self, f: impl [const] Fn() + [const] Destruct) { + f() + } + + fn b(&mut self) { + self.a(const || {}); + } +} + +fn main() {} diff --git a/tests/ui/consts/drop-impl-nonconst-drop-field.rs b/tests/ui/consts/drop-impl-nonconst-drop-field.rs new file mode 100644 index 0000000000000..9715724007cc4 --- /dev/null +++ b/tests/ui/consts/drop-impl-nonconst-drop-field.rs @@ -0,0 +1,32 @@ +#![feature(const_trait_impl)] +#![feature(const_destruct)] + +use std::marker::Destruct; + +struct NotConstDrop; + +impl Drop for NotConstDrop { + fn drop(&mut self) {} +} + +struct ConstDrop(NotConstDrop); +//~^ ERROR: `NotConstDrop` does not implement `[const] Destruct` + +impl const Drop for ConstDrop { + fn drop(&mut self) {} +} + +struct ConstDrop2(T); +//~^ ERROR: `T` does not implement `[const] Destruct` + +impl const Drop for ConstDrop2 { + fn drop(&mut self) {} +} + +struct ConstDrop3(T); + +impl const Drop for ConstDrop3 { + fn drop(&mut self) {} +} + +fn main() {} diff --git a/tests/ui/consts/drop-impl-nonconst-drop-field.stderr b/tests/ui/consts/drop-impl-nonconst-drop-field.stderr new file mode 100644 index 0000000000000..0e626176579c6 --- /dev/null +++ b/tests/ui/consts/drop-impl-nonconst-drop-field.stderr @@ -0,0 +1,27 @@ +error[E0367]: `NotConstDrop` does not implement `[const] Destruct` + --> $DIR/drop-impl-nonconst-drop-field.rs:12:18 + | +LL | struct ConstDrop(NotConstDrop); + | ^^^^^^^^^^^^ + | +note: required for this `Drop` impl + --> $DIR/drop-impl-nonconst-drop-field.rs:15:1 + | +LL | impl const Drop for ConstDrop { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0367]: `T` does not implement `[const] Destruct` + --> $DIR/drop-impl-nonconst-drop-field.rs:19:22 + | +LL | struct ConstDrop2(T); + | ^ + | +note: required for this `Drop` impl + --> $DIR/drop-impl-nonconst-drop-field.rs:22:1 + | +LL | impl const Drop for ConstDrop2 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0367`. diff --git a/tests/ui/suggestions/attribute-typos.rs b/tests/ui/suggestions/attribute-typos.rs index 4c2336e105e2a..6dbfb1df58767 100644 --- a/tests/ui/suggestions/attribute-typos.rs +++ b/tests/ui/suggestions/attribute-typos.rs @@ -8,4 +8,11 @@ fn bar() {} //~^ ERROR cannot find attribute `rustc_dumm` in this scope //~| ERROR attributes starting with `rustc` are reserved for use by the `rustc` compiler +// Regression test for https://github.com/rust-lang/rust/issues/150566. +#[cfg_trace] //~ ERROR cannot find attribute `cfg_trace` in this scope +fn cfg_trace_attr() {} + +#[cfg_attr_trace] //~ ERROR cannot find attribute `cfg_attr_trace` in this scope +fn cfg_attr_trace_attr() {} + fn main() {} diff --git a/tests/ui/suggestions/attribute-typos.stderr b/tests/ui/suggestions/attribute-typos.stderr index 960e0b0f620ff..7ca425fa9bd6f 100644 --- a/tests/ui/suggestions/attribute-typos.stderr +++ b/tests/ui/suggestions/attribute-typos.stderr @@ -4,6 +4,12 @@ error: attributes starting with `rustc` are reserved for use by the `rustc` comp LL | #[rustc_dumm] | ^^^^^^^^^^ +error: cannot find attribute `cfg_attr_trace` in this scope + --> $DIR/attribute-typos.rs:15:3 + | +LL | #[cfg_attr_trace] + | ^^^^^^^^^^^^^^ + error: cannot find attribute `rustc_dumm` in this scope --> $DIR/attribute-typos.rs:7:3 | @@ -15,6 +21,12 @@ help: a built-in attribute with a similar name exists LL | #[rustc_dummy] | + +error: cannot find attribute `cfg_trace` in this scope + --> $DIR/attribute-typos.rs:12:3 + | +LL | #[cfg_trace] + | ^^^^^^^^^ + error: cannot find attribute `tests` in this scope --> $DIR/attribute-typos.rs:4:3 | @@ -41,5 +53,5 @@ help: a built-in attribute with a similar name exists LL | #[deprecated] | + -error: aborting due to 4 previous errors +error: aborting due to 6 previous errors diff --git a/tests/ui/traits/const-traits/const-closure-in-non-const-trait-impl-method.rs b/tests/ui/traits/const-traits/const-closure-in-non-const-trait-impl-method.rs index b538c4b6a32fd..7980bd1793f45 100644 --- a/tests/ui/traits/const-traits/const-closure-in-non-const-trait-impl-method.rs +++ b/tests/ui/traits/const-traits/const-closure-in-non-const-trait-impl-method.rs @@ -11,6 +11,7 @@ impl Foo for &mut T { const fn test() -> impl [const] Fn() { //~^ ERROR functions in trait impls cannot be declared const const move || {} + //~^ ERROR: cannot use `const` closures outside of const contexts } } diff --git a/tests/ui/traits/const-traits/const-closure-in-non-const-trait-impl-method.stderr b/tests/ui/traits/const-traits/const-closure-in-non-const-trait-impl-method.stderr index 3ff5578748d29..15bc5b8458d80 100644 --- a/tests/ui/traits/const-traits/const-closure-in-non-const-trait-impl-method.stderr +++ b/tests/ui/traits/const-traits/const-closure-in-non-const-trait-impl-method.stderr @@ -14,6 +14,12 @@ help: ... and declare the impl to be const instead LL | impl const Foo for &mut T { | +++++ -error: aborting due to 1 previous error +error: cannot use `const` closures outside of const contexts + --> $DIR/const-closure-in-non-const-trait-impl-method.rs:13:9 + | +LL | const move || {} + | ^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0379`. diff --git a/tests/ui/traits/const-traits/const-closure-in-non-const-trait-method.rs b/tests/ui/traits/const-traits/const-closure-in-non-const-trait-method.rs index dfd0793180871..9bb6bf8fe704f 100644 --- a/tests/ui/traits/const-traits/const-closure-in-non-const-trait-method.rs +++ b/tests/ui/traits/const-traits/const-closure-in-non-const-trait-method.rs @@ -6,6 +6,7 @@ trait Tr { const fn test() { //~^ ERROR functions in traits cannot be declared const (const || {})() + //~^ ERROR cannot use `const` closures outside of const contexts } } diff --git a/tests/ui/traits/const-traits/const-closure-in-non-const-trait-method.stderr b/tests/ui/traits/const-traits/const-closure-in-non-const-trait-method.stderr index 79462f620da37..dd728840b8252 100644 --- a/tests/ui/traits/const-traits/const-closure-in-non-const-trait-method.stderr +++ b/tests/ui/traits/const-traits/const-closure-in-non-const-trait-method.stderr @@ -7,6 +7,12 @@ LL | const fn test() { | functions in traits cannot be const | help: remove the `const` -error: aborting due to 1 previous error +error: cannot use `const` closures outside of const contexts + --> $DIR/const-closure-in-non-const-trait-method.rs:8:10 + | +LL | (const || {})() + | ^^^^^^^^ + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0379`. diff --git a/tests/ui/traits/const-traits/const-drop-fail.new_precise.stderr b/tests/ui/traits/const-traits/const-drop-fail.new_precise.stderr index ff803ff889b8f..db4df30800b6e 100644 --- a/tests/ui/traits/const-traits/const-drop-fail.new_precise.stderr +++ b/tests/ui/traits/const-traits/const-drop-fail.new_precise.stderr @@ -1,5 +1,17 @@ +error[E0367]: `NonTrivialDrop` does not implement `[const] Destruct` + --> $DIR/const-drop-fail.rs:19:30 + | +LL | struct ConstImplWithDropGlue(NonTrivialDrop); + | ^^^^^^^^^^^^^^ + | +note: required for this `Drop` impl + --> $DIR/const-drop-fail.rs:22:1 + | +LL | impl const Drop for ConstImplWithDropGlue { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied - --> $DIR/const-drop-fail.rs:34:5 + --> $DIR/const-drop-fail.rs:35:5 | LL | const _: () = check($exp); | ----- required by a bound introduced by this call @@ -8,13 +20,13 @@ LL | NonTrivialDrop, | ^^^^^^^^^^^^^^ | note: required by a bound in `check` - --> $DIR/const-drop-fail.rs:25:19 + --> $DIR/const-drop-fail.rs:26:19 | LL | const fn check(_: T) {} | ^^^^^^^^^^^^^^^^ required by this bound in `check` error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied - --> $DIR/const-drop-fail.rs:36:5 + --> $DIR/const-drop-fail.rs:37:5 | LL | const _: () = check($exp); | ----- required by a bound introduced by this call @@ -23,11 +35,12 @@ LL | ConstImplWithDropGlue(NonTrivialDrop), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: required by a bound in `check` - --> $DIR/const-drop-fail.rs:25:19 + --> $DIR/const-drop-fail.rs:26:19 | LL | const fn check(_: T) {} | ^^^^^^^^^^^^^^^^ required by this bound in `check` -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0277, E0367. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/const-traits/const-drop-fail.new_stock.stderr b/tests/ui/traits/const-traits/const-drop-fail.new_stock.stderr index ff803ff889b8f..db4df30800b6e 100644 --- a/tests/ui/traits/const-traits/const-drop-fail.new_stock.stderr +++ b/tests/ui/traits/const-traits/const-drop-fail.new_stock.stderr @@ -1,5 +1,17 @@ +error[E0367]: `NonTrivialDrop` does not implement `[const] Destruct` + --> $DIR/const-drop-fail.rs:19:30 + | +LL | struct ConstImplWithDropGlue(NonTrivialDrop); + | ^^^^^^^^^^^^^^ + | +note: required for this `Drop` impl + --> $DIR/const-drop-fail.rs:22:1 + | +LL | impl const Drop for ConstImplWithDropGlue { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied - --> $DIR/const-drop-fail.rs:34:5 + --> $DIR/const-drop-fail.rs:35:5 | LL | const _: () = check($exp); | ----- required by a bound introduced by this call @@ -8,13 +20,13 @@ LL | NonTrivialDrop, | ^^^^^^^^^^^^^^ | note: required by a bound in `check` - --> $DIR/const-drop-fail.rs:25:19 + --> $DIR/const-drop-fail.rs:26:19 | LL | const fn check(_: T) {} | ^^^^^^^^^^^^^^^^ required by this bound in `check` error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied - --> $DIR/const-drop-fail.rs:36:5 + --> $DIR/const-drop-fail.rs:37:5 | LL | const _: () = check($exp); | ----- required by a bound introduced by this call @@ -23,11 +35,12 @@ LL | ConstImplWithDropGlue(NonTrivialDrop), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: required by a bound in `check` - --> $DIR/const-drop-fail.rs:25:19 + --> $DIR/const-drop-fail.rs:26:19 | LL | const fn check(_: T) {} | ^^^^^^^^^^^^^^^^ required by this bound in `check` -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0277, E0367. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/const-traits/const-drop-fail.old_precise.stderr b/tests/ui/traits/const-traits/const-drop-fail.old_precise.stderr index ff803ff889b8f..db4df30800b6e 100644 --- a/tests/ui/traits/const-traits/const-drop-fail.old_precise.stderr +++ b/tests/ui/traits/const-traits/const-drop-fail.old_precise.stderr @@ -1,5 +1,17 @@ +error[E0367]: `NonTrivialDrop` does not implement `[const] Destruct` + --> $DIR/const-drop-fail.rs:19:30 + | +LL | struct ConstImplWithDropGlue(NonTrivialDrop); + | ^^^^^^^^^^^^^^ + | +note: required for this `Drop` impl + --> $DIR/const-drop-fail.rs:22:1 + | +LL | impl const Drop for ConstImplWithDropGlue { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied - --> $DIR/const-drop-fail.rs:34:5 + --> $DIR/const-drop-fail.rs:35:5 | LL | const _: () = check($exp); | ----- required by a bound introduced by this call @@ -8,13 +20,13 @@ LL | NonTrivialDrop, | ^^^^^^^^^^^^^^ | note: required by a bound in `check` - --> $DIR/const-drop-fail.rs:25:19 + --> $DIR/const-drop-fail.rs:26:19 | LL | const fn check(_: T) {} | ^^^^^^^^^^^^^^^^ required by this bound in `check` error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied - --> $DIR/const-drop-fail.rs:36:5 + --> $DIR/const-drop-fail.rs:37:5 | LL | const _: () = check($exp); | ----- required by a bound introduced by this call @@ -23,11 +35,12 @@ LL | ConstImplWithDropGlue(NonTrivialDrop), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: required by a bound in `check` - --> $DIR/const-drop-fail.rs:25:19 + --> $DIR/const-drop-fail.rs:26:19 | LL | const fn check(_: T) {} | ^^^^^^^^^^^^^^^^ required by this bound in `check` -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0277, E0367. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/const-traits/const-drop-fail.old_stock.stderr b/tests/ui/traits/const-traits/const-drop-fail.old_stock.stderr index ff803ff889b8f..db4df30800b6e 100644 --- a/tests/ui/traits/const-traits/const-drop-fail.old_stock.stderr +++ b/tests/ui/traits/const-traits/const-drop-fail.old_stock.stderr @@ -1,5 +1,17 @@ +error[E0367]: `NonTrivialDrop` does not implement `[const] Destruct` + --> $DIR/const-drop-fail.rs:19:30 + | +LL | struct ConstImplWithDropGlue(NonTrivialDrop); + | ^^^^^^^^^^^^^^ + | +note: required for this `Drop` impl + --> $DIR/const-drop-fail.rs:22:1 + | +LL | impl const Drop for ConstImplWithDropGlue { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied - --> $DIR/const-drop-fail.rs:34:5 + --> $DIR/const-drop-fail.rs:35:5 | LL | const _: () = check($exp); | ----- required by a bound introduced by this call @@ -8,13 +20,13 @@ LL | NonTrivialDrop, | ^^^^^^^^^^^^^^ | note: required by a bound in `check` - --> $DIR/const-drop-fail.rs:25:19 + --> $DIR/const-drop-fail.rs:26:19 | LL | const fn check(_: T) {} | ^^^^^^^^^^^^^^^^ required by this bound in `check` error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied - --> $DIR/const-drop-fail.rs:36:5 + --> $DIR/const-drop-fail.rs:37:5 | LL | const _: () = check($exp); | ----- required by a bound introduced by this call @@ -23,11 +35,12 @@ LL | ConstImplWithDropGlue(NonTrivialDrop), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: required by a bound in `check` - --> $DIR/const-drop-fail.rs:25:19 + --> $DIR/const-drop-fail.rs:26:19 | LL | const fn check(_: T) {} | ^^^^^^^^^^^^^^^^ required by this bound in `check` -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0277, E0367. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/const-traits/const-drop-fail.rs b/tests/ui/traits/const-traits/const-drop-fail.rs index b74716f00617f..7e12043ce74a7 100644 --- a/tests/ui/traits/const-traits/const-drop-fail.rs +++ b/tests/ui/traits/const-traits/const-drop-fail.rs @@ -17,6 +17,7 @@ impl Drop for NonTrivialDrop { } struct ConstImplWithDropGlue(NonTrivialDrop); +//~^ ERROR: `NonTrivialDrop` does not implement `[const] Destruct` impl const Drop for ConstImplWithDropGlue { fn drop(&mut self) {} diff --git a/tests/ui/traits/const-traits/minicore-drop-fail.rs b/tests/ui/traits/const-traits/minicore-drop-fail.rs index d01d259040c6e..f17a88dd90211 100644 --- a/tests/ui/traits/const-traits/minicore-drop-fail.rs +++ b/tests/ui/traits/const-traits/minicore-drop-fail.rs @@ -19,7 +19,7 @@ const trait Foo {} impl Foo for () {} struct Conditional(T); -impl const Drop for Conditional where T: [const] Foo { +impl const Drop for Conditional where T: [const] Foo + [const] Destruct { fn drop(&mut self) {} } diff --git a/tests/ui/traits/const-traits/non-const-op-const-closure-non-const-outer.stderr b/tests/ui/traits/const-traits/non-const-op-const-closure-non-const-outer.stderr index f5521b90cc2d9..7befeec496d80 100644 --- a/tests/ui/traits/const-traits/non-const-op-const-closure-non-const-outer.stderr +++ b/tests/ui/traits/const-traits/non-const-op-const-closure-non-const-outer.stderr @@ -2,7 +2,7 @@ error: cannot use `const` closures outside of const contexts --> $DIR/non-const-op-const-closure-non-const-outer.rs:14:6 | LL | (const || { (()).foo() })(); - | ^^^^^ + | ^^^^^^^^ error: aborting due to 1 previous error