diff options
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_builtin_macros/src/test.rs | 18 | ||||
| -rw-r--r-- | compiler/rustc_error_codes/src/error_codes/E0706.md | 2 | ||||
| -rw-r--r-- | compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl | 3 | ||||
| -rw-r--r-- | compiler/rustc_error_messages/src/lib.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_errors/src/translation.rs | 38 | ||||
| -rw-r--r-- | compiler/rustc_hir_typeck/src/errors.rs | 8 | ||||
| -rw-r--r-- | compiler/rustc_hir_typeck/src/method/mod.rs | 9 | ||||
| -rw-r--r-- | compiler/rustc_lint/src/unused.rs | 30 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/values.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_passes/src/check_attr.rs | 14 |
10 files changed, 90 insertions, 38 deletions
diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index fee5d04cdae..b62840d4bc8 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -112,7 +112,7 @@ pub fn expand_test_or_bench( }; // Note: non-associated fn items are already handled by `expand_test_or_bench` - if !matches!(item.kind, ast::ItemKind::Fn(_)) { + let ast::ItemKind::Fn(fn_) = &item.kind else { let diag = &cx.sess.parse_sess.span_diagnostic; let msg = "the `#[test]` attribute may only be used on a non-associated function"; let mut err = match item.kind { @@ -130,7 +130,7 @@ pub fn expand_test_or_bench( .emit(); return vec![Annotatable::Item(item)]; - } + }; // has_*_signature will report any errors in the type so compilation // will fail. We shouldn't try to expand in this case because the errors @@ -141,12 +141,14 @@ pub fn expand_test_or_bench( return vec![Annotatable::Item(item)]; } - let (sp, attr_sp) = (cx.with_def_site_ctxt(item.span), cx.with_def_site_ctxt(attr_sp)); + let sp = cx.with_def_site_ctxt(item.span); + let ret_ty_sp = cx.with_def_site_ctxt(fn_.sig.decl.output.span()); + let attr_sp = cx.with_def_site_ctxt(attr_sp); let test_id = Ident::new(sym::test, attr_sp); // creates test::$name - let test_path = |name| cx.path(sp, vec![test_id, Ident::from_str_and_span(name, sp)]); + let test_path = |name| cx.path(ret_ty_sp, vec![test_id, Ident::from_str_and_span(name, sp)]); // creates test::ShouldPanic::$name let should_panic_path = |name| { @@ -192,7 +194,7 @@ pub fn expand_test_or_bench( vec![ // super::$test_fn(b) cx.expr_call( - sp, + ret_ty_sp, cx.expr_path(cx.path(sp, vec![item.ident])), vec![cx.expr_ident(sp, b)], ), @@ -216,7 +218,11 @@ pub fn expand_test_or_bench( cx.expr_path(test_path("assert_test_result")), vec![ // $test_fn() - cx.expr_call(sp, cx.expr_path(cx.path(sp, vec![item.ident])), vec![]), // ) + cx.expr_call( + ret_ty_sp, + cx.expr_path(cx.path(sp, vec![item.ident])), + vec![], + ), // ) ], ), // } ), // ) diff --git a/compiler/rustc_error_codes/src/error_codes/E0706.md b/compiler/rustc_error_codes/src/error_codes/E0706.md index d379b8a2384..fabd855a222 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0706.md +++ b/compiler/rustc_error_codes/src/error_codes/E0706.md @@ -56,4 +56,4 @@ You might be interested in visiting the [async book] for further information. [`async-trait` crate]: https://crates.io/crates/async-trait [async-is-hard]: https://smallcultfollowing.com/babysteps/blog/2019/10/26/async-fn-in-traits-are-hard/ [Generic Associated Types]: https://github.com/rust-lang/rust/issues/44265 -[async book]: https://rust-lang.github.io/async-book/07_workarounds/06_async_in_traits.html +[async book]: https://rust-lang.github.io/async-book/07_workarounds/05_async_in_traits.html diff --git a/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl b/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl index 74088f4dfbe..d27edd47470 100644 --- a/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl +++ b/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl @@ -150,3 +150,6 @@ hir_analysis_const_bound_for_non_const_trait = hir_analysis_self_in_impl_self = `Self` is not valid in the self type of an impl block .note = replace `Self` with a different type + +hir_analysis_op_trait_generic_params = + `{$method_name}` must not have any generic parameters diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index e34acba1057..0b1b75471a6 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -30,7 +30,8 @@ use intl_memoizer::concurrent::IntlLangMemoizer; #[cfg(not(parallel_compiler))] use intl_memoizer::IntlLangMemoizer; -pub use fluent_bundle::{FluentArgs, FluentError, FluentValue}; +pub use fluent_bundle::{self, FluentArgs, FluentError, FluentValue}; + pub use unic_langid::{langid, LanguageIdentifier}; // Generates `DEFAULT_LOCALE_RESOURCES` static and `fluent_generated` module. diff --git a/compiler/rustc_errors/src/translation.rs b/compiler/rustc_errors/src/translation.rs index a7737b467b7..a452fac0747 100644 --- a/compiler/rustc_errors/src/translation.rs +++ b/compiler/rustc_errors/src/translation.rs @@ -1,7 +1,10 @@ use crate::snippet::Style; use crate::{DiagnosticArg, DiagnosticMessage, FluentBundle}; use rustc_data_structures::sync::Lrc; -use rustc_error_messages::FluentArgs; +use rustc_error_messages::{ + fluent_bundle::resolver::errors::{ReferenceKind, ResolverError}, + FluentArgs, FluentError, +}; use std::borrow::Cow; /// Convert diagnostic arguments (a rustc internal type that exists to implement @@ -102,14 +105,31 @@ pub trait Translate { .or_else(|| translate_with_bundle(self.fallback_fluent_bundle())) .map(|(translated, errs)| { // Always bail out for errors with the fallback bundle. - assert!( - errs.is_empty(), - "identifier: {:?}, attr: {:?}, args: {:?}, errors: {:?}", - identifier, - attr, - args, - errs - ); + + let mut help_messages = vec![]; + + if !errs.is_empty() { + for error in &errs { + match error { + FluentError::ResolverError(ResolverError::Reference( + ReferenceKind::Message { id, .. }, + )) if args.iter().any(|(arg_id, _)| arg_id == id) => { + help_messages.push(format!("Argument `{id}` exists but was not referenced correctly. Try using `{{${id}}}` instead")); + } + _ => {} + } + } + + panic!( + "Encountered errors while formatting message for `{identifier}`\n\ + help: {}\n\ + attr: `{attr:?}`\n\ + args: `{args:?}`\n\ + errors: `{errs:?}`", + help_messages.join("\nhelp: ") + ); + } + translated }) .expect("failed to find message in primary or fallback fluent bundles") diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index cfb408396da..afac6e7d94a 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -125,3 +125,11 @@ pub struct AddMissingParenthesesInRange { #[suggestion_part(code = ")")] pub right: Span, } + +#[derive(Diagnostic)] +#[diag(hir_analysis_op_trait_generic_params)] +pub struct OpMethodGenericParams { + #[primary_span] + pub span: Span, + pub method_name: String, +} diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index 2c7b3bbf31c..4a8b7749365 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs @@ -10,6 +10,7 @@ mod suggest; pub use self::suggest::SelfSource; pub use self::MethodError::*; +use crate::errors::OpMethodGenericParams; use crate::{Expectation, FnCtxt}; use rustc_data_structures::sync::Lrc; use rustc_errors::{Applicability, Diagnostic}; @@ -443,7 +444,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let def_id = method_item.def_id; let generics = tcx.generics_of(def_id); - assert_eq!(generics.params.len(), 0); + + if generics.params.len() != 0 { + tcx.sess.emit_fatal(OpMethodGenericParams { + span: tcx.def_span(method_item.def_id), + method_name: m_name.to_string(), + }); + } debug!("lookup_in_trait_adjusted: method_item={:?}", method_item); let mut obligations = vec![]; diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 46706e49844..045d76cac62 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -9,7 +9,7 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_infer::traits::util::elaborate_predicates_with_span; use rustc_middle::ty::adjustment; -use rustc_middle::ty::{self, Ty}; +use rustc_middle::ty::{self, DefIdTree, Ty}; use rustc_span::symbol::Symbol; use rustc_span::symbol::{kw, sym}; use rustc_span::{BytePos, Span}; @@ -87,17 +87,33 @@ declare_lint_pass!(UnusedResults => [UNUSED_MUST_USE, UNUSED_RESULTS]); impl<'tcx> LateLintPass<'tcx> for UnusedResults { fn check_stmt(&mut self, cx: &LateContext<'_>, s: &hir::Stmt<'_>) { - let expr = match s.kind { - hir::StmtKind::Semi(ref expr) => &**expr, - _ => return, - }; + let hir::StmtKind::Semi(expr) = s.kind else { return; }; if let hir::ExprKind::Ret(..) = expr.kind { return; } + if let hir::ExprKind::Match(await_expr, _arms, hir::MatchSource::AwaitDesugar) = expr.kind + && let ty = cx.typeck_results().expr_ty(&await_expr) + && let ty::Opaque(future_def_id, _) = ty.kind() + && cx.tcx.ty_is_opaque_future(ty) + // FIXME: This also includes non-async fns that return `impl Future`. + && let async_fn_def_id = cx.tcx.parent(*future_def_id) + && check_must_use_def( + cx, + async_fn_def_id, + expr.span, + "output of future returned by ", + "", + ) + { + // We have a bare `foo().await;` on an opaque type from an async function that was + // annotated with `#[must_use]`. + return; + } + let ty = cx.typeck_results().expr_ty(&expr); - let type_permits_lack_of_use = check_must_use_ty(cx, ty, &expr, s.span, "", "", 1); + let type_permits_lack_of_use = check_must_use_ty(cx, ty, &expr, expr.span, "", "", 1); let mut fn_warned = false; let mut op_warned = false; @@ -119,7 +135,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { _ => None, }; if let Some(def_id) = maybe_def_id { - fn_warned = check_must_use_def(cx, def_id, s.span, "return value of ", ""); + fn_warned = check_must_use_def(cx, def_id, expr.span, "return value of ", ""); } else if type_permits_lack_of_use { // We don't warn about unused unit or uninhabited types. // (See https://github.com/rust-lang/rust/issues/43806 for details.) diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs index f4b4c3fb05a..f4562cdfb88 100644 --- a/compiler/rustc_middle/src/values.rs +++ b/compiler/rustc_middle/src/values.rs @@ -185,7 +185,8 @@ fn find_item_ty_spans( }); if check_params && let Some(args) = path.segments.last().unwrap().args { let params_in_repr = tcx.params_in_repr(def_id); - for (i, arg) in args.args.iter().enumerate() { + // the domain size check is needed because the HIR may not be well-formed at this point + for (i, arg) in args.args.iter().enumerate().take(params_in_repr.domain_size()) { if let hir::GenericArg::Type(ty) = arg && params_in_repr.contains(i as u32) { find_item_ty_spans(tcx, ty, needle, spans, seen_representable); } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 27a57adf964..e0da0096c4e 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -139,7 +139,7 @@ impl CheckAttrVisitor<'_> { sym::collapse_debuginfo => self.check_collapse_debuginfo(attr, span, target), sym::const_trait => self.check_const_trait(attr, span, target), sym::must_not_suspend => self.check_must_not_suspend(&attr, span, target), - sym::must_use => self.check_must_use(hir_id, &attr, span, target), + sym::must_use => self.check_must_use(hir_id, &attr, target), sym::rustc_pass_by_value => self.check_pass_by_value(&attr, span, target), sym::rustc_allow_incoherent_impl => { self.check_allow_incoherent_impl(&attr, span, target) @@ -1163,17 +1163,7 @@ impl CheckAttrVisitor<'_> { } /// Warns against some misuses of `#[must_use]` - fn check_must_use(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) -> bool { - let node = self.tcx.hir().get(hir_id); - if let Some(kind) = node.fn_kind() && let rustc_hir::IsAsync::Async = kind.asyncness() { - self.tcx.emit_spanned_lint( - UNUSED_ATTRIBUTES, - hir_id, - attr.span, - errors::MustUseAsync { span } - ); - } - + fn check_must_use(&self, hir_id: HirId, attr: &Attribute, target: Target) -> bool { if !matches!( target, Target::Fn |
