diff --git a/compiler/rustc_ast/src/entry.rs b/compiler/rustc_ast/src/entry.rs index 290f6006de0..c0a837985fd 100644 --- a/compiler/rustc_ast/src/entry.rs +++ b/compiler/rustc_ast/src/entry.rs @@ -1,3 +1,4 @@ +#[derive(Debug)] pub enum EntryPointType { None, MainNamed, diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 69fa99993bb..7036c05a593 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -128,7 +128,7 @@ pub struct ResolverOutputs { pub main_def: Option, } -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Debug)] pub struct MainDefinition { pub res: Res, pub is_import: bool, diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs index ca6a7561f3e..34ea5e9abd4 100644 --- a/compiler/rustc_passes/src/entry.rs +++ b/compiler/rustc_passes/src/entry.rs @@ -2,7 +2,7 @@ use rustc_ast::entry::EntryPointType; use rustc_errors::struct_span_err; use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_hir::itemlikevisit::ItemLikeVisitor; -use rustc_hir::{ForeignItem, HirId, ImplItem, Item, ItemKind, TraitItem, CRATE_HIR_ID}; +use rustc_hir::{ForeignItem, HirId, ImplItem, Item, ItemKind, Node, TraitItem, CRATE_HIR_ID}; use rustc_middle::hir::map::Map; use rustc_middle::ty::query::Providers; use rustc_middle::ty::TyCtxt; @@ -148,6 +148,20 @@ fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) -> Option<(De } else if let Some((hir_id, _)) = visitor.attr_main_fn { Some((tcx.hir().local_def_id(hir_id).to_def_id(), EntryFnType::Main)) } else if let Some(def_id) = tcx.main_def.and_then(|main_def| main_def.opt_fn_def_id()) { + // non-local main imports are handled below + if def_id.is_local() { + let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); + if matches!(tcx.hir().find(hir_id), Some(Node::ForeignItem(_))) { + tcx.sess + .struct_span_err( + tcx.hir().span(hir_id), + "the `main` function cannot be declared in an `extern` block", + ) + .emit(); + return None; + } + } + if tcx.main_def.unwrap().is_import && !tcx.features().imported_main { let span = tcx.main_def.unwrap().span; feature_err( diff --git a/src/test/ui/extern/extern-main-issue-86110.rs b/src/test/ui/extern/extern-main-issue-86110.rs new file mode 100644 index 00000000000..83af7a14ccc --- /dev/null +++ b/src/test/ui/extern/extern-main-issue-86110.rs @@ -0,0 +1,7 @@ +// missing and missing2 exist to make sure that the error only happens on a `main` declaration +extern "C" { + fn missing(); + fn main(); + //~^ the `main` function cannot be declared in an `extern` block + fn missing2(); +} diff --git a/src/test/ui/extern/extern-main-issue-86110.stderr b/src/test/ui/extern/extern-main-issue-86110.stderr new file mode 100644 index 00000000000..cd3de227dcf --- /dev/null +++ b/src/test/ui/extern/extern-main-issue-86110.stderr @@ -0,0 +1,8 @@ +error: the `main` function cannot be declared in an `extern` block + --> $DIR/extern-main-issue-86110.rs:4:5 + | +LL | fn main(); + | ^^^^^^^^^^ + +error: aborting due to previous error +