diff --git a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs new file mode 100644 index 0000000000000..eaf1b1167cf21 --- /dev/null +++ b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs @@ -0,0 +1,104 @@ +use crate::util::check_builtin_macro_attribute; + +use rustc_ast::ptr::P; +use rustc_ast::{self as ast, FnHeader, FnSig, Generics, StmtKind}; +use rustc_ast::{Fn, ItemKind, Stmt, TyKind, Unsafe}; +use rustc_expand::base::{Annotatable, ExtCtxt}; +use rustc_span::symbol::{kw, sym, Ident}; +use rustc_span::Span; +use thin_vec::thin_vec; + +pub fn expand( + ecx: &mut ExtCtxt<'_>, + _span: Span, + meta_item: &ast::MetaItem, + item: Annotatable, +) -> Vec { + check_builtin_macro_attribute(ecx, meta_item, sym::alloc_error_handler); + + let orig_item = item.clone(); + let not_function = || { + ecx.sess + .parse_sess + .span_diagnostic + .span_err(item.span(), "alloc_error_handler must be a function"); + vec![orig_item.clone()] + }; + + // Allow using `#[alloc_error_handler]` on an item statement + // FIXME - if we get deref patterns, use them to reduce duplication here + let (item, is_stmt, sig_span) = match &item { + Annotatable::Item(item) => match item.kind { + ItemKind::Fn(ref fn_kind) => (item, false, ecx.with_def_site_ctxt(fn_kind.sig.span)), + _ => return not_function(), + }, + Annotatable::Stmt(stmt) => match &stmt.kind { + StmtKind::Item(item_) => match item_.kind { + ItemKind::Fn(ref fn_kind) => { + (item_, true, ecx.with_def_site_ctxt(fn_kind.sig.span)) + } + _ => return not_function(), + }, + _ => return not_function(), + }, + _ => return not_function(), + }; + + // Generate a bunch of new items using the AllocFnFactory + let span = ecx.with_def_site_ctxt(item.span); + + // Generate item statements for the allocator methods. + let stmts = vec![generate_handler(ecx, item.ident, span, sig_span)]; + + // Generate anonymous constant serving as container for the allocator methods. + let const_ty = ecx.ty(sig_span, TyKind::Tup(Vec::new())); + let const_body = ecx.expr_block(ecx.block(span, stmts)); + let const_item = ecx.item_const(span, Ident::new(kw::Underscore, span), const_ty, const_body); + let const_item = if is_stmt { + Annotatable::Stmt(P(ecx.stmt_item(span, const_item))) + } else { + Annotatable::Item(const_item) + }; + + // Return the original item and the new methods. + vec![orig_item, const_item] +} + +// #[rustc_std_internal_symbol] +// unsafe fn __rg_oom(size: usize, align: usize) -> ! { +// handler(core::alloc::Layout::from_size_align_unchecked(size, align)) +// } +fn generate_handler(cx: &ExtCtxt<'_>, handler: Ident, span: Span, sig_span: Span) -> Stmt { + let usize = cx.path_ident(span, Ident::new(sym::usize, span)); + let ty_usize = cx.ty_path(usize); + let size = Ident::from_str_and_span("size", span); + let align = Ident::from_str_and_span("align", span); + + let layout_new = cx.std_path(&[sym::alloc, sym::Layout, sym::from_size_align_unchecked]); + let layout_new = cx.expr_path(cx.path(span, layout_new)); + let layout = + cx.expr_call(span, layout_new, vec![cx.expr_ident(span, size), cx.expr_ident(span, align)]); + + let call = cx.expr_call_ident(sig_span, handler, vec![layout]); + + let never = ast::FnRetTy::Ty(cx.ty(span, TyKind::Never)); + let params = vec![cx.param(span, size, ty_usize.clone()), cx.param(span, align, ty_usize)]; + let decl = cx.fn_decl(params, never); + let header = FnHeader { unsafety: Unsafe::Yes(span), ..FnHeader::default() }; + let sig = FnSig { decl, header, span: span }; + + let body = Some(cx.block_expr(call)); + let kind = ItemKind::Fn(Box::new(Fn { + defaultness: ast::Defaultness::Final, + sig, + generics: Generics::default(), + body, + })); + + let special = sym::rustc_std_internal_symbol; + let special = cx.meta_word(span, special); + let attrs = thin_vec![cx.attribute(special)]; + + let item = cx.item(span, Ident::from_str_and_span("__rg_oom", span), attrs, kind); + cx.stmt_item(sig_span, item) +} diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index c7ea7de8f4ead..bde0102186a47 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -25,6 +25,7 @@ use rustc_expand::base::{MacroExpanderFn, ResolverExpand, SyntaxExtensionKind}; use rustc_expand::proc_macro::BangProcMacro; use rustc_span::symbol::sym; +mod alloc_error_handler; mod assert; mod cfg; mod cfg_accessible; @@ -94,6 +95,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) { } register_attr! { + alloc_error_handler: alloc_error_handler::expand, bench: test::expand_bench, cfg_accessible: cfg_accessible::Expander, cfg_eval: cfg_eval::expand, diff --git a/compiler/rustc_codegen_cranelift/src/allocator.rs b/compiler/rustc_codegen_cranelift/src/allocator.rs index bad8a87b9bee4..12bb00d346db4 100644 --- a/compiler/rustc_codegen_cranelift/src/allocator.rs +++ b/compiler/rustc_codegen_cranelift/src/allocator.rs @@ -5,6 +5,7 @@ use crate::prelude::*; use rustc_ast::expand::allocator::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS}; use rustc_session::config::OomStrategy; +use rustc_span::symbol::sym; /// Returns whether an allocator shim was created pub(crate) fn codegen( @@ -23,7 +24,7 @@ pub(crate) fn codegen( module, unwind_context, kind, - tcx.lang_items().oom().is_some(), + tcx.alloc_error_handler_kind(()).unwrap(), tcx.sess.opts.unstable_opts.oom, ); true @@ -36,7 +37,7 @@ fn codegen_inner( module: &mut impl Module, unwind_context: &mut UnwindContext, kind: AllocatorKind, - has_alloc_error_handler: bool, + alloc_error_handler_kind: AllocatorKind, oom_strategy: OomStrategy, ) { let usize_ty = module.target_config().pointer_type(); @@ -108,12 +109,12 @@ fn codegen_inner( returns: vec![], }; - let callee_name = if has_alloc_error_handler { "__rg_oom" } else { "__rdl_oom" }; + let callee_name = alloc_error_handler_kind.fn_name(sym::oom); let func_id = module.declare_function("__rust_alloc_error_handler", Linkage::Export, &sig).unwrap(); - let callee_func_id = module.declare_function(callee_name, Linkage::Import, &sig).unwrap(); + let callee_func_id = module.declare_function(&callee_name, Linkage::Import, &sig).unwrap(); let mut ctx = Context::new(); ctx.func.signature = sig; diff --git a/compiler/rustc_codegen_gcc/src/allocator.rs b/compiler/rustc_codegen_gcc/src/allocator.rs index 58efb81e80011..e2c9ffe9c1c30 100644 --- a/compiler/rustc_codegen_gcc/src/allocator.rs +++ b/compiler/rustc_codegen_gcc/src/allocator.rs @@ -7,7 +7,7 @@ use rustc_span::symbol::sym; use crate::GccContext; -pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut GccContext, _module_name: &str, kind: AllocatorKind, has_alloc_error_handler: bool) { +pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut GccContext, _module_name: &str, kind: AllocatorKind, alloc_error_handler_kind: AllocatorKind) { let context = &mods.context; let usize = match tcx.sess.target.pointer_width { @@ -90,14 +90,7 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut GccContext, _module_nam .collect(); let func = context.new_function(None, FunctionType::Exported, void, &args, name, false); - let kind = - if has_alloc_error_handler { - AllocatorKind::Global - } - else { - AllocatorKind::Default - }; - let callee = kind.fn_name(sym::oom); + let callee = alloc_error_handler_kind.fn_name(sym::oom); let args: Vec<_> = types.iter().enumerate() .map(|(index, typ)| context.new_parameter(None, *typ, &format!("param{}", index))) .collect(); diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index accd02ab00269..dd0daf2c38b10 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -153,11 +153,11 @@ impl CodegenBackend for GccCodegenBackend { } impl ExtraBackendMethods for GccCodegenBackend { - fn codegen_allocator<'tcx>(&self, tcx: TyCtxt<'tcx>, module_name: &str, kind: AllocatorKind, has_alloc_error_handler: bool) -> Self::Module { + fn codegen_allocator<'tcx>(&self, tcx: TyCtxt<'tcx>, module_name: &str, kind: AllocatorKind, alloc_error_handler_kind: AllocatorKind) -> Self::Module { let mut mods = GccContext { context: Context::default(), }; - unsafe { allocator::codegen(tcx, &mut mods, module_name, kind, has_alloc_error_handler); } + unsafe { allocator::codegen(tcx, &mut mods, module_name, kind, alloc_error_handler_kind); } mods } diff --git a/compiler/rustc_codegen_llvm/src/allocator.rs b/compiler/rustc_codegen_llvm/src/allocator.rs index 72961ae888e5f..fed56cdd43821 100644 --- a/compiler/rustc_codegen_llvm/src/allocator.rs +++ b/compiler/rustc_codegen_llvm/src/allocator.rs @@ -15,7 +15,7 @@ pub(crate) unsafe fn codegen( module_llvm: &mut ModuleLlvm, module_name: &str, kind: AllocatorKind, - has_alloc_error_handler: bool, + alloc_error_handler_kind: AllocatorKind, ) { let llcx = &*module_llvm.llcx; let llmod = module_llvm.llmod(); @@ -117,8 +117,7 @@ pub(crate) unsafe fn codegen( attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &[uwtable]); } - let kind = if has_alloc_error_handler { AllocatorKind::Global } else { AllocatorKind::Default }; - let callee = kind.fn_name(sym::oom); + let callee = alloc_error_handler_kind.fn_name(sym::oom); let callee = llvm::LLVMRustGetOrInsertFunction(llmod, callee.as_ptr().cast(), callee.len(), ty); // -> ! DIFlagNoReturn attributes::apply_to_llfn(callee, llvm::AttributePlace::Function, &[no_return]); diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 89c7e51d09ec1..d51aced85df43 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -108,11 +108,11 @@ impl ExtraBackendMethods for LlvmCodegenBackend { tcx: TyCtxt<'tcx>, module_name: &str, kind: AllocatorKind, - has_alloc_error_handler: bool, + alloc_error_handler_kind: AllocatorKind, ) -> ModuleLlvm { let mut module_llvm = ModuleLlvm::new_metadata(tcx, module_name); unsafe { - allocator::codegen(tcx, &mut module_llvm, module_name, kind, has_alloc_error_handler); + allocator::codegen(tcx, &mut module_llvm, module_name, kind, alloc_error_handler_kind); } module_llvm } diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index c2ecc41601c8c..752f6b1ef40c9 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -193,8 +193,11 @@ fn exported_symbols_provider_local<'tcx>( } if tcx.allocator_kind(()).is_some() { - for method in ALLOCATOR_METHODS { - let symbol_name = format!("__rust_{}", method.name); + for symbol_name in ALLOCATOR_METHODS + .iter() + .map(|method| format!("__rust_{}", method.name)) + .chain(["__rust_alloc_error_handler".to_string(), OomStrategy::SYMBOL.to_string()]) + { let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(tcx, &symbol_name)); symbols.push(( diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index a92087305b82f..c1411690f8289 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -638,7 +638,14 @@ pub fn codegen_crate( let llmod_id = cgu_name_builder.build_cgu_name(LOCAL_CRATE, &["crate"], Some("allocator")).to_string(); let module_llvm = tcx.sess.time("write_allocator_module", || { - backend.codegen_allocator(tcx, &llmod_id, kind, tcx.lang_items().oom().is_some()) + backend.codegen_allocator( + tcx, + &llmod_id, + kind, + // If allocator_kind is Some then alloc_error_handler_kind must + // also be Some. + tcx.alloc_error_handler_kind(()).unwrap(), + ) }); Some(ModuleCodegen { name: llmod_id, module_llvm, kind: ModuleKind::Allocator }) diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs index 87e347c61e2b8..5c35070ea66f4 100644 --- a/compiler/rustc_codegen_ssa/src/traits/backend.rs +++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs @@ -119,7 +119,7 @@ pub trait ExtraBackendMethods: CodegenBackend + WriteBackendMethods + Sized + Se tcx: TyCtxt<'tcx>, module_name: &str, kind: AllocatorKind, - has_alloc_error_handler: bool, + alloc_error_handler_kind: AllocatorKind, ) -> Self::Module; /// This generates the codegen unit and returns it along with /// a `u64` giving an estimate of the unit's processing cost. diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index a9063ad31cfe6..f7d64f6d4f48a 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -598,7 +598,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // the last field). Can't have foreign types here, how would we // adjust alignment and size for them? let field = layout.field(self, layout.fields.count() - 1); - let Some((unsized_size, unsized_align)) = self.size_and_align_of(metadata, &field)? else { + let Some((unsized_size, mut unsized_align)) = self.size_and_align_of(metadata, &field)? else { // A field with an extern type. We don't know the actual dynamic size // or the alignment. return Ok(None); @@ -614,6 +614,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Return the sum of sizes and max of aligns. let size = sized_size + unsized_size; // `Size` addition + // Packed types ignore the alignment of their fields. + if let ty::Adt(def, _) = layout.ty.kind() { + if def.repr().packed() { + unsized_align = sized_align; + } + } + // Choose max of two known alignments (combined value must // be aligned according to more restrictive of the two). let align = sized_align.max(unsized_align); diff --git a/compiler/rustc_error_messages/locales/en-US/metadata.ftl b/compiler/rustc_error_messages/locales/en-US/metadata.ftl index 08e553d9f1589..c292ae9b32abb 100644 --- a/compiler/rustc_error_messages/locales/en-US/metadata.ftl +++ b/compiler/rustc_error_messages/locales/en-US/metadata.ftl @@ -150,12 +150,28 @@ metadata_no_multiple_global_alloc = metadata_prev_global_alloc = previous global allocator defined here +metadata_no_multiple_alloc_error_handler = + cannot define multiple allocation error handlers + .label = cannot define a new allocation error handler + +metadata_prev_alloc_error_handler = + previous allocation error handler defined here + metadata_conflicting_global_alloc = the `#[global_allocator]` in {$other_crate_name} conflicts with global allocator in: {$crate_name} +metadata_conflicting_alloc_error_handler = + the `#[alloc_error_handler]` in {$other_crate_name} conflicts with allocation error handler in: {$crate_name} + metadata_global_alloc_required = no global memory allocator found but one is required; link to std or add `#[global_allocator]` to a static item that implements the GlobalAlloc trait +metadata_alloc_func_required = + `#[alloc_error_handler]` function required, but not found + +metadata_missing_alloc_error_handler = + use `#![feature(default_alloc_error_handler)]` for a default error handler + metadata_no_transitive_needs_dep = the crate `{$crate_name}` cannot depend on a crate that needs {$needs_crate_name}, but it depends on `{$deps_crate_name}` diff --git a/compiler/rustc_error_messages/locales/en-US/passes.ftl b/compiler/rustc_error_messages/locales/en-US/passes.ftl index 4bc6bd9fb2207..bc5bfe2a24448 100644 --- a/compiler/rustc_error_messages/locales/en-US/passes.ftl +++ b/compiler/rustc_error_messages/locales/en-US/passes.ftl @@ -367,12 +367,6 @@ passes_unknown_external_lang_item = passes_missing_panic_handler = `#[panic_handler]` function required, but not found -passes_alloc_func_required = - `#[alloc_error_handler]` function required, but not found - -passes_missing_alloc_error_handler = - use `#![feature(default_alloc_error_handler)]` for a default error handler - passes_missing_lang_item = language item required, but not found: `{$name}` .note = this can occur when a binary crate with `#![no_std]` is compiled for a target where `{$name}` is defined in the standard library diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 2ead3c2c8d485..14c8e3c458c49 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -554,10 +554,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ rustc_attr!(rustc_reallocator, Normal, template!(Word), WarnFollowing, IMPL_DETAIL), rustc_attr!(rustc_deallocator, Normal, template!(Word), WarnFollowing, IMPL_DETAIL), rustc_attr!(rustc_allocator_zeroed, Normal, template!(Word), WarnFollowing, IMPL_DETAIL), - gated!( - alloc_error_handler, Normal, template!(Word), WarnFollowing, - experimental!(alloc_error_handler) - ), gated!( default_lib_allocator, Normal, template!(Word), WarnFollowing, allocator_internals, experimental!(default_lib_allocator), diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index 72ed73e81b42b..a55224d10972a 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -126,14 +126,12 @@ impl HashStable for LangItem { } /// Extracts the first `lang = "$name"` out of a list of attributes. -/// The attributes `#[panic_handler]` and `#[alloc_error_handler]` -/// are also extracted out when found. +/// The `#[panic_handler]` attribute is also extracted out when found. pub fn extract(attrs: &[ast::Attribute]) -> Option<(Symbol, Span)> { attrs.iter().find_map(|attr| { Some(match attr { _ if attr.has_name(sym::lang) => (attr.value_str()?, attr.span), _ if attr.has_name(sym::panic_handler) => (sym::panic_impl, attr.span), - _ if attr.has_name(sym::alloc_error_handler) => (sym::oom, attr.span), _ => return None, }) }) @@ -240,7 +238,6 @@ language_item_table! { ExchangeMalloc, sym::exchange_malloc, exchange_malloc_fn, Target::Fn, GenericRequirement::None; BoxFree, sym::box_free, box_free_fn, Target::Fn, GenericRequirement::Minimum(1); DropInPlace, sym::drop_in_place, drop_in_place_fn, Target::Fn, GenericRequirement::Minimum(1); - Oom, sym::oom, oom, Target::Fn, GenericRequirement::None; AllocLayout, sym::alloc_layout, alloc_layout, Target::Struct, GenericRequirement::None; Start, sym::start, start_fn, Target::Fn, GenericRequirement::Exact(1); diff --git a/compiler/rustc_hir/src/weak_lang_items.rs b/compiler/rustc_hir/src/weak_lang_items.rs index d8e5dd4ffdc2e..0cc50c6dd8505 100644 --- a/compiler/rustc_hir/src/weak_lang_items.rs +++ b/compiler/rustc_hir/src/weak_lang_items.rs @@ -27,5 +27,4 @@ weak_lang_items! { PanicImpl, rust_begin_unwind; EhPersonality, rust_eh_personality; EhCatchTypeinfo, rust_eh_catch_typeinfo; - Oom, rust_oom; } diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index b70ac02058d3d..133bbd52b9142 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -6,7 +6,7 @@ use super::*; use rustc_attr as attr; use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan}; use rustc_hir as hir; -use rustc_hir::def::{DefKind, Res}; +use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::Visitor; use rustc_hir::{ItemKind, Node, PathSegment}; @@ -75,7 +75,7 @@ fn check_struct(tcx: TyCtxt<'_>, def_id: LocalDefId) { check_simd(tcx, span, def_id); } - check_transparent(tcx, span, def); + check_transparent(tcx, def); check_packed(tcx, span, def); } @@ -83,7 +83,7 @@ fn check_union(tcx: TyCtxt<'_>, def_id: LocalDefId) { let def = tcx.adt_def(def_id); let span = tcx.def_span(def_id); def.destructor(tcx); // force the destructor to be evaluated - check_transparent(tcx, span, def); + check_transparent(tcx, def); check_union_fields(tcx, span, def_id); check_packed(tcx, span, def); } @@ -506,11 +506,7 @@ fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) { tcx.ensure().typeck(id.owner_id.def_id); } DefKind::Enum => { - let item = tcx.hir().item(id); - let hir::ItemKind::Enum(ref enum_definition, _) = item.kind else { - return; - }; - check_enum(tcx, &enum_definition.variants, item.owner_id.def_id); + check_enum(tcx, id.owner_id.def_id); } DefKind::Fn => {} // entirely within check_item_body DefKind::Impl => { @@ -1026,7 +1022,7 @@ pub(super) fn check_packed_inner( None } -pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, adt: ty::AdtDef<'tcx>) { +pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>) { if !adt.repr().transparent() { return; } @@ -1035,14 +1031,14 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, adt: ty::AdtD feature_err( &tcx.sess.parse_sess, sym::transparent_unions, - sp, + tcx.def_span(adt.did()), "transparent unions are unstable", ) .emit(); } if adt.variants().len() != 1 { - bad_variant_count(tcx, adt, sp, adt.did()); + bad_variant_count(tcx, adt, tcx.def_span(adt.did()), adt.did()); if adt.variants().is_empty() { // Don't bother checking the fields. No variants (and thus no fields) exist. return; @@ -1103,7 +1099,7 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, adt: ty::AdtD .filter_map(|(span, zst, _align1, _non_exhaustive)| if !zst { Some(span) } else { None }); let non_zst_count = non_zst_fields.clone().count(); if non_zst_count >= 2 { - bad_non_zero_sized_fields(tcx, adt, non_zst_count, non_zst_fields, sp); + bad_non_zero_sized_fields(tcx, adt, non_zst_count, non_zst_fields, tcx.def_span(adt.did())); } let incompatible_zst_fields = field_infos.clone().filter(|(_, _, _, opt)| opt.is_some()).count(); @@ -1143,12 +1139,11 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, adt: ty::AdtD } #[allow(trivial_numeric_casts)] -fn check_enum<'tcx>(tcx: TyCtxt<'tcx>, vs: &'tcx [hir::Variant<'tcx>], def_id: LocalDefId) { +fn check_enum<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) { let def = tcx.adt_def(def_id); - let sp = tcx.def_span(def_id); def.destructor(tcx); // force the destructor to be evaluated - if vs.is_empty() { + if def.variants().is_empty() { if let Some(attr) = tcx.get_attrs(def_id.to_def_id(), sym::repr).next() { struct_span_err!( tcx.sess, @@ -1156,7 +1151,7 @@ fn check_enum<'tcx>(tcx: TyCtxt<'tcx>, vs: &'tcx [hir::Variant<'tcx>], def_id: L E0084, "unsupported representation for zero-variant enum" ) - .span_label(sp, "zero-variant enum") + .span_label(tcx.def_span(def_id), "zero-variant enum") .emit(); } } @@ -1167,88 +1162,96 @@ fn check_enum<'tcx>(tcx: TyCtxt<'tcx>, vs: &'tcx [hir::Variant<'tcx>], def_id: L feature_err( &tcx.sess.parse_sess, sym::repr128, - sp, + tcx.def_span(def_id), "repr with 128-bit type is unstable", ) .emit(); } } - for v in vs { - if let Some(ref e) = v.disr_expr { - tcx.ensure().typeck(tcx.hir().local_def_id(e.hir_id)); + for v in def.variants() { + if let ty::VariantDiscr::Explicit(discr_def_id) = v.discr { + tcx.ensure().typeck(discr_def_id.expect_local()); } } - if tcx.adt_def(def_id).repr().int.is_none() { - let is_unit = |var: &hir::Variant<'_>| matches!(var.data, hir::VariantData::Unit(..)); + if def.repr().int.is_none() { + let is_unit = |var: &ty::VariantDef| matches!(var.ctor_kind, CtorKind::Const); + let has_disr = |var: &ty::VariantDef| matches!(var.discr, ty::VariantDiscr::Explicit(_)); - let has_disr = |var: &hir::Variant<'_>| var.disr_expr.is_some(); - let has_non_units = vs.iter().any(|var| !is_unit(var)); - let disr_units = vs.iter().any(|var| is_unit(&var) && has_disr(&var)); - let disr_non_unit = vs.iter().any(|var| !is_unit(&var) && has_disr(&var)); + let has_non_units = def.variants().iter().any(|var| !is_unit(var)); + let disr_units = def.variants().iter().any(|var| is_unit(&var) && has_disr(&var)); + let disr_non_unit = def.variants().iter().any(|var| !is_unit(&var) && has_disr(&var)); if disr_non_unit || (disr_units && has_non_units) { - let mut err = - struct_span_err!(tcx.sess, sp, E0732, "`#[repr(inttype)]` must be specified"); + let mut err = struct_span_err!( + tcx.sess, + tcx.def_span(def_id), + E0732, + "`#[repr(inttype)]` must be specified" + ); err.emit(); } } - detect_discriminant_duplicate(tcx, def.discriminants(tcx).collect(), vs, sp); - - check_transparent(tcx, sp, def); + detect_discriminant_duplicate(tcx, def); + check_transparent(tcx, def); } /// Part of enum check. Given the discriminants of an enum, errors if two or more discriminants are equal -fn detect_discriminant_duplicate<'tcx>( - tcx: TyCtxt<'tcx>, - mut discrs: Vec<(VariantIdx, Discr<'tcx>)>, - vs: &'tcx [hir::Variant<'tcx>], - self_span: Span, -) { +fn detect_discriminant_duplicate<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>) { // Helper closure to reduce duplicate code. This gets called everytime we detect a duplicate. // Here `idx` refers to the order of which the discriminant appears, and its index in `vs` - let report = |dis: Discr<'tcx>, idx: usize, err: &mut Diagnostic| { - let var = &vs[idx]; // HIR for the duplicate discriminant - let (span, display_discr) = match var.disr_expr { - Some(ref expr) => { + let report = |dis: Discr<'tcx>, idx, err: &mut Diagnostic| { + let var = adt.variant(idx); // HIR for the duplicate discriminant + let (span, display_discr) = match var.discr { + ty::VariantDiscr::Explicit(discr_def_id) => { // In the case the discriminant is both a duplicate and overflowed, let the user know - if let hir::ExprKind::Lit(lit) = &tcx.hir().body(expr.body).value.kind + if let hir::Node::AnonConst(expr) = tcx.hir().get_by_def_id(discr_def_id.expect_local()) + && let hir::ExprKind::Lit(lit) = &tcx.hir().body(expr.body).value.kind && let rustc_ast::LitKind::Int(lit_value, _int_kind) = &lit.node && *lit_value != dis.val { - (tcx.hir().span(expr.hir_id), format!("`{dis}` (overflowed from `{lit_value}`)")) - // Otherwise, format the value as-is + (tcx.def_span(discr_def_id), format!("`{dis}` (overflowed from `{lit_value}`)")) } else { - (tcx.hir().span(expr.hir_id), format!("`{dis}`")) + // Otherwise, format the value as-is + (tcx.def_span(discr_def_id), format!("`{dis}`")) } } - None => { + // This should not happen. + ty::VariantDiscr::Relative(0) => (tcx.def_span(var.def_id), format!("`{dis}`")), + ty::VariantDiscr::Relative(distance_to_explicit) => { // At this point we know this discriminant is a duplicate, and was not explicitly // assigned by the user. Here we iterate backwards to fetch the HIR for the last // explicitly assigned discriminant, and letting the user know that this was the // increment startpoint, and how many steps from there leading to the duplicate - if let Some((n, hir::Variant { span, ident, .. })) = - vs[..idx].iter().rev().enumerate().find(|v| v.1.disr_expr.is_some()) + if let Some(explicit_idx) = + idx.as_u32().checked_sub(distance_to_explicit).map(VariantIdx::from_u32) { - let ve_ident = var.ident; - let n = n + 1; - let sp = if n > 1 { "variants" } else { "variant" }; + let explicit_variant = adt.variant(explicit_idx); + let ve_ident = var.name; + let ex_ident = explicit_variant.name; + let sp = if distance_to_explicit > 1 { "variants" } else { "variant" }; err.span_label( - *span, - format!("discriminant for `{ve_ident}` incremented from this startpoint (`{ident}` + {n} {sp} later => `{ve_ident}` = {dis})"), + tcx.def_span(explicit_variant.def_id), + format!( + "discriminant for `{ve_ident}` incremented from this startpoint \ + (`{ex_ident}` + {distance_to_explicit} {sp} later \ + => `{ve_ident}` = {dis})" + ), ); } - (vs[idx].span, format!("`{dis}`")) + (tcx.def_span(var.def_id), format!("`{dis}`")) } }; err.span_label(span, format!("{display_discr} assigned here")); }; + let mut discrs = adt.discriminants(tcx).collect::>(); + // Here we loop through the discriminants, comparing each discriminant to another. // When a duplicate is detected, we instantiate an error and point to both // initial and duplicate value. The duplicate discriminant is then discarded by swapping @@ -1257,29 +1260,29 @@ fn detect_discriminant_duplicate<'tcx>( // style as we are mutating `discrs` on the fly). let mut i = 0; while i < discrs.len() { - let hir_var_i_idx = discrs[i].0.index(); + let var_i_idx = discrs[i].0; let mut error: Option> = None; let mut o = i + 1; while o < discrs.len() { - let hir_var_o_idx = discrs[o].0.index(); + let var_o_idx = discrs[o].0; if discrs[i].1.val == discrs[o].1.val { let err = error.get_or_insert_with(|| { let mut ret = struct_span_err!( tcx.sess, - self_span, + tcx.def_span(adt.did()), E0081, "discriminant value `{}` assigned more than once", discrs[i].1, ); - report(discrs[i].1, hir_var_i_idx, &mut ret); + report(discrs[i].1, var_i_idx, &mut ret); ret }); - report(discrs[o].1, hir_var_o_idx, err); + report(discrs[o].1, var_o_idx, err); // Safe to unwrap here, as we wouldn't reach this point if `discrs` was empty discrs[o] = *discrs.last().unwrap(); diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index a23575004655b..99d0beacfa0a1 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -218,19 +218,16 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) { hir::ItemKind::Const(ty, ..) => { check_item_type(tcx, def_id, ty.span, false); } - hir::ItemKind::Struct(ref struct_def, ref ast_generics) => { - check_type_defn(tcx, item, false, |wfcx| vec![wfcx.non_enum_variant(struct_def)]); - + hir::ItemKind::Struct(_, ref ast_generics) => { + check_type_defn(tcx, item, false); check_variances_for_type_defn(tcx, item, ast_generics); } - hir::ItemKind::Union(ref struct_def, ref ast_generics) => { - check_type_defn(tcx, item, true, |wfcx| vec![wfcx.non_enum_variant(struct_def)]); - + hir::ItemKind::Union(_, ref ast_generics) => { + check_type_defn(tcx, item, true); check_variances_for_type_defn(tcx, item, ast_generics); } - hir::ItemKind::Enum(ref enum_def, ref ast_generics) => { - check_type_defn(tcx, item, true, |wfcx| wfcx.enum_variants(enum_def)); - + hir::ItemKind::Enum(_, ref ast_generics) => { + check_type_defn(tcx, item, true); check_variances_for_type_defn(tcx, item, ast_generics); } hir::ItemKind::Trait(..) => { @@ -1037,27 +1034,25 @@ fn item_adt_kind(kind: &ItemKind<'_>) -> Option { } /// In a type definition, we check that to ensure that the types of the fields are well-formed. -fn check_type_defn<'tcx, F>( - tcx: TyCtxt<'tcx>, - item: &hir::Item<'tcx>, - all_sized: bool, - mut lookup_fields: F, -) where - F: FnMut(&WfCheckingCtxt<'_, 'tcx>) -> Vec>, -{ +fn check_type_defn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>, all_sized: bool) { let _ = tcx.representability(item.owner_id.def_id); + let adt_def = tcx.adt_def(item.owner_id); enter_wf_checking_ctxt(tcx, item.span, item.owner_id.def_id, |wfcx| { - let variants = lookup_fields(wfcx); - let packed = tcx.adt_def(item.owner_id).repr().packed(); + let variants = adt_def.variants(); + let packed = adt_def.repr().packed(); - for variant in &variants { + for variant in variants.iter() { // All field types must be well-formed. for field in &variant.fields { + let field_id = field.did.expect_local(); + let hir::Node::Field(hir::FieldDef { ty: hir_ty, .. }) = tcx.hir().get_by_def_id(field_id) + else { bug!() }; + let ty = wfcx.normalize(hir_ty.span, None, tcx.type_of(field.did)); wfcx.register_wf_obligation( - field.span, - Some(WellFormedLoc::Ty(field.def_id)), - field.ty.into(), + hir_ty.span, + Some(WellFormedLoc::Ty(field_id)), + ty.into(), ) } @@ -1065,7 +1060,7 @@ fn check_type_defn<'tcx, F>( // intermediate types must be sized. let needs_drop_copy = || { packed && { - let ty = variant.fields.last().unwrap().ty; + let ty = tcx.type_of(variant.fields.last().unwrap().did); let ty = tcx.erase_regions(ty); if ty.needs_infer() { tcx.sess @@ -1084,27 +1079,31 @@ fn check_type_defn<'tcx, F>( variant.fields[..variant.fields.len() - unsized_len].iter().enumerate() { let last = idx == variant.fields.len() - 1; + let field_id = field.did.expect_local(); + let hir::Node::Field(hir::FieldDef { ty: hir_ty, .. }) = tcx.hir().get_by_def_id(field_id) + else { bug!() }; + let ty = wfcx.normalize(hir_ty.span, None, tcx.type_of(field.did)); wfcx.register_bound( traits::ObligationCause::new( - field.span, + hir_ty.span, wfcx.body_id, traits::FieldSized { adt_kind: match item_adt_kind(&item.kind) { Some(i) => i, None => bug!(), }, - span: field.span, + span: hir_ty.span, last, }, ), wfcx.param_env, - field.ty, + ty, tcx.require_lang_item(LangItem::Sized, None), ); } // Explicit `enum` discriminant values must const-evaluate successfully. - if let Some(discr_def_id) = variant.explicit_discr { + if let ty::VariantDiscr::Explicit(discr_def_id) = variant.discr { let cause = traits::ObligationCause::new( tcx.def_span(discr_def_id), wfcx.body_id, @@ -1114,7 +1113,7 @@ fn check_type_defn<'tcx, F>( cause, wfcx.param_env, ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable( - ty::Const::from_anon_const(tcx, discr_def_id), + ty::Const::from_anon_const(tcx, discr_def_id.expect_local()), )) .to_predicate(tcx), )); @@ -1925,56 +1924,6 @@ fn check_mod_type_wf(tcx: TyCtxt<'_>, module: LocalDefId) { items.par_foreign_items(|item| tcx.ensure().check_well_formed(item.owner_id)); } -/////////////////////////////////////////////////////////////////////////// -// ADT - -// FIXME(eddyb) replace this with getting fields/discriminants through `ty::AdtDef`. -struct AdtVariant<'tcx> { - /// Types of fields in the variant, that must be well-formed. - fields: Vec>, - - /// Explicit discriminant of this variant (e.g. `A = 123`), - /// that must evaluate to a constant value. - explicit_discr: Option, -} - -struct AdtField<'tcx> { - ty: Ty<'tcx>, - def_id: LocalDefId, - span: Span, -} - -impl<'a, 'tcx> WfCheckingCtxt<'a, 'tcx> { - // FIXME(eddyb) replace this with getting fields through `ty::AdtDef`. - fn non_enum_variant(&self, struct_def: &hir::VariantData<'_>) -> AdtVariant<'tcx> { - let fields = struct_def - .fields() - .iter() - .map(|field| { - let def_id = self.tcx().hir().local_def_id(field.hir_id); - let field_ty = self.tcx().type_of(def_id); - let field_ty = self.normalize(field.ty.span, None, field_ty); - debug!("non_enum_variant: type of field {:?} is {:?}", field, field_ty); - AdtField { ty: field_ty, span: field.ty.span, def_id } - }) - .collect(); - AdtVariant { fields, explicit_discr: None } - } - - fn enum_variants(&self, enum_def: &hir::EnumDef<'_>) -> Vec> { - enum_def - .variants - .iter() - .map(|variant| AdtVariant { - fields: self.non_enum_variant(&variant.data).fields, - explicit_discr: variant - .disr_expr - .map(|explicit_discr| self.tcx().hir().local_def_id(explicit_discr.hir_id)), - }) - .collect() - } -} - fn error_392( tcx: TyCtxt<'_>, span: Span, diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 65a1d61e87c1c..46db0f74d4d5f 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -604,11 +604,11 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { } } } - hir::ItemKind::Enum(ref enum_definition, _) => { + hir::ItemKind::Enum(..) => { tcx.ensure().generics_of(def_id); tcx.ensure().type_of(def_id); tcx.ensure().predicates_of(def_id); - convert_enum_variant_types(tcx, def_id.to_def_id(), enum_definition.variants); + convert_enum_variant_types(tcx, def_id.to_def_id()); } hir::ItemKind::Impl { .. } => { tcx.ensure().generics_of(def_id); @@ -640,7 +640,8 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { } if let Some(ctor_hir_id) = struct_def.ctor_hir_id() { - convert_variant_ctor(tcx, ctor_hir_id); + let ctor_def_id = tcx.hir().local_def_id(ctor_hir_id); + convert_variant_ctor(tcx, ctor_def_id); } } @@ -750,37 +751,34 @@ fn convert_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::ImplItemId) { } } -fn convert_variant_ctor(tcx: TyCtxt<'_>, ctor_id: hir::HirId) { - let def_id = tcx.hir().local_def_id(ctor_id); +fn convert_variant_ctor(tcx: TyCtxt<'_>, def_id: LocalDefId) { tcx.ensure().generics_of(def_id); tcx.ensure().type_of(def_id); tcx.ensure().predicates_of(def_id); } -fn convert_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId, variants: &[hir::Variant<'_>]) { +fn convert_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId) { let def = tcx.adt_def(def_id); let repr_type = def.repr().discr_type(); let initial = repr_type.initial_discriminant(tcx); let mut prev_discr = None::>; // fill the discriminant values and field types - for variant in variants { + for variant in def.variants() { let wrapped_discr = prev_discr.map_or(initial, |d| d.wrap_incr(tcx)); prev_discr = Some( - if let Some(ref e) = variant.disr_expr { - let expr_did = tcx.hir().local_def_id(e.hir_id); - def.eval_explicit_discr(tcx, expr_did.to_def_id()) + if let ty::VariantDiscr::Explicit(const_def_id) = variant.discr { + def.eval_explicit_discr(tcx, const_def_id) } else if let Some(discr) = repr_type.disr_incr(tcx, prev_discr) { Some(discr) } else { - struct_span_err!(tcx.sess, variant.span, E0370, "enum discriminant overflowed") - .span_label( - variant.span, - format!("overflowed on value after {}", prev_discr.unwrap()), - ) + let span = tcx.def_span(variant.def_id); + struct_span_err!(tcx.sess, span, E0370, "enum discriminant overflowed") + .span_label(span, format!("overflowed on value after {}", prev_discr.unwrap())) .note(&format!( "explicitly set `{} = {}` if that is desired outcome", - variant.ident, wrapped_discr + tcx.item_name(variant.def_id), + wrapped_discr )) .emit(); None @@ -788,17 +786,16 @@ fn convert_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId, variants: &[hir::V .unwrap_or(wrapped_discr), ); - for f in variant.data.fields() { - let def_id = tcx.hir().local_def_id(f.hir_id); - tcx.ensure().generics_of(def_id); - tcx.ensure().type_of(def_id); - tcx.ensure().predicates_of(def_id); + for f in &variant.fields { + tcx.ensure().generics_of(f.did); + tcx.ensure().type_of(f.did); + tcx.ensure().predicates_of(f.did); } // Convert the ctor, if any. This also registers the variant as // an item. - if let Some(ctor_hir_id) = variant.data.ctor_hir_id() { - convert_variant_ctor(tcx, ctor_hir_id); + if let Some(ctor_def_id) = variant.ctor_def_id { + convert_variant_ctor(tcx, ctor_def_id.expect_local()); } } } diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs index 7f76364e15a75..b706d786b5251 100644 --- a/compiler/rustc_hir_typeck/src/check.rs +++ b/compiler/rustc_hir_typeck/src/check.rs @@ -211,13 +211,6 @@ pub(super) fn check_fn<'a, 'tcx>( check_panic_info_fn(tcx, panic_impl_did.expect_local(), fn_sig, decl, declared_ret_ty); } - // Check that a function marked as `#[alloc_error_handler]` has signature `fn(Layout) -> !` - if let Some(alloc_error_handler_did) = tcx.lang_items().oom() - && alloc_error_handler_did == hir.local_def_id(fn_id).to_def_id() - { - check_alloc_error_fn(tcx, alloc_error_handler_did.expect_local(), fn_sig, decl, declared_ret_ty); - } - (fcx, gen_ty) } @@ -273,52 +266,3 @@ fn check_panic_info_fn( tcx.sess.span_err(span, "should have no const parameters"); } } - -fn check_alloc_error_fn( - tcx: TyCtxt<'_>, - fn_id: LocalDefId, - fn_sig: ty::FnSig<'_>, - decl: &hir::FnDecl<'_>, - declared_ret_ty: Ty<'_>, -) { - let Some(alloc_layout_did) = tcx.lang_items().alloc_layout() else { - tcx.sess.err("language item required, but not found: `alloc_layout`"); - return; - }; - - if *declared_ret_ty.kind() != ty::Never { - tcx.sess.span_err(decl.output.span(), "return type should be `!`"); - } - - let inputs = fn_sig.inputs(); - if inputs.len() != 1 { - tcx.sess.span_err(tcx.def_span(fn_id), "function should have one argument"); - return; - } - - let arg_is_alloc_layout = match inputs[0].kind() { - ty::Adt(ref adt, _) => adt.did() == alloc_layout_did, - _ => false, - }; - - if !arg_is_alloc_layout { - tcx.sess.span_err(decl.inputs[0].span, "argument should be `Layout`"); - } - - let DefKind::Fn = tcx.def_kind(fn_id) else { - let span = tcx.def_span(fn_id); - tcx.sess.span_err(span, "`#[alloc_error_handler]` should be a function"); - return; - }; - - let generic_counts = tcx.generics_of(fn_id).own_counts(); - if generic_counts.types != 0 { - let span = tcx.def_span(fn_id); - tcx.sess.span_err(span, "`#[alloc_error_handler]` function should have no type parameters"); - } - if generic_counts.consts != 0 { - let span = tcx.def_span(fn_id); - tcx.sess - .span_err(span, "`#[alloc_error_handler]` function should have no const parameters"); - } -} diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index cfcceecbef40e..d4c457975a842 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -1,8 +1,10 @@ //! Validates all used crates and extern libraries and loads their metadata use crate::errors::{ - ConflictingGlobalAlloc, CrateNotPanicRuntime, GlobalAllocRequired, NoMultipleGlobalAlloc, - NoPanicStrategy, NoTransitiveNeedsDep, NotProfilerRuntime, ProfilerBuiltinsNeedsCore, + AllocFuncRequired, ConflictingAllocErrorHandler, ConflictingGlobalAlloc, CrateNotPanicRuntime, + GlobalAllocRequired, MissingAllocErrorHandler, NoMultipleAllocErrorHandler, + NoMultipleGlobalAlloc, NoPanicStrategy, NoTransitiveNeedsDep, NotProfilerRuntime, + ProfilerBuiltinsNeedsCore, }; use crate::locator::{CrateError, CrateLocator, CratePaths}; use crate::rmeta::{CrateDep, CrateMetadata, CrateNumMap, CrateRoot, MetadataBlob}; @@ -41,8 +43,13 @@ pub struct CStore { /// This crate needs an allocator and either provides it itself, or finds it in a dependency. /// If the above is true, then this field denotes the kind of the found allocator. allocator_kind: Option, + /// This crate needs an allocation error handler and either provides it itself, or finds it in a dependency. + /// If the above is true, then this field denotes the kind of the found allocator. + alloc_error_handler_kind: Option, /// This crate has a `#[global_allocator]` item. has_global_allocator: bool, + /// This crate has a `#[alloc_error_handler]` item. + has_alloc_error_handler: bool, /// This map is used to verify we get no hash conflicts between /// `StableCrateId` values. @@ -197,10 +204,18 @@ impl CStore { self.allocator_kind } + pub(crate) fn alloc_error_handler_kind(&self) -> Option { + self.alloc_error_handler_kind + } + pub(crate) fn has_global_allocator(&self) -> bool { self.has_global_allocator } + pub(crate) fn has_alloc_error_handler(&self) -> bool { + self.has_alloc_error_handler + } + pub fn report_unused_deps(&self, tcx: TyCtxt<'_>) { let json_unused_externs = tcx.sess.opts.json_unused_externs; @@ -247,7 +262,9 @@ impl<'a> CrateLoader<'a> { metas: IndexVec::from_elem_n(None, 1), injected_panic_runtime: None, allocator_kind: None, + alloc_error_handler_kind: None, has_global_allocator: false, + has_alloc_error_handler: false, stable_crate_ids, unused_externs: Vec::new(), }, @@ -792,6 +809,13 @@ impl<'a> CrateLoader<'a> { } spans => !spans.is_empty(), }; + self.cstore.has_alloc_error_handler = match &*alloc_error_handler_spans(&self.sess, krate) { + [span1, span2, ..] => { + self.sess.emit_err(NoMultipleAllocErrorHandler { span2: *span2, span1: *span1 }); + true + } + spans => !spans.is_empty(), + }; // Check to see if we actually need an allocator. This desire comes // about through the `#![needs_allocator]` attribute and is typically @@ -832,22 +856,48 @@ impl<'a> CrateLoader<'a> { } } } + let mut alloc_error_handler = + self.cstore.has_alloc_error_handler.then(|| Symbol::intern("this crate")); + for (_, data) in self.cstore.iter_crate_data() { + if data.has_alloc_error_handler() { + match alloc_error_handler { + Some(other_crate) => { + self.sess.emit_err(ConflictingAllocErrorHandler { + crate_name: data.name(), + other_crate_name: other_crate, + }); + } + None => alloc_error_handler = Some(data.name()), + } + } + } if global_allocator.is_some() { self.cstore.allocator_kind = Some(AllocatorKind::Global); - return; + } else { + // Ok we haven't found a global allocator but we still need an + // allocator. At this point our allocator request is typically fulfilled + // by the standard library, denoted by the `#![default_lib_allocator]` + // attribute. + if !self.sess.contains_name(&krate.attrs, sym::default_lib_allocator) + && !self.cstore.iter_crate_data().any(|(_, data)| data.has_default_lib_allocator()) + { + self.sess.emit_err(GlobalAllocRequired); + } + self.cstore.allocator_kind = Some(AllocatorKind::Default); } - // Ok we haven't found a global allocator but we still need an - // allocator. At this point our allocator request is typically fulfilled - // by the standard library, denoted by the `#![default_lib_allocator]` - // attribute. - if !self.sess.contains_name(&krate.attrs, sym::default_lib_allocator) - && !self.cstore.iter_crate_data().any(|(_, data)| data.has_default_lib_allocator()) - { - self.sess.emit_err(GlobalAllocRequired); + if alloc_error_handler.is_some() { + self.cstore.alloc_error_handler_kind = Some(AllocatorKind::Global); + } else { + // The alloc crate provides a default allocation error handler if + // one isn't specified. + if !self.sess.features_untracked().default_alloc_error_handler { + self.sess.emit_err(AllocFuncRequired); + self.sess.emit_note(MissingAllocErrorHandler); + } + self.cstore.alloc_error_handler_kind = Some(AllocatorKind::Default); } - self.cstore.allocator_kind = Some(AllocatorKind::Default); } fn inject_dependency_if( @@ -1023,3 +1073,26 @@ fn global_allocator_spans(sess: &Session, krate: &ast::Crate) -> Vec { visit::walk_crate(&mut f, krate); f.spans } + +fn alloc_error_handler_spans(sess: &Session, krate: &ast::Crate) -> Vec { + struct Finder<'a> { + sess: &'a Session, + name: Symbol, + spans: Vec, + } + impl<'ast, 'a> visit::Visitor<'ast> for Finder<'a> { + fn visit_item(&mut self, item: &'ast ast::Item) { + if item.ident.name == self.name + && self.sess.contains_name(&item.attrs, sym::rustc_std_internal_symbol) + { + self.spans.push(item.span); + } + visit::walk_item(self, item) + } + } + + let name = Symbol::intern(&AllocatorKind::Global.fn_name(sym::oom)); + let mut f = Finder { sess, name, spans: Vec::new() }; + visit::walk_crate(&mut f, krate); + f.spans +} diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs index 7c387b9a9ecde..289fa53aa5ef6 100644 --- a/compiler/rustc_metadata/src/errors.rs +++ b/compiler/rustc_metadata/src/errors.rs @@ -343,6 +343,16 @@ pub struct NoMultipleGlobalAlloc { pub span1: Span, } +#[derive(Diagnostic)] +#[diag(metadata_no_multiple_alloc_error_handler)] +pub struct NoMultipleAllocErrorHandler { + #[primary_span] + #[label] + pub span2: Span, + #[label(metadata_prev_alloc_error_handler)] + pub span1: Span, +} + #[derive(Diagnostic)] #[diag(metadata_conflicting_global_alloc)] pub struct ConflictingGlobalAlloc { @@ -350,10 +360,25 @@ pub struct ConflictingGlobalAlloc { pub other_crate_name: Symbol, } +#[derive(Diagnostic)] +#[diag(metadata_conflicting_alloc_error_handler)] +pub struct ConflictingAllocErrorHandler { + pub crate_name: Symbol, + pub other_crate_name: Symbol, +} + #[derive(Diagnostic)] #[diag(metadata_global_alloc_required)] pub struct GlobalAllocRequired; +#[derive(Diagnostic)] +#[diag(metadata_alloc_func_required)] +pub struct AllocFuncRequired; + +#[derive(Diagnostic)] +#[diag(metadata_missing_alloc_error_handler)] +pub struct MissingAllocErrorHandler; + #[derive(Diagnostic)] #[diag(metadata_no_transitive_needs_dep)] pub struct NoTransitiveNeedsDep<'a> { diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 17a7532044a44..8e80d794a1368 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1764,6 +1764,10 @@ impl CrateMetadata { self.root.has_global_allocator } + pub(crate) fn has_alloc_error_handler(&self) -> bool { + self.root.has_alloc_error_handler + } + pub(crate) fn has_default_lib_allocator(&self) -> bool { self.root.has_default_lib_allocator } diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index a0a0855251b8d..f475b0b39811c 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -255,6 +255,7 @@ provide! { tcx, def_id, other, cdata, is_panic_runtime => { cdata.root.panic_runtime } is_compiler_builtins => { cdata.root.compiler_builtins } has_global_allocator => { cdata.root.has_global_allocator } + has_alloc_error_handler => { cdata.root.has_alloc_error_handler } has_panic_handler => { cdata.root.has_panic_handler } is_profiler_runtime => { cdata.root.profiler_runtime } required_panic_strategy => { cdata.root.required_panic_strategy } @@ -339,6 +340,7 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) { // resolve! Does this work? Unsure! That's what the issue is about *providers = Providers { allocator_kind: |tcx, ()| CStore::from_tcx(tcx).allocator_kind(), + alloc_error_handler_kind: |tcx, ()| CStore::from_tcx(tcx).alloc_error_handler_kind(), is_private_dep: |_tcx, cnum| { assert_eq!(cnum, LOCAL_CRATE); false @@ -464,6 +466,10 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) { assert_eq!(cnum, LOCAL_CRATE); CStore::from_tcx(tcx).has_global_allocator() }, + has_alloc_error_handler: |tcx, cnum| { + assert_eq!(cnum, LOCAL_CRATE); + CStore::from_tcx(tcx).has_alloc_error_handler() + }, postorder_cnums: |tcx, ()| { tcx.arena .alloc_slice(&CStore::from_tcx(tcx).crate_dependencies_in_postorder(LOCAL_CRATE)) diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 87fa69e1639a1..c907ee6462870 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -670,6 +670,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { panic_in_drop_strategy: tcx.sess.opts.unstable_opts.panic_in_drop, edition: tcx.sess.edition(), has_global_allocator: tcx.has_global_allocator(LOCAL_CRATE), + has_alloc_error_handler: tcx.has_alloc_error_handler(LOCAL_CRATE), has_panic_handler: tcx.has_panic_handler(LOCAL_CRATE), has_default_lib_allocator: tcx .sess diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 774cff2075d09..aa6d378a43aca 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -223,6 +223,7 @@ pub(crate) struct CrateRoot { panic_in_drop_strategy: PanicStrategy, edition: Edition, has_global_allocator: bool, + has_alloc_error_handler: bool, has_panic_handler: bool, has_default_lib_allocator: bool, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index a098e570305c8..33acaed435b89 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1391,6 +1391,13 @@ rustc_queries! { desc { "checking if the crate has_global_allocator" } separate_provide_extern } + query has_alloc_error_handler(_: CrateNum) -> bool { + // This query depends on untracked global state in CStore + eval_always + fatal_cycle + desc { "checking if the crate has_alloc_error_handler" } + separate_provide_extern + } query has_panic_handler(_: CrateNum) -> bool { fatal_cycle desc { "checking if the crate has_panic_handler" } @@ -1761,6 +1768,10 @@ rustc_queries! { eval_always desc { "getting the allocator kind for the current crate" } } + query alloc_error_handler_kind(_: ()) -> Option { + eval_always + desc { "alloc error handler kind for the current crate" } + } query upvars_mentioned(def_id: DefId) -> Option<&'tcx FxIndexMap> { desc { |tcx| "collecting upvars mentioned in `{}`", tcx.def_path_str(def_id) } diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs index 3dafdcb788710..5c82fb1ddc0d5 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs @@ -2,6 +2,7 @@ use rustc_index::vec::Idx; use rustc_middle::ty::util::IntTypeExt; +use rustc_target::abi::{Abi, Primitive}; use crate::build::expr::as_place::PlaceBase; use crate::build::expr::category::{Category, RvalueFunc}; @@ -198,6 +199,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let (source, ty) = if let ty::Adt(adt_def, ..) = source.ty.kind() && adt_def.is_enum() { let discr_ty = adt_def.repr().discr_type().to_ty(this.tcx); let temp = unpack!(block = this.as_temp(block, scope, source, Mutability::Not)); + let layout = this.tcx.layout_of(this.param_env.and(source.ty)); let discr = this.temp(discr_ty, source.span); this.cfg.push_assign( block, @@ -205,8 +207,55 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { discr, Rvalue::Discriminant(temp.into()), ); + let (op,ty) = (Operand::Move(discr), discr_ty); + + if let Abi::Scalar(scalar) = layout.unwrap().abi{ + if let Primitive::Int(_, signed) = scalar.primitive() { + let range = scalar.valid_range(&this.tcx); + // FIXME: Handle wraparound cases too. + if range.end >= range.start { + let mut assumer = |range: u128, bin_op: BinOp| { + // We will be overwriting this val if our scalar is signed value + // because sign extension on unsigned types might cause unintended things + let mut range_val = + ConstantKind::from_bits(this.tcx, range, ty::ParamEnv::empty().and(discr_ty)); + let bool_ty = this.tcx.types.bool; + if signed { + let scalar_size_extend = scalar.size(&this.tcx).sign_extend(range); + let discr_layout = this.tcx.layout_of(this.param_env.and(discr_ty)); + let truncated_val = discr_layout.unwrap().size.truncate(scalar_size_extend); + range_val = ConstantKind::from_bits( + this.tcx, + truncated_val, + ty::ParamEnv::empty().and(discr_ty), + ); + } + let lit_op = this.literal_operand(expr.span, range_val); + let is_bin_op = this.temp(bool_ty, expr_span); + this.cfg.push_assign( + block, + source_info, + is_bin_op, + Rvalue::BinaryOp(bin_op, Box::new(((lit_op), (Operand::Copy(discr))))), + ); + this.cfg.push( + block, + Statement { + source_info, + kind: StatementKind::Intrinsic(Box::new(NonDivergingIntrinsic::Assume( + Operand::Copy(is_bin_op), + ))), + }, + ) + }; + assumer(range.end, BinOp::Ge); + assumer(range.start, BinOp::Le); + } + } + } + + (op,ty) - (Operand::Move(discr), discr_ty) } else { let ty = source.ty; let source = unpack!( diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs index f8f04214a2ca5..959fcf8d89e86 100644 --- a/compiler/rustc_mir_transform/src/check_unsafety.rs +++ b/compiler/rustc_mir_transform/src/check_unsafety.rs @@ -101,12 +101,10 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> { | StatementKind::Retag { .. } | StatementKind::AscribeUserType(..) | StatementKind::Coverage(..) + | StatementKind::Intrinsic(..) | StatementKind::Nop => { // safe (at least as emitted during MIR construction) } - - // Move to above list once mir construction uses it. - StatementKind::Intrinsic(..) => unreachable!(), } self.super_statement(statement, location); } diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 753d01f46cabd..b779edbc30f75 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -470,11 +470,6 @@ fn has_allow_dead_code_or_lang_attr_helper( return true; } - // (To be) stable attribute for #[lang = "oom"] - if tcx.sess.contains_name(attrs, sym::alloc_error_handler) { - return true; - } - let def_id = tcx.hir().local_def_id(id); if tcx.def_kind(def_id).has_codegen_attrs() { let cg_attrs = tcx.codegen_fn_attrs(def_id); diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index adaaf5392425b..4a5cfd2d429cd 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -701,14 +701,6 @@ pub struct UnknownExternLangItem { #[diag(passes_missing_panic_handler)] pub struct MissingPanicHandler; -#[derive(Diagnostic)] -#[diag(passes_alloc_func_required)] -pub struct AllocFuncRequired; - -#[derive(Diagnostic)] -#[diag(passes_missing_alloc_error_handler)] -pub struct MissingAllocErrorHandler; - #[derive(Diagnostic)] #[diag(passes_missing_lang_item)] #[note] diff --git a/compiler/rustc_passes/src/weak_lang_items.rs b/compiler/rustc_passes/src/weak_lang_items.rs index 94d6a405b530e..f0815fcd8db9a 100644 --- a/compiler/rustc_passes/src/weak_lang_items.rs +++ b/compiler/rustc_passes/src/weak_lang_items.rs @@ -7,10 +7,7 @@ use rustc_middle::middle::lang_items::required; use rustc_middle::ty::TyCtxt; use rustc_session::config::CrateType; -use crate::errors::{ - AllocFuncRequired, MissingAllocErrorHandler, MissingLangItem, MissingPanicHandler, - UnknownExternLangItem, -}; +use crate::errors::{MissingLangItem, MissingPanicHandler, UnknownExternLangItem}; /// Checks the crate for usage of weak lang items, returning a vector of all the /// language items required by this crate, but not defined yet. @@ -69,11 +66,6 @@ fn verify<'tcx>(tcx: TyCtxt<'tcx>, items: &lang_items::LanguageItems) { if missing.contains(&item) && required(tcx, item) && items.get(item).is_none() { if item == LangItem::PanicImpl { tcx.sess.emit_err(MissingPanicHandler); - } else if item == LangItem::Oom { - if !tcx.features().default_alloc_error_handler { - tcx.sess.emit_err(AllocFuncRequired); - tcx.sess.emit_note(MissingAllocErrorHandler); - } } else { tcx.sess.emit_err(MissingLangItem { name: item.name() }); } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 00eb768ad18d4..6d2ee25df320d 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -32,7 +32,7 @@ use smallvec::{smallvec, SmallVec}; use rustc_span::source_map::{respan, Spanned}; use std::assert_matches::debug_assert_matches; use std::collections::{hash_map::Entry, BTreeSet}; -use std::mem::{replace, take}; +use std::mem::{replace, swap, take}; mod diagnostics; @@ -3369,11 +3369,6 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { let (mut err, candidates) = this.smart_resolve_report_errors(path, path_span, PathSource::Type, None); - if candidates.is_empty() { - err.cancel(); - return Some(parent_err); - } - // There are two different error messages user might receive at // this point: // - E0412 cannot find type `{}` in this scope @@ -3383,37 +3378,62 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { // latter one - for paths in expression-position. // // Thus (since we're in expression-position at this point), not to - // confuse the user, we want to keep the *message* from E0432 (so + // confuse the user, we want to keep the *message* from E0433 (so // `parent_err`), but we want *hints* from E0412 (so `err`). // // And that's what happens below - we're just mixing both messages // into a single one. let mut parent_err = this.r.into_struct_error(parent_err.span, parent_err.node); + // overwrite all properties with the parent's error message err.message = take(&mut parent_err.message); err.code = take(&mut parent_err.code); + swap(&mut err.span, &mut parent_err.span); err.children = take(&mut parent_err.children); + err.sort_span = parent_err.sort_span; + err.is_lint = parent_err.is_lint; + + // merge the parent's suggestions with the typo suggestions + fn append_result(res1: &mut Result, E>, res2: Result, E>) { + match res1 { + Ok(vec1) => match res2 { + Ok(mut vec2) => vec1.append(&mut vec2), + Err(e) => *res1 = Err(e), + }, + Err(_) => (), + }; + } + append_result(&mut err.suggestions, parent_err.suggestions.clone()); parent_err.cancel(); let def_id = this.parent_scope.module.nearest_parent_mod(); if this.should_report_errs() { - this.r.use_injections.push(UseError { - err, - candidates, - def_id, - instead: false, - suggestion: None, - path: path.into(), - is_call: source.is_call(), - }); + if candidates.is_empty() { + // When there is no suggested imports, we can just emit the error + // and suggestions immediately. Note that we bypass the usually error + // reporting routine (ie via `self.r.report_error`) because we need + // to post-process the `ResolutionError` above. + err.emit(); + } else { + // If there are suggested imports, the error reporting is delayed + this.r.use_injections.push(UseError { + err, + candidates, + def_id, + instead: false, + suggestion: None, + path: path.into(), + is_call: source.is_call(), + }); + } } else { err.cancel(); } // We don't return `Some(parent_err)` here, because the error will - // be already printed as part of the `use` injections + // be already printed either immediately or as part of the `use` injections None }; diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index 8187517ccfbb4..8c6663569a553 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -402,19 +402,18 @@ pub use std::alloc::handle_alloc_error; #[allow(unused_attributes)] #[unstable(feature = "alloc_internals", issue = "none")] pub mod __alloc_error_handler { - use crate::alloc::Layout; - - // called via generated `__rust_alloc_error_handler` - - // if there is no `#[alloc_error_handler]` + // called via generated `__rust_alloc_error_handler` if there is no + // `#[alloc_error_handler]`. #[rustc_std_internal_symbol] pub unsafe fn __rdl_oom(size: usize, _align: usize) -> ! { panic!("memory allocation of {size} bytes failed") } - // if there is an `#[alloc_error_handler]` + #[cfg(bootstrap)] #[rustc_std_internal_symbol] pub unsafe fn __rg_oom(size: usize, align: usize) -> ! { + use crate::alloc::Layout; + let layout = unsafe { Layout::from_size_align_unchecked(size, align) }; extern "Rust" { #[lang = "oom"] diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index fd96e1ff77d53..2850d84acc327 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -1511,6 +1511,17 @@ pub(crate) mod builtin { /* compiler built-in */ } + /// Attribute macro applied to a function to register it as a handler for allocation failure. + /// + /// See also [`std::alloc::handle_alloc_error`](../../../std/alloc/fn.handle_alloc_error.html). + #[cfg(not(bootstrap))] + #[unstable(feature = "alloc_error_handler", issue = "51540")] + #[allow_internal_unstable(rustc_attrs)] + #[rustc_builtin_macro] + pub macro alloc_error_handler($item:item) { + /* compiler built-in */ + } + /// Keeps the item it's applied to if the passed path is accessible, and removes it otherwise. #[unstable( feature = "cfg_accessible", diff --git a/library/core/src/prelude/v1.rs b/library/core/src/prelude/v1.rs index b566e211cd89d..804a179bdb3c0 100644 --- a/library/core/src/prelude/v1.rs +++ b/library/core/src/prelude/v1.rs @@ -75,6 +75,9 @@ pub use crate::macros::builtin::{RustcDecodable, RustcEncodable}; // Do not `doc(no_inline)` so that they become doc items on their own // (no public module for them to be re-exported from). +#[cfg(not(bootstrap))] +#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] +pub use crate::macros::builtin::alloc_error_handler; #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] pub use crate::macros::builtin::{bench, derive, global_allocator, test, test_case}; diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 51f858adee167..eda176d9fcbe6 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -5,6 +5,7 @@ #![feature(bigint_helper_methods)] #![feature(cell_update)] #![feature(const_assume)] +#![feature(const_align_of_val_raw)] #![feature(const_black_box)] #![feature(const_bool_to_option)] #![feature(const_caller_location)] @@ -42,6 +43,7 @@ #![feature(try_find)] #![feature(inline_const)] #![feature(is_sorted)] +#![feature(layout_for_ptr)] #![feature(pattern)] #![feature(pin_macro)] #![feature(sort_internals)] diff --git a/library/core/tests/mem.rs b/library/core/tests/mem.rs index 0362e1c8afb5e..1cfb4fd9fd186 100644 --- a/library/core/tests/mem.rs +++ b/library/core/tests/mem.rs @@ -1,4 +1,5 @@ use core::mem::*; +use core::ptr; #[cfg(panic = "unwind")] use std::rc::Rc; @@ -75,6 +76,25 @@ fn align_of_val_basic() { assert_eq!(align_of_val(&1u32), 4); } +#[test] +#[cfg(not(bootstrap))] // stage 0 doesn't have the fix yet, so the test fails +fn align_of_val_raw_packed() { + #[repr(C, packed)] + struct B { + f: [u32], + } + let storage = [0u8; 4]; + let b: *const B = ptr::from_raw_parts(storage.as_ptr().cast(), 1); + assert_eq!(unsafe { align_of_val_raw(b) }, 1); + + const ALIGN_OF_VAL_RAW: usize = { + let storage = [0u8; 4]; + let b: *const B = ptr::from_raw_parts(storage.as_ptr().cast(), 1); + unsafe { align_of_val_raw(b) } + }; + assert_eq!(ALIGN_OF_VAL_RAW, 1); +} + #[test] fn test_swap() { let mut x = 31337; diff --git a/library/std/src/net/mod.rs b/library/std/src/net/mod.rs index 01e3db9de51c4..19d90e7ec3839 100644 --- a/library/std/src/net/mod.rs +++ b/library/std/src/net/mod.rs @@ -11,7 +11,7 @@ //! [`Ipv6Addr`] are respectively IPv4 and IPv6 addresses //! * [`SocketAddr`] represents socket addresses of either IPv4 or IPv6; [`SocketAddrV4`] //! and [`SocketAddrV6`] are respectively IPv4 and IPv6 socket addresses -//! * [`ToSocketAddrs`] is a trait that used for generic address resolution when interacting +//! * [`ToSocketAddrs`] is a trait that is used for generic address resolution when interacting //! with networking objects like [`TcpListener`], [`TcpStream`] or [`UdpSocket`] //! * Other types are return or parameter types for various methods in this module //! diff --git a/library/std/src/prelude/v1.rs b/library/std/src/prelude/v1.rs index 0226c4d7a2581..36d9e8921ef31 100644 --- a/library/std/src/prelude/v1.rs +++ b/library/std/src/prelude/v1.rs @@ -59,6 +59,9 @@ pub use core::prelude::v1::{RustcDecodable, RustcEncodable}; // Do not `doc(no_inline)` so that they become doc items on their own // (no public module for them to be re-exported from). +#[cfg(not(bootstrap))] +#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] +pub use core::prelude::v1::alloc_error_handler; #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] pub use core::prelude::v1::{bench, derive, global_allocator, test, test_case}; diff --git a/src/test/codegen/enum-bounds-check-derived-idx.rs b/src/test/codegen/enum-bounds-check-derived-idx.rs index fe02aeb5f6252..aa66c2ed08edb 100644 --- a/src/test/codegen/enum-bounds-check-derived-idx.rs +++ b/src/test/codegen/enum-bounds-check-derived-idx.rs @@ -12,15 +12,13 @@ pub enum Bar { // CHECK-LABEL: @lookup_inc #[no_mangle] pub fn lookup_inc(buf: &[u8; 5], f: Bar) -> u8 { - // FIXME: panic check can be removed by adding the assumes back after https://github.com/rust-lang/rust/pull/98332 - // CHECK: panic_bounds_check + // CHECK-NOT: panic_bounds_check buf[f as usize + 1] } // CHECK-LABEL: @lookup_dec #[no_mangle] pub fn lookup_dec(buf: &[u8; 5], f: Bar) -> u8 { - // FIXME: panic check can be removed by adding the assumes back after https://github.com/rust-lang/rust/pull/98332 - // CHECK: panic_bounds_check + // CHECK-NOT: panic_bounds_check buf[f as usize - 1] } diff --git a/src/test/codegen/enum-bounds-check-issue-13926.rs b/src/test/codegen/enum-bounds-check-issue-13926.rs index 1aec41d54411b..b26945bc54940 100644 --- a/src/test/codegen/enum-bounds-check-issue-13926.rs +++ b/src/test/codegen/enum-bounds-check-issue-13926.rs @@ -13,7 +13,6 @@ pub enum Exception { // CHECK-LABEL: @access #[no_mangle] pub fn access(array: &[usize; 12], exc: Exception) -> usize { - // FIXME: panic check can be removed by adding the assumes back after https://github.com/rust-lang/rust/pull/98332 - // CHECK: panic_bounds_check + // CHECK-NOT: panic_bounds_check array[(exc as u8 - 4) as usize] } diff --git a/src/test/codegen/enum-bounds-check.rs b/src/test/codegen/enum-bounds-check.rs index f85c6817deda3..17322d5911b92 100644 --- a/src/test/codegen/enum-bounds-check.rs +++ b/src/test/codegen/enum-bounds-check.rs @@ -21,7 +21,6 @@ pub enum Bar { // CHECK-LABEL: @lookup_unmodified #[no_mangle] pub fn lookup_unmodified(buf: &[u8; 5], f: Bar) -> u8 { - // FIXME: panic check can be removed by adding the assumes back after https://github.com/rust-lang/rust/pull/98332 - // CHECK: panic_bounds_check + // CHECK-NOT: panic_bounds_check buf[f as usize] } diff --git a/src/test/mir-opt/building/enum_cast.bar.built.after.mir b/src/test/mir-opt/building/enum_cast.bar.built.after.mir index 194b107bead89..0746e0b498e95 100644 --- a/src/test/mir-opt/building/enum_cast.bar.built.after.mir +++ b/src/test/mir-opt/building/enum_cast.bar.built.after.mir @@ -5,11 +5,17 @@ fn bar(_1: Bar) -> usize { let mut _0: usize; // return place in scope 0 at $DIR/enum_cast.rs:+0:21: +0:26 let _2: Bar; // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:8 let mut _3: isize; // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:8 + let mut _4: bool; // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:17 + let mut _5: bool; // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:17 bb0: { StorageLive(_2); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:8 _2 = move _1; // scope 0 at $DIR/enum_cast.rs:+1:5: +1:8 _3 = discriminant(_2); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17 + _4 = Ge(const 1_isize, _3); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17 + assume(_4); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17 + _5 = Le(const 0_isize, _3); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17 + assume(_5); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17 _0 = move _3 as usize (IntToInt); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17 StorageDead(_2); // scope 0 at $DIR/enum_cast.rs:+1:16: +1:17 return; // scope 0 at $DIR/enum_cast.rs:+2:2: +2:2 diff --git a/src/test/mir-opt/building/enum_cast.boo.built.after.mir b/src/test/mir-opt/building/enum_cast.boo.built.after.mir index dde26afc77a0c..699c876b01ac8 100644 --- a/src/test/mir-opt/building/enum_cast.boo.built.after.mir +++ b/src/test/mir-opt/building/enum_cast.boo.built.after.mir @@ -5,11 +5,17 @@ fn boo(_1: Boo) -> usize { let mut _0: usize; // return place in scope 0 at $DIR/enum_cast.rs:+0:21: +0:26 let _2: Boo; // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:8 let mut _3: u8; // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:8 + let mut _4: bool; // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:17 + let mut _5: bool; // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:17 bb0: { StorageLive(_2); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:8 _2 = move _1; // scope 0 at $DIR/enum_cast.rs:+1:5: +1:8 _3 = discriminant(_2); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17 + _4 = Ge(const 1_u8, _3); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17 + assume(_4); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17 + _5 = Le(const 0_u8, _3); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17 + assume(_5); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17 _0 = move _3 as usize (IntToInt); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17 StorageDead(_2); // scope 0 at $DIR/enum_cast.rs:+1:16: +1:17 return; // scope 0 at $DIR/enum_cast.rs:+2:2: +2:2 diff --git a/src/test/mir-opt/building/enum_cast.droppy.built.after.mir b/src/test/mir-opt/building/enum_cast.droppy.built.after.mir index a43c523c71f3c..5231c2eab9574 100644 --- a/src/test/mir-opt/building/enum_cast.droppy.built.after.mir +++ b/src/test/mir-opt/building/enum_cast.droppy.built.after.mir @@ -6,7 +6,9 @@ fn droppy() -> () { let _2: Droppy; // in scope 0 at $DIR/enum_cast.rs:+2:13: +2:14 let _4: Droppy; // in scope 0 at $DIR/enum_cast.rs:+5:17: +5:18 let mut _5: isize; // in scope 0 at $DIR/enum_cast.rs:+5:17: +5:18 - let _6: Droppy; // in scope 0 at $DIR/enum_cast.rs:+7:9: +7:10 + let mut _6: bool; // in scope 0 at $DIR/enum_cast.rs:+5:17: +5:27 + let mut _7: bool; // in scope 0 at $DIR/enum_cast.rs:+5:17: +5:27 + let _8: Droppy; // in scope 0 at $DIR/enum_cast.rs:+7:9: +7:10 scope 1 { debug x => _2; // in scope 1 at $DIR/enum_cast.rs:+2:13: +2:14 scope 2 { @@ -17,7 +19,7 @@ fn droppy() -> () { } } scope 4 { - debug z => _6; // in scope 4 at $DIR/enum_cast.rs:+7:9: +7:10 + debug z => _8; // in scope 4 at $DIR/enum_cast.rs:+7:9: +7:10 } bb0: { @@ -29,6 +31,10 @@ fn droppy() -> () { StorageLive(_4); // scope 3 at $DIR/enum_cast.rs:+5:17: +5:18 _4 = move _2; // scope 3 at $DIR/enum_cast.rs:+5:17: +5:18 _5 = discriminant(_4); // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27 + _6 = Ge(const 2_isize, _5); // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27 + assume(_6); // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27 + _7 = Le(const 0_isize, _5); // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27 + assume(_7); // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27 _3 = move _5 as usize (IntToInt); // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27 drop(_4) -> [return: bb1, unwind: bb4]; // scope 3 at $DIR/enum_cast.rs:+5:26: +5:27 } @@ -44,15 +50,15 @@ fn droppy() -> () { bb2: { StorageDead(_2); // scope 0 at $DIR/enum_cast.rs:+6:5: +6:6 StorageDead(_1); // scope 0 at $DIR/enum_cast.rs:+6:5: +6:6 - StorageLive(_6); // scope 0 at $DIR/enum_cast.rs:+7:9: +7:10 - _6 = Droppy::B; // scope 0 at $DIR/enum_cast.rs:+7:13: +7:22 - FakeRead(ForLet(None), _6); // scope 0 at $DIR/enum_cast.rs:+7:9: +7:10 + StorageLive(_8); // scope 0 at $DIR/enum_cast.rs:+7:9: +7:10 + _8 = Droppy::B; // scope 0 at $DIR/enum_cast.rs:+7:13: +7:22 + FakeRead(ForLet(None), _8); // scope 0 at $DIR/enum_cast.rs:+7:9: +7:10 _0 = const (); // scope 0 at $DIR/enum_cast.rs:+0:13: +8:2 - drop(_6) -> [return: bb3, unwind: bb5]; // scope 0 at $DIR/enum_cast.rs:+8:1: +8:2 + drop(_8) -> [return: bb3, unwind: bb5]; // scope 0 at $DIR/enum_cast.rs:+8:1: +8:2 } bb3: { - StorageDead(_6); // scope 0 at $DIR/enum_cast.rs:+8:1: +8:2 + StorageDead(_8); // scope 0 at $DIR/enum_cast.rs:+8:1: +8:2 return; // scope 0 at $DIR/enum_cast.rs:+8:2: +8:2 } diff --git a/src/test/run-make-fulldeps/issue-51671/Makefile b/src/test/run-make-fulldeps/issue-51671/Makefile index 1d1d370d38264..c93645369928c 100644 --- a/src/test/run-make-fulldeps/issue-51671/Makefile +++ b/src/test/run-make-fulldeps/issue-51671/Makefile @@ -6,4 +6,4 @@ all: $(RUSTC) --emit=obj app.rs nm $(TMPDIR)/app.o | $(CGREP) rust_begin_unwind nm $(TMPDIR)/app.o | $(CGREP) rust_eh_personality - nm $(TMPDIR)/app.o | $(CGREP) rust_oom + nm $(TMPDIR)/app.o | $(CGREP) __rg_oom diff --git a/src/test/run-make-fulldeps/issue-51671/app.rs b/src/test/run-make-fulldeps/issue-51671/app.rs index c13937dcfbe55..e9dc1e9744fb1 100644 --- a/src/test/run-make-fulldeps/issue-51671/app.rs +++ b/src/test/run-make-fulldeps/issue-51671/app.rs @@ -1,5 +1,5 @@ #![crate_type = "bin"] -#![feature(lang_items)] +#![feature(lang_items, alloc_error_handler)] #![no_main] #![no_std] @@ -14,7 +14,7 @@ fn panic(_: &PanicInfo) -> ! { #[lang = "eh_personality"] fn eh() {} -#[lang = "oom"] +#[alloc_error_handler] fn oom(_: Layout) -> ! { loop {} } diff --git a/src/test/ui/alloc-error/alloc-error-handler-bad-signature-1.rs b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-1.rs index 41c9a265cd7bb..cd06423e3a557 100644 --- a/src/test/ui/alloc-error/alloc-error-handler-bad-signature-1.rs +++ b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-1.rs @@ -8,8 +8,8 @@ use core::alloc::Layout; #[alloc_error_handler] fn oom( - info: &Layout, //~ ERROR argument should be `Layout` -) -> () //~ ERROR return type should be `!` + info: &Layout, //~^ ERROR mismatched types +) -> () //~^^ ERROR mismatched types { loop {} } diff --git a/src/test/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr index 34e09da45ad53..d0911fa3985d0 100644 --- a/src/test/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr +++ b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr @@ -1,14 +1,50 @@ -error: return type should be `!` - --> $DIR/alloc-error-handler-bad-signature-1.rs:12:6 +error[E0308]: mismatched types + --> $DIR/alloc-error-handler-bad-signature-1.rs:10:1 | -LL | ) -> () - | ^^ - -error: argument should be `Layout` - --> $DIR/alloc-error-handler-bad-signature-1.rs:11:11 +LL | #[alloc_error_handler] + | ---------------------- in this procedural macro expansion +LL | fn oom( + | _^ + | |_| + | || +LL | || info: &Layout, +LL | || ) -> () + | ||_______- arguments to this function are incorrect +LL | | { +LL | | loop {} +LL | | } + | |__^ expected `&Layout`, found struct `Layout` + | +note: function defined here + --> $DIR/alloc-error-handler-bad-signature-1.rs:10:4 | +LL | fn oom( + | ^^^ LL | info: &Layout, - | ^^^^^^^ + | ------------- + = note: this error originates in the attribute macro `alloc_error_handler` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> $DIR/alloc-error-handler-bad-signature-1.rs:10:1 + | +LL | #[alloc_error_handler] + | ---------------------- in this procedural macro expansion +LL | fn oom( + | _^ + | |_| + | || +LL | || info: &Layout, +LL | || ) -> () + | ||_______^ expected `!`, found `()` +LL | | { +LL | | loop {} +LL | | } + | |__- expected `!` because of return type + | + = note: expected type `!` + found unit type `()` + = note: this error originates in the attribute macro `alloc_error_handler` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/alloc-error/alloc-error-handler-bad-signature-2.rs b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-2.rs index 49ea3105fbd7a..4f76257fc7267 100644 --- a/src/test/ui/alloc-error/alloc-error-handler-bad-signature-2.rs +++ b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-2.rs @@ -8,8 +8,8 @@ struct Layout; #[alloc_error_handler] fn oom( - info: Layout, //~ ERROR argument should be `Layout` -) { //~ ERROR return type should be `!` + info: Layout, //~^ ERROR mismatched types +) { //~^^ ERROR mismatched types loop {} } diff --git a/src/test/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr index 85544b0c3849e..5777279855d97 100644 --- a/src/test/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr +++ b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr @@ -1,14 +1,63 @@ -error: return type should be `!` - --> $DIR/alloc-error-handler-bad-signature-2.rs:12:3 +error[E0308]: mismatched types + --> $DIR/alloc-error-handler-bad-signature-2.rs:10:1 | -LL | ) { - | ^ - -error: argument should be `Layout` - --> $DIR/alloc-error-handler-bad-signature-2.rs:11:11 +LL | #[alloc_error_handler] + | ---------------------- in this procedural macro expansion +LL | fn oom( + | _^ + | |_| + | || +LL | || info: Layout, +LL | || ) { + | || - + | ||_| + | | arguments to this function are incorrect +LL | | loop {} +LL | | } + | |__^ expected struct `Layout`, found struct `core::alloc::Layout` + | + = note: struct `core::alloc::Layout` and struct `Layout` have similar names, but are actually distinct types +note: struct `core::alloc::Layout` is defined in crate `core` + --> $SRC_DIR/core/src/alloc/layout.rs:LL:COL + | +LL | pub struct Layout { + | ^^^^^^^^^^^^^^^^^ +note: struct `Layout` is defined in the current crate + --> $DIR/alloc-error-handler-bad-signature-2.rs:7:1 + | +LL | struct Layout; + | ^^^^^^^^^^^^^ +note: function defined here + --> $DIR/alloc-error-handler-bad-signature-2.rs:10:4 | +LL | fn oom( + | ^^^ LL | info: Layout, - | ^^^^^^ + | ------------ + = note: this error originates in the attribute macro `alloc_error_handler` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> $DIR/alloc-error-handler-bad-signature-2.rs:10:1 + | +LL | #[alloc_error_handler] + | ---------------------- in this procedural macro expansion +LL | fn oom( + | _^ + | |_| + | || +LL | || info: Layout, +LL | || ) { + | || ^ + | ||_| + | | expected `!`, found `()` +LL | | loop {} +LL | | } + | |__- expected `!` because of return type + | + = note: expected type `!` + found unit type `()` + = note: this error originates in the attribute macro `alloc_error_handler` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/alloc-error/alloc-error-handler-bad-signature-3.rs b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-3.rs index 321fd954db6d0..8430fabe84d09 100644 --- a/src/test/ui/alloc-error/alloc-error-handler-bad-signature-3.rs +++ b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-3.rs @@ -7,7 +7,7 @@ struct Layout; #[alloc_error_handler] -fn oom() -> ! { //~ ERROR function should have one argument +fn oom() -> ! { //~ ERROR this function takes 0 arguments but 1 argument was supplied loop {} } diff --git a/src/test/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr index 8575e7508f125..77ea8ef052091 100644 --- a/src/test/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr +++ b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr @@ -1,8 +1,25 @@ -error: function should have one argument +error[E0061]: this function takes 0 arguments but 1 argument was supplied --> $DIR/alloc-error-handler-bad-signature-3.rs:10:1 | +LL | #[alloc_error_handler] + | ---------------------- in this procedural macro expansion +LL | fn oom() -> ! { + | _-^^^^^^^^^^^^ +LL | | loop {} +LL | | } + | |_- argument of type `core::alloc::Layout` unexpected + | +note: function defined here + --> $DIR/alloc-error-handler-bad-signature-3.rs:10:4 + | LL | fn oom() -> ! { - | ^^^^^^^^^^^^^ + | ^^^ + = note: this error originates in the attribute macro `alloc_error_handler` (in Nightly builds, run with -Z macro-backtrace for more info) +help: remove the extra argument + | +LL | fn oom() -> !() { + | ++ error: aborting due to previous error +For more information about this error, try `rustc --explain E0061`. diff --git a/src/test/ui/const-generics/issues/issue-82956.stderr b/src/test/ui/const-generics/issues/issue-82956.stderr index c8b999da98104..d2320293e857e 100644 --- a/src/test/ui/const-generics/issues/issue-82956.stderr +++ b/src/test/ui/const-generics/issues/issue-82956.stderr @@ -2,7 +2,7 @@ error[E0433]: failed to resolve: use of undeclared type `IntoIter` --> $DIR/issue-82956.rs:25:24 | LL | let mut iter = IntoIter::new(self); - | ^^^^^^^^ not found in this scope + | ^^^^^^^^ use of undeclared type `IntoIter` | help: consider importing one of these items | diff --git a/src/test/ui/derived-errors/issue-31997-1.stderr b/src/test/ui/derived-errors/issue-31997-1.stderr index 6d177666ed0fa..2f4aabf845311 100644 --- a/src/test/ui/derived-errors/issue-31997-1.stderr +++ b/src/test/ui/derived-errors/issue-31997-1.stderr @@ -2,7 +2,7 @@ error[E0433]: failed to resolve: use of undeclared type `HashMap` --> $DIR/issue-31997-1.rs:20:19 | LL | let mut map = HashMap::new(); - | ^^^^^^^ not found in this scope + | ^^^^^^^ use of undeclared type `HashMap` | help: consider importing this struct | diff --git a/src/test/ui/error-codes/E0081.stderr b/src/test/ui/error-codes/E0081.stderr index 64562fefc866c..d4b21f6893b43 100644 --- a/src/test/ui/error-codes/E0081.stderr +++ b/src/test/ui/error-codes/E0081.stderr @@ -32,7 +32,7 @@ LL | First = -1, | -- `-1` assigned here LL | LL | Second = -2, - | ----------- discriminant for `Last` incremented from this startpoint (`Second` + 1 variant later => `Last` = -1) + | ------ discriminant for `Last` incremented from this startpoint (`Second` + 1 variant later => `Last` = -1) LL | LL | Last, | ---- `-1` assigned here @@ -53,7 +53,7 @@ LL | V4 = 0, | - `0` assigned here LL | LL | V5 = -2, - | ------- discriminant for `V7` incremented from this startpoint (`V5` + 2 variants later => `V7` = 0) + | -- discriminant for `V7` incremented from this startpoint (`V5` + 2 variants later => `V7` = 0) ... LL | V7, | -- `0` assigned here @@ -68,7 +68,7 @@ LL | V5 = -2, | -- `-2` assigned here ... LL | V8 = -3, - | ------- discriminant for `V9` incremented from this startpoint (`V8` + 1 variant later => `V9` = -2) + | -- discriminant for `V9` incremented from this startpoint (`V8` + 1 variant later => `V9` = -2) LL | LL | V9, | -- `-2` assigned here diff --git a/src/test/ui/feature-gates/feature-gate-alloc-error-handler.rs b/src/test/ui/feature-gates/feature-gate-alloc-error-handler.rs index ad89096183080..78d189d20b64d 100644 --- a/src/test/ui/feature-gates/feature-gate-alloc-error-handler.rs +++ b/src/test/ui/feature-gates/feature-gate-alloc-error-handler.rs @@ -5,10 +5,12 @@ use core::alloc::Layout; -#[alloc_error_handler] //~ ERROR the `#[alloc_error_handler]` attribute is an experimental feature +#[alloc_error_handler] //~ ERROR use of unstable library feature 'alloc_error_handler' fn oom(info: Layout) -> ! { loop {} } #[panic_handler] -fn panic(_: &core::panic::PanicInfo) -> ! { loop {} } +fn panic(_: &core::panic::PanicInfo) -> ! { + loop {} +} diff --git a/src/test/ui/feature-gates/feature-gate-alloc-error-handler.stderr b/src/test/ui/feature-gates/feature-gate-alloc-error-handler.stderr index 03f31e53f4f2a..f414eb463dfbc 100644 --- a/src/test/ui/feature-gates/feature-gate-alloc-error-handler.stderr +++ b/src/test/ui/feature-gates/feature-gate-alloc-error-handler.stderr @@ -1,8 +1,8 @@ -error[E0658]: the `#[alloc_error_handler]` attribute is an experimental feature - --> $DIR/feature-gate-alloc-error-handler.rs:8:1 +error[E0658]: use of unstable library feature 'alloc_error_handler' + --> $DIR/feature-gate-alloc-error-handler.rs:8:3 | LL | #[alloc_error_handler] - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ | = note: see issue #51540 for more information = help: add `#![feature(alloc_error_handler)]` to the crate attributes to enable diff --git a/src/test/ui/hygiene/no_implicit_prelude.stderr b/src/test/ui/hygiene/no_implicit_prelude.stderr index 0f2ff96b5edb6..c48c840352fa0 100644 --- a/src/test/ui/hygiene/no_implicit_prelude.stderr +++ b/src/test/ui/hygiene/no_implicit_prelude.stderr @@ -5,7 +5,7 @@ LL | fn f() { ::bar::m!(); } | ----------- in this macro invocation ... LL | Vec::new(); - | ^^^ not found in this scope + | ^^^ use of undeclared type `Vec` | = note: this error originates in the macro `::bar::m` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider importing this struct diff --git a/src/test/ui/proc-macro/amputate-span.stderr b/src/test/ui/proc-macro/amputate-span.stderr index 9553ba3da5428..ab46704114460 100644 --- a/src/test/ui/proc-macro/amputate-span.stderr +++ b/src/test/ui/proc-macro/amputate-span.stderr @@ -2,7 +2,7 @@ error[E0433]: failed to resolve: use of undeclared type `Command` --> $DIR/amputate-span.rs:49:5 | LL | Command::new("git"); - | ^^^^^^^ not found in this scope + | ^^^^^^^ use of undeclared type `Command` | help: consider importing this struct | @@ -13,7 +13,7 @@ error[E0433]: failed to resolve: use of undeclared type `Command` --> $DIR/amputate-span.rs:63:9 | LL | Command::new("git"); - | ^^^^^^^ not found in this scope + | ^^^^^^^ use of undeclared type `Command` | help: consider importing this struct | diff --git a/src/test/ui/resolve/missing-in-namespace.stderr b/src/test/ui/resolve/missing-in-namespace.stderr index 3d49b2e5dfcd8..fc925ba3b6a8f 100644 --- a/src/test/ui/resolve/missing-in-namespace.stderr +++ b/src/test/ui/resolve/missing-in-namespace.stderr @@ -1,8 +1,8 @@ error[E0433]: failed to resolve: could not find `hahmap` in `std` - --> $DIR/missing-in-namespace.rs:2:29 + --> $DIR/missing-in-namespace.rs:2:21 | LL | let _map = std::hahmap::HashMap::new(); - | ^^^^^^^ not found in `std::hahmap` + | ^^^^^^ could not find `hahmap` in `std` | help: consider importing this struct | diff --git a/src/test/ui/resolve/typo-suggestion-mistyped-in-path.rs b/src/test/ui/resolve/typo-suggestion-mistyped-in-path.rs new file mode 100644 index 0000000000000..3ce17a14f146b --- /dev/null +++ b/src/test/ui/resolve/typo-suggestion-mistyped-in-path.rs @@ -0,0 +1,42 @@ +struct Struct; +//~^ NOTE function or associated item `fob` not found for this struct + +impl Struct { + fn foo() { } +} + +mod module { + fn foo() { } + + struct Struct; + + impl Struct { + fn foo() { } + } +} + +trait Trait { + fn foo(); +} + +fn main() { + Struct::fob(); + //~^ ERROR no function or associated item named `fob` found for struct `Struct` in the current scope + //~| NOTE function or associated item not found in `Struct` + + Struc::foo(); + //~^ ERROR failed to resolve: use of undeclared type `Struc` + //~| NOTE use of undeclared type `Struc` + + modul::foo(); + //~^ ERROR failed to resolve: use of undeclared crate or module `modul` + //~| NOTE use of undeclared crate or module `modul` + + module::Struc::foo(); + //~^ ERROR failed to resolve: could not find `Struc` in `module` + //~| NOTE could not find `Struc` in `module` + + Trai::foo(); + //~^ ERROR failed to resolve: use of undeclared type `Trai` + //~| NOTE use of undeclared type `Trai` +} diff --git a/src/test/ui/resolve/typo-suggestion-mistyped-in-path.stderr b/src/test/ui/resolve/typo-suggestion-mistyped-in-path.stderr new file mode 100644 index 0000000000000..ff7cf531c06dd --- /dev/null +++ b/src/test/ui/resolve/typo-suggestion-mistyped-in-path.stderr @@ -0,0 +1,54 @@ +error[E0433]: failed to resolve: use of undeclared type `Struc` + --> $DIR/typo-suggestion-mistyped-in-path.rs:27:5 + | +LL | Struc::foo(); + | ^^^^^ + | | + | use of undeclared type `Struc` + | help: a struct with a similar name exists: `Struct` + +error[E0433]: failed to resolve: use of undeclared crate or module `modul` + --> $DIR/typo-suggestion-mistyped-in-path.rs:31:5 + | +LL | modul::foo(); + | ^^^^^ use of undeclared crate or module `modul` + | +help: there is a crate or module with a similar name + | +LL | module::foo(); + | ~~~~~~ + +error[E0433]: failed to resolve: could not find `Struc` in `module` + --> $DIR/typo-suggestion-mistyped-in-path.rs:35:13 + | +LL | module::Struc::foo(); + | ^^^^^ + | | + | could not find `Struc` in `module` + | help: a struct with a similar name exists: `Struct` + +error[E0433]: failed to resolve: use of undeclared type `Trai` + --> $DIR/typo-suggestion-mistyped-in-path.rs:39:5 + | +LL | Trai::foo(); + | ^^^^ + | | + | use of undeclared type `Trai` + | help: a trait with a similar name exists: `Trait` + +error[E0599]: no function or associated item named `fob` found for struct `Struct` in the current scope + --> $DIR/typo-suggestion-mistyped-in-path.rs:23:13 + | +LL | struct Struct; + | ------------- function or associated item `fob` not found for this struct +... +LL | Struct::fob(); + | ^^^ + | | + | function or associated item not found in `Struct` + | help: there is an associated function with a similar name: `foo` + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0433, E0599. +For more information about an error, try `rustc --explain E0433`. diff --git a/src/test/ui/resolve/use_suggestion.stderr b/src/test/ui/resolve/use_suggestion.stderr index 4fff179b1fecc..58cb659e82203 100644 --- a/src/test/ui/resolve/use_suggestion.stderr +++ b/src/test/ui/resolve/use_suggestion.stderr @@ -8,7 +8,7 @@ error[E0433]: failed to resolve: use of undeclared type `HashMap` --> $DIR/use_suggestion.rs:2:14 | LL | let x1 = HashMap::new(); - | ^^^^^^^ not found in this scope + | ^^^^^^^ use of undeclared type `HashMap` | help: consider importing this struct | diff --git a/src/test/ui/suggestions/core-std-import-order-issue-83564.stderr b/src/test/ui/suggestions/core-std-import-order-issue-83564.stderr index ce85d93b96ca8..e4e1fc591c476 100644 --- a/src/test/ui/suggestions/core-std-import-order-issue-83564.stderr +++ b/src/test/ui/suggestions/core-std-import-order-issue-83564.stderr @@ -2,7 +2,7 @@ error[E0433]: failed to resolve: use of undeclared type `NonZeroU32` --> $DIR/core-std-import-order-issue-83564.rs:8:14 | LL | let _x = NonZeroU32::new(5).unwrap(); - | ^^^^^^^^^^ not found in this scope + | ^^^^^^^^^^ use of undeclared type `NonZeroU32` | help: consider importing one of these items | diff --git a/src/test/ui/suggestions/suggest-tryinto-edition-change.rs b/src/test/ui/suggestions/suggest-tryinto-edition-change.rs index f03b42bbe4751..70c4b210d3a7b 100644 --- a/src/test/ui/suggestions/suggest-tryinto-edition-change.rs +++ b/src/test/ui/suggestions/suggest-tryinto-edition-change.rs @@ -10,18 +10,19 @@ fn test() { let _i: i16 = TryFrom::try_from(0_i32).unwrap(); //~^ ERROR failed to resolve: use of undeclared type - //~| NOTE not found in this scope + //~| NOTE use of undeclared type //~| NOTE 'std::convert::TryFrom' is included in the prelude starting in Edition 2021 //~| NOTE 'core::convert::TryFrom' is included in the prelude starting in Edition 2021 let _i: i16 = TryInto::try_into(0_i32).unwrap(); //~^ ERROR failed to resolve: use of undeclared type - //~| NOTE not found in this scope + //~| NOTE use of undeclared type //~| NOTE 'std::convert::TryInto' is included in the prelude starting in Edition 2021 //~| NOTE 'core::convert::TryInto' is included in the prelude starting in Edition 2021 let _v: Vec<_> = FromIterator::from_iter(&[1]); //~^ ERROR failed to resolve: use of undeclared type + //~| NOTE use of undeclared type //~| NOTE 'std::iter::FromIterator' is included in the prelude starting in Edition 2021 //~| NOTE 'core::iter::FromIterator' is included in the prelude starting in Edition 2021 } diff --git a/src/test/ui/suggestions/suggest-tryinto-edition-change.stderr b/src/test/ui/suggestions/suggest-tryinto-edition-change.stderr index 86f48716b16b5..3d1f2492360bf 100644 --- a/src/test/ui/suggestions/suggest-tryinto-edition-change.stderr +++ b/src/test/ui/suggestions/suggest-tryinto-edition-change.stderr @@ -2,7 +2,7 @@ error[E0433]: failed to resolve: use of undeclared type `TryFrom` --> $DIR/suggest-tryinto-edition-change.rs:11:19 | LL | let _i: i16 = TryFrom::try_from(0_i32).unwrap(); - | ^^^^^^^ not found in this scope + | ^^^^^^^ use of undeclared type `TryFrom` | = note: 'std::convert::TryFrom' is included in the prelude starting in Edition 2021 = note: 'core::convert::TryFrom' is included in the prelude starting in Edition 2021 @@ -17,7 +17,7 @@ error[E0433]: failed to resolve: use of undeclared type `TryInto` --> $DIR/suggest-tryinto-edition-change.rs:17:19 | LL | let _i: i16 = TryInto::try_into(0_i32).unwrap(); - | ^^^^^^^ not found in this scope + | ^^^^^^^ use of undeclared type `TryInto` | = note: 'std::convert::TryInto' is included in the prelude starting in Edition 2021 = note: 'core::convert::TryInto' is included in the prelude starting in Edition 2021 @@ -32,12 +32,7 @@ error[E0433]: failed to resolve: use of undeclared type `FromIterator` --> $DIR/suggest-tryinto-edition-change.rs:23:22 | LL | let _v: Vec<_> = FromIterator::from_iter(&[1]); - | ^^^^^^^^^^^^ - | - ::: $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL - | -LL | pub trait IntoIterator { - | ---------------------- similarly named trait `IntoIterator` defined here + | ^^^^^^^^^^^^ use of undeclared type `FromIterator` | = note: 'std::iter::FromIterator' is included in the prelude starting in Edition 2021 = note: 'core::iter::FromIterator' is included in the prelude starting in Edition 2021 diff --git a/src/test/ui/type-alias-enum-variants/self-in-enum-definition.stderr b/src/test/ui/type-alias-enum-variants/self-in-enum-definition.stderr index 4775e68820b52..576fc6a4f8d51 100644 --- a/src/test/ui/type-alias-enum-variants/self-in-enum-definition.stderr +++ b/src/test/ui/type-alias-enum-variants/self-in-enum-definition.stderr @@ -12,6 +12,46 @@ LL | V3 = Self::V1 {} as u8 + 2, note: ...which requires const-evaluating + checking `Alpha::V3::{constant#0}`... --> $DIR/self-in-enum-definition.rs:5:10 | +LL | V3 = Self::V1 {} as u8 + 2, + | ^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires caching mir of `Alpha::V3::{constant#0}` for CTFE... + --> $DIR/self-in-enum-definition.rs:5:10 + | +LL | V3 = Self::V1 {} as u8 + 2, + | ^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires elaborating drops for `Alpha::V3::{constant#0}`... + --> $DIR/self-in-enum-definition.rs:5:10 + | +LL | V3 = Self::V1 {} as u8 + 2, + | ^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires borrow-checking `Alpha::V3::{constant#0}`... + --> $DIR/self-in-enum-definition.rs:5:10 + | +LL | V3 = Self::V1 {} as u8 + 2, + | ^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires processing MIR for `Alpha::V3::{constant#0}`... + --> $DIR/self-in-enum-definition.rs:5:10 + | +LL | V3 = Self::V1 {} as u8 + 2, + | ^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires const checking `Alpha::V3::{constant#0}`... + --> $DIR/self-in-enum-definition.rs:5:10 + | +LL | V3 = Self::V1 {} as u8 + 2, + | ^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires preparing `Alpha::V3::{constant#0}` for borrow checking... + --> $DIR/self-in-enum-definition.rs:5:10 + | +LL | V3 = Self::V1 {} as u8 + 2, + | ^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires unsafety-checking `Alpha::V3::{constant#0}`... + --> $DIR/self-in-enum-definition.rs:5:10 + | +LL | V3 = Self::V1 {} as u8 + 2, + | ^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires building MIR for `Alpha::V3::{constant#0}`... + --> $DIR/self-in-enum-definition.rs:5:10 + | LL | V3 = Self::V1 {} as u8 + 2, | ^^^^^^^^^^^^^^^^^^^^^ = note: ...which requires computing layout of `Alpha`...