diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:11:38 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:12:43 +0000 |
commit | cf94bdc0742c13e2a0cac864c478b8626b266e1b (patch) | |
tree | 044670aa50cc5e2b4229aa0b6b3df6676730c0a6 /compiler/rustc_lint/src/builtin.rs | |
parent | Adding debian version 1.65.0+dfsg1-2. (diff) | |
download | rustc-cf94bdc0742c13e2a0cac864c478b8626b266e1b.tar.xz rustc-cf94bdc0742c13e2a0cac864c478b8626b266e1b.zip |
Merging upstream version 1.66.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_lint/src/builtin.rs')
-rw-r--r-- | compiler/rustc_lint/src/builtin.rs | 896 |
1 files changed, 487 insertions, 409 deletions
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 0ff2ef5cd..d425adf47 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -33,8 +33,8 @@ use rustc_ast_pretty::pprust::{self, expr_to_string}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{ - fluent, Applicability, Diagnostic, DiagnosticMessage, DiagnosticStyledString, - LintDiagnosticBuilder, MultiSpan, + fluent, Applicability, DelayDm, Diagnostic, DiagnosticBuilder, DiagnosticMessage, + DiagnosticStyledString, MultiSpan, }; use rustc_feature::{deprecated_attributes, AttributeGate, BuiltinAttribute, GateIssue, Stability}; use rustc_hir as hir; @@ -46,8 +46,7 @@ use rustc_middle::lint::in_external_macro; use rustc_middle::ty::layout::{LayoutError, LayoutOf}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::subst::GenericArgKind; -use rustc_middle::ty::Instance; -use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::ty::{self, Instance, Ty, TyCtxt, VariantDef}; use rustc_session::lint::{BuiltinLintDiagnostics, FutureIncompatibilityReason}; use rustc_span::edition::Edition; use rustc_span::source_map::Spanned; @@ -98,30 +97,31 @@ fn pierce_parens(mut expr: &ast::Expr) -> &ast::Expr { impl EarlyLintPass for WhileTrue { fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) { - if let ast::ExprKind::While(cond, _, label) = &e.kind { - if let ast::ExprKind::Lit(ref lit) = pierce_parens(cond).kind { - if let ast::LitKind::Bool(true) = lit.kind { - if !lit.span.from_expansion() { - let condition_span = e.span.with_hi(cond.span.hi()); - cx.struct_span_lint(WHILE_TRUE, condition_span, |lint| { - lint.build(fluent::lint::builtin_while_true) - .span_suggestion_short( - condition_span, - fluent::lint::suggestion, - format!( - "{}loop", - label.map_or_else(String::new, |label| format!( - "{}: ", - label.ident, - )) - ), - Applicability::MachineApplicable, - ) - .emit(); - }) - } - } - } + if let ast::ExprKind::While(cond, _, label) = &e.kind + && let ast::ExprKind::Lit(ref lit) = pierce_parens(cond).kind + && let ast::LitKind::Bool(true) = lit.kind + && !lit.span.from_expansion() + { + let condition_span = e.span.with_hi(cond.span.hi()); + cx.struct_span_lint( + WHILE_TRUE, + condition_span, + fluent::lint_builtin_while_true, + |lint| { + lint.span_suggestion_short( + condition_span, + fluent::suggestion, + format!( + "{}loop", + label.map_or_else(String::new, |label| format!( + "{}: ", + label.ident, + )) + ), + Applicability::MachineApplicable, + ) + }, + ) } } } @@ -157,9 +157,12 @@ impl BoxPointers { for leaf in ty.walk() { if let GenericArgKind::Type(leaf_ty) = leaf.unpack() { if leaf_ty.is_box() { - cx.struct_span_lint(BOX_POINTERS, span, |lint| { - lint.build(fluent::lint::builtin_box_pointers).set_arg("ty", ty).emit(); - }); + cx.struct_span_lint( + BOX_POINTERS, + span, + fluent::lint_builtin_box_pointers, + |lint| lint.set_arg("ty", ty), + ); } } } @@ -174,7 +177,7 @@ impl<'tcx> LateLintPass<'tcx> for BoxPointers { | hir::ItemKind::Enum(..) | hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) => { - self.check_heap_type(cx, it.span, cx.tcx.type_of(it.def_id)) + self.check_heap_type(cx, it.span, cx.tcx.type_of(it.owner_id)) } _ => (), } @@ -258,19 +261,21 @@ impl<'tcx> LateLintPass<'tcx> for NonShorthandFieldPatterns { if cx.tcx.find_field_index(ident, &variant) == Some(cx.tcx.field_index(fieldpat.hir_id, cx.typeck_results())) { - cx.struct_span_lint(NON_SHORTHAND_FIELD_PATTERNS, fieldpat.span, |lint| { - let suggested_ident = - format!("{}{}", binding_annot.prefix_str(), ident); - lint.build(fluent::lint::builtin_non_shorthand_field_patterns) - .set_arg("ident", ident.clone()) - .span_suggestion( + cx.struct_span_lint( + NON_SHORTHAND_FIELD_PATTERNS, + fieldpat.span, + fluent::lint_builtin_non_shorthand_field_patterns, + |lint| { + let suggested_ident = + format!("{}{}", binding_annot.prefix_str(), ident); + lint.set_arg("ident", ident.clone()).span_suggestion( fieldpat.span, - fluent::lint::suggestion, + fluent::suggestion, suggested_ident, Applicability::MachineApplicable, ) - .emit(); - }); + }, + ); } } } @@ -310,14 +315,17 @@ impl UnsafeCode { &self, cx: &EarlyContext<'_>, span: Span, - decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>), + msg: impl Into<DiagnosticMessage>, + decorate: impl for<'a, 'b> FnOnce( + &'b mut DiagnosticBuilder<'a, ()>, + ) -> &'b mut DiagnosticBuilder<'a, ()>, ) { // This comes from a macro that has `#[allow_internal_unsafe]`. if span.allows_unsafe() { return; } - cx.struct_span_lint(UNSAFE_CODE, span, decorate); + cx.struct_span_lint(UNSAFE_CODE, span, msg, decorate); } fn report_overridden_symbol_name( @@ -326,8 +334,8 @@ impl UnsafeCode { span: Span, msg: DiagnosticMessage, ) { - self.report_unsafe(cx, span, |lint| { - lint.build(msg).note(fluent::lint::builtin_overridden_symbol_name).emit(); + self.report_unsafe(cx, span, msg, |lint| { + lint.note(fluent::lint_builtin_overridden_symbol_name) }) } @@ -337,8 +345,8 @@ impl UnsafeCode { span: Span, msg: DiagnosticMessage, ) { - self.report_unsafe(cx, span, |lint| { - lint.build(msg).note(fluent::lint::builtin_overridden_symbol_section).emit(); + self.report_unsafe(cx, span, msg, |lint| { + lint.note(fluent::lint_builtin_overridden_symbol_section) }) } } @@ -346,8 +354,8 @@ impl UnsafeCode { impl EarlyLintPass for UnsafeCode { fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &ast::Attribute) { if attr.has_name(sym::allow_internal_unsafe) { - self.report_unsafe(cx, attr.span, |lint| { - lint.build(fluent::lint::builtin_allow_internal_unsafe).emit(); + self.report_unsafe(cx, attr.span, fluent::lint_builtin_allow_internal_unsafe, |lint| { + lint }); } } @@ -356,31 +364,27 @@ impl EarlyLintPass for UnsafeCode { if let ast::ExprKind::Block(ref blk, _) = e.kind { // Don't warn about generated blocks; that'll just pollute the output. if blk.rules == ast::BlockCheckMode::Unsafe(ast::UserProvided) { - self.report_unsafe(cx, blk.span, |lint| { - lint.build(fluent::lint::builtin_unsafe_block).emit(); - }); + self.report_unsafe(cx, blk.span, fluent::lint_builtin_unsafe_block, |lint| lint); } } } fn check_item(&mut self, cx: &EarlyContext<'_>, it: &ast::Item) { match it.kind { - ast::ItemKind::Trait(box ast::Trait { unsafety: ast::Unsafe::Yes(_), .. }) => self - .report_unsafe(cx, it.span, |lint| { - lint.build(fluent::lint::builtin_unsafe_trait).emit(); - }), + ast::ItemKind::Trait(box ast::Trait { unsafety: ast::Unsafe::Yes(_), .. }) => { + self.report_unsafe(cx, it.span, fluent::lint_builtin_unsafe_trait, |lint| lint) + } - ast::ItemKind::Impl(box ast::Impl { unsafety: ast::Unsafe::Yes(_), .. }) => self - .report_unsafe(cx, it.span, |lint| { - lint.build(fluent::lint::builtin_unsafe_impl).emit(); - }), + ast::ItemKind::Impl(box ast::Impl { unsafety: ast::Unsafe::Yes(_), .. }) => { + self.report_unsafe(cx, it.span, fluent::lint_builtin_unsafe_impl, |lint| lint) + } ast::ItemKind::Fn(..) => { if let Some(attr) = cx.sess().find_by_name(&it.attrs, sym::no_mangle) { self.report_overridden_symbol_name( cx, attr.span, - fluent::lint::builtin_no_mangle_fn, + fluent::lint_builtin_no_mangle_fn, ); } @@ -388,7 +392,7 @@ impl EarlyLintPass for UnsafeCode { self.report_overridden_symbol_name( cx, attr.span, - fluent::lint::builtin_export_name_fn, + fluent::lint_builtin_export_name_fn, ); } @@ -396,7 +400,7 @@ impl EarlyLintPass for UnsafeCode { self.report_overridden_symbol_section( cx, attr.span, - fluent::lint::builtin_link_section_fn, + fluent::lint_builtin_link_section_fn, ); } } @@ -406,7 +410,7 @@ impl EarlyLintPass for UnsafeCode { self.report_overridden_symbol_name( cx, attr.span, - fluent::lint::builtin_no_mangle_static, + fluent::lint_builtin_no_mangle_static, ); } @@ -414,7 +418,7 @@ impl EarlyLintPass for UnsafeCode { self.report_overridden_symbol_name( cx, attr.span, - fluent::lint::builtin_export_name_static, + fluent::lint_builtin_export_name_static, ); } @@ -422,7 +426,7 @@ impl EarlyLintPass for UnsafeCode { self.report_overridden_symbol_section( cx, attr.span, - fluent::lint::builtin_link_section_static, + fluent::lint_builtin_link_section_static, ); } } @@ -437,14 +441,14 @@ impl EarlyLintPass for UnsafeCode { self.report_overridden_symbol_name( cx, attr.span, - fluent::lint::builtin_no_mangle_method, + fluent::lint_builtin_no_mangle_method, ); } if let Some(attr) = cx.sess().find_by_name(&it.attrs, sym::export_name) { self.report_overridden_symbol_name( cx, attr.span, - fluent::lint::builtin_export_name_method, + fluent::lint_builtin_export_name_method, ); } } @@ -462,13 +466,11 @@ impl EarlyLintPass for UnsafeCode { { let msg = match ctxt { FnCtxt::Foreign => return, - FnCtxt::Free => fluent::lint::builtin_decl_unsafe_fn, - FnCtxt::Assoc(_) if body.is_none() => fluent::lint::builtin_decl_unsafe_method, - FnCtxt::Assoc(_) => fluent::lint::builtin_impl_unsafe_method, + FnCtxt::Free => fluent::lint_builtin_decl_unsafe_fn, + FnCtxt::Assoc(_) if body.is_none() => fluent::lint_builtin_decl_unsafe_method, + FnCtxt::Assoc(_) => fluent::lint_builtin_impl_unsafe_method, }; - self.report_unsafe(cx, span, |lint| { - lint.build(msg).emit(); - }); + self.report_unsafe(cx, span, msg, |lint| lint); } } } @@ -561,7 +563,7 @@ impl MissingDoc { // It's an option so the crate root can also use this function (it doesn't // have a `NodeId`). if def_id != CRATE_DEF_ID { - if !cx.access_levels.is_exported(def_id) { + if !cx.effective_visibilities.is_exported(def_id) { return; } } @@ -569,12 +571,12 @@ impl MissingDoc { let attrs = cx.tcx.hir().attrs(cx.tcx.hir().local_def_id_to_hir_id(def_id)); let has_doc = attrs.iter().any(has_doc); if !has_doc { - cx.struct_span_lint(MISSING_DOCS, cx.tcx.def_span(def_id), |lint| { - lint.build(fluent::lint::builtin_missing_doc) - .set_arg("article", article) - .set_arg("desc", desc) - .emit(); - }); + cx.struct_span_lint( + MISSING_DOCS, + cx.tcx.def_span(def_id), + fluent::lint_builtin_missing_doc, + |lint| lint.set_arg("article", article).set_arg("desc", desc), + ); } } } @@ -604,9 +606,9 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { match it.kind { hir::ItemKind::Trait(..) => { // Issue #11592: traits are always considered exported, even when private. - if cx.tcx.visibility(it.def_id) + if cx.tcx.visibility(it.owner_id) == ty::Visibility::Restricted( - cx.tcx.parent_module_from_def_id(it.def_id).to_def_id(), + cx.tcx.parent_module_from_def_id(it.owner_id.def_id).to_def_id(), ) { return; @@ -625,15 +627,15 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { _ => return, }; - let (article, desc) = cx.tcx.article_and_description(it.def_id.to_def_id()); + let (article, desc) = cx.tcx.article_and_description(it.owner_id.to_def_id()); - self.check_missing_docs_attrs(cx, it.def_id, article, desc); + self.check_missing_docs_attrs(cx, it.owner_id.def_id, article, desc); } fn check_trait_item(&mut self, cx: &LateContext<'_>, trait_item: &hir::TraitItem<'_>) { - let (article, desc) = cx.tcx.article_and_description(trait_item.def_id.to_def_id()); + let (article, desc) = cx.tcx.article_and_description(trait_item.owner_id.to_def_id()); - self.check_missing_docs_attrs(cx, trait_item.def_id, article, desc); + self.check_missing_docs_attrs(cx, trait_item.owner_id.def_id, article, desc); } fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_>) { @@ -660,13 +662,13 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { } } - let (article, desc) = cx.tcx.article_and_description(impl_item.def_id.to_def_id()); - self.check_missing_docs_attrs(cx, impl_item.def_id, article, desc); + let (article, desc) = cx.tcx.article_and_description(impl_item.owner_id.to_def_id()); + self.check_missing_docs_attrs(cx, impl_item.owner_id.def_id, article, desc); } fn check_foreign_item(&mut self, cx: &LateContext<'_>, foreign_item: &hir::ForeignItem<'_>) { - let (article, desc) = cx.tcx.article_and_description(foreign_item.def_id.to_def_id()); - self.check_missing_docs_attrs(cx, foreign_item.def_id, article, desc); + let (article, desc) = cx.tcx.article_and_description(foreign_item.owner_id.to_def_id()); + self.check_missing_docs_attrs(cx, foreign_item.owner_id.def_id, article, desc); } fn check_field_def(&mut self, cx: &LateContext<'_>, sf: &hir::FieldDef<'_>) { @@ -719,7 +721,7 @@ declare_lint_pass!(MissingCopyImplementations => [MISSING_COPY_IMPLEMENTATIONS]) impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations { fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) { - if !cx.access_levels.is_reachable(item.def_id) { + if !cx.effective_visibilities.is_reachable(item.owner_id.def_id) { return; } let (def, ty) = match item.kind { @@ -727,21 +729,21 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations { if !ast_generics.params.is_empty() { return; } - let def = cx.tcx.adt_def(item.def_id); + let def = cx.tcx.adt_def(item.owner_id); (def, cx.tcx.mk_adt(def, cx.tcx.intern_substs(&[]))) } hir::ItemKind::Union(_, ref ast_generics) => { if !ast_generics.params.is_empty() { return; } - let def = cx.tcx.adt_def(item.def_id); + let def = cx.tcx.adt_def(item.owner_id); (def, cx.tcx.mk_adt(def, cx.tcx.intern_substs(&[]))) } hir::ItemKind::Enum(_, ref ast_generics) => { if !ast_generics.params.is_empty() { return; } - let def = cx.tcx.adt_def(item.def_id); + let def = cx.tcx.adt_def(item.owner_id); (def, cx.tcx.mk_adt(def, cx.tcx.intern_substs(&[]))) } _ => return, @@ -750,7 +752,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations { return; } let param_env = ty::ParamEnv::empty(); - if ty.is_copy_modulo_regions(cx.tcx.at(item.span), param_env) { + if ty.is_copy_modulo_regions(cx.tcx, param_env) { return; } if can_type_implement_copy( @@ -761,9 +763,12 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations { ) .is_ok() { - cx.struct_span_lint(MISSING_COPY_IMPLEMENTATIONS, item.span, |lint| { - lint.build(fluent::lint::builtin_missing_copy_impl).emit(); - }) + cx.struct_span_lint( + MISSING_COPY_IMPLEMENTATIONS, + item.span, + fluent::lint_builtin_missing_copy_impl, + |lint| lint, + ) } } } @@ -809,7 +814,7 @@ impl_lint_pass!(MissingDebugImplementations => [MISSING_DEBUG_IMPLEMENTATIONS]); impl<'tcx> LateLintPass<'tcx> for MissingDebugImplementations { fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) { - if !cx.access_levels.is_reachable(item.def_id) { + if !cx.effective_visibilities.is_reachable(item.owner_id.def_id) { return; } @@ -836,12 +841,13 @@ impl<'tcx> LateLintPass<'tcx> for MissingDebugImplementations { debug!("{:?}", self.impling_types); } - if !self.impling_types.as_ref().unwrap().contains(&item.def_id) { - cx.struct_span_lint(MISSING_DEBUG_IMPLEMENTATIONS, item.span, |lint| { - lint.build(fluent::lint::builtin_missing_debug_impl) - .set_arg("debug", cx.tcx.def_path_str(debug)) - .emit(); - }); + if !self.impling_types.as_ref().unwrap().contains(&item.owner_id.def_id) { + cx.struct_span_lint( + MISSING_DEBUG_IMPLEMENTATIONS, + item.span, + fluent::lint_builtin_missing_debug_impl, + |lint| lint.set_arg("debug", cx.tcx.def_path_str(debug)), + ); } } } @@ -909,24 +915,26 @@ impl EarlyLintPass for AnonymousParameters { for arg in sig.decl.inputs.iter() { if let ast::PatKind::Ident(_, ident, None) = arg.pat.kind { if ident.name == kw::Empty { - cx.struct_span_lint(ANONYMOUS_PARAMETERS, arg.pat.span, |lint| { - let ty_snip = cx.sess().source_map().span_to_snippet(arg.ty.span); - - let (ty_snip, appl) = if let Ok(ref snip) = ty_snip { - (snip.as_str(), Applicability::MachineApplicable) - } else { - ("<type>", Applicability::HasPlaceholders) - }; + let ty_snip = cx.sess().source_map().span_to_snippet(arg.ty.span); - lint.build(fluent::lint::builtin_anonymous_params) - .span_suggestion( + let (ty_snip, appl) = if let Ok(ref snip) = ty_snip { + (snip.as_str(), Applicability::MachineApplicable) + } else { + ("<type>", Applicability::HasPlaceholders) + }; + cx.struct_span_lint( + ANONYMOUS_PARAMETERS, + arg.pat.span, + fluent::lint_builtin_anonymous_params, + |lint| { + lint.span_suggestion( arg.pat.span, - fluent::lint::suggestion, + fluent::suggestion, format!("_: {}", ty_snip), appl, ) - .emit(); - }) + }, + ) } } } @@ -961,38 +969,44 @@ impl EarlyLintPass for DeprecatedAttr { _, ) = gate { - cx.struct_span_lint(DEPRECATED, attr.span, |lint| { - // FIXME(davidtwco) translatable deprecated attr - lint.build(fluent::lint::builtin_deprecated_attr_link) - .set_arg("name", name) - .set_arg("reason", reason) - .set_arg("link", link) - .span_suggestion_short( - attr.span, - suggestion.map(|s| s.into()).unwrap_or( - fluent::lint::builtin_deprecated_attr_default_suggestion, - ), - "", - Applicability::MachineApplicable, - ) - .emit(); - }); + // FIXME(davidtwco) translatable deprecated attr + cx.struct_span_lint( + DEPRECATED, + attr.span, + fluent::lint_builtin_deprecated_attr_link, + |lint| { + lint.set_arg("name", name) + .set_arg("reason", reason) + .set_arg("link", link) + .span_suggestion_short( + attr.span, + suggestion.map(|s| s.into()).unwrap_or( + fluent::lint_builtin_deprecated_attr_default_suggestion, + ), + "", + Applicability::MachineApplicable, + ) + }, + ); } return; } } if attr.has_name(sym::no_start) || attr.has_name(sym::crate_id) { - cx.struct_span_lint(DEPRECATED, attr.span, |lint| { - lint.build(fluent::lint::builtin_deprecated_attr_used) - .set_arg("name", pprust::path_to_string(&attr.get_normal_item().path)) - .span_suggestion_short( - attr.span, - fluent::lint::builtin_deprecated_attr_default_suggestion, - "", - Applicability::MachineApplicable, - ) - .emit(); - }); + cx.struct_span_lint( + DEPRECATED, + attr.span, + fluent::lint_builtin_deprecated_attr_used, + |lint| { + lint.set_arg("name", pprust::path_to_string(&attr.get_normal_item().path)) + .span_suggestion_short( + attr.span, + fluent::lint_builtin_deprecated_attr_default_suggestion, + "", + Applicability::MachineApplicable, + ) + }, + ); } } } @@ -1019,20 +1033,21 @@ fn warn_if_doc(cx: &EarlyContext<'_>, node_span: Span, node_kind: &str, attrs: & let span = sugared_span.take().unwrap_or(attr.span); if is_doc_comment || attr.has_name(sym::doc) { - cx.struct_span_lint(UNUSED_DOC_COMMENTS, span, |lint| { - let mut err = lint.build(fluent::lint::builtin_unused_doc_comment); - err.set_arg("kind", node_kind); - err.span_label(node_span, fluent::lint::label); - match attr.kind { - AttrKind::DocComment(CommentKind::Line, _) | AttrKind::Normal(..) => { - err.help(fluent::lint::plain_help); - } - AttrKind::DocComment(CommentKind::Block, _) => { - err.help(fluent::lint::block_help); - } - } - err.emit(); - }); + cx.struct_span_lint( + UNUSED_DOC_COMMENTS, + span, + fluent::lint_builtin_unused_doc_comment, + |lint| { + lint.set_arg("kind", node_kind).span_label(node_span, fluent::label).help( + match attr.kind { + AttrKind::DocComment(CommentKind::Line, _) | AttrKind::Normal(..) => { + fluent::plain_help + } + AttrKind::DocComment(CommentKind::Block, _) => fluent::block_help, + }, + ) + }, + ); } } } @@ -1146,18 +1161,21 @@ impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems { match param.kind { GenericParamKind::Lifetime { .. } => {} GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => { - cx.struct_span_lint(NO_MANGLE_GENERIC_ITEMS, span, |lint| { - lint.build(fluent::lint::builtin_no_mangle_generic) - .span_suggestion_short( + cx.struct_span_lint( + NO_MANGLE_GENERIC_ITEMS, + span, + fluent::lint_builtin_no_mangle_generic, + |lint| { + lint.span_suggestion_short( no_mangle_attr.span, - fluent::lint::suggestion, + fluent::suggestion, "", // Use of `#[no_mangle]` suggests FFI intent; correct // fix may be to monomorphize source by hand Applicability::MaybeIncorrect, ) - .emit(); - }); + }, + ); break; } } @@ -1173,27 +1191,29 @@ impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems { if cx.sess().contains_name(attrs, sym::no_mangle) { // Const items do not refer to a particular location in memory, and therefore // don't have anything to attach a symbol to - cx.struct_span_lint(NO_MANGLE_CONST_ITEMS, it.span, |lint| { - let mut err = lint.build(fluent::lint::builtin_const_no_mangle); - - // account for "pub const" (#45562) - let start = cx - .tcx - .sess - .source_map() - .span_to_snippet(it.span) - .map(|snippet| snippet.find("const").unwrap_or(0)) - .unwrap_or(0) as u32; - // `const` is 5 chars - let const_span = it.span.with_hi(BytePos(it.span.lo().0 + start + 5)); - err.span_suggestion( - const_span, - fluent::lint::suggestion, - "pub static", - Applicability::MachineApplicable, - ); - err.emit(); - }); + cx.struct_span_lint( + NO_MANGLE_CONST_ITEMS, + it.span, + fluent::lint_builtin_const_no_mangle, + |lint| { + // account for "pub const" (#45562) + let start = cx + .tcx + .sess + .source_map() + .span_to_snippet(it.span) + .map(|snippet| snippet.find("const").unwrap_or(0)) + .unwrap_or(0) as u32; + // `const` is 5 chars + let const_span = it.span.with_hi(BytePos(it.span.lo().0 + start + 5)); + lint.span_suggestion( + const_span, + fluent::suggestion, + "pub static", + Applicability::MachineApplicable, + ) + }, + ); } } hir::ItemKind::Impl(hir::Impl { generics, items, .. }) => { @@ -1206,7 +1226,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems { check_no_mangle_on_generic_fn( no_mangle_attr, Some(generics), - cx.tcx.hir().get_generics(it.id.def_id).unwrap(), + cx.tcx.hir().get_generics(it.id.owner_id.def_id).unwrap(), it.span, ); } @@ -1253,9 +1273,12 @@ impl<'tcx> LateLintPass<'tcx> for MutableTransmutes { get_transmute_from_to(cx, expr).map(|(ty1, ty2)| (ty1.kind(), ty2.kind())) { if to_mt == hir::Mutability::Mut && from_mt == hir::Mutability::Not { - cx.struct_span_lint(MUTABLE_TRANSMUTES, expr.span, |lint| { - lint.build(fluent::lint::builtin_mutable_transmutes).emit(); - }); + cx.struct_span_lint( + MUTABLE_TRANSMUTES, + expr.span, + fluent::lint_builtin_mutable_transmutes, + |lint| lint, + ); } } @@ -1303,9 +1326,12 @@ impl<'tcx> LateLintPass<'tcx> for UnstableFeatures { if attr.has_name(sym::feature) { if let Some(items) = attr.meta_item_list() { for item in items { - cx.struct_span_lint(UNSTABLE_FEATURES, item.span(), |lint| { - lint.build(fluent::lint::builtin_unstable_features).emit(); - }); + cx.struct_span_lint( + UNSTABLE_FEATURES, + item.span(), + fluent::lint_builtin_unstable_features, + |lint| lint, + ); } } } @@ -1359,26 +1385,26 @@ impl UnreachablePub { exportable: bool, ) { let mut applicability = Applicability::MachineApplicable; - if cx.tcx.visibility(def_id).is_public() && !cx.access_levels.is_reachable(def_id) { + if cx.tcx.visibility(def_id).is_public() && !cx.effective_visibilities.is_reachable(def_id) + { if vis_span.from_expansion() { applicability = Applicability::MaybeIncorrect; } let def_span = cx.tcx.def_span(def_id); - cx.struct_span_lint(UNREACHABLE_PUB, def_span, |lint| { - let mut err = lint.build(fluent::lint::builtin_unreachable_pub); - err.set_arg("what", what); - - err.span_suggestion( - vis_span, - fluent::lint::suggestion, - "pub(crate)", - applicability, - ); - if exportable { - err.help(fluent::lint::help); - } - err.emit(); - }); + cx.struct_span_lint( + UNREACHABLE_PUB, + def_span, + fluent::lint_builtin_unreachable_pub, + |lint| { + lint.set_arg("what", what); + + lint.span_suggestion(vis_span, fluent::suggestion, "pub(crate)", applicability); + if exportable { + lint.help(fluent::help); + } + lint + }, + ); } } } @@ -1389,11 +1415,11 @@ impl<'tcx> LateLintPass<'tcx> for UnreachablePub { if let hir::ItemKind::Use(_, hir::UseKind::ListStem) = &item.kind { return; } - self.perform_lint(cx, "item", item.def_id, item.vis_span, true); + self.perform_lint(cx, "item", item.owner_id.def_id, item.vis_span, true); } fn check_foreign_item(&mut self, cx: &LateContext<'_>, foreign_item: &hir::ForeignItem<'tcx>) { - self.perform_lint(cx, "item", foreign_item.def_id, foreign_item.vis_span, true); + self.perform_lint(cx, "item", foreign_item.owner_id.def_id, foreign_item.vis_span, true); } fn check_field_def(&mut self, cx: &LateContext<'_>, field: &hir::FieldDef<'_>) { @@ -1403,8 +1429,8 @@ impl<'tcx> LateLintPass<'tcx> for UnreachablePub { fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_>) { // Only lint inherent impl items. - if cx.tcx.associated_item(impl_item.def_id).trait_item_def_id.is_none() { - self.perform_lint(cx, "item", impl_item.def_id, impl_item.vis_span, false); + if cx.tcx.associated_item(impl_item.owner_id).trait_item_def_id.is_none() { + self.perform_lint(cx, "item", impl_item.owner_id.def_id, impl_item.vis_span, false); } } } @@ -1465,7 +1491,7 @@ impl TypeAliasBounds { impl Visitor<'_> for WalkAssocTypes<'_> { fn visit_qpath(&mut self, qpath: &hir::QPath<'_>, id: hir::HirId, span: Span) { if TypeAliasBounds::is_type_variable_assoc(qpath) { - self.err.span_help(span, fluent::lint::builtin_type_alias_bounds_help); + self.err.span_help(span, fluent::lint_builtin_type_alias_bounds_help); } intravisit::walk_qpath(self, qpath, id) } @@ -1508,36 +1534,34 @@ impl<'tcx> LateLintPass<'tcx> for TypeAliasBounds { let mut suggested_changing_assoc_types = false; if !where_spans.is_empty() { - cx.lint(TYPE_ALIAS_BOUNDS, |lint| { - let mut err = lint.build(fluent::lint::builtin_type_alias_where_clause); - err.set_span(where_spans); - err.span_suggestion( + cx.lint(TYPE_ALIAS_BOUNDS, fluent::lint_builtin_type_alias_where_clause, |lint| { + lint.set_span(where_spans); + lint.span_suggestion( type_alias_generics.where_clause_span, - fluent::lint::suggestion, + fluent::suggestion, "", Applicability::MachineApplicable, ); if !suggested_changing_assoc_types { - TypeAliasBounds::suggest_changing_assoc_types(ty, &mut err); + TypeAliasBounds::suggest_changing_assoc_types(ty, lint); suggested_changing_assoc_types = true; } - err.emit(); + lint }); } if !inline_spans.is_empty() { - cx.lint(TYPE_ALIAS_BOUNDS, |lint| { - let mut err = lint.build(fluent::lint::builtin_type_alias_generic_bounds); - err.set_span(inline_spans); - err.multipart_suggestion( - fluent::lint::suggestion, + cx.lint(TYPE_ALIAS_BOUNDS, fluent::lint_builtin_type_alias_generic_bounds, |lint| { + lint.set_span(inline_spans); + lint.multipart_suggestion( + fluent::suggestion, inline_sugg, Applicability::MachineApplicable, ); if !suggested_changing_assoc_types { - TypeAliasBounds::suggest_changing_assoc_types(ty, &mut err); + TypeAliasBounds::suggest_changing_assoc_types(ty, lint); } - err.emit(); + lint }); } } @@ -1615,7 +1639,7 @@ impl<'tcx> LateLintPass<'tcx> for TrivialConstraints { use rustc_middle::ty::PredicateKind::*; if cx.tcx.features().trivial_bounds { - let predicates = cx.tcx.predicates_of(item.def_id); + let predicates = cx.tcx.predicates_of(item.owner_id); for &(predicate, span) in predicates.predicates { let predicate_kind_name = match predicate.kind().skip_binder() { Trait(..) => "trait", @@ -1636,12 +1660,15 @@ impl<'tcx> LateLintPass<'tcx> for TrivialConstraints { TypeWellFormedFromEnv(..) => continue, }; if predicate.is_global() { - cx.struct_span_lint(TRIVIAL_BOUNDS, span, |lint| { - lint.build(fluent::lint::builtin_trivial_bounds) - .set_arg("predicate_kind_name", predicate_kind_name) - .set_arg("predicate", predicate) - .emit(); - }); + cx.struct_span_lint( + TRIVIAL_BOUNDS, + span, + fluent::lint_builtin_trivial_bounds, + |lint| { + lint.set_arg("predicate_kind_name", predicate_kind_name) + .set_arg("predicate", predicate) + }, + ); } } } @@ -1741,8 +1768,8 @@ impl EarlyLintPass for EllipsisInclusiveRangePatterns { }; if let Some((start, end, join)) = endpoints { - let msg = fluent::lint::builtin_ellipsis_inclusive_range_patterns; - let suggestion = fluent::lint::suggestion; + let msg = fluent::lint_builtin_ellipsis_inclusive_range_patterns; + let suggestion = fluent::suggestion; if parenthesise { self.node_id = Some(pat.id); let end = expr_to_string(&end); @@ -1757,15 +1784,13 @@ impl EarlyLintPass for EllipsisInclusiveRangePatterns { replace, }); } else { - cx.struct_span_lint(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, pat.span, |lint| { - lint.build(msg) - .span_suggestion( - pat.span, - suggestion, - replace, - Applicability::MachineApplicable, - ) - .emit(); + cx.struct_span_lint(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, pat.span, msg, |lint| { + lint.span_suggestion( + pat.span, + suggestion, + replace, + Applicability::MachineApplicable, + ) }); } } else { @@ -1777,15 +1802,13 @@ impl EarlyLintPass for EllipsisInclusiveRangePatterns { replace: replace.to_string(), }); } else { - cx.struct_span_lint(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, join, |lint| { - lint.build(msg) - .span_suggestion_short( - join, - suggestion, - replace, - Applicability::MachineApplicable, - ) - .emit(); + cx.struct_span_lint(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, join, msg, |lint| { + lint.span_suggestion_short( + join, + suggestion, + replace, + Applicability::MachineApplicable, + ) }); } }; @@ -1841,7 +1864,7 @@ declare_lint! { } pub struct UnnameableTestItems { - boundary: Option<LocalDefId>, // Id of the item under which things are not nameable + boundary: Option<hir::OwnerId>, // Id of the item under which things are not nameable items_nameable: bool, } @@ -1859,21 +1882,24 @@ impl<'tcx> LateLintPass<'tcx> for UnnameableTestItems { if let hir::ItemKind::Mod(..) = it.kind { } else { self.items_nameable = false; - self.boundary = Some(it.def_id); + self.boundary = Some(it.owner_id); } return; } let attrs = cx.tcx.hir().attrs(it.hir_id()); if let Some(attr) = cx.sess().find_by_name(attrs, sym::rustc_test_marker) { - cx.struct_span_lint(UNNAMEABLE_TEST_ITEMS, attr.span, |lint| { - lint.build(fluent::lint::builtin_unnameable_test_items).emit(); - }); + cx.struct_span_lint( + UNNAMEABLE_TEST_ITEMS, + attr.span, + fluent::lint_builtin_unnameable_test_items, + |lint| lint, + ); } } fn check_item_post(&mut self, _cx: &LateContext<'_>, it: &hir::Item<'_>) { - if !self.items_nameable && self.boundary == Some(it.def_id) { + if !self.items_nameable && self.boundary == Some(it.owner_id) { self.items_nameable = true; } } @@ -1984,18 +2010,19 @@ impl KeywordIdents { return; } - cx.struct_span_lint(KEYWORD_IDENTS, ident.span, |lint| { - lint.build(fluent::lint::builtin_keyword_idents) - .set_arg("kw", ident.clone()) - .set_arg("next", next_edition) - .span_suggestion( + cx.struct_span_lint( + KEYWORD_IDENTS, + ident.span, + fluent::lint_builtin_keyword_idents, + |lint| { + lint.set_arg("kw", ident.clone()).set_arg("next", next_edition).span_suggestion( ident.span, - fluent::lint::suggestion, + fluent::suggestion, format!("r#{}", ident), Applicability::MachineApplicable, ) - .emit(); - }); + }, + ); } } @@ -2138,7 +2165,7 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) { use rustc_middle::middle::resolve_lifetime::Region; - let def_id = item.def_id; + let def_id = item.owner_id.def_id; if let hir::ItemKind::Struct(_, ref hir_generics) | hir::ItemKind::Enum(_, ref hir_generics) | hir::ItemKind::Union(_, ref hir_generics) = item.kind @@ -2246,19 +2273,21 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements { } if !lint_spans.is_empty() { - cx.struct_span_lint(EXPLICIT_OUTLIVES_REQUIREMENTS, lint_spans.clone(), |lint| { - lint.build(fluent::lint::builtin_explicit_outlives) - .set_arg("count", bound_count) - .multipart_suggestion( - fluent::lint::suggestion, + cx.struct_span_lint( + EXPLICIT_OUTLIVES_REQUIREMENTS, + lint_spans.clone(), + fluent::lint_builtin_explicit_outlives, + |lint| { + lint.set_arg("count", bound_count).multipart_suggestion( + fluent::suggestion, lint_spans .into_iter() .map(|span| (span, String::new())) .collect::<Vec<_>>(), Applicability::MachineApplicable, ) - .emit(); - }); + }, + ); } } } @@ -2305,18 +2334,24 @@ impl EarlyLintPass for IncompleteFeatures { .chain(features.declared_lib_features.iter().map(|(name, span)| (name, span))) .filter(|(&name, _)| features.incomplete(name)) .for_each(|(&name, &span)| { - cx.struct_span_lint(INCOMPLETE_FEATURES, span, |lint| { - let mut builder = lint.build(fluent::lint::builtin_incomplete_features); - builder.set_arg("name", name); - if let Some(n) = rustc_feature::find_feature_issue(name, GateIssue::Language) { - builder.set_arg("n", n); - builder.note(fluent::lint::note); - } - if HAS_MIN_FEATURES.contains(&name) { - builder.help(fluent::lint::help); - } - builder.emit(); - }) + cx.struct_span_lint( + INCOMPLETE_FEATURES, + span, + fluent::lint_builtin_incomplete_features, + |lint| { + lint.set_arg("name", name); + if let Some(n) = + rustc_feature::find_feature_issue(name, GateIssue::Language) + { + lint.set_arg("n", n); + lint.note(fluent::note); + } + if HAS_MIN_FEATURES.contains(&name) { + lint.help(fluent::help); + } + lint + }, + ) }); } } @@ -2425,12 +2460,27 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue { None } - /// Test if this enum has several actually "existing" variants. - /// Zero-sized uninhabited variants do not always have a tag assigned and thus do not "exist". - fn is_multi_variant<'tcx>(adt: ty::AdtDef<'tcx>) -> bool { - // As an approximation, we only count dataless variants. Those are definitely inhabited. - let existing_variants = adt.variants().iter().filter(|v| v.fields.is_empty()).count(); - existing_variants > 1 + fn variant_find_init_error<'tcx>( + cx: &LateContext<'tcx>, + variant: &VariantDef, + substs: ty::SubstsRef<'tcx>, + descr: &str, + init: InitKind, + ) -> Option<InitError> { + variant.fields.iter().find_map(|field| { + ty_find_init_error(cx, field.ty(cx.tcx, substs), init).map(|(mut msg, span)| { + if span.is_none() { + // Point to this field, should be helpful for figuring + // out where the source of the error is. + let span = cx.tcx.def_span(field.did); + write!(&mut msg, " (in this {descr})").unwrap(); + (msg, Some(span)) + } else { + // Just forward. + (msg, span) + } + }) + }) } /// Return `Some` only if we are sure this type does *not* @@ -2468,7 +2518,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue { RawPtr(_) if init == InitKind::Uninit => { Some(("raw pointers must not be uninitialized".to_string(), None)) } - // Recurse and checks for some compound types. + // Recurse and checks for some compound types. (but not unions) Adt(adt_def, substs) if !adt_def.is_union() => { // First check if this ADT has a layout attribute (like `NonNull` and friends). use std::ops::Bound; @@ -2476,7 +2526,11 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue { // We exploit here that `layout_scalar_valid_range` will never // return `Bound::Excluded`. (And we have tests checking that we // handle the attribute correctly.) - (Bound::Included(lo), _) if lo > 0 => { + // We don't add a span since users cannot declare such types anyway. + (Bound::Included(lo), Bound::Included(hi)) if 0 < lo && lo < hi => { + return Some((format!("`{}` must be non-null", ty), None)); + } + (Bound::Included(lo), Bound::Unbounded) if 0 < lo => { return Some((format!("`{}` must be non-null", ty), None)); } (Bound::Included(_), _) | (_, Bound::Included(_)) @@ -2492,50 +2546,65 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue { } _ => {} } - // Now, recurse. - match adt_def.variants().len() { - 0 => Some(("enums with no variants have no valid value".to_string(), None)), - 1 => { - // Struct, or enum with exactly one variant. - // Proceed recursively, check all fields. - let variant = &adt_def.variant(VariantIdx::from_u32(0)); - variant.fields.iter().find_map(|field| { - ty_find_init_error(cx, field.ty(cx.tcx, substs), init).map( - |(mut msg, span)| { - if span.is_none() { - // Point to this field, should be helpful for figuring - // out where the source of the error is. - let span = cx.tcx.def_span(field.did); - write!( - &mut msg, - " (in this {} field)", - adt_def.descr() - ) - .unwrap(); - (msg, Some(span)) - } else { - // Just forward. - (msg, span) - } - }, - ) - }) - } - // Multi-variant enum. - _ => { - if init == InitKind::Uninit && is_multi_variant(*adt_def) { - let span = cx.tcx.def_span(adt_def.did()); - Some(( - "enums have to be initialized to a variant".to_string(), - Some(span), - )) - } else { - // In principle, for zero-initialization we could figure out which variant corresponds - // to tag 0, and check that... but for now we just accept all zero-initializations. - None - } + // Handle structs. + if adt_def.is_struct() { + return variant_find_init_error( + cx, + adt_def.non_enum_variant(), + substs, + "struct field", + init, + ); + } + // And now, enums. + let span = cx.tcx.def_span(adt_def.did()); + let mut potential_variants = adt_def.variants().iter().filter_map(|variant| { + let definitely_inhabited = match variant + .inhabited_predicate(cx.tcx, *adt_def) + .subst(cx.tcx, substs) + .apply_any_module(cx.tcx, cx.param_env) + { + // Entirely skip uninhbaited variants. + Some(false) => return None, + // Forward the others, but remember which ones are definitely inhabited. + Some(true) => true, + None => false, + }; + Some((variant, definitely_inhabited)) + }); + let Some(first_variant) = potential_variants.next() else { + return Some(("enums with no inhabited variants have no valid value".to_string(), Some(span))); + }; + // So we have at least one potentially inhabited variant. Might we have two? + let Some(second_variant) = potential_variants.next() else { + // There is only one potentially inhabited variant. So we can recursively check that variant! + return variant_find_init_error( + cx, + &first_variant.0, + substs, + "field of the only potentially inhabited enum variant", + init, + ); + }; + // So we have at least two potentially inhabited variants. + // If we can prove that we have at least two *definitely* inhabited variants, + // then we have a tag and hence leaving this uninit is definitely disallowed. + // (Leaving it zeroed could be okay, depending on which variant is encoded as zero tag.) + if init == InitKind::Uninit { + let definitely_inhabited = (first_variant.1 as usize) + + (second_variant.1 as usize) + + potential_variants + .filter(|(_variant, definitely_inhabited)| *definitely_inhabited) + .count(); + if definitely_inhabited > 1 { + return Some(( + "enums with multiple inhabited variants have to be initialized to a variant".to_string(), + Some(span), + )); } } + // We couldn't find anything wrong here. + None } Tuple(..) => { // Proceed recursively, check all fields. @@ -2564,28 +2633,37 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue { with_no_trimmed_paths!(ty_find_init_error(cx, conjured_ty, init)) { // FIXME(davidtwco): make translatable - cx.struct_span_lint(INVALID_VALUE, expr.span, |lint| { - let mut err = lint.build(&format!( - "the type `{}` does not permit {}", - conjured_ty, - match init { - InitKind::Zeroed => "zero-initialization", - InitKind::Uninit => "being left uninitialized", - }, - )); - err.span_label(expr.span, "this code causes undefined behavior when executed"); - err.span_label( - expr.span, - "help: use `MaybeUninit<T>` instead, \ + cx.struct_span_lint( + INVALID_VALUE, + expr.span, + DelayDm(|| { + format!( + "the type `{}` does not permit {}", + conjured_ty, + match init { + InitKind::Zeroed => "zero-initialization", + InitKind::Uninit => "being left uninitialized", + }, + ) + }), + |lint| { + lint.span_label( + expr.span, + "this code causes undefined behavior when executed", + ); + lint.span_label( + expr.span, + "help: use `MaybeUninit<T>` instead, \ and only call `assume_init` after initialization is done", - ); - if let Some(span) = span { - err.span_note(span, &msg); - } else { - err.note(&msg); - } - err.emit(); - }); + ); + if let Some(span) = span { + lint.span_note(span, &msg); + } else { + lint.note(&msg); + } + lint + }, + ); } } } @@ -2666,7 +2744,7 @@ impl ClashingExternDeclarations { /// Insert a new foreign item into the seen set. If a symbol with the same name already exists /// for the item, return its HirId without updating the set. fn insert(&mut self, tcx: TyCtxt<'_>, fi: &hir::ForeignItem<'_>) -> Option<HirId> { - let did = fi.def_id.to_def_id(); + let did = fi.owner_id.to_def_id(); let instance = Instance::new(did, ty::List::identity_for_item(tcx, did)); let name = Symbol::intern(tcx.symbol_name(instance).name); if let Some(&hir_id) = self.seen_decls.get(&name) { @@ -2684,14 +2762,14 @@ impl ClashingExternDeclarations { /// symbol's name. fn name_of_extern_decl(tcx: TyCtxt<'_>, fi: &hir::ForeignItem<'_>) -> SymbolName { if let Some((overridden_link_name, overridden_link_name_span)) = - tcx.codegen_fn_attrs(fi.def_id).link_name.map(|overridden_link_name| { + tcx.codegen_fn_attrs(fi.owner_id).link_name.map(|overridden_link_name| { // FIXME: Instead of searching through the attributes again to get span // information, we could have codegen_fn_attrs also give span information back for // where the attribute was defined. However, until this is found to be a // bottleneck, this does just fine. ( overridden_link_name, - tcx.get_attr(fi.def_id.to_def_id(), sym::link_name).unwrap().span, + tcx.get_attr(fi.owner_id.to_def_id(), sym::link_name).unwrap().span, ) }) { @@ -2908,10 +2986,10 @@ impl<'tcx> LateLintPass<'tcx> for ClashingExternDeclarations { let tcx = cx.tcx; if let Some(existing_hid) = self.insert(tcx, this_fi) { let existing_decl_ty = tcx.type_of(tcx.hir().local_def_id(existing_hid)); - let this_decl_ty = tcx.type_of(this_fi.def_id); + let this_decl_ty = tcx.type_of(this_fi.owner_id); debug!( "ClashingExternDeclarations: Comparing existing {:?}: {:?} to this {:?}: {:?}", - existing_hid, existing_decl_ty, this_fi.def_id, this_decl_ty + existing_hid, existing_decl_ty, this_fi.owner_id, this_decl_ty ); // Check that the declarations match. if !Self::structurally_same_type( @@ -2931,31 +3009,29 @@ impl<'tcx> LateLintPass<'tcx> for ClashingExternDeclarations { SymbolName::Link(_, annot_span) => fi.span.to(annot_span), }; // Finally, emit the diagnostic. + + let msg = if orig.get_name() == this_fi.ident.name { + fluent::lint_builtin_clashing_extern_same_name + } else { + fluent::lint_builtin_clashing_extern_diff_name + }; tcx.struct_span_lint_hir( CLASHING_EXTERN_DECLARATIONS, this_fi.hir_id(), get_relevant_span(this_fi), + msg, |lint| { let mut expected_str = DiagnosticStyledString::new(); expected_str.push(existing_decl_ty.fn_sig(tcx).to_string(), false); let mut found_str = DiagnosticStyledString::new(); found_str.push(this_decl_ty.fn_sig(tcx).to_string(), true); - lint.build(if orig.get_name() == this_fi.ident.name { - fluent::lint::builtin_clashing_extern_same_name - } else { - fluent::lint::builtin_clashing_extern_diff_name - }) - .set_arg("this_fi", this_fi.ident.name) - .set_arg("orig", orig.get_name()) - .span_label( - get_relevant_span(orig_fi), - fluent::lint::previous_decl_label, - ) - .span_label(get_relevant_span(this_fi), fluent::lint::mismatch_label) - // FIXME(davidtwco): translatable expected/found - .note_expected_found(&"", expected_str, &"", found_str) - .emit(); + lint.set_arg("this_fi", this_fi.ident.name) + .set_arg("orig", orig.get_name()) + .span_label(get_relevant_span(orig_fi), fluent::previous_decl_label) + .span_label(get_relevant_span(this_fi), fluent::mismatch_label) + // FIXME(davidtwco): translatable expected/found + .note_expected_found(&"", expected_str, &"", found_str) }, ); } @@ -3036,11 +3112,12 @@ impl<'tcx> LateLintPass<'tcx> for DerefNullPtr { if let rustc_hir::ExprKind::Unary(rustc_hir::UnOp::Deref, expr_deref) = expr.kind { if is_null_ptr(cx, expr_deref) { - cx.struct_span_lint(DEREF_NULLPTR, expr.span, |lint| { - let mut err = lint.build(fluent::lint::builtin_deref_nullptr); - err.span_label(expr.span, fluent::lint::label); - err.emit(); - }); + cx.struct_span_lint( + DEREF_NULLPTR, + expr.span, + fluent::lint_builtin_deref_nullptr, + |lint| lint.span_label(expr.span, fluent::label), + ); } } } @@ -3053,6 +3130,7 @@ declare_lint! { /// ### Example /// /// ```rust,compile_fail + /// # #![feature(asm_experimental_arch)] /// use std::arch::asm; /// /// fn main() { @@ -3150,9 +3228,8 @@ impl<'tcx> LateLintPass<'tcx> for NamedAsmLabels { cx.lookup_with_diagnostics( NAMED_ASM_LABELS, Some(target_spans), - |diag| { - diag.build(fluent::lint::builtin_asm_labels).emit(); - }, + fluent::lint_builtin_asm_labels, + |lint| lint, BuiltinLintDiagnostics::NamedAsmLabel( "only local labels of the form `<number>:` should be used in inline asm" .to_string(), @@ -3188,7 +3265,7 @@ declare_lint! { /// explicitly. /// /// To access a library from a binary target within the same crate, - /// use `your_crate_name::` as the path path instead of `lib::`: + /// use `your_crate_name::` as the path instead of `lib::`: /// /// ```rust,compile_fail /// // bar/src/lib.rs @@ -3224,16 +3301,14 @@ impl EarlyLintPass for SpecialModuleName { } match item.ident.name.as_str() { - "lib" => cx.struct_span_lint(SPECIAL_MODULE_NAME, item.span, |lint| { - lint.build("found module declaration for lib.rs") + "lib" => cx.struct_span_lint(SPECIAL_MODULE_NAME, item.span, "found module declaration for lib.rs", |lint| { + lint .note("lib.rs is the root of this crate's library target") .help("to refer to it from other targets, use the library's name as the path") - .emit() }), - "main" => cx.struct_span_lint(SPECIAL_MODULE_NAME, item.span, |lint| { - lint.build("found module declaration for main.rs") + "main" => cx.struct_span_lint(SPECIAL_MODULE_NAME, item.span, "found module declaration for main.rs", |lint| { + lint .note("a binary crate cannot be used as library") - .emit() }), _ => continue } @@ -3253,24 +3328,27 @@ impl EarlyLintPass for UnexpectedCfgs { for &(name, value) in cfg { if let Some(names_valid) = &check_cfg.names_valid { if !names_valid.contains(&name) { - cx.lookup(UNEXPECTED_CFGS, None::<MultiSpan>, |diag| { - diag.build(fluent::lint::builtin_unexpected_cli_config_name) - .help(fluent::lint::help) - .set_arg("name", name) - .emit(); - }); + cx.lookup( + UNEXPECTED_CFGS, + None::<MultiSpan>, + fluent::lint_builtin_unexpected_cli_config_name, + |diag| diag.help(fluent::help).set_arg("name", name), + ); } } if let Some(value) = value { if let Some(values) = &check_cfg.values_valid.get(&name) { if !values.contains(&value) { - cx.lookup(UNEXPECTED_CFGS, None::<MultiSpan>, |diag| { - diag.build(fluent::lint::builtin_unexpected_cli_config_value) - .help(fluent::lint::help) - .set_arg("name", name) - .set_arg("value", value) - .emit(); - }); + cx.lookup( + UNEXPECTED_CFGS, + None::<MultiSpan>, + fluent::lint_builtin_unexpected_cli_config_value, + |diag| { + diag.help(fluent::help) + .set_arg("name", name) + .set_arg("value", value) + }, + ); } } } |