Auto merge of #103832 - Dylan-DPC:rollup-maw3kmx, r=Dylan-DPC
Rollup of 6 pull requests Successful merges: - #103061 (Rewrite implementation of `#[alloc_error_handler]`) - #103584 (Remove bounds check when array is indexed by enum) - #103706 (Fix E0433 No Typo Suggestions) - #103729 (interpret: fix align_of_val on packed types) - #103759 (Use `adt_def` during type collection.) - #103809 (Fix a typo in std::net mod doc comment) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
c493bae0d8
69 changed files with 853 additions and 387 deletions
104
compiler/rustc_builtin_macros/src/alloc_error_handler.rs
Normal file
104
compiler/rustc_builtin_macros/src/alloc_error_handler.rs
Normal file
|
@ -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<Annotatable> {
|
||||||
|
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)
|
||||||
|
}
|
|
@ -25,6 +25,7 @@ use rustc_expand::base::{MacroExpanderFn, ResolverExpand, SyntaxExtensionKind};
|
||||||
use rustc_expand::proc_macro::BangProcMacro;
|
use rustc_expand::proc_macro::BangProcMacro;
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
|
|
||||||
|
mod alloc_error_handler;
|
||||||
mod assert;
|
mod assert;
|
||||||
mod cfg;
|
mod cfg;
|
||||||
mod cfg_accessible;
|
mod cfg_accessible;
|
||||||
|
@ -94,6 +95,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
|
||||||
}
|
}
|
||||||
|
|
||||||
register_attr! {
|
register_attr! {
|
||||||
|
alloc_error_handler: alloc_error_handler::expand,
|
||||||
bench: test::expand_bench,
|
bench: test::expand_bench,
|
||||||
cfg_accessible: cfg_accessible::Expander,
|
cfg_accessible: cfg_accessible::Expander,
|
||||||
cfg_eval: cfg_eval::expand,
|
cfg_eval: cfg_eval::expand,
|
||||||
|
|
|
@ -5,6 +5,7 @@ use crate::prelude::*;
|
||||||
|
|
||||||
use rustc_ast::expand::allocator::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS};
|
use rustc_ast::expand::allocator::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS};
|
||||||
use rustc_session::config::OomStrategy;
|
use rustc_session::config::OomStrategy;
|
||||||
|
use rustc_span::symbol::sym;
|
||||||
|
|
||||||
/// Returns whether an allocator shim was created
|
/// Returns whether an allocator shim was created
|
||||||
pub(crate) fn codegen(
|
pub(crate) fn codegen(
|
||||||
|
@ -23,7 +24,7 @@ pub(crate) fn codegen(
|
||||||
module,
|
module,
|
||||||
unwind_context,
|
unwind_context,
|
||||||
kind,
|
kind,
|
||||||
tcx.lang_items().oom().is_some(),
|
tcx.alloc_error_handler_kind(()).unwrap(),
|
||||||
tcx.sess.opts.unstable_opts.oom,
|
tcx.sess.opts.unstable_opts.oom,
|
||||||
);
|
);
|
||||||
true
|
true
|
||||||
|
@ -36,7 +37,7 @@ fn codegen_inner(
|
||||||
module: &mut impl Module,
|
module: &mut impl Module,
|
||||||
unwind_context: &mut UnwindContext,
|
unwind_context: &mut UnwindContext,
|
||||||
kind: AllocatorKind,
|
kind: AllocatorKind,
|
||||||
has_alloc_error_handler: bool,
|
alloc_error_handler_kind: AllocatorKind,
|
||||||
oom_strategy: OomStrategy,
|
oom_strategy: OomStrategy,
|
||||||
) {
|
) {
|
||||||
let usize_ty = module.target_config().pointer_type();
|
let usize_ty = module.target_config().pointer_type();
|
||||||
|
@ -108,12 +109,12 @@ fn codegen_inner(
|
||||||
returns: vec![],
|
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 =
|
let func_id =
|
||||||
module.declare_function("__rust_alloc_error_handler", Linkage::Export, &sig).unwrap();
|
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();
|
let mut ctx = Context::new();
|
||||||
ctx.func.signature = sig;
|
ctx.func.signature = sig;
|
||||||
|
|
|
@ -7,7 +7,7 @@ use rustc_span::symbol::sym;
|
||||||
|
|
||||||
use crate::GccContext;
|
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 context = &mods.context;
|
||||||
let usize =
|
let usize =
|
||||||
match tcx.sess.target.pointer_width {
|
match tcx.sess.target.pointer_width {
|
||||||
|
@ -90,14 +90,7 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut GccContext, _module_nam
|
||||||
.collect();
|
.collect();
|
||||||
let func = context.new_function(None, FunctionType::Exported, void, &args, name, false);
|
let func = context.new_function(None, FunctionType::Exported, void, &args, name, false);
|
||||||
|
|
||||||
let kind =
|
let callee = alloc_error_handler_kind.fn_name(sym::oom);
|
||||||
if has_alloc_error_handler {
|
|
||||||
AllocatorKind::Global
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
AllocatorKind::Default
|
|
||||||
};
|
|
||||||
let callee = kind.fn_name(sym::oom);
|
|
||||||
let args: Vec<_> = types.iter().enumerate()
|
let args: Vec<_> = types.iter().enumerate()
|
||||||
.map(|(index, typ)| context.new_parameter(None, *typ, &format!("param{}", index)))
|
.map(|(index, typ)| context.new_parameter(None, *typ, &format!("param{}", index)))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
|
@ -153,11 +153,11 @@ impl CodegenBackend for GccCodegenBackend {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExtraBackendMethods 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 {
|
let mut mods = GccContext {
|
||||||
context: Context::default(),
|
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
|
mods
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ pub(crate) unsafe fn codegen(
|
||||||
module_llvm: &mut ModuleLlvm,
|
module_llvm: &mut ModuleLlvm,
|
||||||
module_name: &str,
|
module_name: &str,
|
||||||
kind: AllocatorKind,
|
kind: AllocatorKind,
|
||||||
has_alloc_error_handler: bool,
|
alloc_error_handler_kind: AllocatorKind,
|
||||||
) {
|
) {
|
||||||
let llcx = &*module_llvm.llcx;
|
let llcx = &*module_llvm.llcx;
|
||||||
let llmod = module_llvm.llmod();
|
let llmod = module_llvm.llmod();
|
||||||
|
@ -117,8 +117,7 @@ pub(crate) unsafe fn codegen(
|
||||||
attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &[uwtable]);
|
attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &[uwtable]);
|
||||||
}
|
}
|
||||||
|
|
||||||
let kind = if has_alloc_error_handler { AllocatorKind::Global } else { AllocatorKind::Default };
|
let callee = alloc_error_handler_kind.fn_name(sym::oom);
|
||||||
let callee = kind.fn_name(sym::oom);
|
|
||||||
let callee = llvm::LLVMRustGetOrInsertFunction(llmod, callee.as_ptr().cast(), callee.len(), ty);
|
let callee = llvm::LLVMRustGetOrInsertFunction(llmod, callee.as_ptr().cast(), callee.len(), ty);
|
||||||
// -> ! DIFlagNoReturn
|
// -> ! DIFlagNoReturn
|
||||||
attributes::apply_to_llfn(callee, llvm::AttributePlace::Function, &[no_return]);
|
attributes::apply_to_llfn(callee, llvm::AttributePlace::Function, &[no_return]);
|
||||||
|
|
|
@ -108,11 +108,11 @@ impl ExtraBackendMethods for LlvmCodegenBackend {
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
module_name: &str,
|
module_name: &str,
|
||||||
kind: AllocatorKind,
|
kind: AllocatorKind,
|
||||||
has_alloc_error_handler: bool,
|
alloc_error_handler_kind: AllocatorKind,
|
||||||
) -> ModuleLlvm {
|
) -> ModuleLlvm {
|
||||||
let mut module_llvm = ModuleLlvm::new_metadata(tcx, module_name);
|
let mut module_llvm = ModuleLlvm::new_metadata(tcx, module_name);
|
||||||
unsafe {
|
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
|
module_llvm
|
||||||
}
|
}
|
||||||
|
|
|
@ -193,8 +193,11 @@ fn exported_symbols_provider_local<'tcx>(
|
||||||
}
|
}
|
||||||
|
|
||||||
if tcx.allocator_kind(()).is_some() {
|
if tcx.allocator_kind(()).is_some() {
|
||||||
for method in ALLOCATOR_METHODS {
|
for symbol_name in ALLOCATOR_METHODS
|
||||||
let symbol_name = format!("__rust_{}", method.name);
|
.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));
|
let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(tcx, &symbol_name));
|
||||||
|
|
||||||
symbols.push((
|
symbols.push((
|
||||||
|
|
|
@ -638,7 +638,14 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
|
||||||
let llmod_id =
|
let llmod_id =
|
||||||
cgu_name_builder.build_cgu_name(LOCAL_CRATE, &["crate"], Some("allocator")).to_string();
|
cgu_name_builder.build_cgu_name(LOCAL_CRATE, &["crate"], Some("allocator")).to_string();
|
||||||
let module_llvm = tcx.sess.time("write_allocator_module", || {
|
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 })
|
Some(ModuleCodegen { name: llmod_id, module_llvm, kind: ModuleKind::Allocator })
|
||||||
|
|
|
@ -119,7 +119,7 @@ pub trait ExtraBackendMethods: CodegenBackend + WriteBackendMethods + Sized + Se
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
module_name: &str,
|
module_name: &str,
|
||||||
kind: AllocatorKind,
|
kind: AllocatorKind,
|
||||||
has_alloc_error_handler: bool,
|
alloc_error_handler_kind: AllocatorKind,
|
||||||
) -> Self::Module;
|
) -> Self::Module;
|
||||||
/// This generates the codegen unit and returns it along with
|
/// This generates the codegen unit and returns it along with
|
||||||
/// a `u64` giving an estimate of the unit's processing cost.
|
/// a `u64` giving an estimate of the unit's processing cost.
|
||||||
|
|
|
@ -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
|
// the last field). Can't have foreign types here, how would we
|
||||||
// adjust alignment and size for them?
|
// adjust alignment and size for them?
|
||||||
let field = layout.field(self, layout.fields.count() - 1);
|
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
|
// A field with an extern type. We don't know the actual dynamic size
|
||||||
// or the alignment.
|
// or the alignment.
|
||||||
return Ok(None);
|
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.
|
// Return the sum of sizes and max of aligns.
|
||||||
let size = sized_size + unsized_size; // `Size` addition
|
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
|
// Choose max of two known alignments (combined value must
|
||||||
// be aligned according to more restrictive of the two).
|
// be aligned according to more restrictive of the two).
|
||||||
let align = sized_align.max(unsized_align);
|
let align = sized_align.max(unsized_align);
|
||||||
|
|
|
@ -150,12 +150,28 @@ metadata_no_multiple_global_alloc =
|
||||||
metadata_prev_global_alloc =
|
metadata_prev_global_alloc =
|
||||||
previous global allocator defined here
|
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 =
|
metadata_conflicting_global_alloc =
|
||||||
the `#[global_allocator]` in {$other_crate_name} conflicts with global allocator in: {$crate_name}
|
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 =
|
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
|
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 =
|
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}`
|
the crate `{$crate_name}` cannot depend on a crate that needs {$needs_crate_name}, but it depends on `{$deps_crate_name}`
|
||||||
|
|
||||||
|
|
|
@ -367,12 +367,6 @@ passes_unknown_external_lang_item =
|
||||||
passes_missing_panic_handler =
|
passes_missing_panic_handler =
|
||||||
`#[panic_handler]` function required, but not found
|
`#[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 =
|
passes_missing_lang_item =
|
||||||
language item required, but not found: `{$name}`
|
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
|
.note = this can occur when a binary crate with `#![no_std]` is compiled for a target where `{$name}` is defined in the standard library
|
||||||
|
|
|
@ -554,10 +554,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
||||||
rustc_attr!(rustc_reallocator, Normal, template!(Word), WarnFollowing, IMPL_DETAIL),
|
rustc_attr!(rustc_reallocator, Normal, template!(Word), WarnFollowing, IMPL_DETAIL),
|
||||||
rustc_attr!(rustc_deallocator, 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),
|
rustc_attr!(rustc_allocator_zeroed, Normal, template!(Word), WarnFollowing, IMPL_DETAIL),
|
||||||
gated!(
|
|
||||||
alloc_error_handler, Normal, template!(Word), WarnFollowing,
|
|
||||||
experimental!(alloc_error_handler)
|
|
||||||
),
|
|
||||||
gated!(
|
gated!(
|
||||||
default_lib_allocator, Normal, template!(Word), WarnFollowing, allocator_internals,
|
default_lib_allocator, Normal, template!(Word), WarnFollowing, allocator_internals,
|
||||||
experimental!(default_lib_allocator),
|
experimental!(default_lib_allocator),
|
||||||
|
|
|
@ -126,14 +126,12 @@ impl<CTX> HashStable<CTX> for LangItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extracts the first `lang = "$name"` out of a list of attributes.
|
/// Extracts the first `lang = "$name"` out of a list of attributes.
|
||||||
/// The attributes `#[panic_handler]` and `#[alloc_error_handler]`
|
/// The `#[panic_handler]` attribute is also extracted out when found.
|
||||||
/// are also extracted out when found.
|
|
||||||
pub fn extract(attrs: &[ast::Attribute]) -> Option<(Symbol, Span)> {
|
pub fn extract(attrs: &[ast::Attribute]) -> Option<(Symbol, Span)> {
|
||||||
attrs.iter().find_map(|attr| {
|
attrs.iter().find_map(|attr| {
|
||||||
Some(match attr {
|
Some(match attr {
|
||||||
_ if attr.has_name(sym::lang) => (attr.value_str()?, attr.span),
|
_ 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::panic_handler) => (sym::panic_impl, attr.span),
|
||||||
_ if attr.has_name(sym::alloc_error_handler) => (sym::oom, attr.span),
|
|
||||||
_ => return None,
|
_ => return None,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -240,7 +238,6 @@ language_item_table! {
|
||||||
ExchangeMalloc, sym::exchange_malloc, exchange_malloc_fn, Target::Fn, GenericRequirement::None;
|
ExchangeMalloc, sym::exchange_malloc, exchange_malloc_fn, Target::Fn, GenericRequirement::None;
|
||||||
BoxFree, sym::box_free, box_free_fn, Target::Fn, GenericRequirement::Minimum(1);
|
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);
|
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;
|
AllocLayout, sym::alloc_layout, alloc_layout, Target::Struct, GenericRequirement::None;
|
||||||
|
|
||||||
Start, sym::start, start_fn, Target::Fn, GenericRequirement::Exact(1);
|
Start, sym::start, start_fn, Target::Fn, GenericRequirement::Exact(1);
|
||||||
|
|
|
@ -27,5 +27,4 @@ weak_lang_items! {
|
||||||
PanicImpl, rust_begin_unwind;
|
PanicImpl, rust_begin_unwind;
|
||||||
EhPersonality, rust_eh_personality;
|
EhPersonality, rust_eh_personality;
|
||||||
EhCatchTypeinfo, rust_eh_catch_typeinfo;
|
EhCatchTypeinfo, rust_eh_catch_typeinfo;
|
||||||
Oom, rust_oom;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ use super::*;
|
||||||
use rustc_attr as attr;
|
use rustc_attr as attr;
|
||||||
use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan};
|
use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan};
|
||||||
use rustc_hir as hir;
|
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::def_id::{DefId, LocalDefId};
|
||||||
use rustc_hir::intravisit::Visitor;
|
use rustc_hir::intravisit::Visitor;
|
||||||
use rustc_hir::{ItemKind, Node, PathSegment};
|
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_simd(tcx, span, def_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
check_transparent(tcx, span, def);
|
check_transparent(tcx, def);
|
||||||
check_packed(tcx, span, 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 def = tcx.adt_def(def_id);
|
||||||
let span = tcx.def_span(def_id);
|
let span = tcx.def_span(def_id);
|
||||||
def.destructor(tcx); // force the destructor to be evaluated
|
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_union_fields(tcx, span, def_id);
|
||||||
check_packed(tcx, span, def);
|
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);
|
tcx.ensure().typeck(id.owner_id.def_id);
|
||||||
}
|
}
|
||||||
DefKind::Enum => {
|
DefKind::Enum => {
|
||||||
let item = tcx.hir().item(id);
|
check_enum(tcx, id.owner_id.def_id);
|
||||||
let hir::ItemKind::Enum(ref enum_definition, _) = item.kind else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
check_enum(tcx, &enum_definition.variants, item.owner_id.def_id);
|
|
||||||
}
|
}
|
||||||
DefKind::Fn => {} // entirely within check_item_body
|
DefKind::Fn => {} // entirely within check_item_body
|
||||||
DefKind::Impl => {
|
DefKind::Impl => {
|
||||||
|
@ -1026,7 +1022,7 @@ pub(super) fn check_packed_inner(
|
||||||
None
|
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() {
|
if !adt.repr().transparent() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1035,14 +1031,14 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, adt: ty::AdtD
|
||||||
feature_err(
|
feature_err(
|
||||||
&tcx.sess.parse_sess,
|
&tcx.sess.parse_sess,
|
||||||
sym::transparent_unions,
|
sym::transparent_unions,
|
||||||
sp,
|
tcx.def_span(adt.did()),
|
||||||
"transparent unions are unstable",
|
"transparent unions are unstable",
|
||||||
)
|
)
|
||||||
.emit();
|
.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
if adt.variants().len() != 1 {
|
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() {
|
if adt.variants().is_empty() {
|
||||||
// Don't bother checking the fields. No variants (and thus no fields) exist.
|
// Don't bother checking the fields. No variants (and thus no fields) exist.
|
||||||
return;
|
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 });
|
.filter_map(|(span, zst, _align1, _non_exhaustive)| if !zst { Some(span) } else { None });
|
||||||
let non_zst_count = non_zst_fields.clone().count();
|
let non_zst_count = non_zst_fields.clone().count();
|
||||||
if non_zst_count >= 2 {
|
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 =
|
let incompatible_zst_fields =
|
||||||
field_infos.clone().filter(|(_, _, _, opt)| opt.is_some()).count();
|
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)]
|
#[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 def = tcx.adt_def(def_id);
|
||||||
let sp = tcx.def_span(def_id);
|
|
||||||
def.destructor(tcx); // force the destructor to be evaluated
|
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() {
|
if let Some(attr) = tcx.get_attrs(def_id.to_def_id(), sym::repr).next() {
|
||||||
struct_span_err!(
|
struct_span_err!(
|
||||||
tcx.sess,
|
tcx.sess,
|
||||||
|
@ -1156,7 +1151,7 @@ fn check_enum<'tcx>(tcx: TyCtxt<'tcx>, vs: &'tcx [hir::Variant<'tcx>], def_id: L
|
||||||
E0084,
|
E0084,
|
||||||
"unsupported representation for zero-variant enum"
|
"unsupported representation for zero-variant enum"
|
||||||
)
|
)
|
||||||
.span_label(sp, "zero-variant enum")
|
.span_label(tcx.def_span(def_id), "zero-variant enum")
|
||||||
.emit();
|
.emit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1167,88 +1162,96 @@ fn check_enum<'tcx>(tcx: TyCtxt<'tcx>, vs: &'tcx [hir::Variant<'tcx>], def_id: L
|
||||||
feature_err(
|
feature_err(
|
||||||
&tcx.sess.parse_sess,
|
&tcx.sess.parse_sess,
|
||||||
sym::repr128,
|
sym::repr128,
|
||||||
sp,
|
tcx.def_span(def_id),
|
||||||
"repr with 128-bit type is unstable",
|
"repr with 128-bit type is unstable",
|
||||||
)
|
)
|
||||||
.emit();
|
.emit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for v in vs {
|
for v in def.variants() {
|
||||||
if let Some(ref e) = v.disr_expr {
|
if let ty::VariantDiscr::Explicit(discr_def_id) = v.discr {
|
||||||
tcx.ensure().typeck(tcx.hir().local_def_id(e.hir_id));
|
tcx.ensure().typeck(discr_def_id.expect_local());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if tcx.adt_def(def_id).repr().int.is_none() {
|
if def.repr().int.is_none() {
|
||||||
let is_unit = |var: &hir::Variant<'_>| matches!(var.data, hir::VariantData::Unit(..));
|
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 = def.variants().iter().any(|var| !is_unit(var));
|
||||||
let has_non_units = vs.iter().any(|var| !is_unit(var));
|
let disr_units = def.variants().iter().any(|var| is_unit(&var) && has_disr(&var));
|
||||||
let disr_units = vs.iter().any(|var| is_unit(&var) && has_disr(&var));
|
let disr_non_unit = def.variants().iter().any(|var| !is_unit(&var) && has_disr(&var));
|
||||||
let disr_non_unit = vs.iter().any(|var| !is_unit(&var) && has_disr(&var));
|
|
||||||
|
|
||||||
if disr_non_unit || (disr_units && has_non_units) {
|
if disr_non_unit || (disr_units && has_non_units) {
|
||||||
let mut err =
|
let mut err = struct_span_err!(
|
||||||
struct_span_err!(tcx.sess, sp, E0732, "`#[repr(inttype)]` must be specified");
|
tcx.sess,
|
||||||
|
tcx.def_span(def_id),
|
||||||
|
E0732,
|
||||||
|
"`#[repr(inttype)]` must be specified"
|
||||||
|
);
|
||||||
err.emit();
|
err.emit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
detect_discriminant_duplicate(tcx, def.discriminants(tcx).collect(), vs, sp);
|
detect_discriminant_duplicate(tcx, def);
|
||||||
|
check_transparent(tcx, def);
|
||||||
check_transparent(tcx, sp, def);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Part of enum check. Given the discriminants of an enum, errors if two or more discriminants are equal
|
/// Part of enum check. Given the discriminants of an enum, errors if two or more discriminants are equal
|
||||||
fn detect_discriminant_duplicate<'tcx>(
|
fn detect_discriminant_duplicate<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>) {
|
||||||
tcx: TyCtxt<'tcx>,
|
|
||||||
mut discrs: Vec<(VariantIdx, Discr<'tcx>)>,
|
|
||||||
vs: &'tcx [hir::Variant<'tcx>],
|
|
||||||
self_span: Span,
|
|
||||||
) {
|
|
||||||
// Helper closure to reduce duplicate code. This gets called everytime we detect a duplicate.
|
// 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`
|
// 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 report = |dis: Discr<'tcx>, idx, err: &mut Diagnostic| {
|
||||||
let var = &vs[idx]; // HIR for the duplicate discriminant
|
let var = adt.variant(idx); // HIR for the duplicate discriminant
|
||||||
let (span, display_discr) = match var.disr_expr {
|
let (span, display_discr) = match var.discr {
|
||||||
Some(ref expr) => {
|
ty::VariantDiscr::Explicit(discr_def_id) => {
|
||||||
// In the case the discriminant is both a duplicate and overflowed, let the user know
|
// 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
|
&& let rustc_ast::LitKind::Int(lit_value, _int_kind) = &lit.node
|
||||||
&& *lit_value != dis.val
|
&& *lit_value != dis.val
|
||||||
{
|
{
|
||||||
(tcx.hir().span(expr.hir_id), format!("`{dis}` (overflowed from `{lit_value}`)"))
|
(tcx.def_span(discr_def_id), format!("`{dis}` (overflowed from `{lit_value}`)"))
|
||||||
// Otherwise, format the value as-is
|
|
||||||
} else {
|
} 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
|
// 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
|
// 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
|
// explicitly assigned discriminant, and letting the user know that this was the
|
||||||
// increment startpoint, and how many steps from there leading to the duplicate
|
// increment startpoint, and how many steps from there leading to the duplicate
|
||||||
if let Some((n, hir::Variant { span, ident, .. })) =
|
if let Some(explicit_idx) =
|
||||||
vs[..idx].iter().rev().enumerate().find(|v| v.1.disr_expr.is_some())
|
idx.as_u32().checked_sub(distance_to_explicit).map(VariantIdx::from_u32)
|
||||||
{
|
{
|
||||||
let ve_ident = var.ident;
|
let explicit_variant = adt.variant(explicit_idx);
|
||||||
let n = n + 1;
|
let ve_ident = var.name;
|
||||||
let sp = if n > 1 { "variants" } else { "variant" };
|
let ex_ident = explicit_variant.name;
|
||||||
|
let sp = if distance_to_explicit > 1 { "variants" } else { "variant" };
|
||||||
|
|
||||||
err.span_label(
|
err.span_label(
|
||||||
*span,
|
tcx.def_span(explicit_variant.def_id),
|
||||||
format!("discriminant for `{ve_ident}` incremented from this startpoint (`{ident}` + {n} {sp} later => `{ve_ident}` = {dis})"),
|
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"));
|
err.span_label(span, format!("{display_discr} assigned here"));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let mut discrs = adt.discriminants(tcx).collect::<Vec<_>>();
|
||||||
|
|
||||||
// Here we loop through the discriminants, comparing each discriminant to another.
|
// Here we loop through the discriminants, comparing each discriminant to another.
|
||||||
// When a duplicate is detected, we instantiate an error and point to both
|
// 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
|
// 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).
|
// style as we are mutating `discrs` on the fly).
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
while i < discrs.len() {
|
while i < discrs.len() {
|
||||||
let hir_var_i_idx = discrs[i].0.index();
|
let var_i_idx = discrs[i].0;
|
||||||
let mut error: Option<DiagnosticBuilder<'_, _>> = None;
|
let mut error: Option<DiagnosticBuilder<'_, _>> = None;
|
||||||
|
|
||||||
let mut o = i + 1;
|
let mut o = i + 1;
|
||||||
while o < discrs.len() {
|
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 {
|
if discrs[i].1.val == discrs[o].1.val {
|
||||||
let err = error.get_or_insert_with(|| {
|
let err = error.get_or_insert_with(|| {
|
||||||
let mut ret = struct_span_err!(
|
let mut ret = struct_span_err!(
|
||||||
tcx.sess,
|
tcx.sess,
|
||||||
self_span,
|
tcx.def_span(adt.did()),
|
||||||
E0081,
|
E0081,
|
||||||
"discriminant value `{}` assigned more than once",
|
"discriminant value `{}` assigned more than once",
|
||||||
discrs[i].1,
|
discrs[i].1,
|
||||||
);
|
);
|
||||||
|
|
||||||
report(discrs[i].1, hir_var_i_idx, &mut ret);
|
report(discrs[i].1, var_i_idx, &mut ret);
|
||||||
|
|
||||||
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
|
// Safe to unwrap here, as we wouldn't reach this point if `discrs` was empty
|
||||||
discrs[o] = *discrs.last().unwrap();
|
discrs[o] = *discrs.last().unwrap();
|
||||||
|
|
|
@ -218,19 +218,16 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) {
|
||||||
hir::ItemKind::Const(ty, ..) => {
|
hir::ItemKind::Const(ty, ..) => {
|
||||||
check_item_type(tcx, def_id, ty.span, false);
|
check_item_type(tcx, def_id, ty.span, false);
|
||||||
}
|
}
|
||||||
hir::ItemKind::Struct(ref struct_def, ref ast_generics) => {
|
hir::ItemKind::Struct(_, ref ast_generics) => {
|
||||||
check_type_defn(tcx, item, false, |wfcx| vec![wfcx.non_enum_variant(struct_def)]);
|
check_type_defn(tcx, item, false);
|
||||||
|
|
||||||
check_variances_for_type_defn(tcx, item, ast_generics);
|
check_variances_for_type_defn(tcx, item, ast_generics);
|
||||||
}
|
}
|
||||||
hir::ItemKind::Union(ref struct_def, ref ast_generics) => {
|
hir::ItemKind::Union(_, ref ast_generics) => {
|
||||||
check_type_defn(tcx, item, true, |wfcx| vec![wfcx.non_enum_variant(struct_def)]);
|
check_type_defn(tcx, item, true);
|
||||||
|
|
||||||
check_variances_for_type_defn(tcx, item, ast_generics);
|
check_variances_for_type_defn(tcx, item, ast_generics);
|
||||||
}
|
}
|
||||||
hir::ItemKind::Enum(ref enum_def, ref ast_generics) => {
|
hir::ItemKind::Enum(_, ref ast_generics) => {
|
||||||
check_type_defn(tcx, item, true, |wfcx| wfcx.enum_variants(enum_def));
|
check_type_defn(tcx, item, true);
|
||||||
|
|
||||||
check_variances_for_type_defn(tcx, item, ast_generics);
|
check_variances_for_type_defn(tcx, item, ast_generics);
|
||||||
}
|
}
|
||||||
hir::ItemKind::Trait(..) => {
|
hir::ItemKind::Trait(..) => {
|
||||||
|
@ -1037,27 +1034,25 @@ fn item_adt_kind(kind: &ItemKind<'_>) -> Option<AdtKind> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// In a type definition, we check that to ensure that the types of the fields are well-formed.
|
/// In a type definition, we check that to ensure that the types of the fields are well-formed.
|
||||||
fn check_type_defn<'tcx, F>(
|
fn check_type_defn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>, all_sized: bool) {
|
||||||
tcx: TyCtxt<'tcx>,
|
|
||||||
item: &hir::Item<'tcx>,
|
|
||||||
all_sized: bool,
|
|
||||||
mut lookup_fields: F,
|
|
||||||
) where
|
|
||||||
F: FnMut(&WfCheckingCtxt<'_, 'tcx>) -> Vec<AdtVariant<'tcx>>,
|
|
||||||
{
|
|
||||||
let _ = tcx.representability(item.owner_id.def_id);
|
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| {
|
enter_wf_checking_ctxt(tcx, item.span, item.owner_id.def_id, |wfcx| {
|
||||||
let variants = lookup_fields(wfcx);
|
let variants = adt_def.variants();
|
||||||
let packed = tcx.adt_def(item.owner_id).repr().packed();
|
let packed = adt_def.repr().packed();
|
||||||
|
|
||||||
for variant in &variants {
|
for variant in variants.iter() {
|
||||||
// All field types must be well-formed.
|
// All field types must be well-formed.
|
||||||
for field in &variant.fields {
|
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(
|
wfcx.register_wf_obligation(
|
||||||
field.span,
|
hir_ty.span,
|
||||||
Some(WellFormedLoc::Ty(field.def_id)),
|
Some(WellFormedLoc::Ty(field_id)),
|
||||||
field.ty.into(),
|
ty.into(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1065,7 +1060,7 @@ fn check_type_defn<'tcx, F>(
|
||||||
// intermediate types must be sized.
|
// intermediate types must be sized.
|
||||||
let needs_drop_copy = || {
|
let needs_drop_copy = || {
|
||||||
packed && {
|
packed && {
|
||||||
let ty = variant.fields.last().unwrap().ty;
|
let ty = tcx.type_of(variant.fields.last().unwrap().did);
|
||||||
let ty = tcx.erase_regions(ty);
|
let ty = tcx.erase_regions(ty);
|
||||||
if ty.needs_infer() {
|
if ty.needs_infer() {
|
||||||
tcx.sess
|
tcx.sess
|
||||||
|
@ -1084,27 +1079,31 @@ fn check_type_defn<'tcx, F>(
|
||||||
variant.fields[..variant.fields.len() - unsized_len].iter().enumerate()
|
variant.fields[..variant.fields.len() - unsized_len].iter().enumerate()
|
||||||
{
|
{
|
||||||
let last = idx == variant.fields.len() - 1;
|
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(
|
wfcx.register_bound(
|
||||||
traits::ObligationCause::new(
|
traits::ObligationCause::new(
|
||||||
field.span,
|
hir_ty.span,
|
||||||
wfcx.body_id,
|
wfcx.body_id,
|
||||||
traits::FieldSized {
|
traits::FieldSized {
|
||||||
adt_kind: match item_adt_kind(&item.kind) {
|
adt_kind: match item_adt_kind(&item.kind) {
|
||||||
Some(i) => i,
|
Some(i) => i,
|
||||||
None => bug!(),
|
None => bug!(),
|
||||||
},
|
},
|
||||||
span: field.span,
|
span: hir_ty.span,
|
||||||
last,
|
last,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
wfcx.param_env,
|
wfcx.param_env,
|
||||||
field.ty,
|
ty,
|
||||||
tcx.require_lang_item(LangItem::Sized, None),
|
tcx.require_lang_item(LangItem::Sized, None),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Explicit `enum` discriminant values must const-evaluate successfully.
|
// 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(
|
let cause = traits::ObligationCause::new(
|
||||||
tcx.def_span(discr_def_id),
|
tcx.def_span(discr_def_id),
|
||||||
wfcx.body_id,
|
wfcx.body_id,
|
||||||
|
@ -1114,7 +1113,7 @@ fn check_type_defn<'tcx, F>(
|
||||||
cause,
|
cause,
|
||||||
wfcx.param_env,
|
wfcx.param_env,
|
||||||
ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(
|
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),
|
.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));
|
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<AdtField<'tcx>>,
|
|
||||||
|
|
||||||
/// Explicit discriminant of this variant (e.g. `A = 123`),
|
|
||||||
/// that must evaluate to a constant value.
|
|
||||||
explicit_discr: Option<LocalDefId>,
|
|
||||||
}
|
|
||||||
|
|
||||||
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<AdtVariant<'tcx>> {
|
|
||||||
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(
|
fn error_392(
|
||||||
tcx: TyCtxt<'_>,
|
tcx: TyCtxt<'_>,
|
||||||
span: Span,
|
span: Span,
|
||||||
|
|
|
@ -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().generics_of(def_id);
|
||||||
tcx.ensure().type_of(def_id);
|
tcx.ensure().type_of(def_id);
|
||||||
tcx.ensure().predicates_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 { .. } => {
|
hir::ItemKind::Impl { .. } => {
|
||||||
tcx.ensure().generics_of(def_id);
|
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() {
|
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) {
|
fn convert_variant_ctor(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
||||||
let def_id = tcx.hir().local_def_id(ctor_id);
|
|
||||||
tcx.ensure().generics_of(def_id);
|
tcx.ensure().generics_of(def_id);
|
||||||
tcx.ensure().type_of(def_id);
|
tcx.ensure().type_of(def_id);
|
||||||
tcx.ensure().predicates_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 def = tcx.adt_def(def_id);
|
||||||
let repr_type = def.repr().discr_type();
|
let repr_type = def.repr().discr_type();
|
||||||
let initial = repr_type.initial_discriminant(tcx);
|
let initial = repr_type.initial_discriminant(tcx);
|
||||||
let mut prev_discr = None::<Discr<'_>>;
|
let mut prev_discr = None::<Discr<'_>>;
|
||||||
|
|
||||||
// fill the discriminant values and field types
|
// 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));
|
let wrapped_discr = prev_discr.map_or(initial, |d| d.wrap_incr(tcx));
|
||||||
prev_discr = Some(
|
prev_discr = Some(
|
||||||
if let Some(ref e) = variant.disr_expr {
|
if let ty::VariantDiscr::Explicit(const_def_id) = variant.discr {
|
||||||
let expr_did = tcx.hir().local_def_id(e.hir_id);
|
def.eval_explicit_discr(tcx, const_def_id)
|
||||||
def.eval_explicit_discr(tcx, expr_did.to_def_id())
|
|
||||||
} else if let Some(discr) = repr_type.disr_incr(tcx, prev_discr) {
|
} else if let Some(discr) = repr_type.disr_incr(tcx, prev_discr) {
|
||||||
Some(discr)
|
Some(discr)
|
||||||
} else {
|
} else {
|
||||||
struct_span_err!(tcx.sess, variant.span, E0370, "enum discriminant overflowed")
|
let span = tcx.def_span(variant.def_id);
|
||||||
.span_label(
|
struct_span_err!(tcx.sess, span, E0370, "enum discriminant overflowed")
|
||||||
variant.span,
|
.span_label(span, format!("overflowed on value after {}", prev_discr.unwrap()))
|
||||||
format!("overflowed on value after {}", prev_discr.unwrap()),
|
|
||||||
)
|
|
||||||
.note(&format!(
|
.note(&format!(
|
||||||
"explicitly set `{} = {}` if that is desired outcome",
|
"explicitly set `{} = {}` if that is desired outcome",
|
||||||
variant.ident, wrapped_discr
|
tcx.item_name(variant.def_id),
|
||||||
|
wrapped_discr
|
||||||
))
|
))
|
||||||
.emit();
|
.emit();
|
||||||
None
|
None
|
||||||
|
@ -788,17 +786,16 @@ fn convert_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId, variants: &[hir::V
|
||||||
.unwrap_or(wrapped_discr),
|
.unwrap_or(wrapped_discr),
|
||||||
);
|
);
|
||||||
|
|
||||||
for f in variant.data.fields() {
|
for f in &variant.fields {
|
||||||
let def_id = tcx.hir().local_def_id(f.hir_id);
|
tcx.ensure().generics_of(f.did);
|
||||||
tcx.ensure().generics_of(def_id);
|
tcx.ensure().type_of(f.did);
|
||||||
tcx.ensure().type_of(def_id);
|
tcx.ensure().predicates_of(f.did);
|
||||||
tcx.ensure().predicates_of(def_id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert the ctor, if any. This also registers the variant as
|
// Convert the ctor, if any. This also registers the variant as
|
||||||
// an item.
|
// an item.
|
||||||
if let Some(ctor_hir_id) = variant.data.ctor_hir_id() {
|
if let Some(ctor_def_id) = variant.ctor_def_id {
|
||||||
convert_variant_ctor(tcx, ctor_hir_id);
|
convert_variant_ctor(tcx, ctor_def_id.expect_local());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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_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)
|
(fcx, gen_ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -273,52 +266,3 @@ fn check_panic_info_fn(
|
||||||
tcx.sess.span_err(span, "should have no const parameters");
|
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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
//! Validates all used crates and extern libraries and loads their metadata
|
//! Validates all used crates and extern libraries and loads their metadata
|
||||||
|
|
||||||
use crate::errors::{
|
use crate::errors::{
|
||||||
ConflictingGlobalAlloc, CrateNotPanicRuntime, GlobalAllocRequired, NoMultipleGlobalAlloc,
|
AllocFuncRequired, ConflictingAllocErrorHandler, ConflictingGlobalAlloc, CrateNotPanicRuntime,
|
||||||
NoPanicStrategy, NoTransitiveNeedsDep, NotProfilerRuntime, ProfilerBuiltinsNeedsCore,
|
GlobalAllocRequired, MissingAllocErrorHandler, NoMultipleAllocErrorHandler,
|
||||||
|
NoMultipleGlobalAlloc, NoPanicStrategy, NoTransitiveNeedsDep, NotProfilerRuntime,
|
||||||
|
ProfilerBuiltinsNeedsCore,
|
||||||
};
|
};
|
||||||
use crate::locator::{CrateError, CrateLocator, CratePaths};
|
use crate::locator::{CrateError, CrateLocator, CratePaths};
|
||||||
use crate::rmeta::{CrateDep, CrateMetadata, CrateNumMap, CrateRoot, MetadataBlob};
|
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.
|
/// 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.
|
/// If the above is true, then this field denotes the kind of the found allocator.
|
||||||
allocator_kind: Option<AllocatorKind>,
|
allocator_kind: Option<AllocatorKind>,
|
||||||
|
/// 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<AllocatorKind>,
|
||||||
/// This crate has a `#[global_allocator]` item.
|
/// This crate has a `#[global_allocator]` item.
|
||||||
has_global_allocator: bool,
|
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
|
/// This map is used to verify we get no hash conflicts between
|
||||||
/// `StableCrateId` values.
|
/// `StableCrateId` values.
|
||||||
|
@ -197,10 +204,18 @@ impl CStore {
|
||||||
self.allocator_kind
|
self.allocator_kind
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn alloc_error_handler_kind(&self) -> Option<AllocatorKind> {
|
||||||
|
self.alloc_error_handler_kind
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn has_global_allocator(&self) -> bool {
|
pub(crate) fn has_global_allocator(&self) -> bool {
|
||||||
self.has_global_allocator
|
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<'_>) {
|
pub fn report_unused_deps(&self, tcx: TyCtxt<'_>) {
|
||||||
let json_unused_externs = tcx.sess.opts.json_unused_externs;
|
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),
|
metas: IndexVec::from_elem_n(None, 1),
|
||||||
injected_panic_runtime: None,
|
injected_panic_runtime: None,
|
||||||
allocator_kind: None,
|
allocator_kind: None,
|
||||||
|
alloc_error_handler_kind: None,
|
||||||
has_global_allocator: false,
|
has_global_allocator: false,
|
||||||
|
has_alloc_error_handler: false,
|
||||||
stable_crate_ids,
|
stable_crate_ids,
|
||||||
unused_externs: Vec::new(),
|
unused_externs: Vec::new(),
|
||||||
},
|
},
|
||||||
|
@ -792,6 +809,13 @@ impl<'a> CrateLoader<'a> {
|
||||||
}
|
}
|
||||||
spans => !spans.is_empty(),
|
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
|
// Check to see if we actually need an allocator. This desire comes
|
||||||
// about through the `#![needs_allocator]` attribute and is typically
|
// about through the `#![needs_allocator]` attribute and is typically
|
||||||
|
@ -832,12 +856,25 @@ 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() {
|
if global_allocator.is_some() {
|
||||||
self.cstore.allocator_kind = Some(AllocatorKind::Global);
|
self.cstore.allocator_kind = Some(AllocatorKind::Global);
|
||||||
return;
|
} else {
|
||||||
}
|
|
||||||
|
|
||||||
// Ok we haven't found a global allocator but we still need an
|
// Ok we haven't found a global allocator but we still need an
|
||||||
// allocator. At this point our allocator request is typically fulfilled
|
// allocator. At this point our allocator request is typically fulfilled
|
||||||
// by the standard library, denoted by the `#![default_lib_allocator]`
|
// by the standard library, denoted by the `#![default_lib_allocator]`
|
||||||
|
@ -850,6 +887,19 @@ impl<'a> CrateLoader<'a> {
|
||||||
self.cstore.allocator_kind = Some(AllocatorKind::Default);
|
self.cstore.allocator_kind = Some(AllocatorKind::Default);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn inject_dependency_if(
|
fn inject_dependency_if(
|
||||||
&self,
|
&self,
|
||||||
krate: CrateNum,
|
krate: CrateNum,
|
||||||
|
@ -1023,3 +1073,26 @@ fn global_allocator_spans(sess: &Session, krate: &ast::Crate) -> Vec<Span> {
|
||||||
visit::walk_crate(&mut f, krate);
|
visit::walk_crate(&mut f, krate);
|
||||||
f.spans
|
f.spans
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn alloc_error_handler_spans(sess: &Session, krate: &ast::Crate) -> Vec<Span> {
|
||||||
|
struct Finder<'a> {
|
||||||
|
sess: &'a Session,
|
||||||
|
name: Symbol,
|
||||||
|
spans: Vec<Span>,
|
||||||
|
}
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
|
@ -343,6 +343,16 @@ pub struct NoMultipleGlobalAlloc {
|
||||||
pub span1: Span,
|
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)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(metadata_conflicting_global_alloc)]
|
#[diag(metadata_conflicting_global_alloc)]
|
||||||
pub struct ConflictingGlobalAlloc {
|
pub struct ConflictingGlobalAlloc {
|
||||||
|
@ -350,10 +360,25 @@ pub struct ConflictingGlobalAlloc {
|
||||||
pub other_crate_name: Symbol,
|
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)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(metadata_global_alloc_required)]
|
#[diag(metadata_global_alloc_required)]
|
||||||
pub struct GlobalAllocRequired;
|
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)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(metadata_no_transitive_needs_dep)]
|
#[diag(metadata_no_transitive_needs_dep)]
|
||||||
pub struct NoTransitiveNeedsDep<'a> {
|
pub struct NoTransitiveNeedsDep<'a> {
|
||||||
|
|
|
@ -1764,6 +1764,10 @@ impl CrateMetadata {
|
||||||
self.root.has_global_allocator
|
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 {
|
pub(crate) fn has_default_lib_allocator(&self) -> bool {
|
||||||
self.root.has_default_lib_allocator
|
self.root.has_default_lib_allocator
|
||||||
}
|
}
|
||||||
|
|
|
@ -255,6 +255,7 @@ provide! { tcx, def_id, other, cdata,
|
||||||
is_panic_runtime => { cdata.root.panic_runtime }
|
is_panic_runtime => { cdata.root.panic_runtime }
|
||||||
is_compiler_builtins => { cdata.root.compiler_builtins }
|
is_compiler_builtins => { cdata.root.compiler_builtins }
|
||||||
has_global_allocator => { cdata.root.has_global_allocator }
|
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 }
|
has_panic_handler => { cdata.root.has_panic_handler }
|
||||||
is_profiler_runtime => { cdata.root.profiler_runtime }
|
is_profiler_runtime => { cdata.root.profiler_runtime }
|
||||||
required_panic_strategy => { cdata.root.required_panic_strategy }
|
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
|
// resolve! Does this work? Unsure! That's what the issue is about
|
||||||
*providers = Providers {
|
*providers = Providers {
|
||||||
allocator_kind: |tcx, ()| CStore::from_tcx(tcx).allocator_kind(),
|
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| {
|
is_private_dep: |_tcx, cnum| {
|
||||||
assert_eq!(cnum, LOCAL_CRATE);
|
assert_eq!(cnum, LOCAL_CRATE);
|
||||||
false
|
false
|
||||||
|
@ -464,6 +466,10 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) {
|
||||||
assert_eq!(cnum, LOCAL_CRATE);
|
assert_eq!(cnum, LOCAL_CRATE);
|
||||||
CStore::from_tcx(tcx).has_global_allocator()
|
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, ()| {
|
postorder_cnums: |tcx, ()| {
|
||||||
tcx.arena
|
tcx.arena
|
||||||
.alloc_slice(&CStore::from_tcx(tcx).crate_dependencies_in_postorder(LOCAL_CRATE))
|
.alloc_slice(&CStore::from_tcx(tcx).crate_dependencies_in_postorder(LOCAL_CRATE))
|
||||||
|
|
|
@ -670,6 +670,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||||
panic_in_drop_strategy: tcx.sess.opts.unstable_opts.panic_in_drop,
|
panic_in_drop_strategy: tcx.sess.opts.unstable_opts.panic_in_drop,
|
||||||
edition: tcx.sess.edition(),
|
edition: tcx.sess.edition(),
|
||||||
has_global_allocator: tcx.has_global_allocator(LOCAL_CRATE),
|
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_panic_handler: tcx.has_panic_handler(LOCAL_CRATE),
|
||||||
has_default_lib_allocator: tcx
|
has_default_lib_allocator: tcx
|
||||||
.sess
|
.sess
|
||||||
|
|
|
@ -223,6 +223,7 @@ pub(crate) struct CrateRoot {
|
||||||
panic_in_drop_strategy: PanicStrategy,
|
panic_in_drop_strategy: PanicStrategy,
|
||||||
edition: Edition,
|
edition: Edition,
|
||||||
has_global_allocator: bool,
|
has_global_allocator: bool,
|
||||||
|
has_alloc_error_handler: bool,
|
||||||
has_panic_handler: bool,
|
has_panic_handler: bool,
|
||||||
has_default_lib_allocator: bool,
|
has_default_lib_allocator: bool,
|
||||||
|
|
||||||
|
|
|
@ -1391,6 +1391,13 @@ rustc_queries! {
|
||||||
desc { "checking if the crate has_global_allocator" }
|
desc { "checking if the crate has_global_allocator" }
|
||||||
separate_provide_extern
|
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 {
|
query has_panic_handler(_: CrateNum) -> bool {
|
||||||
fatal_cycle
|
fatal_cycle
|
||||||
desc { "checking if the crate has_panic_handler" }
|
desc { "checking if the crate has_panic_handler" }
|
||||||
|
@ -1761,6 +1768,10 @@ rustc_queries! {
|
||||||
eval_always
|
eval_always
|
||||||
desc { "getting the allocator kind for the current crate" }
|
desc { "getting the allocator kind for the current crate" }
|
||||||
}
|
}
|
||||||
|
query alloc_error_handler_kind(_: ()) -> Option<AllocatorKind> {
|
||||||
|
eval_always
|
||||||
|
desc { "alloc error handler kind for the current crate" }
|
||||||
|
}
|
||||||
|
|
||||||
query upvars_mentioned(def_id: DefId) -> Option<&'tcx FxIndexMap<hir::HirId, hir::Upvar>> {
|
query upvars_mentioned(def_id: DefId) -> Option<&'tcx FxIndexMap<hir::HirId, hir::Upvar>> {
|
||||||
desc { |tcx| "collecting upvars mentioned in `{}`", tcx.def_path_str(def_id) }
|
desc { |tcx| "collecting upvars mentioned in `{}`", tcx.def_path_str(def_id) }
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
use rustc_index::vec::Idx;
|
use rustc_index::vec::Idx;
|
||||||
use rustc_middle::ty::util::IntTypeExt;
|
use rustc_middle::ty::util::IntTypeExt;
|
||||||
|
use rustc_target::abi::{Abi, Primitive};
|
||||||
|
|
||||||
use crate::build::expr::as_place::PlaceBase;
|
use crate::build::expr::as_place::PlaceBase;
|
||||||
use crate::build::expr::category::{Category, RvalueFunc};
|
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 (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 discr_ty = adt_def.repr().discr_type().to_ty(this.tcx);
|
||||||
let temp = unpack!(block = this.as_temp(block, scope, source, Mutability::Not));
|
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);
|
let discr = this.temp(discr_ty, source.span);
|
||||||
this.cfg.push_assign(
|
this.cfg.push_assign(
|
||||||
block,
|
block,
|
||||||
|
@ -205,8 +207,55 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
discr,
|
discr,
|
||||||
Rvalue::Discriminant(temp.into()),
|
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 {
|
} else {
|
||||||
let ty = source.ty;
|
let ty = source.ty;
|
||||||
let source = unpack!(
|
let source = unpack!(
|
||||||
|
|
|
@ -101,12 +101,10 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> {
|
||||||
| StatementKind::Retag { .. }
|
| StatementKind::Retag { .. }
|
||||||
| StatementKind::AscribeUserType(..)
|
| StatementKind::AscribeUserType(..)
|
||||||
| StatementKind::Coverage(..)
|
| StatementKind::Coverage(..)
|
||||||
|
| StatementKind::Intrinsic(..)
|
||||||
| StatementKind::Nop => {
|
| StatementKind::Nop => {
|
||||||
// safe (at least as emitted during MIR construction)
|
// 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);
|
self.super_statement(statement, location);
|
||||||
}
|
}
|
||||||
|
|
|
@ -470,11 +470,6 @@ fn has_allow_dead_code_or_lang_attr_helper(
|
||||||
return true;
|
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);
|
let def_id = tcx.hir().local_def_id(id);
|
||||||
if tcx.def_kind(def_id).has_codegen_attrs() {
|
if tcx.def_kind(def_id).has_codegen_attrs() {
|
||||||
let cg_attrs = tcx.codegen_fn_attrs(def_id);
|
let cg_attrs = tcx.codegen_fn_attrs(def_id);
|
||||||
|
|
|
@ -701,14 +701,6 @@ pub struct UnknownExternLangItem {
|
||||||
#[diag(passes_missing_panic_handler)]
|
#[diag(passes_missing_panic_handler)]
|
||||||
pub struct MissingPanicHandler;
|
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)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(passes_missing_lang_item)]
|
#[diag(passes_missing_lang_item)]
|
||||||
#[note]
|
#[note]
|
||||||
|
|
|
@ -7,10 +7,7 @@ use rustc_middle::middle::lang_items::required;
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
use rustc_session::config::CrateType;
|
use rustc_session::config::CrateType;
|
||||||
|
|
||||||
use crate::errors::{
|
use crate::errors::{MissingLangItem, MissingPanicHandler, UnknownExternLangItem};
|
||||||
AllocFuncRequired, MissingAllocErrorHandler, MissingLangItem, MissingPanicHandler,
|
|
||||||
UnknownExternLangItem,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Checks the crate for usage of weak lang items, returning a vector of all the
|
/// 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.
|
/// 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 missing.contains(&item) && required(tcx, item) && items.get(item).is_none() {
|
||||||
if item == LangItem::PanicImpl {
|
if item == LangItem::PanicImpl {
|
||||||
tcx.sess.emit_err(MissingPanicHandler);
|
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 {
|
} else {
|
||||||
tcx.sess.emit_err(MissingLangItem { name: item.name() });
|
tcx.sess.emit_err(MissingLangItem { name: item.name() });
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ use smallvec::{smallvec, SmallVec};
|
||||||
use rustc_span::source_map::{respan, Spanned};
|
use rustc_span::source_map::{respan, Spanned};
|
||||||
use std::assert_matches::debug_assert_matches;
|
use std::assert_matches::debug_assert_matches;
|
||||||
use std::collections::{hash_map::Entry, BTreeSet};
|
use std::collections::{hash_map::Entry, BTreeSet};
|
||||||
use std::mem::{replace, take};
|
use std::mem::{replace, swap, take};
|
||||||
|
|
||||||
mod diagnostics;
|
mod diagnostics;
|
||||||
|
|
||||||
|
@ -3369,11 +3369,6 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||||
let (mut err, candidates) =
|
let (mut err, candidates) =
|
||||||
this.smart_resolve_report_errors(path, path_span, PathSource::Type, None);
|
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
|
// There are two different error messages user might receive at
|
||||||
// this point:
|
// this point:
|
||||||
// - E0412 cannot find type `{}` in this scope
|
// - E0412 cannot find type `{}` in this scope
|
||||||
|
@ -3383,22 +3378,46 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||||
// latter one - for paths in expression-position.
|
// latter one - for paths in expression-position.
|
||||||
//
|
//
|
||||||
// Thus (since we're in expression-position at this point), not to
|
// 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`).
|
// `parent_err`), but we want *hints* from E0412 (so `err`).
|
||||||
//
|
//
|
||||||
// And that's what happens below - we're just mixing both messages
|
// And that's what happens below - we're just mixing both messages
|
||||||
// into a single one.
|
// into a single one.
|
||||||
let mut parent_err = this.r.into_struct_error(parent_err.span, parent_err.node);
|
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.message = take(&mut parent_err.message);
|
||||||
err.code = take(&mut parent_err.code);
|
err.code = take(&mut parent_err.code);
|
||||||
|
swap(&mut err.span, &mut parent_err.span);
|
||||||
err.children = take(&mut parent_err.children);
|
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<T, E>(res1: &mut Result<Vec<T>, E>, res2: Result<Vec<T>, 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();
|
parent_err.cancel();
|
||||||
|
|
||||||
let def_id = this.parent_scope.module.nearest_parent_mod();
|
let def_id = this.parent_scope.module.nearest_parent_mod();
|
||||||
|
|
||||||
if this.should_report_errs() {
|
if this.should_report_errs() {
|
||||||
|
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 {
|
this.r.use_injections.push(UseError {
|
||||||
err,
|
err,
|
||||||
candidates,
|
candidates,
|
||||||
|
@ -3408,12 +3427,13 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||||
path: path.into(),
|
path: path.into(),
|
||||||
is_call: source.is_call(),
|
is_call: source.is_call(),
|
||||||
});
|
});
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
err.cancel();
|
err.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
// We don't return `Some(parent_err)` here, because the error will
|
// 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
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -402,19 +402,18 @@ pub use std::alloc::handle_alloc_error;
|
||||||
#[allow(unused_attributes)]
|
#[allow(unused_attributes)]
|
||||||
#[unstable(feature = "alloc_internals", issue = "none")]
|
#[unstable(feature = "alloc_internals", issue = "none")]
|
||||||
pub mod __alloc_error_handler {
|
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]
|
#[rustc_std_internal_symbol]
|
||||||
pub unsafe fn __rdl_oom(size: usize, _align: usize) -> ! {
|
pub unsafe fn __rdl_oom(size: usize, _align: usize) -> ! {
|
||||||
panic!("memory allocation of {size} bytes failed")
|
panic!("memory allocation of {size} bytes failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
// if there is an `#[alloc_error_handler]`
|
#[cfg(bootstrap)]
|
||||||
#[rustc_std_internal_symbol]
|
#[rustc_std_internal_symbol]
|
||||||
pub unsafe fn __rg_oom(size: usize, align: usize) -> ! {
|
pub unsafe fn __rg_oom(size: usize, align: usize) -> ! {
|
||||||
|
use crate::alloc::Layout;
|
||||||
|
|
||||||
let layout = unsafe { Layout::from_size_align_unchecked(size, align) };
|
let layout = unsafe { Layout::from_size_align_unchecked(size, align) };
|
||||||
extern "Rust" {
|
extern "Rust" {
|
||||||
#[lang = "oom"]
|
#[lang = "oom"]
|
||||||
|
|
|
@ -1511,6 +1511,17 @@ pub(crate) mod builtin {
|
||||||
/* compiler built-in */
|
/* 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.
|
/// Keeps the item it's applied to if the passed path is accessible, and removes it otherwise.
|
||||||
#[unstable(
|
#[unstable(
|
||||||
feature = "cfg_accessible",
|
feature = "cfg_accessible",
|
||||||
|
|
|
@ -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
|
// Do not `doc(no_inline)` so that they become doc items on their own
|
||||||
// (no public module for them to be re-exported from).
|
// (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")]
|
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
|
||||||
pub use crate::macros::builtin::{bench, derive, global_allocator, test, test_case};
|
pub use crate::macros::builtin::{bench, derive, global_allocator, test, test_case};
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#![feature(bigint_helper_methods)]
|
#![feature(bigint_helper_methods)]
|
||||||
#![feature(cell_update)]
|
#![feature(cell_update)]
|
||||||
#![feature(const_assume)]
|
#![feature(const_assume)]
|
||||||
|
#![feature(const_align_of_val_raw)]
|
||||||
#![feature(const_black_box)]
|
#![feature(const_black_box)]
|
||||||
#![feature(const_bool_to_option)]
|
#![feature(const_bool_to_option)]
|
||||||
#![feature(const_caller_location)]
|
#![feature(const_caller_location)]
|
||||||
|
@ -42,6 +43,7 @@
|
||||||
#![feature(try_find)]
|
#![feature(try_find)]
|
||||||
#![feature(inline_const)]
|
#![feature(inline_const)]
|
||||||
#![feature(is_sorted)]
|
#![feature(is_sorted)]
|
||||||
|
#![feature(layout_for_ptr)]
|
||||||
#![feature(pattern)]
|
#![feature(pattern)]
|
||||||
#![feature(pin_macro)]
|
#![feature(pin_macro)]
|
||||||
#![feature(sort_internals)]
|
#![feature(sort_internals)]
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use core::mem::*;
|
use core::mem::*;
|
||||||
|
use core::ptr;
|
||||||
|
|
||||||
#[cfg(panic = "unwind")]
|
#[cfg(panic = "unwind")]
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
@ -75,6 +76,25 @@ fn align_of_val_basic() {
|
||||||
assert_eq!(align_of_val(&1u32), 4);
|
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]
|
#[test]
|
||||||
fn test_swap() {
|
fn test_swap() {
|
||||||
let mut x = 31337;
|
let mut x = 31337;
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
//! [`Ipv6Addr`] are respectively IPv4 and IPv6 addresses
|
//! [`Ipv6Addr`] are respectively IPv4 and IPv6 addresses
|
||||||
//! * [`SocketAddr`] represents socket addresses of either IPv4 or IPv6; [`SocketAddrV4`]
|
//! * [`SocketAddr`] represents socket addresses of either IPv4 or IPv6; [`SocketAddrV4`]
|
||||||
//! and [`SocketAddrV6`] are respectively IPv4 and IPv6 socket addresses
|
//! 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`]
|
//! with networking objects like [`TcpListener`], [`TcpStream`] or [`UdpSocket`]
|
||||||
//! * Other types are return or parameter types for various methods in this module
|
//! * Other types are return or parameter types for various methods in this module
|
||||||
//!
|
//!
|
||||||
|
|
|
@ -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
|
// Do not `doc(no_inline)` so that they become doc items on their own
|
||||||
// (no public module for them to be re-exported from).
|
// (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")]
|
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
|
||||||
pub use core::prelude::v1::{bench, derive, global_allocator, test, test_case};
|
pub use core::prelude::v1::{bench, derive, global_allocator, test, test_case};
|
||||||
|
|
||||||
|
|
|
@ -12,15 +12,13 @@ pub enum Bar {
|
||||||
// CHECK-LABEL: @lookup_inc
|
// CHECK-LABEL: @lookup_inc
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn lookup_inc(buf: &[u8; 5], f: Bar) -> u8 {
|
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-NOT: panic_bounds_check
|
||||||
// CHECK: panic_bounds_check
|
|
||||||
buf[f as usize + 1]
|
buf[f as usize + 1]
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK-LABEL: @lookup_dec
|
// CHECK-LABEL: @lookup_dec
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn lookup_dec(buf: &[u8; 5], f: Bar) -> u8 {
|
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-NOT: panic_bounds_check
|
||||||
// CHECK: panic_bounds_check
|
|
||||||
buf[f as usize - 1]
|
buf[f as usize - 1]
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,6 @@ pub enum Exception {
|
||||||
// CHECK-LABEL: @access
|
// CHECK-LABEL: @access
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn access(array: &[usize; 12], exc: Exception) -> usize {
|
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-NOT: panic_bounds_check
|
||||||
// CHECK: panic_bounds_check
|
|
||||||
array[(exc as u8 - 4) as usize]
|
array[(exc as u8 - 4) as usize]
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,6 @@ pub enum Bar {
|
||||||
// CHECK-LABEL: @lookup_unmodified
|
// CHECK-LABEL: @lookup_unmodified
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn lookup_unmodified(buf: &[u8; 5], f: Bar) -> u8 {
|
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-NOT: panic_bounds_check
|
||||||
// CHECK: panic_bounds_check
|
|
||||||
buf[f as usize]
|
buf[f as usize]
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 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 _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 _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: {
|
bb0: {
|
||||||
StorageLive(_2); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
|
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
|
_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
|
_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
|
_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
|
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
|
return; // scope 0 at $DIR/enum_cast.rs:+2:2: +2:2
|
||||||
|
|
|
@ -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 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 _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 _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: {
|
bb0: {
|
||||||
StorageLive(_2); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
|
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
|
_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
|
_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
|
_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
|
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
|
return; // scope 0 at $DIR/enum_cast.rs:+2:2: +2:2
|
||||||
|
|
|
@ -6,7 +6,9 @@ fn droppy() -> () {
|
||||||
let _2: Droppy; // in scope 0 at $DIR/enum_cast.rs:+2:13: +2:14
|
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 _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 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 {
|
scope 1 {
|
||||||
debug x => _2; // in scope 1 at $DIR/enum_cast.rs:+2:13: +2:14
|
debug x => _2; // in scope 1 at $DIR/enum_cast.rs:+2:13: +2:14
|
||||||
scope 2 {
|
scope 2 {
|
||||||
|
@ -17,7 +19,7 @@ fn droppy() -> () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scope 4 {
|
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: {
|
bb0: {
|
||||||
|
@ -29,6 +31,10 @@ fn droppy() -> () {
|
||||||
StorageLive(_4); // scope 3 at $DIR/enum_cast.rs:+5:17: +5:18
|
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
|
_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
|
_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
|
_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
|
drop(_4) -> [return: bb1, unwind: bb4]; // scope 3 at $DIR/enum_cast.rs:+5:26: +5:27
|
||||||
}
|
}
|
||||||
|
@ -44,15 +50,15 @@ fn droppy() -> () {
|
||||||
bb2: {
|
bb2: {
|
||||||
StorageDead(_2); // scope 0 at $DIR/enum_cast.rs:+6:5: +6:6
|
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
|
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
|
StorageLive(_8); // 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
|
_8 = 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
|
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
|
_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: {
|
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
|
return; // scope 0 at $DIR/enum_cast.rs:+8:2: +8:2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,4 +6,4 @@ all:
|
||||||
$(RUSTC) --emit=obj app.rs
|
$(RUSTC) --emit=obj app.rs
|
||||||
nm $(TMPDIR)/app.o | $(CGREP) rust_begin_unwind
|
nm $(TMPDIR)/app.o | $(CGREP) rust_begin_unwind
|
||||||
nm $(TMPDIR)/app.o | $(CGREP) rust_eh_personality
|
nm $(TMPDIR)/app.o | $(CGREP) rust_eh_personality
|
||||||
nm $(TMPDIR)/app.o | $(CGREP) rust_oom
|
nm $(TMPDIR)/app.o | $(CGREP) __rg_oom
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#![crate_type = "bin"]
|
#![crate_type = "bin"]
|
||||||
#![feature(lang_items)]
|
#![feature(lang_items, alloc_error_handler)]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ fn panic(_: &PanicInfo) -> ! {
|
||||||
#[lang = "eh_personality"]
|
#[lang = "eh_personality"]
|
||||||
fn eh() {}
|
fn eh() {}
|
||||||
|
|
||||||
#[lang = "oom"]
|
#[alloc_error_handler]
|
||||||
fn oom(_: Layout) -> ! {
|
fn oom(_: Layout) -> ! {
|
||||||
loop {}
|
loop {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,8 +8,8 @@ use core::alloc::Layout;
|
||||||
|
|
||||||
#[alloc_error_handler]
|
#[alloc_error_handler]
|
||||||
fn oom(
|
fn oom(
|
||||||
info: &Layout, //~ ERROR argument should be `Layout`
|
info: &Layout, //~^ ERROR mismatched types
|
||||||
) -> () //~ ERROR return type should be `!`
|
) -> () //~^^ ERROR mismatched types
|
||||||
{
|
{
|
||||||
loop {}
|
loop {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,50 @@
|
||||||
error: return type should be `!`
|
error[E0308]: mismatched types
|
||||||
--> $DIR/alloc-error-handler-bad-signature-1.rs:12:6
|
--> $DIR/alloc-error-handler-bad-signature-1.rs:10:1
|
||||||
|
|
|
|
||||||
LL | ) -> ()
|
LL | #[alloc_error_handler]
|
||||||
| ^^
|
| ---------------------- in this procedural macro expansion
|
||||||
|
LL | fn oom(
|
||||||
error: argument should be `Layout`
|
| _^
|
||||||
--> $DIR/alloc-error-handler-bad-signature-1.rs:11:11
|
| |_|
|
||||||
|
| ||
|
||||||
|
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,
|
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
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0308`.
|
||||||
|
|
|
@ -8,8 +8,8 @@ struct Layout;
|
||||||
|
|
||||||
#[alloc_error_handler]
|
#[alloc_error_handler]
|
||||||
fn oom(
|
fn oom(
|
||||||
info: Layout, //~ ERROR argument should be `Layout`
|
info: Layout, //~^ ERROR mismatched types
|
||||||
) { //~ ERROR return type should be `!`
|
) { //~^^ ERROR mismatched types
|
||||||
loop {}
|
loop {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,63 @@
|
||||||
error: return type should be `!`
|
error[E0308]: mismatched types
|
||||||
--> $DIR/alloc-error-handler-bad-signature-2.rs:12:3
|
--> $DIR/alloc-error-handler-bad-signature-2.rs:10:1
|
||||||
|
|
|
|
||||||
LL | ) {
|
LL | #[alloc_error_handler]
|
||||||
| ^
|
| ---------------------- in this procedural macro expansion
|
||||||
|
LL | fn oom(
|
||||||
error: argument should be `Layout`
|
| _^
|
||||||
--> $DIR/alloc-error-handler-bad-signature-2.rs:11:11
|
| |_|
|
||||||
|
| ||
|
||||||
|
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,
|
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
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0308`.
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
struct Layout;
|
struct Layout;
|
||||||
|
|
||||||
#[alloc_error_handler]
|
#[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 {}
|
loop {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
--> $DIR/alloc-error-handler-bad-signature-3.rs:10:1
|
||||||
|
|
|
|
||||||
|
LL | #[alloc_error_handler]
|
||||||
|
| ---------------------- in this procedural macro expansion
|
||||||
LL | fn oom() -> ! {
|
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
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0061`.
|
||||||
|
|
|
@ -2,7 +2,7 @@ error[E0433]: failed to resolve: use of undeclared type `IntoIter`
|
||||||
--> $DIR/issue-82956.rs:25:24
|
--> $DIR/issue-82956.rs:25:24
|
||||||
|
|
|
|
||||||
LL | let mut iter = IntoIter::new(self);
|
LL | let mut iter = IntoIter::new(self);
|
||||||
| ^^^^^^^^ not found in this scope
|
| ^^^^^^^^ use of undeclared type `IntoIter`
|
||||||
|
|
|
|
||||||
help: consider importing one of these items
|
help: consider importing one of these items
|
||||||
|
|
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ error[E0433]: failed to resolve: use of undeclared type `HashMap`
|
||||||
--> $DIR/issue-31997-1.rs:20:19
|
--> $DIR/issue-31997-1.rs:20:19
|
||||||
|
|
|
|
||||||
LL | let mut map = HashMap::new();
|
LL | let mut map = HashMap::new();
|
||||||
| ^^^^^^^ not found in this scope
|
| ^^^^^^^ use of undeclared type `HashMap`
|
||||||
|
|
|
|
||||||
help: consider importing this struct
|
help: consider importing this struct
|
||||||
|
|
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ LL | First = -1,
|
||||||
| -- `-1` assigned here
|
| -- `-1` assigned here
|
||||||
LL |
|
LL |
|
||||||
LL | Second = -2,
|
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 |
|
||||||
LL | Last,
|
LL | Last,
|
||||||
| ---- `-1` assigned here
|
| ---- `-1` assigned here
|
||||||
|
@ -53,7 +53,7 @@ LL | V4 = 0,
|
||||||
| - `0` assigned here
|
| - `0` assigned here
|
||||||
LL |
|
LL |
|
||||||
LL | V5 = -2,
|
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,
|
LL | V7,
|
||||||
| -- `0` assigned here
|
| -- `0` assigned here
|
||||||
|
@ -68,7 +68,7 @@ LL | V5 = -2,
|
||||||
| -- `-2` assigned here
|
| -- `-2` assigned here
|
||||||
...
|
...
|
||||||
LL | V8 = -3,
|
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 |
|
||||||
LL | V9,
|
LL | V9,
|
||||||
| -- `-2` assigned here
|
| -- `-2` assigned here
|
||||||
|
|
|
@ -5,10 +5,12 @@
|
||||||
|
|
||||||
use core::alloc::Layout;
|
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) -> ! {
|
fn oom(info: Layout) -> ! {
|
||||||
loop {}
|
loop {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
fn panic(_: &core::panic::PanicInfo) -> ! { loop {} }
|
fn panic(_: &core::panic::PanicInfo) -> ! {
|
||||||
|
loop {}
|
||||||
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
error[E0658]: the `#[alloc_error_handler]` attribute is an experimental feature
|
error[E0658]: use of unstable library feature 'alloc_error_handler'
|
||||||
--> $DIR/feature-gate-alloc-error-handler.rs:8:1
|
--> $DIR/feature-gate-alloc-error-handler.rs:8:3
|
||||||
|
|
|
|
||||||
LL | #[alloc_error_handler]
|
LL | #[alloc_error_handler]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: see issue #51540 <https://github.com/rust-lang/rust/issues/51540> for more information
|
= note: see issue #51540 <https://github.com/rust-lang/rust/issues/51540> for more information
|
||||||
= help: add `#![feature(alloc_error_handler)]` to the crate attributes to enable
|
= help: add `#![feature(alloc_error_handler)]` to the crate attributes to enable
|
||||||
|
|
|
@ -5,7 +5,7 @@ LL | fn f() { ::bar::m!(); }
|
||||||
| ----------- in this macro invocation
|
| ----------- in this macro invocation
|
||||||
...
|
...
|
||||||
LL | Vec::new();
|
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)
|
= 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
|
help: consider importing this struct
|
||||||
|
|
|
@ -2,7 +2,7 @@ error[E0433]: failed to resolve: use of undeclared type `Command`
|
||||||
--> $DIR/amputate-span.rs:49:5
|
--> $DIR/amputate-span.rs:49:5
|
||||||
|
|
|
|
||||||
LL | Command::new("git");
|
LL | Command::new("git");
|
||||||
| ^^^^^^^ not found in this scope
|
| ^^^^^^^ use of undeclared type `Command`
|
||||||
|
|
|
|
||||||
help: consider importing this struct
|
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
|
--> $DIR/amputate-span.rs:63:9
|
||||||
|
|
|
|
||||||
LL | Command::new("git");
|
LL | Command::new("git");
|
||||||
| ^^^^^^^ not found in this scope
|
| ^^^^^^^ use of undeclared type `Command`
|
||||||
|
|
|
|
||||||
help: consider importing this struct
|
help: consider importing this struct
|
||||||
|
|
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
error[E0433]: failed to resolve: could not find `hahmap` in `std`
|
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();
|
LL | let _map = std::hahmap::HashMap::new();
|
||||||
| ^^^^^^^ not found in `std::hahmap`
|
| ^^^^^^ could not find `hahmap` in `std`
|
||||||
|
|
|
|
||||||
help: consider importing this struct
|
help: consider importing this struct
|
||||||
|
|
|
|
||||||
|
|
42
src/test/ui/resolve/typo-suggestion-mistyped-in-path.rs
Normal file
42
src/test/ui/resolve/typo-suggestion-mistyped-in-path.rs
Normal file
|
@ -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`
|
||||||
|
}
|
54
src/test/ui/resolve/typo-suggestion-mistyped-in-path.stderr
Normal file
54
src/test/ui/resolve/typo-suggestion-mistyped-in-path.stderr
Normal file
|
@ -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`.
|
|
@ -8,7 +8,7 @@ error[E0433]: failed to resolve: use of undeclared type `HashMap`
|
||||||
--> $DIR/use_suggestion.rs:2:14
|
--> $DIR/use_suggestion.rs:2:14
|
||||||
|
|
|
|
||||||
LL | let x1 = HashMap::new();
|
LL | let x1 = HashMap::new();
|
||||||
| ^^^^^^^ not found in this scope
|
| ^^^^^^^ use of undeclared type `HashMap`
|
||||||
|
|
|
|
||||||
help: consider importing this struct
|
help: consider importing this struct
|
||||||
|
|
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ error[E0433]: failed to resolve: use of undeclared type `NonZeroU32`
|
||||||
--> $DIR/core-std-import-order-issue-83564.rs:8:14
|
--> $DIR/core-std-import-order-issue-83564.rs:8:14
|
||||||
|
|
|
|
||||||
LL | let _x = NonZeroU32::new(5).unwrap();
|
LL | let _x = NonZeroU32::new(5).unwrap();
|
||||||
| ^^^^^^^^^^ not found in this scope
|
| ^^^^^^^^^^ use of undeclared type `NonZeroU32`
|
||||||
|
|
|
|
||||||
help: consider importing one of these items
|
help: consider importing one of these items
|
||||||
|
|
|
|
||||||
|
|
|
@ -10,18 +10,19 @@ fn test() {
|
||||||
|
|
||||||
let _i: i16 = TryFrom::try_from(0_i32).unwrap();
|
let _i: i16 = TryFrom::try_from(0_i32).unwrap();
|
||||||
//~^ ERROR failed to resolve: use of undeclared type
|
//~^ 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 '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
|
//~| NOTE 'core::convert::TryFrom' is included in the prelude starting in Edition 2021
|
||||||
|
|
||||||
let _i: i16 = TryInto::try_into(0_i32).unwrap();
|
let _i: i16 = TryInto::try_into(0_i32).unwrap();
|
||||||
//~^ ERROR failed to resolve: use of undeclared type
|
//~^ 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 '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
|
//~| NOTE 'core::convert::TryInto' is included in the prelude starting in Edition 2021
|
||||||
|
|
||||||
let _v: Vec<_> = FromIterator::from_iter(&[1]);
|
let _v: Vec<_> = FromIterator::from_iter(&[1]);
|
||||||
//~^ ERROR failed to resolve: use of undeclared type
|
//~^ 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 '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
|
//~| NOTE 'core::iter::FromIterator' is included in the prelude starting in Edition 2021
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ error[E0433]: failed to resolve: use of undeclared type `TryFrom`
|
||||||
--> $DIR/suggest-tryinto-edition-change.rs:11:19
|
--> $DIR/suggest-tryinto-edition-change.rs:11:19
|
||||||
|
|
|
|
||||||
LL | let _i: i16 = TryFrom::try_from(0_i32).unwrap();
|
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: '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
|
= 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
|
--> $DIR/suggest-tryinto-edition-change.rs:17:19
|
||||||
|
|
|
|
||||||
LL | let _i: i16 = TryInto::try_into(0_i32).unwrap();
|
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: '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
|
= 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
|
--> $DIR/suggest-tryinto-edition-change.rs:23:22
|
||||||
|
|
|
|
||||||
LL | let _v: Vec<_> = FromIterator::from_iter(&[1]);
|
LL | let _v: Vec<_> = FromIterator::from_iter(&[1]);
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^ use of undeclared type `FromIterator`
|
||||||
|
|
|
||||||
::: $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
|
|
||||||
|
|
|
||||||
LL | pub trait IntoIterator {
|
|
||||||
| ---------------------- similarly named trait `IntoIterator` defined here
|
|
||||||
|
|
|
|
||||||
= note: 'std::iter::FromIterator' is included in the prelude starting in Edition 2021
|
= 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
|
= note: 'core::iter::FromIterator' is included in the prelude starting in Edition 2021
|
||||||
|
|
|
@ -12,6 +12,46 @@ LL | V3 = Self::V1 {} as u8 + 2,
|
||||||
note: ...which requires const-evaluating + checking `Alpha::V3::{constant#0}`...
|
note: ...which requires const-evaluating + checking `Alpha::V3::{constant#0}`...
|
||||||
--> $DIR/self-in-enum-definition.rs:5:10
|
--> $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,
|
LL | V3 = Self::V1 {} as u8 + 2,
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^
|
||||||
= note: ...which requires computing layout of `Alpha`...
|
= note: ...which requires computing layout of `Alpha`...
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue