Skip to content

Migrate rustc_passes diagnostics #102110

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 29 commits into from
Oct 12, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
bde80f7
Add lint for diagnostic migration
naritanara Aug 22, 2022
2f74d1d
Migrate weak_lang_items.rs
naritanara Aug 22, 2022
17a4a68
Migrate derivable diagnostics in lang_items.rs
naritanara Sep 1, 2022
0315d7c
Migrate derivable diagnostics in check_attr.rs
naritanara Sep 2, 2022
2c3351c
Migrate InvalidAttrAtCrateLevel
naritanara Sep 2, 2022
c24a873
always put ftl message on next line, resolve all but 1 output compari…
CleanCut Sep 21, 2022
b8e03cf
use consistent names
CleanCut Sep 22, 2022
1222541
resolve merge conflict from cherry-picking 6a47326a0452cc8d5cb5767650…
diegooliveira Sep 14, 2022
c103c30
migrate the rest of weak_lang_items.rs to translateable diagnostics
CleanCut Sep 22, 2022
1e86226
migrate debugger_visualizer.rs to translateable diagnostics
CleanCut Sep 22, 2022
f8ebc72
errors: add `emit_note`/`create_note`
davidtwco Sep 1, 2022
3a74833
use cherry-picked commit from #100754 to emit note without error
CleanCut Sep 22, 2022
0609c0f
migrate diagnostic_items.rs to translateable diagnostics
CleanCut Sep 23, 2022
40d5f00
migrate layout_test.rs to translateable diagnostics
CleanCut Sep 23, 2022
c457abe
migrate lib_features.rs to translateable diagnostics
CleanCut Sep 24, 2022
572f341
migrate check_const.rs to translateable diagnostics
CleanCut Sep 24, 2022
69766e4
migrate loops.rs to translateable diagnostics
CleanCut Sep 26, 2022
96f92ea
migrate naked_functions.rs to translateable diagnostics
CleanCut Sep 27, 2022
b17ec43
migrate entry.rs to translateable diagnostics
CleanCut Sep 28, 2022
f0afb88
migrate lang_items.rs to translateable diagnostics
CleanCut Oct 1, 2022
a7aa185
migrate dead.rs to translateable diagnostics
CleanCut Oct 2, 2022
3fe8e00
migrate the rest of check_attr.rs to translateable diagnostics
CleanCut Oct 2, 2022
be4059d
migrate stability.rs to translateable diagnostics
CleanCut Oct 3, 2022
965dbf6
First batch of review feedback changes from #102110
CleanCut Oct 3, 2022
8e07a85
Remove code that was removed in master, and the corresponding diagnostic
CleanCut Oct 5, 2022
57eba4f
avoid string dispatch in fluent
CleanCut Oct 5, 2022
31c269a
avoid string dispatch in fluent
CleanCut Oct 7, 2022
50e2795
remove out-of-date fixme
CleanCut Oct 10, 2022
5ef1c03
make up your mind, rustfmt
CleanCut Oct 10, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
migrate entry.rs to translateable diagnostics
  • Loading branch information
CleanCut committed Oct 7, 2022
commit b17ec43637276773cd331844896fe7071de2475c
39 changes: 39 additions & 0 deletions compiler/rustc_error_messages/locales/en-US/passes.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -495,3 +495,42 @@ passes_naked_functions_asm_options =
passes_naked_functions_must_use_noreturn =
asm in naked functions must use `noreturn` option
.suggestion = consider specifying that the asm block is responsible for returning from the function

passes_attr_only_on_main =
`{$attr}` attribute can only be used on `fn main()`

passes_attr_only_on_root_main =
`{$attr}` attribute can only be used on root `fn main()`

passes_attr_only_in_functions =
`{$attr}` attribute can only be used on functions

passes_multiple_rustc_main =
multiple functions with a `#[rustc_main]` attribute
.first = first `#[rustc_main]` function
.additional = additional `#[rustc_main]` function

passes_multiple_start_functions =
multiple `start` functions
.label = multiple `start` functions
.previous = previous `#[start]` function here

passes_extern_main =
the `main` function cannot be declared in an `extern` block

passes_unix_sigpipe_values =
valid values for `#[unix_sigpipe = "..."]` are `inherit`, `sig_ign`, or `sig_dfl`

passes_no_main_function =
`main` function not found in crate `{$crate_name}`
.here_is_main = here is a function named `main`
.one_or_more_possible_main = you have one or more functions named `main` not defined at the crate level
.consider_moving_main = consider moving the `main` function definitions
.main_must_be_defined_at_crate = the main function must be defined at the crate level{$has_filename ->
[true] {" "}(in `{$filename}`)
*[false] {""}
}
.consider_adding_main_to_file = consider adding a `main` function to `{$filename}`
.consider_adding_main_at_crate = consider adding a `main` function at the crate level
.teach_note = If you don't know the basics of Rust, you can go look to the Rust Book to get started: https://doc.rust-lang.org/book/
.non_function_main = non-function item at `crate::main` is found
145 changes: 55 additions & 90 deletions compiler/rustc_passes/src/entry.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use rustc_ast::entry::EntryPointType;
use rustc_errors::struct_span_err;
use rustc_errors::error_code;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
use rustc_hir::{ItemId, Node, CRATE_HIR_ID};
Expand All @@ -8,7 +8,12 @@ use rustc_middle::ty::{DefIdTree, TyCtxt};
use rustc_session::config::{sigpipe, CrateType, EntryFnType};
use rustc_session::parse::feature_err;
use rustc_span::symbol::sym;
use rustc_span::{Span, Symbol, DUMMY_SP};
use rustc_span::{Span, Symbol};

use crate::errors::{
AttrOnlyInFunctions, AttrOnlyOnMain, AttrOnlyOnRootMain, ExternMain, MultipleRustcMain,
MultipleStartFunctions, NoMainErr, UnixSigpipeValues,
};

struct EntryContext<'tcx> {
tcx: TyCtxt<'tcx>,
Expand Down Expand Up @@ -71,64 +76,57 @@ fn entry_point_type(ctxt: &EntryContext<'_>, id: ItemId, at_root: bool) -> Entry
}
}

fn err_if_attr_found(ctxt: &EntryContext<'_>, id: ItemId, sym: Symbol, details: &str) {
fn attr_span_by_symbol(ctxt: &EntryContext<'_>, id: ItemId, sym: Symbol) -> Option<Span> {
let attrs = ctxt.tcx.hir().attrs(id.hir_id());
if let Some(attr) = ctxt.tcx.sess.find_by_name(attrs, sym) {
ctxt.tcx
.sess
.struct_span_err(attr.span, &format!("`{}` attribute {}", sym, details))
.emit();
}
ctxt.tcx.sess.find_by_name(attrs, sym).map(|attr| attr.span)
}

fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) {
let at_root = ctxt.tcx.opt_local_parent(id.def_id.def_id) == Some(CRATE_DEF_ID);

match entry_point_type(ctxt, id, at_root) {
EntryPointType::None => {
err_if_attr_found(ctxt, id, sym::unix_sigpipe, "can only be used on `fn main()`");
if let Some(span) = attr_span_by_symbol(ctxt, id, sym::unix_sigpipe) {
ctxt.tcx.sess.emit_err(AttrOnlyOnMain { span, attr: sym::unix_sigpipe });
}
}
_ if !matches!(ctxt.tcx.def_kind(id.def_id), DefKind::Fn) => {
err_if_attr_found(ctxt, id, sym::start, "can only be used on functions");
err_if_attr_found(ctxt, id, sym::rustc_main, "can only be used on functions");
for attr in [sym::start, sym::rustc_main] {
if let Some(span) = attr_span_by_symbol(ctxt, id, attr) {
ctxt.tcx.sess.emit_err(AttrOnlyInFunctions { span, attr });
}
}
}
EntryPointType::MainNamed => (),
EntryPointType::OtherMain => {
err_if_attr_found(ctxt, id, sym::unix_sigpipe, "can only be used on root `fn main()`");
if let Some(span) = attr_span_by_symbol(ctxt, id, sym::unix_sigpipe) {
ctxt.tcx.sess.emit_err(AttrOnlyOnRootMain { span, attr: sym::unix_sigpipe });
}
ctxt.non_main_fns.push(ctxt.tcx.def_span(id.def_id));
}
EntryPointType::RustcMainAttr => {
if ctxt.attr_main_fn.is_none() {
ctxt.attr_main_fn = Some((id.def_id.def_id, ctxt.tcx.def_span(id.def_id)));
} else {
struct_span_err!(
ctxt.tcx.sess,
ctxt.tcx.def_span(id.def_id.to_def_id()),
E0137,
"multiple functions with a `#[rustc_main]` attribute"
)
.span_label(
ctxt.tcx.def_span(id.def_id.to_def_id()),
"additional `#[rustc_main]` function",
)
.span_label(ctxt.attr_main_fn.unwrap().1, "first `#[rustc_main]` function")
.emit();
ctxt.tcx.sess.emit_err(MultipleRustcMain {
span: ctxt.tcx.def_span(id.def_id.to_def_id()),
first: ctxt.attr_main_fn.unwrap().1,
additional: ctxt.tcx.def_span(id.def_id.to_def_id()),
});
}
}
EntryPointType::Start => {
err_if_attr_found(ctxt, id, sym::unix_sigpipe, "can only be used on `fn main()`");
if let Some(span) = attr_span_by_symbol(ctxt, id, sym::unix_sigpipe) {
ctxt.tcx.sess.emit_err(AttrOnlyOnMain { span, attr: sym::unix_sigpipe });
}
if ctxt.start_fn.is_none() {
ctxt.start_fn = Some((id.def_id.def_id, ctxt.tcx.def_span(id.def_id)));
} else {
struct_span_err!(
ctxt.tcx.sess,
ctxt.tcx.def_span(id.def_id),
E0138,
"multiple `start` functions"
)
.span_label(ctxt.start_fn.unwrap().1, "previous `#[start]` function here")
.span_label(ctxt.tcx.def_span(id.def_id.to_def_id()), "multiple `start` functions")
.emit();
ctxt.tcx.sess.emit_err(MultipleStartFunctions {
span: ctxt.tcx.def_span(id.def_id),
labeled: ctxt.tcx.def_span(id.def_id.to_def_id()),
previous: ctxt.start_fn.unwrap().1,
});
}
}
}
Expand All @@ -144,12 +142,7 @@ fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) -> Option<(DefId,
if let Some(main_def) = tcx.resolutions(()).main_def && let Some(def_id) = main_def.opt_fn_def_id() {
// non-local main imports are handled below
if let Some(def_id) = def_id.as_local() && matches!(tcx.hir().find_by_def_id(def_id), Some(Node::ForeignItem(_))) {
tcx.sess
.struct_span_err(
tcx.def_span(def_id),
"the `main` function cannot be declared in an `extern` block",
)
.emit();
tcx.sess.emit_err(ExternMain { span: tcx.def_span(def_id) });
return None;
}

Expand Down Expand Up @@ -182,12 +175,7 @@ fn sigpipe(tcx: TyCtxt<'_>, def_id: DefId) -> u8 {
sigpipe::DEFAULT
}
_ => {
tcx.sess
.struct_span_err(
attr.span,
"valid values for `#[unix_sigpipe = \"...\"]` are `inherit`, `sig_ign`, or `sig_dfl`",
)
.emit();
tcx.sess.emit_err(UnixSigpipeValues { span: attr.span });
sigpipe::DEFAULT
}
}
Expand All @@ -206,52 +194,29 @@ fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) {
}

// There is no main function.
let mut err = struct_span_err!(
tcx.sess,
DUMMY_SP,
E0601,
"`main` function not found in crate `{}`",
tcx.crate_name(LOCAL_CRATE)
);
let filename = &tcx.sess.local_crate_source_file;
let note = if !visitor.non_main_fns.is_empty() {
for &span in &visitor.non_main_fns {
err.span_note(span, "here is a function named `main`");
}
err.note("you have one or more functions named `main` not defined at the crate level");
err.help("consider moving the `main` function definitions");
// There were some functions named `main` though. Try to give the user a hint.
format!(
"the main function must be defined at the crate level{}",
filename.as_ref().map(|f| format!(" (in `{}`)", f.display())).unwrap_or_default()
)
} else if let Some(filename) = filename {
format!("consider adding a `main` function to `{}`", filename.display())
} else {
String::from("consider adding a `main` function at the crate level")
};
let mut has_filename = true;
let filename = tcx.sess.local_crate_source_file.clone().unwrap_or_else(|| {
has_filename = false;
Default::default()
});
let main_def_opt = tcx.resolutions(()).main_def;
let diagnostic_id = error_code!(E0601);
let add_teach_note = tcx.sess.teach(&diagnostic_id);
// The file may be empty, which leads to the diagnostic machinery not emitting this
// note. This is a relatively simple way to detect that case and emit a span-less
// note instead.
if tcx.sess.source_map().lookup_line(sp.hi()).is_ok() {
err.set_span(sp.shrink_to_hi());
err.span_label(sp.shrink_to_hi(), &note);
} else {
err.note(&note);
}

if let Some(main_def) = tcx.resolutions(()).main_def && main_def.opt_fn_def_id().is_none(){
// There is something at `crate::main`, but it is not a function definition.
err.span_label(main_def.span, "non-function item at `crate::main` is found");
}

if tcx.sess.teach(&err.get_code().unwrap()) {
err.note(
"If you don't know the basics of Rust, you can go look to the Rust Book \
to get started: https://doc.rust-lang.org/book/",
);
}
err.emit();
let file_empty = !tcx.sess.source_map().lookup_line(sp.hi()).is_ok();

tcx.sess.emit_err(NoMainErr {
sp,
crate_name: tcx.crate_name(LOCAL_CRATE),
has_filename,
filename,
file_empty,
non_main_fns: visitor.non_main_fns.clone(),
main_def_opt,
add_teach_note,
});
}

pub fn provide(providers: &mut Providers) {
Expand Down
Loading