diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index f9f273acb7e6f..5346f1ced8294 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -849,21 +849,22 @@ impl<'hir> LoweringContext<'_, 'hir> { (body_id, generator_option) }); - let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params); - // Lower outside new scope to preserve `is_in_loop_condition`. - let fn_decl = self.lower_fn_decl(decl, None, FnDeclKind::Closure, None); - - let c = self.arena.alloc(hir::Closure { - binder: binder_clause, - capture_clause, - bound_generic_params, - fn_decl, - body: body_id, - fn_decl_span: self.lower_span(fn_decl_span), - movability: generator_option, - }); + self.lower_lifetime_binder(closure_id, generic_params, |lctx, bound_generic_params| { + // Lower outside new scope to preserve `is_in_loop_condition`. + let fn_decl = lctx.lower_fn_decl(decl, None, FnDeclKind::Closure, None); + + let c = lctx.arena.alloc(hir::Closure { + binder: binder_clause, + capture_clause, + bound_generic_params, + fn_decl, + body: body_id, + fn_decl_span: lctx.lower_span(fn_decl_span), + movability: generator_option, + }); - hir::ExprKind::Closure(c) + hir::ExprKind::Closure(c) + }) } fn generator_movability_for_fn( @@ -950,23 +951,23 @@ impl<'hir> LoweringContext<'_, 'hir> { body_id }); - let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params); - - // We need to lower the declaration outside the new scope, because we - // have to conserve the state of being inside a loop condition for the - // closure argument types. - let fn_decl = self.lower_fn_decl(&outer_decl, None, FnDeclKind::Closure, None); - - let c = self.arena.alloc(hir::Closure { - binder: binder_clause, - capture_clause, - bound_generic_params, - fn_decl, - body, - fn_decl_span: self.lower_span(fn_decl_span), - movability: None, - }); - hir::ExprKind::Closure(c) + self.lower_lifetime_binder(closure_id, generic_params, |lctx, bound_generic_params| { + // We need to lower the declaration outside the new scope, because we + // have to conserve the state of being inside a loop condition for the + // closure argument types. + let fn_decl = lctx.lower_fn_decl(&outer_decl, None, FnDeclKind::Closure, None); + + let c = lctx.arena.alloc(hir::Closure { + binder: binder_clause, + capture_clause, + bound_generic_params, + fn_decl, + body, + fn_decl_span: lctx.lower_span(fn_decl_span), + movability: None, + }); + hir::ExprKind::Closure(c) + }) } /// Destructure the LHS of complex assignments. diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index e484f77cad443..04cf8f6411c2c 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -810,23 +810,31 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// name resolver owing to lifetime elision; this also populates the resolver's node-id->def-id /// map, so that later calls to `opt_node_id_to_def_id` that refer to these extra lifetime /// parameters will be successful. - #[instrument(level = "debug", skip(self))] + #[instrument(level = "debug", skip(self, in_binder))] #[inline] - fn lower_lifetime_binder( + fn lower_lifetime_binder( &mut self, binder: NodeId, generic_params: &[GenericParam], - ) -> &'hir [hir::GenericParam<'hir>] { - let mut generic_params: Vec<_> = self.lower_generic_params_mut(generic_params).collect(); + in_binder: impl FnOnce(&mut Self, &'hir [hir::GenericParam<'hir>]) -> R, + ) -> R { let extra_lifetimes = self.resolver.take_extra_lifetime_params(binder); debug!(?extra_lifetimes); - generic_params.extend(extra_lifetimes.into_iter().filter_map(|(ident, node_id, res)| { - self.lifetime_res_to_generic_param(ident, node_id, res) - })); + let extra_lifetimes: Vec<_> = extra_lifetimes + .into_iter() + .filter_map(|(ident, node_id, res)| { + self.lifetime_res_to_generic_param(ident, node_id, res) + }) + .collect(); + + let generic_params: Vec<_> = self + .lower_generic_params_mut(generic_params) + .chain(extra_lifetimes.into_iter()) + .collect(); let generic_params = self.arena.alloc_from_iter(generic_params); debug!(?generic_params); - generic_params + in_binder(self, generic_params) } fn with_dyn_type_scope(&mut self, in_scope: bool, f: impl FnOnce(&mut Self) -> T) -> T { @@ -1236,14 +1244,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::TyKind::Rptr(lifetime, self.lower_mt(mt, itctx)) } TyKind::BareFn(ref f) => { - let generic_params = self.lower_lifetime_binder(t.id, &f.generic_params); - hir::TyKind::BareFn(self.arena.alloc(hir::BareFnTy { - generic_params, - unsafety: self.lower_unsafety(f.unsafety), - abi: self.lower_extern(f.ext), - decl: self.lower_fn_decl(&f.decl, None, FnDeclKind::Pointer, None), - param_names: self.lower_fn_params_to_names(&f.decl), - })) + self.lower_lifetime_binder(t.id, &f.generic_params, |lctx, generic_params| { + hir::TyKind::BareFn(lctx.arena.alloc(hir::BareFnTy { + generic_params, + unsafety: lctx.lower_unsafety(f.unsafety), + abi: lctx.lower_extern(f.ext), + decl: lctx.lower_fn_decl(&f.decl, None, FnDeclKind::Pointer, None), + param_names: lctx.lower_fn_params_to_names(&f.decl), + })) + }) } TyKind::Never => hir::TyKind::Never, TyKind::Tup(ref tys) => hir::TyKind::Tup( @@ -2143,10 +2152,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { p: &PolyTraitRef, itctx: &mut ImplTraitContext, ) -> hir::PolyTraitRef<'hir> { - let bound_generic_params = - self.lower_lifetime_binder(p.trait_ref.ref_id, &p.bound_generic_params); - let trait_ref = self.lower_trait_ref(&p.trait_ref, itctx); - hir::PolyTraitRef { bound_generic_params, trait_ref, span: self.lower_span(p.span) } + self.lower_lifetime_binder( + p.trait_ref.ref_id, + &p.bound_generic_params, + |lctx, bound_generic_params| { + let trait_ref = lctx.lower_trait_ref(&p.trait_ref, itctx); + hir::PolyTraitRef { bound_generic_params, trait_ref, span: lctx.lower_span(p.span) } + }, + ) } fn lower_mt(&mut self, mt: &MutTy, itctx: &mut ImplTraitContext) -> hir::MutTy<'hir> { diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 8dc9368a0b994..de70b17e44ccd 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -135,7 +135,6 @@ pub struct RegionInferenceContext<'tcx> { /// adds a new lower bound to the SCC it is analyzing: so you wind up /// with `'R: 'O` where `'R` is the pick-region and `'O` is the /// minimal viable option. -#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)] pub(crate) struct AppliedMemberConstraint { /// The SCC that was affected. (The "member region".) /// diff --git a/compiler/rustc_error_messages/locales/en-US/parser.ftl b/compiler/rustc_error_messages/locales/en-US/parser.ftl index bc17754c56ae3..f74df3d9746ae 100644 --- a/compiler/rustc_error_messages/locales/en-US/parser.ftl +++ b/compiler/rustc_error_messages/locales/en-US/parser.ftl @@ -153,3 +153,6 @@ parser_left_arrow_operator = unexpected token: `<-` parser_remove_let = expected pattern, found `let` .suggestion = remove the unnecessary `let` keyword + +parser_use_eq_instead = unexpected `==` + .suggestion = try using `=` instead diff --git a/compiler/rustc_error_messages/locales/en-US/session.ftl b/compiler/rustc_error_messages/locales/en-US/session.ftl index 983e5cee8237d..d2a2958f62436 100644 --- a/compiler/rustc_error_messages/locales/en-US/session.ftl +++ b/compiler/rustc_error_messages/locales/en-US/session.ftl @@ -14,3 +14,45 @@ session_feature_diagnostic_for_issue = session_feature_diagnostic_help = add `#![feature({$feature})]` to the crate attributes to enable + +session_not_circumvent_feature = `-Zunleash-the-miri-inside-of-you` may not be used to circumvent feature gates, except when testing error paths in the CTFE engine + +session_profile_use_file_does_not_exist = file `{$path}` passed to `-C profile-use` does not exist. + +session_linker_plugin_lto_windows_not_supported = linker plugin based LTO is not supported together with `-C prefer-dynamic` when targeting Windows-like targets + +session_profile_sample_use_file_does_not_exist = file `{$path}` passed to `-C profile-sample-use` does not exist. + +session_target_requires_unwind_tables = target requires unwind tables, they cannot be disabled with `-C force-unwind-tables=no` + +session_sanitizer_not_supported = {$us} sanitizer is not supported for this target + +session_sanitizers_not_supported = {$us} sanitizers are not supported for this target + +session_cannot_mix_and_match_sanitizers = `-Zsanitizer={$first}` is incompatible with `-Zsanitizer={$second}` + +session_cannot_enable_crt_static_linux = sanitizer is incompatible with statically linked libc, disable it using `-C target-feature=-crt-static` + +session_sanitizer_cfi_enabled = `-Zsanitizer=cfi` requires `-Clto` + +session_unstable_virtual_function_elimination = `-Zvirtual-function-elimination` requires `-Clto` + +session_unsupported_dwarf_version = requested DWARF version {$dwarf_version} is greater than 5 + +session_target_invalid_address_space = invalid address space `{$addr_space}` for `{$cause}` in "data-layout": {$err} + +session_target_invalid_bits = invalid {$kind} `{$bit}` for `{$cause}` in "data-layout": {$err} + +session_target_missing_alignment = missing alignment for `{$cause}` in "data-layout" + +session_target_invalid_alignment = invalid alignment for `{$cause}` in "data-layout": {$err} + +session_target_inconsistent_architecture = inconsistent target specification: "data-layout" claims architecture is {$dl}-endian, while "target-endian" is `{$target}` + +session_target_inconsistent_pointer_width = inconsistent target specification: "data-layout" claims pointers are {$pointer_size}-bit, while "target-pointer-width" is `{$target}` + +session_target_invalid_bits_size = {$err} + +session_target_stack_protector_not_supported = `-Z stack-protector={$stack_protector}` is not supported for target {$target_triple} and will be ignored + +session_split_debuginfo_unstable_platform = `-Csplit-debuginfo={$debuginfo}` is unstable on this platform diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index a052aaee04756..a774b52c8a592 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -10,10 +10,11 @@ use rustc_lint_defs::{Applicability, LintExpectationId}; use rustc_span::edition::LATEST_STABLE_EDITION; use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent, Symbol}; use rustc_span::{edition::Edition, Span, DUMMY_SP}; -use rustc_target::spec::PanicStrategy; +use rustc_target::spec::{PanicStrategy, SplitDebuginfo, StackProtector, TargetTriple}; use std::borrow::Cow; use std::fmt; use std::hash::{Hash, Hasher}; +use std::num::ParseIntError; use std::path::{Path, PathBuf}; /// Error type for `Diagnostic`'s `suggestions` field, indicating that @@ -91,6 +92,10 @@ into_diagnostic_arg_using_display!( Edition, Ident, MacroRulesNormalizedIdent, + ParseIntError, + StackProtector, + &TargetTriple, + SplitDebuginfo ); impl IntoDiagnosticArg for bool { diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 513225e160645..3e02d2ebb7e3e 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -456,7 +456,7 @@ struct HandlerInner { } /// A key denoting where from a diagnostic was stashed. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash)] pub enum StashKey { ItemNoType, UnderscoreForArrayLengths, diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index d5ac07f1e6315..b44ee02cfe3bb 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -457,7 +457,7 @@ impl PartialRes { /// Different kinds of symbols can coexist even if they share the same textual name. /// Therefore, they each have a separate universe (known as a "namespace"). -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] pub enum Namespace { /// The type namespace includes `struct`s, `enum`s, `union`s, `trait`s, and `mod`s /// (and, by extension, crates). diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index 178366f7d8045..a79c982649afc 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -141,7 +141,7 @@ pub enum TokenKind { Unknown, } -#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum DocStyle { Outer, Inner, diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 9a163cf207e97..7ca6ec5d96234 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -50,6 +50,10 @@ use std::cell::Cell; use std::iter; use std::slice; +type EarlyLintPassFactory = dyn Fn() -> EarlyLintPassObject + sync::Send + sync::Sync; +type LateLintPassFactory = + dyn for<'tcx> Fn(TyCtxt<'tcx>) -> LateLintPassObject<'tcx> + sync::Send + sync::Sync; + /// Information about the registered lints. /// /// This is basically the subset of `Context` that we can @@ -64,11 +68,11 @@ pub struct LintStore { /// interior mutability, we don't enforce this (and lints should, in theory, /// be compatible with being constructed more than once, though not /// necessarily in a sane manner. This is safe though.) - pub pre_expansion_passes: Vec EarlyLintPassObject + sync::Send + sync::Sync>>, - pub early_passes: Vec EarlyLintPassObject + sync::Send + sync::Sync>>, - pub late_passes: Vec LateLintPassObject + sync::Send + sync::Sync>>, + pub pre_expansion_passes: Vec>, + pub early_passes: Vec>, + pub late_passes: Vec>, /// This is unique in that we construct them per-module, so not once. - pub late_module_passes: Vec LateLintPassObject + sync::Send + sync::Sync>>, + pub late_module_passes: Vec>, /// Lints indexed by name. by_name: FxHashMap, @@ -186,14 +190,20 @@ impl LintStore { pub fn register_late_pass( &mut self, - pass: impl Fn() -> LateLintPassObject + 'static + sync::Send + sync::Sync, + pass: impl for<'tcx> Fn(TyCtxt<'tcx>) -> LateLintPassObject<'tcx> + + 'static + + sync::Send + + sync::Sync, ) { self.late_passes.push(Box::new(pass)); } pub fn register_late_mod_pass( &mut self, - pass: impl Fn() -> LateLintPassObject + 'static + sync::Send + sync::Sync, + pass: impl for<'tcx> Fn(TyCtxt<'tcx>) -> LateLintPassObject<'tcx> + + 'static + + sync::Send + + sync::Sync, ) { self.late_module_passes.push(Box::new(pass)); } @@ -558,7 +568,7 @@ pub trait LintPassObject: Sized {} impl LintPassObject for EarlyLintPassObject {} -impl LintPassObject for LateLintPassObject {} +impl LintPassObject for LateLintPassObject<'_> {} pub trait LintContext: Sized { type PassObject: LintPassObject; @@ -949,8 +959,8 @@ impl<'a> EarlyContext<'a> { } } -impl LintContext for LateContext<'_> { - type PassObject = LateLintPassObject; +impl<'tcx> LintContext for LateContext<'tcx> { + type PassObject = LateLintPassObject<'tcx>; /// Gets the overall compiler `Session` object. fn sess(&self) -> &Session { diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs index 8a336844dc2fa..66dc3ed59a384 100644 --- a/compiler/rustc_lint/src/late.rs +++ b/compiler/rustc_lint/src/late.rs @@ -306,12 +306,12 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas } } -struct LateLintPassObjects<'a> { - lints: &'a mut [LateLintPassObject], +struct LateLintPassObjects<'a, 'tcx> { + lints: &'a mut [LateLintPassObject<'tcx>], } #[allow(rustc::lint_pass_impl_without_macro)] -impl LintPass for LateLintPassObjects<'_> { +impl LintPass for LateLintPassObjects<'_, '_> { fn name(&self) -> &'static str { panic!() } @@ -329,7 +329,7 @@ macro_rules! expand_late_lint_pass_impl_methods { macro_rules! late_lint_pass_impl { ([], [$hir:tt], $methods:tt) => { - impl<$hir> LateLintPass<$hir> for LateLintPassObjects<'_> { + impl<$hir> LateLintPass<$hir> for LateLintPassObjects<'_, $hir> { expand_late_lint_pass_impl_methods!([$hir], $methods); } }; @@ -382,7 +382,7 @@ pub fn late_lint_mod<'tcx, T: LateLintPass<'tcx>>( late_lint_mod_pass(tcx, module_def_id, builtin_lints); let mut passes: Vec<_> = - unerased_lint_store(tcx).late_module_passes.iter().map(|pass| (pass)()).collect(); + unerased_lint_store(tcx).late_module_passes.iter().map(|pass| (pass)(tcx)).collect(); if !passes.is_empty() { late_lint_mod_pass(tcx, module_def_id, LateLintPassObjects { lints: &mut passes[..] }); @@ -418,7 +418,8 @@ fn late_lint_pass_crate<'tcx, T: LateLintPass<'tcx>>(tcx: TyCtxt<'tcx>, pass: T) } fn late_lint_crate<'tcx, T: LateLintPass<'tcx>>(tcx: TyCtxt<'tcx>, builtin_lints: T) { - let mut passes = unerased_lint_store(tcx).late_passes.iter().map(|p| (p)()).collect::>(); + let mut passes = + unerased_lint_store(tcx).late_passes.iter().map(|p| (p)(tcx)).collect::>(); if !tcx.sess.opts.unstable_opts.no_interleave_lints { if !passes.is_empty() { @@ -434,7 +435,7 @@ fn late_lint_crate<'tcx, T: LateLintPass<'tcx>>(tcx: TyCtxt<'tcx>, builtin_lints } let mut passes: Vec<_> = - unerased_lint_store(tcx).late_module_passes.iter().map(|pass| (pass)()).collect(); + unerased_lint_store(tcx).late_module_passes.iter().map(|pass| (pass)(tcx)).collect(); for pass in &mut passes { tcx.sess.prof.extra_verbose_generic_activity("run_late_module_lint", pass.name()).run( diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 370a75cf70069..e0e6f1a8c080c 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -260,26 +260,41 @@ fn register_builtins(store: &mut LintStore, no_interleave_lints: bool) { ) } - macro_rules! register_pass { + macro_rules! register_early_pass { ($method:ident, $ty:ident, $constructor:expr) => { store.register_lints(&$ty::get_lints()); store.$method(|| Box::new($constructor)); }; } - macro_rules! register_passes { + macro_rules! register_late_pass { + ($method:ident, $ty:ident, $constructor:expr) => { + store.register_lints(&$ty::get_lints()); + store.$method(|_| Box::new($constructor)); + }; + } + + macro_rules! register_early_passes { + ($method:ident, [$($passes:ident: $constructor:expr,)*]) => ( + $( + register_early_pass!($method, $passes, $constructor); + )* + ) + } + + macro_rules! register_late_passes { ($method:ident, [$($passes:ident: $constructor:expr,)*]) => ( $( - register_pass!($method, $passes, $constructor); + register_late_pass!($method, $passes, $constructor); )* ) } if no_interleave_lints { - pre_expansion_lint_passes!(register_passes, register_pre_expansion_pass); - early_lint_passes!(register_passes, register_early_pass); - late_lint_passes!(register_passes, register_late_pass); - late_lint_mod_passes!(register_passes, register_late_mod_pass); + pre_expansion_lint_passes!(register_early_passes, register_pre_expansion_pass); + early_lint_passes!(register_early_passes, register_early_pass); + late_lint_passes!(register_late_passes, register_late_pass); + late_lint_mod_passes!(register_late_passes, register_late_mod_pass); } else { store.register_lints(&BuiltinCombinedPreExpansionLintPass::get_lints()); store.register_lints(&BuiltinCombinedEarlyLintPass::get_lints()); @@ -510,19 +525,19 @@ fn register_internals(store: &mut LintStore) { store.register_lints(&LintPassImpl::get_lints()); store.register_early_pass(|| Box::new(LintPassImpl)); store.register_lints(&DefaultHashTypes::get_lints()); - store.register_late_pass(|| Box::new(DefaultHashTypes)); + store.register_late_pass(|_| Box::new(DefaultHashTypes)); store.register_lints(&QueryStability::get_lints()); - store.register_late_pass(|| Box::new(QueryStability)); + store.register_late_pass(|_| Box::new(QueryStability)); store.register_lints(&ExistingDocKeyword::get_lints()); - store.register_late_pass(|| Box::new(ExistingDocKeyword)); + store.register_late_pass(|_| Box::new(ExistingDocKeyword)); store.register_lints(&TyTyKind::get_lints()); - store.register_late_pass(|| Box::new(TyTyKind)); + store.register_late_pass(|_| Box::new(TyTyKind)); store.register_lints(&Diagnostics::get_lints()); - store.register_late_pass(|| Box::new(Diagnostics)); + store.register_late_pass(|_| Box::new(Diagnostics)); store.register_lints(&BadOptAccess::get_lints()); - store.register_late_pass(|| Box::new(BadOptAccess)); + store.register_late_pass(|_| Box::new(BadOptAccess)); store.register_lints(&PassByValue::get_lints()); - store.register_late_pass(|| Box::new(PassByValue)); + store.register_late_pass(|_| Box::new(PassByValue)); // FIXME(davidtwco): deliberately do not include `UNTRANSLATABLE_DIAGNOSTIC` and // `DIAGNOSTIC_OUTSIDE_OF_IMPL` here because `-Wrustc::internal` is provided to every crate and // these lints will trigger all of the time - change this once migration to diagnostic structs diff --git a/compiler/rustc_lint/src/passes.rs b/compiler/rustc_lint/src/passes.rs index 90c554c2e040b..666e61b85acfc 100644 --- a/compiler/rustc_lint/src/passes.rs +++ b/compiler/rustc_lint/src/passes.rs @@ -244,4 +244,4 @@ macro_rules! declare_combined_early_lint_pass { /// A lint pass boxed up as a trait object. pub type EarlyLintPassObject = Box; -pub type LateLintPassObject = Box LateLintPass<'tcx> + sync::Send + 'static>; +pub type LateLintPassObject<'tcx> = Box + sync::Send + 'tcx>; diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index e149535bec7b5..1f7643a76afe5 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -741,7 +741,7 @@ pub enum TerminatorKind<'tcx> { } /// Information about an assertion failure. -#[derive(Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq, PartialOrd)] +#[derive(Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq)] pub enum AssertKind { BoundsCheck { len: O, index: O }, Overflow(BinOp, O, O), diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs index 9ccf5aea63ca8..02a9958525b22 100644 --- a/compiler/rustc_middle/src/mir/terminator.rs +++ b/compiler/rustc_middle/src/mir/terminator.rs @@ -14,7 +14,7 @@ use std::slice; pub use super::query::*; -#[derive(Debug, Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq, PartialOrd)] +#[derive(Debug, Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq)] pub struct SwitchTargets { /// Possible values. The locations to branch to in each case /// are found in the corresponding indices from the `targets` vector. diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index ab7e5ba3a1067..a56fac7c4dd2c 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -12,7 +12,7 @@ pub mod util; use crate::infer::canonical::Canonical; use crate::ty::abstract_const::NotConstEvaluatable; use crate::ty::subst::SubstsRef; -use crate::ty::{self, AdtKind, Predicate, Ty, TyCtxt}; +use crate::ty::{self, AdtKind, Ty, TyCtxt}; use rustc_data_structures::sync::Lrc; use rustc_errors::{Applicability, Diagnostic}; @@ -416,7 +416,7 @@ pub enum ObligationCauseCode<'tcx> { BinOp { rhs_span: Option, is_lit: bool, - output_pred: Option>, + output_ty: Option>, }, } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index c2e5decfc786e..53e91e48c24d0 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1252,7 +1252,7 @@ impl<'tcx> TyCtxt<'tcx> { output_filenames: OutputFilenames, ) -> GlobalCtxt<'tcx> { let data_layout = TargetDataLayout::parse(&s.target).unwrap_or_else(|err| { - s.fatal(&err); + s.emit_fatal(err); }); let interners = CtxtInterners::new(arena); let common_types = CommonTypes::new( diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index dd2f43210603a..e4ad96b659b08 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -102,13 +102,25 @@ pub fn suggest_arbitrary_trait_bound<'tcx>( generics: &hir::Generics<'_>, err: &mut Diagnostic, trait_pred: PolyTraitPredicate<'tcx>, + associated_ty: Option<(&'static str, Ty<'tcx>)>, ) -> bool { if !trait_pred.is_suggestable(tcx, false) { return false; } let param_name = trait_pred.skip_binder().self_ty().to_string(); - let constraint = trait_pred.print_modifiers_and_trait_path().to_string(); + let mut constraint = trait_pred.print_modifiers_and_trait_path().to_string(); + + if let Some((name, term)) = associated_ty { + // FIXME: this case overlaps with code in TyCtxt::note_and_explain_type_err. + // That should be extracted into a helper function. + if constraint.ends_with('>') { + constraint = format!("{}, {} = {}>", &constraint[..constraint.len() - 1], name, term); + } else { + constraint.push_str(&format!("<{} = {}>", name, term)); + } + } + let param = generics.params.iter().find(|p| p.name.ident().as_str() == param_name); // Skip, there is a param named Self diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs index 5e042c3acfce2..5f8cb57820210 100644 --- a/compiler/rustc_middle/src/ty/visit.rs +++ b/compiler/rustc_middle/src/ty/visit.rs @@ -666,7 +666,7 @@ impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector { // ignore the inputs to a projection, as they may not appear // in the normalized form if self.just_constrained { - if let ty::Projection(..) = t.kind() { + if let ty::Projection(..) | ty::Opaque(..) = t.kind() { return ControlFlow::CONTINUE; } } diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index ad49227222b2c..be524db785bc0 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -713,6 +713,14 @@ pub(crate) struct RemoveLet { pub span: Span, } +#[derive(SessionDiagnostic)] +#[diag(parser::use_eq_instead)] +pub(crate) struct UseEqInstead { + #[primary_span] + #[suggestion_short(applicability = "machine-applicable", code = "=")] + pub span: Span, +} + // SnapshotParser is used to create a snapshot of the parser // without causing duplicate errors being emitted when the `Parser` // is dropped. @@ -957,6 +965,14 @@ impl<'a> Parser<'a> { } } + if self.token.kind == TokenKind::EqEq + && self.prev_token.is_ident() + && expected.iter().any(|tok| matches!(tok, TokenType::Token(TokenKind::Eq))) + { + // Likely typo: `=` → `==` in let expr or enum item + return Err(self.sess.create_err(UseEqInstead { span: self.token.span })); + } + let expect = tokens_to_string(&expected); let actual = super::token_descr(&self.token); let (msg_exp, (label_sp, label_exp)) = if expected.len() > 1 { diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index f7b7313d1049d..749a78a7552ed 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -57,7 +57,7 @@ use rustc_span::{Span, DUMMY_SP}; use smallvec::{smallvec, SmallVec}; use std::cell::{Cell, RefCell}; use std::collections::BTreeSet; -use std::{cmp, fmt, ptr}; +use std::{fmt, ptr}; use diagnostics::{ImportSuggestion, LabelSuggestion, Suggestion}; use imports::{Import, ImportKind, ImportResolver, NameResolution}; @@ -163,7 +163,6 @@ enum ImplTraitContext { Universal(LocalDefId), } -#[derive(Eq)] struct BindingError { name: Symbol, origin: BTreeSet, @@ -171,24 +170,6 @@ struct BindingError { could_be_path: bool, } -impl PartialOrd for BindingError { - fn partial_cmp(&self, other: &BindingError) -> Option { - Some(self.cmp(other)) - } -} - -impl PartialEq for BindingError { - fn eq(&self, other: &BindingError) -> bool { - self.name == other.name - } -} - -impl Ord for BindingError { - fn cmp(&self, other: &BindingError) -> cmp::Ordering { - self.name.cmp(&other.name) - } -} - enum ResolutionError<'a> { /// Error E0401: can't use type or const parameters from outer function. GenericParamsFromOuterFunction(Res, HasGenericParams), @@ -845,7 +826,7 @@ impl<'a> NameBinding<'a> { } } -#[derive(Debug, Default, Clone)] +#[derive(Default, Clone)] pub struct ExternPreludeEntry<'a> { extern_crate_item: Option<&'a NameBinding<'a>>, pub introduced_by_item: bool, diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 04bd685f19001..8bb3878fbbb47 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -898,7 +898,7 @@ fn default_configuration(sess: &Session) -> CrateConfig { let max_atomic_width = sess.target.max_atomic_width(); let atomic_cas = sess.target.atomic_cas; let layout = TargetDataLayout::parse(&sess.target).unwrap_or_else(|err| { - sess.fatal(&err); + sess.emit_fatal(err); }); let mut ret = CrateConfig::default(); diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index 7252f1799dac1..3c93cfab183d2 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -1,10 +1,12 @@ use std::num::NonZeroU32; -use crate as rustc_session; use crate::cgu_reuse_tracker::CguReuse; -use rustc_errors::MultiSpan; +use crate::{self as rustc_session, SessionDiagnostic}; +use rustc_errors::{fluent, DiagnosticBuilder, Handler, MultiSpan}; use rustc_macros::SessionDiagnostic; use rustc_span::{Span, Symbol}; +use rustc_target::abi::TargetDataLayoutErrors; +use rustc_target::spec::{SplitDebuginfo, StackProtector, TargetTriple}; #[derive(SessionDiagnostic)] #[diag(session::incorrect_cgu_reuse_type)] @@ -43,3 +45,128 @@ pub struct FeatureDiagnosticForIssue { pub struct FeatureDiagnosticHelp { pub feature: Symbol, } + +impl SessionDiagnostic<'_, !> for TargetDataLayoutErrors<'_> { + fn into_diagnostic(self, sess: &Handler) -> DiagnosticBuilder<'_, !> { + let mut diag; + match self { + TargetDataLayoutErrors::InvalidAddressSpace { addr_space, err, cause } => { + diag = sess.struct_fatal(fluent::session::target_invalid_address_space); + diag.set_arg("addr_space", addr_space); + diag.set_arg("cause", cause); + diag.set_arg("err", err); + diag + } + TargetDataLayoutErrors::InvalidBits { kind, bit, cause, err } => { + diag = sess.struct_fatal(fluent::session::target_invalid_bits); + diag.set_arg("kind", kind); + diag.set_arg("bit", bit); + diag.set_arg("cause", cause); + diag.set_arg("err", err); + diag + } + TargetDataLayoutErrors::MissingAlignment { cause } => { + diag = sess.struct_fatal(fluent::session::target_missing_alignment); + diag.set_arg("cause", cause); + diag + } + TargetDataLayoutErrors::InvalidAlignment { cause, err } => { + diag = sess.struct_fatal(fluent::session::target_invalid_alignment); + diag.set_arg("cause", cause); + diag.set_arg("err", err); + diag + } + TargetDataLayoutErrors::InconsistentTargetArchitecture { dl, target } => { + diag = sess.struct_fatal(fluent::session::target_inconsistent_architecture); + diag.set_arg("dl", dl); + diag.set_arg("target", target); + diag + } + TargetDataLayoutErrors::InconsistentTargetPointerWidth { pointer_size, target } => { + diag = sess.struct_fatal(fluent::session::target_inconsistent_pointer_width); + diag.set_arg("pointer_size", pointer_size); + diag.set_arg("target", target); + diag + } + TargetDataLayoutErrors::InvalidBitsSize { err } => { + diag = sess.struct_fatal(fluent::session::target_invalid_bits_size); + diag.set_arg("err", err); + diag + } + } + } +} + +#[derive(SessionDiagnostic)] +#[diag(session::not_circumvent_feature)] +pub struct NotCircumventFeature; + +#[derive(SessionDiagnostic)] +#[diag(session::linker_plugin_lto_windows_not_supported)] +pub struct LinkerPluginToWindowsNotSupported; + +#[derive(SessionDiagnostic)] +#[diag(session::profile_use_file_does_not_exist)] +pub struct ProfileUseFileDoesNotExist<'a> { + pub path: &'a std::path::Path, +} + +#[derive(SessionDiagnostic)] +#[diag(session::profile_sample_use_file_does_not_exist)] +pub struct ProfileSampleUseFileDoesNotExist<'a> { + pub path: &'a std::path::Path, +} + +#[derive(SessionDiagnostic)] +#[diag(session::target_requires_unwind_tables)] +pub struct TargetRequiresUnwindTables; + +#[derive(SessionDiagnostic)] +#[diag(session::sanitizer_not_supported)] +pub struct SanitizerNotSupported { + pub us: String, +} + +#[derive(SessionDiagnostic)] +#[diag(session::sanitizers_not_supported)] +pub struct SanitizersNotSupported { + pub us: String, +} + +#[derive(SessionDiagnostic)] +#[diag(session::cannot_mix_and_match_sanitizers)] +pub struct CannotMixAndMatchSanitizers { + pub first: String, + pub second: String, +} + +#[derive(SessionDiagnostic)] +#[diag(session::cannot_enable_crt_static_linux)] +pub struct CannotEnableCrtStaticLinux; + +#[derive(SessionDiagnostic)] +#[diag(session::sanitizer_cfi_enabled)] +pub struct SanitizerCfiEnabled; + +#[derive(SessionDiagnostic)] +#[diag(session::unstable_virtual_function_elimination)] +pub struct UnstableVirtualFunctionElimination; + +#[derive(SessionDiagnostic)] +#[diag(session::unsupported_dwarf_version)] +pub struct UnsupportedDwarfVersion { + pub dwarf_version: u32, +} + +#[derive(SessionDiagnostic)] +#[diag(session::target_stack_protector_not_supported)] +pub struct StackProtectorNotSupportedForTarget<'a> { + pub stack_protector: StackProtector, + pub target_triple: &'a TargetTriple, +} + +#[derive(SessionDiagnostic)] +#[diag(session::split_debuginfo_unstable_platform)] +pub struct SplitDebugInfoUnstablePlatform { + pub debuginfo: SplitDebuginfo, +} diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 557edad548c64..caf9d582ab099 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -2,6 +2,13 @@ use crate::cgu_reuse_tracker::CguReuseTracker; use crate::code_stats::CodeStats; pub use crate::code_stats::{DataTypeKind, FieldInfo, SizeKind, VariantInfo}; use crate::config::{self, CrateType, InstrumentCoverage, OptLevel, OutputType, SwitchWithOptPath}; +use crate::errors::{ + CannotEnableCrtStaticLinux, CannotMixAndMatchSanitizers, LinkerPluginToWindowsNotSupported, + NotCircumventFeature, ProfileSampleUseFileDoesNotExist, ProfileUseFileDoesNotExist, + SanitizerCfiEnabled, SanitizerNotSupported, SanitizersNotSupported, + SplitDebugInfoUnstablePlatform, StackProtectorNotSupportedForTarget, + TargetRequiresUnwindTables, UnstableVirtualFunctionElimination, UnsupportedDwarfVersion, +}; use crate::parse::{add_feature_diagnostics, ParseSess}; use crate::search_paths::{PathKind, SearchPath}; use crate::{filesearch, lint}; @@ -235,6 +242,9 @@ impl Session { if !unleashed_features.is_empty() { let mut must_err = false; // Create a diagnostic pointing at where things got unleashed. + // FIXME(#100717): needs eager translation/lists + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] let mut diag = self.struct_warn("skipping const checks"); for &(span, feature_gate) in unleashed_features.iter() { // FIXME: `span_label` doesn't do anything, so we use "help" as a hack. @@ -250,10 +260,7 @@ impl Session { // If we should err, make sure we did. if must_err && self.has_errors().is_none() { // We have skipped a feature gate, and not run into other errors... reject. - self.err( - "`-Zunleash-the-miri-inside-of-you` may not be used to circumvent feature \ - gates, except when testing error paths in the CTFE engine", - ); + self.emit_err(NotCircumventFeature); } } } @@ -534,9 +541,13 @@ impl Session { Err(ErrorGuaranteed::unchecked_claim_error_was_emitted()) } } + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] pub fn span_warn>(&self, sp: S, msg: impl Into) { self.diagnostic().span_warn(sp, msg) } + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] pub fn span_warn_with_code>( &self, sp: S, @@ -585,6 +596,8 @@ impl Session { ) { self.diagnostic().span_note_without_error(sp, msg) } + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] pub fn struct_note_without_error( &self, msg: impl Into, @@ -1469,40 +1482,28 @@ fn validate_commandline_args_with_session_available(sess: &Session) { && sess.opts.cg.prefer_dynamic && sess.target.is_like_windows { - sess.err( - "Linker plugin based LTO is not supported together with \ - `-C prefer-dynamic` when targeting Windows-like targets", - ); + sess.emit_err(LinkerPluginToWindowsNotSupported); } // Make sure that any given profiling data actually exists so LLVM can't // decide to silently skip PGO. if let Some(ref path) = sess.opts.cg.profile_use { if !path.exists() { - sess.err(&format!( - "File `{}` passed to `-C profile-use` does not exist.", - path.display() - )); + sess.emit_err(ProfileUseFileDoesNotExist { path }); } } // Do the same for sample profile data. if let Some(ref path) = sess.opts.unstable_opts.profile_sample_use { if !path.exists() { - sess.err(&format!( - "File `{}` passed to `-C profile-sample-use` does not exist.", - path.display() - )); + sess.emit_err(ProfileSampleUseFileDoesNotExist { path }); } } // Unwind tables cannot be disabled if the target requires them. if let Some(include_uwtables) = sess.opts.cg.force_unwind_tables { if sess.target.requires_uwtable && !include_uwtables { - sess.err( - "target requires unwind tables, they cannot be disabled with \ - `-C force-unwind-tables=no`.", - ); + sess.emit_err(TargetRequiresUnwindTables); } } @@ -1512,64 +1513,55 @@ fn validate_commandline_args_with_session_available(sess: &Session) { match unsupported_sanitizers.into_iter().count() { 0 => {} 1 => { - sess.err(&format!( - "{} sanitizer is not supported for this target", - unsupported_sanitizers - )); + sess.emit_err(SanitizerNotSupported { us: unsupported_sanitizers.to_string() }); } _ => { - sess.err(&format!( - "{} sanitizers are not supported for this target", - unsupported_sanitizers - )); + sess.emit_err(SanitizersNotSupported { us: unsupported_sanitizers.to_string() }); } } // Cannot mix and match sanitizers. let mut sanitizer_iter = sess.opts.unstable_opts.sanitizer.into_iter(); if let (Some(first), Some(second)) = (sanitizer_iter.next(), sanitizer_iter.next()) { - sess.err(&format!("`-Zsanitizer={first}` is incompatible with `-Zsanitizer={second}`")); + sess.emit_err(CannotMixAndMatchSanitizers { + first: first.to_string(), + second: second.to_string(), + }); } // Cannot enable crt-static with sanitizers on Linux if sess.crt_static(None) && !sess.opts.unstable_opts.sanitizer.is_empty() { - sess.err( - "sanitizer is incompatible with statically linked libc, \ - disable it using `-C target-feature=-crt-static`", - ); + sess.emit_err(CannotEnableCrtStaticLinux); } // LLVM CFI and VFE both require LTO. if sess.lto() != config::Lto::Fat { if sess.is_sanitizer_cfi_enabled() { - sess.err("`-Zsanitizer=cfi` requires `-Clto`"); + sess.emit_err(SanitizerCfiEnabled); } if sess.opts.unstable_opts.virtual_function_elimination { - sess.err("`-Zvirtual-function-elimination` requires `-Clto`"); + sess.emit_err(UnstableVirtualFunctionElimination); } } if sess.opts.unstable_opts.stack_protector != StackProtector::None { if !sess.target.options.supports_stack_protector { - sess.warn(&format!( - "`-Z stack-protector={}` is not supported for target {} and will be ignored", - sess.opts.unstable_opts.stack_protector, sess.opts.target_triple - )) + sess.emit_warning(StackProtectorNotSupportedForTarget { + stack_protector: sess.opts.unstable_opts.stack_protector, + target_triple: &sess.opts.target_triple, + }); } } if let Some(dwarf_version) = sess.opts.unstable_opts.dwarf_version { if dwarf_version > 5 { - sess.err(&format!("requested DWARF version {} is greater than 5", dwarf_version)); + sess.emit_err(UnsupportedDwarfVersion { dwarf_version }); } } if !sess.target.options.supported_split_debuginfo.contains(&sess.split_debuginfo()) && !sess.opts.unstable_opts.unstable_options { - sess.err(&format!( - "`-Csplit-debuginfo={}` is unstable on this platform", - sess.split_debuginfo() - )); + sess.emit_err(SplitDebugInfoUnstablePlatform { debuginfo: sess.split_debuginfo() }); } } @@ -1614,14 +1606,20 @@ fn early_error_handler(output: config::ErrorOutputType) -> rustc_errors::Handler rustc_errors::Handler::with_emitter(true, None, emitter) } +#[allow(rustc::untranslatable_diagnostic)] +#[allow(rustc::diagnostic_outside_of_impl)] pub fn early_error_no_abort(output: config::ErrorOutputType, msg: &str) -> ErrorGuaranteed { early_error_handler(output).struct_err(msg).emit() } +#[allow(rustc::untranslatable_diagnostic)] +#[allow(rustc::diagnostic_outside_of_impl)] pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! { early_error_handler(output).struct_fatal(msg).emit() } +#[allow(rustc::untranslatable_diagnostic)] +#[allow(rustc::diagnostic_outside_of_impl)] pub fn early_warn(output: config::ErrorOutputType, msg: &str) { early_error_handler(output).struct_warn(msg).emit() } diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs index bcaf209f84b65..ec334e5887ab7 100644 --- a/compiler/rustc_target/src/abi/mod.rs +++ b/compiler/rustc_target/src/abi/mod.rs @@ -7,7 +7,7 @@ use crate::spec::Target; use std::convert::{TryFrom, TryInto}; use std::fmt; use std::iter::Step; -use std::num::NonZeroUsize; +use std::num::{NonZeroUsize, ParseIntError}; use std::ops::{Add, AddAssign, Deref, Mul, RangeInclusive, Sub}; use std::str::FromStr; @@ -69,34 +69,46 @@ impl Default for TargetDataLayout { } } +pub enum TargetDataLayoutErrors<'a> { + InvalidAddressSpace { addr_space: &'a str, cause: &'a str, err: ParseIntError }, + InvalidBits { kind: &'a str, bit: &'a str, cause: &'a str, err: ParseIntError }, + MissingAlignment { cause: &'a str }, + InvalidAlignment { cause: &'a str, err: String }, + InconsistentTargetArchitecture { dl: &'a str, target: &'a str }, + InconsistentTargetPointerWidth { pointer_size: u64, target: u32 }, + InvalidBitsSize { err: String }, +} + impl TargetDataLayout { - pub fn parse(target: &Target) -> Result { + pub fn parse<'a>(target: &'a Target) -> Result> { // Parse an address space index from a string. - let parse_address_space = |s: &str, cause: &str| { + let parse_address_space = |s: &'a str, cause: &'a str| { s.parse::().map(AddressSpace).map_err(|err| { - format!("invalid address space `{}` for `{}` in \"data-layout\": {}", s, cause, err) + TargetDataLayoutErrors::InvalidAddressSpace { addr_space: s, cause, err } }) }; // Parse a bit count from a string. - let parse_bits = |s: &str, kind: &str, cause: &str| { - s.parse::().map_err(|err| { - format!("invalid {} `{}` for `{}` in \"data-layout\": {}", kind, s, cause, err) + let parse_bits = |s: &'a str, kind: &'a str, cause: &'a str| { + s.parse::().map_err(|err| TargetDataLayoutErrors::InvalidBits { + kind, + bit: s, + cause, + err, }) }; // Parse a size string. - let size = |s: &str, cause: &str| parse_bits(s, "size", cause).map(Size::from_bits); + let size = |s: &'a str, cause: &'a str| parse_bits(s, "size", cause).map(Size::from_bits); // Parse an alignment string. - let align = |s: &[&str], cause: &str| { + let align = |s: &[&'a str], cause: &'a str| { if s.is_empty() { - return Err(format!("missing alignment for `{}` in \"data-layout\"", cause)); + return Err(TargetDataLayoutErrors::MissingAlignment { cause }); } let align_from_bits = |bits| { - Align::from_bits(bits).map_err(|err| { - format!("invalid alignment for `{}` in \"data-layout\": {}", cause, err) - }) + Align::from_bits(bits) + .map_err(|err| TargetDataLayoutErrors::InvalidAlignment { cause, err }) }; let abi = parse_bits(s[0], "alignment", cause)?; let pref = s.get(1).map_or(Ok(abi), |pref| parse_bits(pref, "alignment", cause))?; @@ -158,25 +170,24 @@ impl TargetDataLayout { // Perform consistency checks against the Target information. if dl.endian != target.endian { - return Err(format!( - "inconsistent target specification: \"data-layout\" claims \ - architecture is {}-endian, while \"target-endian\" is `{}`", - dl.endian.as_str(), - target.endian.as_str(), - )); + return Err(TargetDataLayoutErrors::InconsistentTargetArchitecture { + dl: dl.endian.as_str(), + target: target.endian.as_str(), + }); } let target_pointer_width: u64 = target.pointer_width.into(); if dl.pointer_size.bits() != target_pointer_width { - return Err(format!( - "inconsistent target specification: \"data-layout\" claims \ - pointers are {}-bit, while \"target-pointer-width\" is `{}`", - dl.pointer_size.bits(), - target.pointer_width - )); + return Err(TargetDataLayoutErrors::InconsistentTargetPointerWidth { + pointer_size: dl.pointer_size.bits(), + target: target.pointer_width, + }); } - dl.c_enum_min_size = Integer::from_size(Size::from_bits(target.c_enum_min_bits))?; + dl.c_enum_min_size = match Integer::from_size(Size::from_bits(target.c_enum_min_bits)) { + Ok(bits) => bits, + Err(err) => return Err(TargetDataLayoutErrors::InvalidBitsSize { err }), + }; Ok(dl) } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index b012073f7719d..ecbeb9d79b118 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -25,8 +25,7 @@ use rustc_middle::hir::map; use rustc_middle::ty::{ self, suggest_arbitrary_trait_bound, suggest_constraining_type_param, AdtKind, DefIdTree, GeneratorDiagnosticData, GeneratorInteriorTypeCause, Infer, InferTy, IsSuggestable, - ProjectionPredicate, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, - TypeVisitable, + ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable, }; use rustc_middle::ty::{TypeAndMut, TypeckResults}; use rustc_session::Limit; @@ -174,7 +173,7 @@ pub trait InferCtxtExt<'tcx> { &self, err: &mut Diagnostic, trait_pred: ty::PolyTraitPredicate<'tcx>, - proj_pred: Option>, + associated_item: Option<(&'static str, Ty<'tcx>)>, body_id: hir::HirId, ); @@ -467,7 +466,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { &self, mut err: &mut Diagnostic, trait_pred: ty::PolyTraitPredicate<'tcx>, - proj_pred: Option>, + associated_ty: Option<(&'static str, Ty<'tcx>)>, body_id: hir::HirId, ) { let trait_pred = self.resolve_numeric_literals_with_default(trait_pred); @@ -604,21 +603,18 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { trait_pred.print_modifiers_and_trait_path().to_string() ); - if let Some(proj_pred) = proj_pred { - let ProjectionPredicate { projection_ty, term } = proj_pred.skip_binder(); - let item = self.tcx.associated_item(projection_ty.item_def_id); - + if let Some((name, term)) = associated_ty { // FIXME: this case overlaps with code in TyCtxt::note_and_explain_type_err. // That should be extracted into a helper function. if constraint.ends_with('>') { constraint = format!( - "{}, {}={}>", + "{}, {} = {}>", &constraint[..constraint.len() - 1], - item.name, + name, term ); } else { - constraint.push_str(&format!("<{}={}>", item.name, term)); + constraint.push_str(&format!("<{} = {}>", name, term)); } } @@ -648,7 +644,13 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { .. }) if !param_ty => { // Missing generic type parameter bound. - if suggest_arbitrary_trait_bound(self.tcx, generics, &mut err, trait_pred) { + if suggest_arbitrary_trait_bound( + self.tcx, + generics, + &mut err, + trait_pred, + associated_ty, + ) { return; } } diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 801063583e633..d66cf6d099ad5 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -2940,8 +2940,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // though we can easily give a hint that ought to be // relevant. err.note( - "lifetimes appearing in an associated type are not considered constrained", + "lifetimes appearing in an associated or opaque type are not considered constrained", ); + err.note("consider introducing a named lifetime parameter"); } err.emit(); diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index b07edd43c0716..a40478db96901 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -409,7 +409,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { rhs_span: opt_input_expr.map(|expr| expr.span), is_lit: opt_input_expr .map_or(false, |expr| matches!(expr.kind, ExprKind::Lit(_))), - output_pred: None, + output_ty: None, }, ), self.param_env, diff --git a/compiler/rustc_typeck/src/check/method/mod.rs b/compiler/rustc_typeck/src/check/method/mod.rs index c597efbe7468e..249e9c66ba72a 100644 --- a/compiler/rustc_typeck/src/check/method/mod.rs +++ b/compiler/rustc_typeck/src/check/method/mod.rs @@ -20,10 +20,7 @@ use rustc_hir::def_id::DefId; use rustc_infer::infer::{self, InferOk}; use rustc_middle::ty::subst::Subst; use rustc_middle::ty::subst::{InternalSubsts, SubstsRef}; -use rustc_middle::ty::{ - self, AssocKind, DefIdTree, GenericParamDefKind, ProjectionPredicate, ProjectionTy, - ToPredicate, Ty, TypeVisitable, -}; +use rustc_middle::ty::{self, DefIdTree, GenericParamDefKind, ToPredicate, Ty, TypeVisitable}; use rustc_span::symbol::Ident; use rustc_span::Span; use rustc_trait_selection::traits; @@ -337,22 +334,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Construct an obligation let poly_trait_ref = ty::Binder::dummy(trait_ref); - let opt_output_ty = - expected.only_has_type(self).and_then(|ty| (!ty.needs_infer()).then(|| ty)); - let opt_output_assoc_item = self.tcx.associated_items(trait_def_id).find_by_name_and_kind( - self.tcx, - Ident::from_str("Output"), - AssocKind::Type, - trait_def_id, - ); - let output_pred = - opt_output_ty.zip(opt_output_assoc_item).map(|(output_ty, output_assoc_item)| { - ty::Binder::dummy(ty::PredicateKind::Projection(ProjectionPredicate { - projection_ty: ProjectionTy { substs, item_def_id: output_assoc_item.def_id }, - term: output_ty.into(), - })) - .to_predicate(self.tcx) - }); + let output_ty = expected.only_has_type(self).and_then(|ty| (!ty.needs_infer()).then(|| ty)); ( traits::Obligation::new( @@ -363,7 +345,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { rhs_span: opt_input_expr.map(|expr| expr.span), is_lit: opt_input_expr .map_or(false, |expr| matches!(expr.kind, hir::ExprKind::Lit(_))), - output_pred, + output_ty, }, ), self.param_env, @@ -518,7 +500,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { rhs_span: opt_input_expr.map(|expr| expr.span), is_lit: opt_input_expr .map_or(false, |expr| matches!(expr.kind, hir::ExprKind::Lit(_))), - output_pred: None, + output_ty: None, }, ) } else { diff --git a/compiler/rustc_typeck/src/check/op.rs b/compiler/rustc_typeck/src/check/op.rs index 0d9dbb5bc11c2..4754717c29aba 100644 --- a/compiler/rustc_typeck/src/check/op.rs +++ b/compiler/rustc_typeck/src/check/op.rs @@ -11,9 +11,8 @@ use rustc_infer::traits::ObligationCauseCode; use rustc_middle::ty::adjustment::{ Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, }; -use rustc_middle::ty::{ - self, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitor, -}; +use rustc_middle::ty::print::with_no_trimmed_paths; +use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, TypeVisitable}; use rustc_span::source_map::Spanned; use rustc_span::symbol::{sym, Ident}; use rustc_span::Span; @@ -22,8 +21,6 @@ use rustc_trait_selection::traits::error_reporting::suggestions::InferCtxtExt as use rustc_trait_selection::traits::{FulfillmentError, TraitEngine, TraitEngineExt}; use rustc_type_ir::sty::TyKind::*; -use std::ops::ControlFlow; - impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Checks a `a = b` pub fn check_binop_assign( @@ -313,8 +310,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // error types are considered "builtin" Err(_) if lhs_ty.references_error() || rhs_ty.references_error() => self.tcx.ty_error(), Err(errors) => { - let source_map = self.tcx.sess.source_map(); - let (mut err, missing_trait, use_output) = match is_assign { + let (_, trait_def_id) = + lang_item_for_op(self.tcx, Op::Binary(op, is_assign), op.span); + let missing_trait = trait_def_id + .map(|def_id| with_no_trimmed_paths!(self.tcx.def_path_str(def_id))); + let (mut err, output_def_id) = match is_assign { IsAssign::Yes => { let mut err = struct_span_err!( self.tcx.sess, @@ -328,112 +328,63 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { lhs_expr.span, format!("cannot use `{}=` on type `{}`", op.node.as_str(), lhs_ty), ); - let missing_trait = match op.node { - hir::BinOpKind::Add => Some("std::ops::AddAssign"), - hir::BinOpKind::Sub => Some("std::ops::SubAssign"), - hir::BinOpKind::Mul => Some("std::ops::MulAssign"), - hir::BinOpKind::Div => Some("std::ops::DivAssign"), - hir::BinOpKind::Rem => Some("std::ops::RemAssign"), - hir::BinOpKind::BitAnd => Some("std::ops::BitAndAssign"), - hir::BinOpKind::BitXor => Some("std::ops::BitXorAssign"), - hir::BinOpKind::BitOr => Some("std::ops::BitOrAssign"), - hir::BinOpKind::Shl => Some("std::ops::ShlAssign"), - hir::BinOpKind::Shr => Some("std::ops::ShrAssign"), - _ => None, - }; self.note_unmet_impls_on_type(&mut err, errors); - (err, missing_trait, false) + (err, None) } IsAssign::No => { - let (message, missing_trait, use_output) = match op.node { - hir::BinOpKind::Add => ( - format!("cannot add `{rhs_ty}` to `{lhs_ty}`"), - Some("std::ops::Add"), - true, - ), - hir::BinOpKind::Sub => ( - format!("cannot subtract `{rhs_ty}` from `{lhs_ty}`"), - Some("std::ops::Sub"), - true, - ), - hir::BinOpKind::Mul => ( - format!("cannot multiply `{lhs_ty}` by `{rhs_ty}`"), - Some("std::ops::Mul"), - true, - ), - hir::BinOpKind::Div => ( - format!("cannot divide `{lhs_ty}` by `{rhs_ty}`"), - Some("std::ops::Div"), - true, - ), - hir::BinOpKind::Rem => ( - format!("cannot mod `{lhs_ty}` by `{rhs_ty}`"), - Some("std::ops::Rem"), - true, - ), - hir::BinOpKind::BitAnd => ( - format!("no implementation for `{lhs_ty} & {rhs_ty}`"), - Some("std::ops::BitAnd"), - true, - ), - hir::BinOpKind::BitXor => ( - format!("no implementation for `{lhs_ty} ^ {rhs_ty}`"), - Some("std::ops::BitXor"), - true, - ), - hir::BinOpKind::BitOr => ( - format!("no implementation for `{lhs_ty} | {rhs_ty}`"), - Some("std::ops::BitOr"), - true, - ), - hir::BinOpKind::Shl => ( - format!("no implementation for `{lhs_ty} << {rhs_ty}`"), - Some("std::ops::Shl"), - true, - ), - hir::BinOpKind::Shr => ( - format!("no implementation for `{lhs_ty} >> {rhs_ty}`"), - Some("std::ops::Shr"), - true, - ), - hir::BinOpKind::Eq | hir::BinOpKind::Ne => ( - format!( - "binary operation `{}` cannot be applied to type `{}`", - op.node.as_str(), - lhs_ty - ), - Some("std::cmp::PartialEq"), - false, - ), - hir::BinOpKind::Lt - | hir::BinOpKind::Le - | hir::BinOpKind::Gt - | hir::BinOpKind::Ge => ( - format!( - "binary operation `{}` cannot be applied to type `{}`", - op.node.as_str(), - lhs_ty - ), - Some("std::cmp::PartialOrd"), - false, - ), - _ => ( - format!( - "binary operation `{}` cannot be applied to type `{}`", - op.node.as_str(), - lhs_ty - ), - None, - false, + let message = match op.node { + hir::BinOpKind::Add => { + format!("cannot add `{rhs_ty}` to `{lhs_ty}`") + } + hir::BinOpKind::Sub => { + format!("cannot subtract `{rhs_ty}` from `{lhs_ty}`") + } + hir::BinOpKind::Mul => { + format!("cannot multiply `{lhs_ty}` by `{rhs_ty}`") + } + hir::BinOpKind::Div => { + format!("cannot divide `{lhs_ty}` by `{rhs_ty}`") + } + hir::BinOpKind::Rem => { + format!("cannot mod `{lhs_ty}` by `{rhs_ty}`") + } + hir::BinOpKind::BitAnd => { + format!("no implementation for `{lhs_ty} & {rhs_ty}`") + } + hir::BinOpKind::BitXor => { + format!("no implementation for `{lhs_ty} ^ {rhs_ty}`") + } + hir::BinOpKind::BitOr => { + format!("no implementation for `{lhs_ty} | {rhs_ty}`") + } + hir::BinOpKind::Shl => { + format!("no implementation for `{lhs_ty} << {rhs_ty}`") + } + hir::BinOpKind::Shr => { + format!("no implementation for `{lhs_ty} >> {rhs_ty}`") + } + _ => format!( + "binary operation `{}` cannot be applied to type `{}`", + op.node.as_str(), + lhs_ty ), }; + let output_def_id = trait_def_id.and_then(|def_id| { + self.tcx + .associated_item_def_ids(def_id) + .iter() + .find(|item_def_id| { + self.tcx.associated_item(*item_def_id).name == sym::Output + }) + .cloned() + }); let mut err = struct_span_err!(self.tcx.sess, op.span, E0369, "{message}"); if !lhs_expr.span.eq(&rhs_expr.span) { err.span_label(lhs_expr.span, lhs_ty.to_string()); err.span_label(rhs_expr.span, rhs_ty.to_string()); } self.note_unmet_impls_on_type(&mut err, errors); - (err, missing_trait, use_output) + (err, output_def_id) } }; @@ -448,24 +399,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) .is_ok() { - if let Ok(lstring) = source_map.span_to_snippet(lhs_expr.span) { - let msg = &format!( - "`{}{}` can be used on `{}`, you can dereference `{}`", - op.node.as_str(), - match is_assign { - IsAssign::Yes => "=", - IsAssign::No => "", - }, - lhs_deref_ty.peel_refs(), - lstring, - ); - err.span_suggestion_verbose( - lhs_expr.span.shrink_to_lo(), - msg, - "*", - rustc_errors::Applicability::MachineApplicable, - ); - } + let msg = &format!( + "`{}{}` can be used on `{}` if you dereference the left-hand side", + op.node.as_str(), + match is_assign { + IsAssign::Yes => "=", + IsAssign::No => "", + }, + lhs_deref_ty, + ); + err.span_suggestion_verbose( + lhs_expr.span.shrink_to_lo(), + msg, + "*", + rustc_errors::Applicability::MachineApplicable, + ); } }; @@ -514,9 +462,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } if let Some(missing_trait) = missing_trait { - let mut visitor = TypeParamVisitor(vec![]); - visitor.visit_ty(lhs_ty); - if op.node == hir::BinOpKind::Add && self.check_str_addition( lhs_expr, rhs_expr, lhs_ty, rhs_ty, &mut err, is_assign, op, @@ -525,7 +470,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // This has nothing here because it means we did string // concatenation (e.g., "Hello " + "World!"). This means // we don't want the note in the else clause to be emitted - } else if let [ty] = &visitor.0[..] { + } else if lhs_ty.has_param_types_or_consts() { // Look for a TraitPredicate in the Fulfillment errors, // and use it to generate a suggestion. // @@ -547,12 +492,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Some(trait_pred) = error.obligation.predicate.to_opt_poly_trait_pred() { - let proj_pred = match error.obligation.cause.code() { + let output_associated_item = match error.obligation.cause.code() + { ObligationCauseCode::BinOp { - output_pred: Some(output_pred), + output_ty: Some(output_ty), .. - } if use_output => { - output_pred.to_opt_poly_projection_pred() + } => { + // Make sure that we're attaching `Output = ..` to the right trait predicate + if let Some(output_def_id) = output_def_id + && let Some(trait_def_id) = trait_def_id + && self.tcx.parent(output_def_id) == trait_def_id + { + Some(("Output", *output_ty)) + } else { + None + } } _ => None, }; @@ -560,12 +514,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.suggest_restricting_param_bound( &mut err, trait_pred, - proj_pred, + output_associated_item, self.body_id, ); } } - } else if *ty != lhs_ty { + } else { // When we know that a missing bound is responsible, we don't show // this note as it is redundant. err.note(&format!( @@ -702,14 +656,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { format!("cannot apply unary operator `{}`", op.as_str()), ); - let mut visitor = TypeParamVisitor(vec![]); - visitor.visit_ty(operand_ty); - if let [_] = &visitor.0[..] && let ty::Param(_) = *operand_ty.kind() { - let predicates = errors - .iter() - .filter_map(|error| { - error.obligation.predicate.to_opt_poly_trait_pred() - }); + if operand_ty.has_param_types_or_consts() { + let predicates = errors.iter().filter_map(|error| { + error.obligation.predicate.to_opt_poly_trait_pred() + }); for pred in predicates { self.suggest_restricting_param_bound( &mut err, @@ -777,64 +727,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { op: Op, expected: Expectation<'tcx>, ) -> Result, Vec>> { - let lang = self.tcx.lang_items(); - let span = match op { Op::Binary(op, _) => op.span, Op::Unary(_, span) => span, }; - let (opname, trait_did) = if let Op::Binary(op, IsAssign::Yes) = op { - match op.node { - hir::BinOpKind::Add => (sym::add_assign, lang.add_assign_trait()), - hir::BinOpKind::Sub => (sym::sub_assign, lang.sub_assign_trait()), - hir::BinOpKind::Mul => (sym::mul_assign, lang.mul_assign_trait()), - hir::BinOpKind::Div => (sym::div_assign, lang.div_assign_trait()), - hir::BinOpKind::Rem => (sym::rem_assign, lang.rem_assign_trait()), - hir::BinOpKind::BitXor => (sym::bitxor_assign, lang.bitxor_assign_trait()), - hir::BinOpKind::BitAnd => (sym::bitand_assign, lang.bitand_assign_trait()), - hir::BinOpKind::BitOr => (sym::bitor_assign, lang.bitor_assign_trait()), - hir::BinOpKind::Shl => (sym::shl_assign, lang.shl_assign_trait()), - hir::BinOpKind::Shr => (sym::shr_assign, lang.shr_assign_trait()), - hir::BinOpKind::Lt - | hir::BinOpKind::Le - | hir::BinOpKind::Ge - | hir::BinOpKind::Gt - | hir::BinOpKind::Eq - | hir::BinOpKind::Ne - | hir::BinOpKind::And - | hir::BinOpKind::Or => { - span_bug!(span, "impossible assignment operation: {}=", op.node.as_str()) - } - } - } else if let Op::Binary(op, IsAssign::No) = op { - match op.node { - hir::BinOpKind::Add => (sym::add, lang.add_trait()), - hir::BinOpKind::Sub => (sym::sub, lang.sub_trait()), - hir::BinOpKind::Mul => (sym::mul, lang.mul_trait()), - hir::BinOpKind::Div => (sym::div, lang.div_trait()), - hir::BinOpKind::Rem => (sym::rem, lang.rem_trait()), - hir::BinOpKind::BitXor => (sym::bitxor, lang.bitxor_trait()), - hir::BinOpKind::BitAnd => (sym::bitand, lang.bitand_trait()), - hir::BinOpKind::BitOr => (sym::bitor, lang.bitor_trait()), - hir::BinOpKind::Shl => (sym::shl, lang.shl_trait()), - hir::BinOpKind::Shr => (sym::shr, lang.shr_trait()), - hir::BinOpKind::Lt => (sym::lt, lang.partial_ord_trait()), - hir::BinOpKind::Le => (sym::le, lang.partial_ord_trait()), - hir::BinOpKind::Ge => (sym::ge, lang.partial_ord_trait()), - hir::BinOpKind::Gt => (sym::gt, lang.partial_ord_trait()), - hir::BinOpKind::Eq => (sym::eq, lang.eq_trait()), - hir::BinOpKind::Ne => (sym::ne, lang.eq_trait()), - hir::BinOpKind::And | hir::BinOpKind::Or => { - span_bug!(span, "&& and || are not overloadable") - } - } - } else if let Op::Unary(hir::UnOp::Not, _) = op { - (sym::not, lang.not_trait()) - } else if let Op::Unary(hir::UnOp::Neg, _) = op { - (sym::neg, lang.neg_trait()) - } else { - bug!("lookup_op_method: op not supported: {:?}", op) - }; + let (opname, trait_did) = lang_item_for_op(self.tcx, op, span); debug!( "lookup_op_method(lhs_ty={:?}, op={:?}, opname={:?}, trait_did={:?})", @@ -895,6 +792,66 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } +fn lang_item_for_op( + tcx: TyCtxt<'_>, + op: Op, + span: Span, +) -> (rustc_span::Symbol, Option) { + let lang = tcx.lang_items(); + if let Op::Binary(op, IsAssign::Yes) = op { + match op.node { + hir::BinOpKind::Add => (sym::add_assign, lang.add_assign_trait()), + hir::BinOpKind::Sub => (sym::sub_assign, lang.sub_assign_trait()), + hir::BinOpKind::Mul => (sym::mul_assign, lang.mul_assign_trait()), + hir::BinOpKind::Div => (sym::div_assign, lang.div_assign_trait()), + hir::BinOpKind::Rem => (sym::rem_assign, lang.rem_assign_trait()), + hir::BinOpKind::BitXor => (sym::bitxor_assign, lang.bitxor_assign_trait()), + hir::BinOpKind::BitAnd => (sym::bitand_assign, lang.bitand_assign_trait()), + hir::BinOpKind::BitOr => (sym::bitor_assign, lang.bitor_assign_trait()), + hir::BinOpKind::Shl => (sym::shl_assign, lang.shl_assign_trait()), + hir::BinOpKind::Shr => (sym::shr_assign, lang.shr_assign_trait()), + hir::BinOpKind::Lt + | hir::BinOpKind::Le + | hir::BinOpKind::Ge + | hir::BinOpKind::Gt + | hir::BinOpKind::Eq + | hir::BinOpKind::Ne + | hir::BinOpKind::And + | hir::BinOpKind::Or => { + span_bug!(span, "impossible assignment operation: {}=", op.node.as_str()) + } + } + } else if let Op::Binary(op, IsAssign::No) = op { + match op.node { + hir::BinOpKind::Add => (sym::add, lang.add_trait()), + hir::BinOpKind::Sub => (sym::sub, lang.sub_trait()), + hir::BinOpKind::Mul => (sym::mul, lang.mul_trait()), + hir::BinOpKind::Div => (sym::div, lang.div_trait()), + hir::BinOpKind::Rem => (sym::rem, lang.rem_trait()), + hir::BinOpKind::BitXor => (sym::bitxor, lang.bitxor_trait()), + hir::BinOpKind::BitAnd => (sym::bitand, lang.bitand_trait()), + hir::BinOpKind::BitOr => (sym::bitor, lang.bitor_trait()), + hir::BinOpKind::Shl => (sym::shl, lang.shl_trait()), + hir::BinOpKind::Shr => (sym::shr, lang.shr_trait()), + hir::BinOpKind::Lt => (sym::lt, lang.partial_ord_trait()), + hir::BinOpKind::Le => (sym::le, lang.partial_ord_trait()), + hir::BinOpKind::Ge => (sym::ge, lang.partial_ord_trait()), + hir::BinOpKind::Gt => (sym::gt, lang.partial_ord_trait()), + hir::BinOpKind::Eq => (sym::eq, lang.eq_trait()), + hir::BinOpKind::Ne => (sym::ne, lang.eq_trait()), + hir::BinOpKind::And | hir::BinOpKind::Or => { + span_bug!(span, "&& and || are not overloadable") + } + } + } else if let Op::Unary(hir::UnOp::Not, _) = op { + (sym::not, lang.not_trait()) + } else if let Op::Unary(hir::UnOp::Neg, _) = op { + (sym::neg, lang.neg_trait()) + } else { + bug!("lookup_op_method: op not supported: {:?}", op) + } +} + // Binary operator categories. These categories summarize the behavior // with respect to the builtin operations supported. enum BinOpCategory { @@ -1017,17 +974,6 @@ fn is_builtin_binop<'tcx>(lhs: Ty<'tcx>, rhs: Ty<'tcx>, op: hir::BinOp) -> bool } } -struct TypeParamVisitor<'tcx>(Vec>); - -impl<'tcx> TypeVisitor<'tcx> for TypeParamVisitor<'tcx> { - fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { - if let ty::Param(_) = ty.kind() { - self.0.push(ty); - } - ty.super_visit_with(self) - } -} - struct TypeParamEraser<'a, 'tcx>(&'a FnCtxt<'a, 'tcx>, Span); impl<'tcx> TypeFolder<'tcx> for TypeParamEraser<'_, 'tcx> { diff --git a/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs b/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs index 802b867a301aa..03ad3ca826146 100644 --- a/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs +++ b/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs @@ -21,7 +21,7 @@ use rustc_span::source_map; #[no_mangle] fn __rustc_plugin_registrar(reg: &mut Registry) { reg.lint_store.register_lints(&[&MISSING_ALLOWED_ATTR]); - reg.lint_store.register_late_pass(|| Box::new(MissingAllowedAttrPass)); + reg.lint_store.register_late_pass(|_| Box::new(MissingAllowedAttrPass)); } declare_lint! { diff --git a/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs b/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs index bc153faa8925a..a3b570ad8c40c 100644 --- a/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs +++ b/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs @@ -74,7 +74,7 @@ fn __rustc_plugin_registrar(reg: &mut Registry) { &CRATE_NOT_GREY, &CRATE_NOT_GREEN, ]); - reg.lint_store.register_late_pass(|| Box::new(PassOkay)); - reg.lint_store.register_late_pass(|| Box::new(PassRedBlue)); - reg.lint_store.register_late_pass(|| Box::new(PassGreyGreen)); + reg.lint_store.register_late_pass(|_| Box::new(PassOkay)); + reg.lint_store.register_late_pass(|_| Box::new(PassRedBlue)); + reg.lint_store.register_late_pass(|_| Box::new(PassGreyGreen)); } diff --git a/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs b/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs index 29d0abfbe5388..0b1534939b778 100644 --- a/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs +++ b/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs @@ -39,5 +39,5 @@ impl<'tcx> LateLintPass<'tcx> for Pass { #[no_mangle] fn __rustc_plugin_registrar(reg: &mut Registry) { reg.lint_store.register_lints(&[&CRATE_NOT_OKAY]); - reg.lint_store.register_late_pass(|| Box::new(Pass)); + reg.lint_store.register_late_pass(|_| Box::new(Pass)); } diff --git a/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs b/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs index 691cfb97d9218..2d41b5f30e975 100644 --- a/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs +++ b/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs @@ -36,7 +36,7 @@ impl<'tcx> LateLintPass<'tcx> for Pass { #[no_mangle] fn __rustc_plugin_registrar(reg: &mut Registry) { reg.lint_store.register_lints(&[&TEST_LINT, &PLEASE_LINT]); - reg.lint_store.register_late_pass(|| Box::new(Pass)); + reg.lint_store.register_late_pass(|_| Box::new(Pass)); reg.lint_store.register_group( true, "lint_me", diff --git a/src/test/ui/associated-types/issue-62200.rs b/src/test/ui/associated-types/issue-62200.rs index 9d18690e96049..499bbd6b6fad2 100644 --- a/src/test/ui/associated-types/issue-62200.rs +++ b/src/test/ui/associated-types/issue-62200.rs @@ -10,6 +10,7 @@ impl T<'_> for S { fn foo(x: impl Fn(>::A) -> >::A) {} //~^ ERROR binding for associated type `Output` references an anonymous lifetime -//~^^ NOTE lifetimes appearing in an associated type are not considered constrained +//~| NOTE lifetimes appearing in an associated or opaque type are not considered constrained +//~| NOTE consider introducing a named lifetime parameter fn main() {} diff --git a/src/test/ui/associated-types/issue-62200.stderr b/src/test/ui/associated-types/issue-62200.stderr index f14cd81fdfe1f..04f0728f58ea8 100644 --- a/src/test/ui/associated-types/issue-62200.stderr +++ b/src/test/ui/associated-types/issue-62200.stderr @@ -4,7 +4,8 @@ error[E0582]: binding for associated type `Output` references an anonymous lifet LL | fn foo(x: impl Fn(>::A) -> >::A) {} | ^^^^^^^^^^^^^^^ | - = note: lifetimes appearing in an associated type are not considered constrained + = note: lifetimes appearing in an associated or opaque type are not considered constrained + = note: consider introducing a named lifetime parameter error: aborting due to previous error diff --git a/src/test/ui/binop/binary-op-on-double-ref.stderr b/src/test/ui/binop/binary-op-on-double-ref.stderr index 1651f70d5cde7..34826d2f4bf7a 100644 --- a/src/test/ui/binop/binary-op-on-double-ref.stderr +++ b/src/test/ui/binop/binary-op-on-double-ref.stderr @@ -6,7 +6,7 @@ LL | x % 2 == 0 | | | &&{integer} | -help: `%` can be used on `{integer}`, you can dereference `x` +help: `%` can be used on `&{integer}` if you dereference the left-hand side | LL | *x % 2 == 0 | + diff --git a/src/test/ui/generic-associated-types/missing-bounds.fixed b/src/test/ui/generic-associated-types/missing-bounds.fixed index 2315810a47ace..ee758f19ec105 100644 --- a/src/test/ui/generic-associated-types/missing-bounds.fixed +++ b/src/test/ui/generic-associated-types/missing-bounds.fixed @@ -24,7 +24,7 @@ impl> Add for C { struct D(B); -impl> Add for D { +impl> Add for D { type Output = Self; fn add(self, rhs: Self) -> Self { diff --git a/src/test/ui/generic-associated-types/missing-bounds.stderr b/src/test/ui/generic-associated-types/missing-bounds.stderr index 138c642dd7952..c913483a8747c 100644 --- a/src/test/ui/generic-associated-types/missing-bounds.stderr +++ b/src/test/ui/generic-associated-types/missing-bounds.stderr @@ -66,8 +66,8 @@ LL | Self(self.0 + rhs.0) | help: consider restricting type parameter `B` | -LL | impl> Add for D { - | +++++++++++++++++++++++++ +LL | impl> Add for D { + | +++++++++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/missing-bounds.rs:42:14 diff --git a/src/test/ui/issues/issue-47511.stderr b/src/test/ui/issues/issue-47511.stderr index 5b84f7ed62c3a..9998ee0e8d0c6 100644 --- a/src/test/ui/issues/issue-47511.stderr +++ b/src/test/ui/issues/issue-47511.stderr @@ -4,7 +4,8 @@ error[E0581]: return type references an anonymous lifetime, which is not constra LL | fn f(_: X) -> X { | ^ | - = note: lifetimes appearing in an associated type are not considered constrained + = note: lifetimes appearing in an associated or opaque type are not considered constrained + = note: consider introducing a named lifetime parameter error[E0581]: return type references lifetime `'a`, which is not constrained by the fn input types --> $DIR/issue-47511.rs:12:23 diff --git a/src/test/ui/parser/issue-101477-enum.fixed b/src/test/ui/parser/issue-101477-enum.fixed new file mode 100644 index 0000000000000..1dfeae22aea2f --- /dev/null +++ b/src/test/ui/parser/issue-101477-enum.fixed @@ -0,0 +1,10 @@ +// run-rustfix + +#[allow(dead_code)] +enum Demo { + A = 1, + B = 2 //~ ERROR unexpected `==` + //~^ expected item, found `==` +} + +fn main() {} diff --git a/src/test/ui/parser/issue-101477-enum.rs b/src/test/ui/parser/issue-101477-enum.rs new file mode 100644 index 0000000000000..ea7051d69a4c7 --- /dev/null +++ b/src/test/ui/parser/issue-101477-enum.rs @@ -0,0 +1,10 @@ +// run-rustfix + +#[allow(dead_code)] +enum Demo { + A = 1, + B == 2 //~ ERROR unexpected `==` + //~^ expected item, found `==` +} + +fn main() {} diff --git a/src/test/ui/parser/issue-101477-enum.stderr b/src/test/ui/parser/issue-101477-enum.stderr new file mode 100644 index 0000000000000..bffc881bdc84b --- /dev/null +++ b/src/test/ui/parser/issue-101477-enum.stderr @@ -0,0 +1,14 @@ +error: unexpected `==` + --> $DIR/issue-101477-enum.rs:6:7 + | +LL | B == 2 + | ^^ help: try using `=` instead + +error: expected item, found `==` + --> $DIR/issue-101477-enum.rs:6:7 + | +LL | B == 2 + | ^^ expected item + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/parser/issue-101477-let.fixed b/src/test/ui/parser/issue-101477-let.fixed new file mode 100644 index 0000000000000..9989ad81524e1 --- /dev/null +++ b/src/test/ui/parser/issue-101477-let.fixed @@ -0,0 +1,6 @@ +// run-rustfix + +fn main() { + let x = 2; //~ ERROR unexpected `==` + println!("x: {}", x) +} diff --git a/src/test/ui/parser/issue-101477-let.rs b/src/test/ui/parser/issue-101477-let.rs new file mode 100644 index 0000000000000..8b0e8bee1799d --- /dev/null +++ b/src/test/ui/parser/issue-101477-let.rs @@ -0,0 +1,6 @@ +// run-rustfix + +fn main() { + let x == 2; //~ ERROR unexpected `==` + println!("x: {}", x) +} diff --git a/src/test/ui/parser/issue-101477-let.stderr b/src/test/ui/parser/issue-101477-let.stderr new file mode 100644 index 0000000000000..1b30d4b17861a --- /dev/null +++ b/src/test/ui/parser/issue-101477-let.stderr @@ -0,0 +1,8 @@ +error: unexpected `==` + --> $DIR/issue-101477-let.rs:4:11 + | +LL | let x == 2; + | ^^ help: try using `=` instead + +error: aborting due to previous error + diff --git a/src/test/ui/suggestions/issue-97677.fixed b/src/test/ui/suggestions/issue-97677.fixed index 73ca9f97b43a3..1e7569fa45106 100644 --- a/src/test/ui/suggestions/issue-97677.fixed +++ b/src/test/ui/suggestions/issue-97677.fixed @@ -1,6 +1,6 @@ // run-rustfix -fn add_ten>(n: N) -> N { +fn add_ten>(n: N) -> N { n + 10 //~^ ERROR cannot add `{integer}` to `N` } diff --git a/src/test/ui/suggestions/issue-97677.stderr b/src/test/ui/suggestions/issue-97677.stderr index 069b184ac636c..575d79267f20d 100644 --- a/src/test/ui/suggestions/issue-97677.stderr +++ b/src/test/ui/suggestions/issue-97677.stderr @@ -8,8 +8,8 @@ LL | n + 10 | help: consider restricting type parameter `N` | -LL | fn add_ten>(n: N) -> N { - | ++++++++++++++++++++++++++++++ +LL | fn add_ten>(n: N) -> N { + | ++++++++++++++++++++++++++++++++ error: aborting due to previous error diff --git a/src/test/ui/suggestions/restrict-type-not-param.rs b/src/test/ui/suggestions/restrict-type-not-param.rs new file mode 100644 index 0000000000000..60f5ba45c268d --- /dev/null +++ b/src/test/ui/suggestions/restrict-type-not-param.rs @@ -0,0 +1,12 @@ +use std::ops::Add; + +struct Wrapper(T); + +trait Foo {} + +fn qux(a: Wrapper, b: T) -> T { + a + b + //~^ ERROR cannot add `T` to `Wrapper` +} + +fn main() {} diff --git a/src/test/ui/suggestions/restrict-type-not-param.stderr b/src/test/ui/suggestions/restrict-type-not-param.stderr new file mode 100644 index 0000000000000..e7d9c5ecbe482 --- /dev/null +++ b/src/test/ui/suggestions/restrict-type-not-param.stderr @@ -0,0 +1,26 @@ +error[E0369]: cannot add `T` to `Wrapper` + --> $DIR/restrict-type-not-param.rs:8:7 + | +LL | a + b + | - ^ - T + | | + | Wrapper + | +note: an implementation of `Add<_>` might be missing for `Wrapper` + --> $DIR/restrict-type-not-param.rs:3:1 + | +LL | struct Wrapper(T); + | ^^^^^^^^^^^^^^^^^ must implement `Add<_>` +note: the following trait must be implemented + --> $SRC_DIR/core/src/ops/arith.rs:LL:COL + | +LL | pub trait Add { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | fn qux(a: Wrapper, b: T) -> T where Wrapper: Add { + | ++++++++++++++++++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0369`. diff --git a/src/test/ui/traits/resolution-in-overloaded-op.stderr b/src/test/ui/traits/resolution-in-overloaded-op.stderr index 34fae64e4d20f..fe5e1d6d2854d 100644 --- a/src/test/ui/traits/resolution-in-overloaded-op.stderr +++ b/src/test/ui/traits/resolution-in-overloaded-op.stderr @@ -8,8 +8,8 @@ LL | a * b | help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement | -LL | fn foo>(a: &T, b: f64) -> f64 where &T: Mul { - | ++++++++++++++++++ +LL | fn foo>(a: &T, b: f64) -> f64 where &T: Mul { + | ++++++++++++++++++++++++++++++++ error: aborting due to previous error diff --git a/src/test/ui/type-alias-impl-trait/constrain_inputs.rs b/src/test/ui/type-alias-impl-trait/constrain_inputs.rs index c32174288ee68..03fb64b7b94d7 100644 --- a/src/test/ui/type-alias-impl-trait/constrain_inputs.rs +++ b/src/test/ui/type-alias-impl-trait/constrain_inputs.rs @@ -1,17 +1,33 @@ -// check-pass - #![feature(type_alias_impl_trait)] -mod foo { +mod lifetime_params { type Ty<'a> = impl Sized; fn defining(s: &str) -> Ty<'_> { s } fn execute(ty: Ty<'_>) -> &str { todo!() } + //~^ ERROR return type references an anonymous lifetime, which is not constrained by the fn input types + + type BadFnSig = fn(Ty<'_>) -> &str; + //~^ ERROR return type references an anonymous lifetime, which is not constrained by the fn input types + type BadTraitRef = dyn Fn(Ty<'_>) -> &str; + //~^ ERROR binding for associated type `Output` references an anonymous lifetime } -mod bar { +mod lifetime_params_2 { type Ty<'a> = impl FnOnce() -> &'a str; fn defining(s: &str) -> Ty<'_> { move || s } fn execute(ty: Ty<'_>) -> &str { ty() } + //~^ ERROR return type references an anonymous lifetime, which is not constrained by the fn input types +} + +// regression test for https://github.com/rust-lang/rust/issues/97104 +mod type_params { + type Ty = impl Sized; + fn define(s: T) -> Ty { s } + + type BadFnSig = fn(Ty<&str>) -> &str; + //~^ ERROR return type references an anonymous lifetime, which is not constrained by the fn input types + type BadTraitRef = dyn Fn(Ty<&str>) -> &str; + //~^ ERROR binding for associated type `Output` references an anonymous lifetime } fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/constrain_inputs.stderr b/src/test/ui/type-alias-impl-trait/constrain_inputs.stderr new file mode 100644 index 0000000000000..93953fd06d1fd --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/constrain_inputs.stderr @@ -0,0 +1,58 @@ +error[E0581]: return type references an anonymous lifetime, which is not constrained by the fn input types + --> $DIR/constrain_inputs.rs:6:31 + | +LL | fn execute(ty: Ty<'_>) -> &str { todo!() } + | ^^^^ + | + = note: lifetimes appearing in an associated or opaque type are not considered constrained + = note: consider introducing a named lifetime parameter + +error[E0581]: return type references an anonymous lifetime, which is not constrained by the fn input types + --> $DIR/constrain_inputs.rs:9:35 + | +LL | type BadFnSig = fn(Ty<'_>) -> &str; + | ^^^^ + | + = note: lifetimes appearing in an associated or opaque type are not considered constrained + = note: consider introducing a named lifetime parameter + +error[E0582]: binding for associated type `Output` references an anonymous lifetime, which does not appear in the trait input types + --> $DIR/constrain_inputs.rs:11:42 + | +LL | type BadTraitRef = dyn Fn(Ty<'_>) -> &str; + | ^^^^ + | + = note: lifetimes appearing in an associated or opaque type are not considered constrained + = note: consider introducing a named lifetime parameter + +error[E0581]: return type references an anonymous lifetime, which is not constrained by the fn input types + --> $DIR/constrain_inputs.rs:18:31 + | +LL | fn execute(ty: Ty<'_>) -> &str { ty() } + | ^^^^ + | + = note: lifetimes appearing in an associated or opaque type are not considered constrained + = note: consider introducing a named lifetime parameter + +error[E0581]: return type references an anonymous lifetime, which is not constrained by the fn input types + --> $DIR/constrain_inputs.rs:27:37 + | +LL | type BadFnSig = fn(Ty<&str>) -> &str; + | ^^^^ + | + = note: lifetimes appearing in an associated or opaque type are not considered constrained + = note: consider introducing a named lifetime parameter + +error[E0582]: binding for associated type `Output` references an anonymous lifetime, which does not appear in the trait input types + --> $DIR/constrain_inputs.rs:29:44 + | +LL | type BadTraitRef = dyn Fn(Ty<&str>) -> &str; + | ^^^^ + | + = note: lifetimes appearing in an associated or opaque type are not considered constrained + = note: consider introducing a named lifetime parameter + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0581, E0582. +For more information about an error, try `rustc --explain E0581`. diff --git a/src/test/ui/type-alias-impl-trait/constrain_inputs_unsound.rs b/src/test/ui/type-alias-impl-trait/constrain_inputs_unsound.rs new file mode 100644 index 0000000000000..3bae0f1730994 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/constrain_inputs_unsound.rs @@ -0,0 +1,31 @@ +#![feature(type_alias_impl_trait)] + +trait Static: 'static {} +impl Static for () {} + +type Gal = impl Static; +fn _defining() -> Gal {} + +trait Callable { type Output; } + +/// We can infer `>::Output: 'static`, +/// because we know `C: 'static` and `Arg: 'static`, +fn box_str(s: C::Output) -> Box + 'static> +where + Arg: Static, + C: ?Sized + Callable + 'static, + C::Output: AsRef, +{ + Box::new(s) +} + +fn extend_lifetime(s: &str) -> Box + 'static> { + type MalformedTy = dyn for<'a> Callable, Output = &'a str>; + //~^ ERROR binding for associated type `Output` references lifetime `'a` + box_str::(s) +} + +fn main() { + let extended = extend_lifetime(&String::from("hello")); + println!("{}", extended.as_ref().as_ref()); +} diff --git a/src/test/ui/type-alias-impl-trait/constrain_inputs_unsound.stderr b/src/test/ui/type-alias-impl-trait/constrain_inputs_unsound.stderr new file mode 100644 index 0000000000000..d5fc46cb1f596 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/constrain_inputs_unsound.stderr @@ -0,0 +1,9 @@ +error[E0582]: binding for associated type `Output` references lifetime `'a`, which does not appear in the trait input types + --> $DIR/constrain_inputs_unsound.rs:23:58 + | +LL | type MalformedTy = dyn for<'a> Callable, Output = &'a str>; + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0582`. diff --git a/src/test/ui/typeck/assign-non-lval-derefmut.stderr b/src/test/ui/typeck/assign-non-lval-derefmut.stderr index a6fcdfe21f481..e394cf8206ede 100644 --- a/src/test/ui/typeck/assign-non-lval-derefmut.stderr +++ b/src/test/ui/typeck/assign-non-lval-derefmut.stderr @@ -19,7 +19,7 @@ LL | x.lock().unwrap() += 1; | | | cannot use `+=` on type `MutexGuard<'_, usize>` | -help: `+=` can be used on `usize`, you can dereference `x.lock().unwrap()` +help: `+=` can be used on `usize` if you dereference the left-hand side | LL | *x.lock().unwrap() += 1; | + @@ -47,7 +47,7 @@ LL | y += 1; | | | cannot use `+=` on type `MutexGuard<'_, usize>` | -help: `+=` can be used on `usize`, you can dereference `y` +help: `+=` can be used on `usize` if you dereference the left-hand side | LL | *y += 1; | + diff --git a/src/test/ui/typeck/assign-non-lval-mut-ref.stderr b/src/test/ui/typeck/assign-non-lval-mut-ref.stderr index be2e9fe95e871..cbdc960baab8e 100644 --- a/src/test/ui/typeck/assign-non-lval-mut-ref.stderr +++ b/src/test/ui/typeck/assign-non-lval-mut-ref.stderr @@ -19,7 +19,7 @@ LL | x.last_mut().unwrap() += 1; | | | cannot use `+=` on type `&mut usize` | -help: `+=` can be used on `usize`, you can dereference `x.last_mut().unwrap()` +help: `+=` can be used on `usize` if you dereference the left-hand side | LL | *x.last_mut().unwrap() += 1; | + @@ -45,7 +45,7 @@ LL | y += 1; | | | cannot use `+=` on type `&mut usize` | -help: `+=` can be used on `usize`, you can dereference `y` +help: `+=` can be used on `usize` if you dereference the left-hand side | LL | *y += 1; | + diff --git a/src/tools/clippy/clippy_dev/src/new_lint.rs b/src/tools/clippy/clippy_dev/src/new_lint.rs index be05e67d724df..331b76484b8a5 100644 --- a/src/tools/clippy/clippy_dev/src/new_lint.rs +++ b/src/tools/clippy/clippy_dev/src/new_lint.rs @@ -120,15 +120,17 @@ fn add_lint(lint: &LintData<'_>, enable_msrv: bool) -> io::Result<()> { let new_lint = if enable_msrv { format!( - "store.register_{lint_pass}_pass(move || Box::new({module_name}::{camel_name}::new(msrv)));\n ", + "store.register_{lint_pass}_pass(move |{ctor_arg}| Box::new({module_name}::{camel_name}::new(msrv)));\n ", lint_pass = lint.pass, + ctor_arg = if lint.pass == "late" { "_" } else { "" }, module_name = lint.name, camel_name = to_camel_case(lint.name), ) } else { format!( - "store.register_{lint_pass}_pass(|| Box::new({module_name}::{camel_name}));\n ", + "store.register_{lint_pass}_pass(|{ctor_arg}| Box::new({module_name}::{camel_name}));\n ", lint_pass = lint.pass, + ctor_arg = if lint.pass == "late" { "_" } else { "" }, module_name = lint.name, camel_name = to_camel_case(lint.name), ) diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs index dfdaf90f09f48..c70aa79ac8dcf 100644 --- a/src/tools/clippy/clippy_lints/src/lib.rs +++ b/src/tools/clippy/clippy_lints/src/lib.rs @@ -523,7 +523,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: #[cfg(feature = "internal")] { if std::env::var("ENABLE_METADATA_COLLECTION").eq(&Ok("1".to_string())) { - store.register_late_pass(|| Box::new(utils::internal_lints::metadata_collector::MetadataCollector::new())); + store.register_late_pass(|_| Box::new(utils::internal_lints::metadata_collector::MetadataCollector::new())); return; } } @@ -533,69 +533,69 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: { store.register_early_pass(|| Box::new(utils::internal_lints::ClippyLintsInternal)); store.register_early_pass(|| Box::new(utils::internal_lints::ProduceIce)); - store.register_late_pass(|| Box::new(utils::internal_lints::CollapsibleCalls)); - store.register_late_pass(|| Box::new(utils::internal_lints::CompilerLintFunctions::new())); - store.register_late_pass(|| Box::new(utils::internal_lints::IfChainStyle)); - store.register_late_pass(|| Box::new(utils::internal_lints::InvalidPaths)); - store.register_late_pass(|| Box::new(utils::internal_lints::InterningDefinedSymbol::default())); - store.register_late_pass(|| Box::new(utils::internal_lints::LintWithoutLintPass::default())); - store.register_late_pass(|| Box::new(utils::internal_lints::MatchTypeOnDiagItem)); - store.register_late_pass(|| Box::new(utils::internal_lints::OuterExpnDataPass)); - store.register_late_pass(|| Box::new(utils::internal_lints::MsrvAttrImpl)); + store.register_late_pass(|_| Box::new(utils::internal_lints::CollapsibleCalls)); + store.register_late_pass(|_| Box::new(utils::internal_lints::CompilerLintFunctions::new())); + store.register_late_pass(|_| Box::new(utils::internal_lints::IfChainStyle)); + store.register_late_pass(|_| Box::new(utils::internal_lints::InvalidPaths)); + store.register_late_pass(|_| Box::new(utils::internal_lints::InterningDefinedSymbol::default())); + store.register_late_pass(|_| Box::new(utils::internal_lints::LintWithoutLintPass::default())); + store.register_late_pass(|_| Box::new(utils::internal_lints::MatchTypeOnDiagItem)); + store.register_late_pass(|_| Box::new(utils::internal_lints::OuterExpnDataPass)); + store.register_late_pass(|_| Box::new(utils::internal_lints::MsrvAttrImpl)); } let arithmetic_allowed = conf.arithmetic_allowed.clone(); - store.register_late_pass(move || Box::new(operators::arithmetic::Arithmetic::new(arithmetic_allowed.clone()))); - store.register_late_pass(|| Box::new(utils::dump_hir::DumpHir)); - store.register_late_pass(|| Box::new(utils::author::Author)); + store.register_late_pass(move |_| Box::new(operators::arithmetic::Arithmetic::new(arithmetic_allowed.clone()))); + store.register_late_pass(|_| Box::new(utils::dump_hir::DumpHir)); + store.register_late_pass(|_| Box::new(utils::author::Author)); let await_holding_invalid_types = conf.await_holding_invalid_types.clone(); - store.register_late_pass(move || { + store.register_late_pass(move |_| { Box::new(await_holding_invalid::AwaitHolding::new( await_holding_invalid_types.clone(), )) }); - store.register_late_pass(|| Box::new(serde_api::SerdeApi)); + store.register_late_pass(|_| Box::new(serde_api::SerdeApi)); let vec_box_size_threshold = conf.vec_box_size_threshold; let type_complexity_threshold = conf.type_complexity_threshold; let avoid_breaking_exported_api = conf.avoid_breaking_exported_api; - store.register_late_pass(move || { + store.register_late_pass(move |_| { Box::new(types::Types::new( vec_box_size_threshold, type_complexity_threshold, avoid_breaking_exported_api, )) }); - store.register_late_pass(|| Box::new(booleans::NonminimalBool)); - store.register_late_pass(|| Box::new(enum_clike::UnportableVariant)); - store.register_late_pass(|| Box::new(float_literal::FloatLiteral)); - store.register_late_pass(|| Box::new(ptr::Ptr)); - store.register_late_pass(|| Box::new(needless_bool::NeedlessBool)); - store.register_late_pass(|| Box::new(needless_bool::BoolComparison)); - store.register_late_pass(|| Box::new(needless_for_each::NeedlessForEach)); - store.register_late_pass(|| Box::new(misc::MiscLints)); - store.register_late_pass(|| Box::new(eta_reduction::EtaReduction)); - store.register_late_pass(|| Box::new(mut_mut::MutMut)); - store.register_late_pass(|| Box::new(mut_reference::UnnecessaryMutPassed)); - store.register_late_pass(|| Box::new(len_zero::LenZero)); - store.register_late_pass(|| Box::new(attrs::Attributes)); - store.register_late_pass(|| Box::new(blocks_in_if_conditions::BlocksInIfConditions)); - store.register_late_pass(|| Box::new(unicode::Unicode)); - store.register_late_pass(|| Box::new(uninit_vec::UninitVec)); - store.register_late_pass(|| Box::new(unit_return_expecting_ord::UnitReturnExpectingOrd)); - store.register_late_pass(|| Box::new(strings::StringAdd)); - store.register_late_pass(|| Box::new(implicit_return::ImplicitReturn)); - store.register_late_pass(|| Box::new(implicit_saturating_sub::ImplicitSaturatingSub)); - store.register_late_pass(|| Box::new(default_numeric_fallback::DefaultNumericFallback)); - store.register_late_pass(|| Box::new(inconsistent_struct_constructor::InconsistentStructConstructor)); - store.register_late_pass(|| Box::new(non_octal_unix_permissions::NonOctalUnixPermissions)); + store.register_late_pass(|_| Box::new(booleans::NonminimalBool)); + store.register_late_pass(|_| Box::new(enum_clike::UnportableVariant)); + store.register_late_pass(|_| Box::new(float_literal::FloatLiteral)); + store.register_late_pass(|_| Box::new(ptr::Ptr)); + store.register_late_pass(|_| Box::new(needless_bool::NeedlessBool)); + store.register_late_pass(|_| Box::new(needless_bool::BoolComparison)); + store.register_late_pass(|_| Box::new(needless_for_each::NeedlessForEach)); + store.register_late_pass(|_| Box::new(misc::MiscLints)); + store.register_late_pass(|_| Box::new(eta_reduction::EtaReduction)); + store.register_late_pass(|_| Box::new(mut_mut::MutMut)); + store.register_late_pass(|_| Box::new(mut_reference::UnnecessaryMutPassed)); + store.register_late_pass(|_| Box::new(len_zero::LenZero)); + store.register_late_pass(|_| Box::new(attrs::Attributes)); + store.register_late_pass(|_| Box::new(blocks_in_if_conditions::BlocksInIfConditions)); + store.register_late_pass(|_| Box::new(unicode::Unicode)); + store.register_late_pass(|_| Box::new(uninit_vec::UninitVec)); + store.register_late_pass(|_| Box::new(unit_return_expecting_ord::UnitReturnExpectingOrd)); + store.register_late_pass(|_| Box::new(strings::StringAdd)); + store.register_late_pass(|_| Box::new(implicit_return::ImplicitReturn)); + store.register_late_pass(|_| Box::new(implicit_saturating_sub::ImplicitSaturatingSub)); + store.register_late_pass(|_| Box::new(default_numeric_fallback::DefaultNumericFallback)); + store.register_late_pass(|_| Box::new(inconsistent_struct_constructor::InconsistentStructConstructor)); + store.register_late_pass(|_| Box::new(non_octal_unix_permissions::NonOctalUnixPermissions)); store.register_early_pass(|| Box::new(unnecessary_self_imports::UnnecessarySelfImports)); let msrv = read_msrv(conf, sess); let avoid_breaking_exported_api = conf.avoid_breaking_exported_api; let allow_expect_in_tests = conf.allow_expect_in_tests; let allow_unwrap_in_tests = conf.allow_unwrap_in_tests; - store.register_late_pass(move || Box::new(approx_const::ApproxConstant::new(msrv))); - store.register_late_pass(move || { + store.register_late_pass(move |_| Box::new(approx_const::ApproxConstant::new(msrv))); + store.register_late_pass(move |_| { Box::new(methods::Methods::new( avoid_breaking_exported_api, msrv, @@ -603,74 +603,74 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: allow_unwrap_in_tests, )) }); - store.register_late_pass(move || Box::new(matches::Matches::new(msrv))); + store.register_late_pass(move |_| Box::new(matches::Matches::new(msrv))); store.register_early_pass(move || Box::new(manual_non_exhaustive::ManualNonExhaustiveStruct::new(msrv))); - store.register_late_pass(move || Box::new(manual_non_exhaustive::ManualNonExhaustiveEnum::new(msrv))); - store.register_late_pass(move || Box::new(manual_strip::ManualStrip::new(msrv))); + store.register_late_pass(move |_| Box::new(manual_non_exhaustive::ManualNonExhaustiveEnum::new(msrv))); + store.register_late_pass(move |_| Box::new(manual_strip::ManualStrip::new(msrv))); store.register_early_pass(move || Box::new(redundant_static_lifetimes::RedundantStaticLifetimes::new(msrv))); store.register_early_pass(move || Box::new(redundant_field_names::RedundantFieldNames::new(msrv))); - store.register_late_pass(move || Box::new(checked_conversions::CheckedConversions::new(msrv))); - store.register_late_pass(move || Box::new(mem_replace::MemReplace::new(msrv))); - store.register_late_pass(move || Box::new(ranges::Ranges::new(msrv))); - store.register_late_pass(move || Box::new(from_over_into::FromOverInto::new(msrv))); - store.register_late_pass(move || Box::new(use_self::UseSelf::new(msrv))); - store.register_late_pass(move || Box::new(missing_const_for_fn::MissingConstForFn::new(msrv))); - store.register_late_pass(move || Box::new(needless_question_mark::NeedlessQuestionMark)); - store.register_late_pass(move || Box::new(casts::Casts::new(msrv))); + store.register_late_pass(move |_| Box::new(checked_conversions::CheckedConversions::new(msrv))); + store.register_late_pass(move |_| Box::new(mem_replace::MemReplace::new(msrv))); + store.register_late_pass(move |_| Box::new(ranges::Ranges::new(msrv))); + store.register_late_pass(move |_| Box::new(from_over_into::FromOverInto::new(msrv))); + store.register_late_pass(move |_| Box::new(use_self::UseSelf::new(msrv))); + store.register_late_pass(move |_| Box::new(missing_const_for_fn::MissingConstForFn::new(msrv))); + store.register_late_pass(move |_| Box::new(needless_question_mark::NeedlessQuestionMark)); + store.register_late_pass(move |_| Box::new(casts::Casts::new(msrv))); store.register_early_pass(move || Box::new(unnested_or_patterns::UnnestedOrPatterns::new(msrv))); - store.register_late_pass(|| Box::new(size_of_in_element_count::SizeOfInElementCount)); - store.register_late_pass(|| Box::new(same_name_method::SameNameMethod)); + store.register_late_pass(|_| Box::new(size_of_in_element_count::SizeOfInElementCount)); + store.register_late_pass(|_| Box::new(same_name_method::SameNameMethod)); let max_suggested_slice_pattern_length = conf.max_suggested_slice_pattern_length; - store.register_late_pass(move || { + store.register_late_pass(move |_| { Box::new(index_refutable_slice::IndexRefutableSlice::new( max_suggested_slice_pattern_length, msrv, )) }); - store.register_late_pass(|| Box::new(shadow::Shadow::default())); - store.register_late_pass(|| Box::new(unit_types::UnitTypes)); - store.register_late_pass(|| Box::new(loops::Loops)); - store.register_late_pass(|| Box::new(main_recursion::MainRecursion::default())); - store.register_late_pass(|| Box::new(lifetimes::Lifetimes)); - store.register_late_pass(|| Box::new(entry::HashMapPass)); - store.register_late_pass(|| Box::new(minmax::MinMaxPass)); - store.register_late_pass(|| Box::new(zero_div_zero::ZeroDiv)); - store.register_late_pass(|| Box::new(mutex_atomic::Mutex)); - store.register_late_pass(|| Box::new(needless_update::NeedlessUpdate)); - store.register_late_pass(|| Box::new(needless_borrowed_ref::NeedlessBorrowedRef)); - store.register_late_pass(|| Box::new(borrow_deref_ref::BorrowDerefRef)); - store.register_late_pass(|| Box::new(no_effect::NoEffect)); - store.register_late_pass(|| Box::new(temporary_assignment::TemporaryAssignment)); - store.register_late_pass(move || Box::new(transmute::Transmute::new(msrv))); + store.register_late_pass(|_| Box::new(shadow::Shadow::default())); + store.register_late_pass(|_| Box::new(unit_types::UnitTypes)); + store.register_late_pass(|_| Box::new(loops::Loops)); + store.register_late_pass(|_| Box::new(main_recursion::MainRecursion::default())); + store.register_late_pass(|_| Box::new(lifetimes::Lifetimes)); + store.register_late_pass(|_| Box::new(entry::HashMapPass)); + store.register_late_pass(|_| Box::new(minmax::MinMaxPass)); + store.register_late_pass(|_| Box::new(zero_div_zero::ZeroDiv)); + store.register_late_pass(|_| Box::new(mutex_atomic::Mutex)); + store.register_late_pass(|_| Box::new(needless_update::NeedlessUpdate)); + store.register_late_pass(|_| Box::new(needless_borrowed_ref::NeedlessBorrowedRef)); + store.register_late_pass(|_| Box::new(borrow_deref_ref::BorrowDerefRef)); + store.register_late_pass(|_| Box::new(no_effect::NoEffect)); + store.register_late_pass(|_| Box::new(temporary_assignment::TemporaryAssignment)); + store.register_late_pass(move |_| Box::new(transmute::Transmute::new(msrv))); let cognitive_complexity_threshold = conf.cognitive_complexity_threshold; - store.register_late_pass(move || { + store.register_late_pass(move |_| { Box::new(cognitive_complexity::CognitiveComplexity::new( cognitive_complexity_threshold, )) }); let too_large_for_stack = conf.too_large_for_stack; - store.register_late_pass(move || Box::new(escape::BoxedLocal { too_large_for_stack })); - store.register_late_pass(move || Box::new(vec::UselessVec { too_large_for_stack })); - store.register_late_pass(|| Box::new(panic_unimplemented::PanicUnimplemented)); - store.register_late_pass(|| Box::new(strings::StringLitAsBytes)); - store.register_late_pass(|| Box::new(derive::Derive)); - store.register_late_pass(|| Box::new(derivable_impls::DerivableImpls)); - store.register_late_pass(|| Box::new(drop_forget_ref::DropForgetRef)); - store.register_late_pass(|| Box::new(empty_enum::EmptyEnum)); - store.register_late_pass(|| Box::new(invalid_upcast_comparisons::InvalidUpcastComparisons)); - store.register_late_pass(|| Box::new(regex::Regex)); - store.register_late_pass(|| Box::new(copies::CopyAndPaste)); - store.register_late_pass(|| Box::new(copy_iterator::CopyIterator)); - store.register_late_pass(|| Box::new(format::UselessFormat)); - store.register_late_pass(|| Box::new(swap::Swap)); - store.register_late_pass(|| Box::new(overflow_check_conditional::OverflowCheckConditional)); - store.register_late_pass(|| Box::new(new_without_default::NewWithoutDefault::default())); + store.register_late_pass(move |_| Box::new(escape::BoxedLocal { too_large_for_stack })); + store.register_late_pass(move |_| Box::new(vec::UselessVec { too_large_for_stack })); + store.register_late_pass(|_| Box::new(panic_unimplemented::PanicUnimplemented)); + store.register_late_pass(|_| Box::new(strings::StringLitAsBytes)); + store.register_late_pass(|_| Box::new(derive::Derive)); + store.register_late_pass(|_| Box::new(derivable_impls::DerivableImpls)); + store.register_late_pass(|_| Box::new(drop_forget_ref::DropForgetRef)); + store.register_late_pass(|_| Box::new(empty_enum::EmptyEnum)); + store.register_late_pass(|_| Box::new(invalid_upcast_comparisons::InvalidUpcastComparisons)); + store.register_late_pass(|_| Box::new(regex::Regex)); + store.register_late_pass(|_| Box::new(copies::CopyAndPaste)); + store.register_late_pass(|_| Box::new(copy_iterator::CopyIterator)); + store.register_late_pass(|_| Box::new(format::UselessFormat)); + store.register_late_pass(|_| Box::new(swap::Swap)); + store.register_late_pass(|_| Box::new(overflow_check_conditional::OverflowCheckConditional)); + store.register_late_pass(|_| Box::new(new_without_default::NewWithoutDefault::default())); let disallowed_names = conf.disallowed_names.iter().cloned().collect::>(); - store.register_late_pass(move || Box::new(disallowed_names::DisallowedNames::new(disallowed_names.clone()))); + store.register_late_pass(move |_| Box::new(disallowed_names::DisallowedNames::new(disallowed_names.clone()))); let too_many_arguments_threshold = conf.too_many_arguments_threshold; let too_many_lines_threshold = conf.too_many_lines_threshold; let large_error_threshold = conf.large_error_threshold; - store.register_late_pass(move || { + store.register_late_pass(move |_| { Box::new(functions::Functions::new( too_many_arguments_threshold, too_many_lines_threshold, @@ -678,73 +678,73 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: )) }); let doc_valid_idents = conf.doc_valid_idents.iter().cloned().collect::>(); - store.register_late_pass(move || Box::new(doc::DocMarkdown::new(doc_valid_idents.clone()))); - store.register_late_pass(|| Box::new(neg_multiply::NegMultiply)); - store.register_late_pass(|| Box::new(mem_forget::MemForget)); - store.register_late_pass(|| Box::new(let_if_seq::LetIfSeq)); - store.register_late_pass(|| Box::new(mixed_read_write_in_expression::EvalOrderDependence)); - store.register_late_pass(|| Box::new(missing_doc::MissingDoc::new())); - store.register_late_pass(|| Box::new(missing_inline::MissingInline)); - store.register_late_pass(move || Box::new(exhaustive_items::ExhaustiveItems)); - store.register_late_pass(|| Box::new(match_result_ok::MatchResultOk)); - store.register_late_pass(|| Box::new(partialeq_ne_impl::PartialEqNeImpl)); - store.register_late_pass(|| Box::new(unused_io_amount::UnusedIoAmount)); + store.register_late_pass(move |_| Box::new(doc::DocMarkdown::new(doc_valid_idents.clone()))); + store.register_late_pass(|_| Box::new(neg_multiply::NegMultiply)); + store.register_late_pass(|_| Box::new(mem_forget::MemForget)); + store.register_late_pass(|_| Box::new(let_if_seq::LetIfSeq)); + store.register_late_pass(|_| Box::new(mixed_read_write_in_expression::EvalOrderDependence)); + store.register_late_pass(|_| Box::new(missing_doc::MissingDoc::new())); + store.register_late_pass(|_| Box::new(missing_inline::MissingInline)); + store.register_late_pass(move |_| Box::new(exhaustive_items::ExhaustiveItems)); + store.register_late_pass(|_| Box::new(match_result_ok::MatchResultOk)); + store.register_late_pass(|_| Box::new(partialeq_ne_impl::PartialEqNeImpl)); + store.register_late_pass(|_| Box::new(unused_io_amount::UnusedIoAmount)); let enum_variant_size_threshold = conf.enum_variant_size_threshold; - store.register_late_pass(move || Box::new(large_enum_variant::LargeEnumVariant::new(enum_variant_size_threshold))); - store.register_late_pass(|| Box::new(explicit_write::ExplicitWrite)); - store.register_late_pass(|| Box::new(needless_pass_by_value::NeedlessPassByValue)); + store.register_late_pass(move |_| Box::new(large_enum_variant::LargeEnumVariant::new(enum_variant_size_threshold))); + store.register_late_pass(|_| Box::new(explicit_write::ExplicitWrite)); + store.register_late_pass(|_| Box::new(needless_pass_by_value::NeedlessPassByValue)); let pass_by_ref_or_value = pass_by_ref_or_value::PassByRefOrValue::new( conf.trivial_copy_size_limit, conf.pass_by_value_size_limit, conf.avoid_breaking_exported_api, &sess.target, ); - store.register_late_pass(move || Box::new(pass_by_ref_or_value)); - store.register_late_pass(|| Box::new(ref_option_ref::RefOptionRef)); - store.register_late_pass(|| Box::new(infinite_iter::InfiniteIter)); - store.register_late_pass(|| Box::new(inline_fn_without_body::InlineFnWithoutBody)); - store.register_late_pass(|| Box::new(useless_conversion::UselessConversion::default())); - store.register_late_pass(|| Box::new(implicit_hasher::ImplicitHasher)); - store.register_late_pass(|| Box::new(fallible_impl_from::FallibleImplFrom)); - store.register_late_pass(|| Box::new(question_mark::QuestionMark)); + store.register_late_pass(move |_| Box::new(pass_by_ref_or_value)); + store.register_late_pass(|_| Box::new(ref_option_ref::RefOptionRef)); + store.register_late_pass(|_| Box::new(infinite_iter::InfiniteIter)); + store.register_late_pass(|_| Box::new(inline_fn_without_body::InlineFnWithoutBody)); + store.register_late_pass(|_| Box::new(useless_conversion::UselessConversion::default())); + store.register_late_pass(|_| Box::new(implicit_hasher::ImplicitHasher)); + store.register_late_pass(|_| Box::new(fallible_impl_from::FallibleImplFrom)); + store.register_late_pass(|_| Box::new(question_mark::QuestionMark)); store.register_early_pass(|| Box::new(suspicious_operation_groupings::SuspiciousOperationGroupings)); - store.register_late_pass(|| Box::new(suspicious_trait_impl::SuspiciousImpl)); - store.register_late_pass(|| Box::new(map_unit_fn::MapUnit)); - store.register_late_pass(|| Box::new(inherent_impl::MultipleInherentImpl)); - store.register_late_pass(|| Box::new(neg_cmp_op_on_partial_ord::NoNegCompOpForPartialOrd)); - store.register_late_pass(|| Box::new(unwrap::Unwrap)); - store.register_late_pass(|| Box::new(indexing_slicing::IndexingSlicing)); - store.register_late_pass(|| Box::new(non_copy_const::NonCopyConst)); - store.register_late_pass(|| Box::new(ptr_offset_with_cast::PtrOffsetWithCast)); - store.register_late_pass(|| Box::new(redundant_clone::RedundantClone)); - store.register_late_pass(|| Box::new(slow_vector_initialization::SlowVectorInit)); - store.register_late_pass(move || Box::new(unnecessary_wraps::UnnecessaryWraps::new(avoid_breaking_exported_api))); - store.register_late_pass(|| Box::new(assertions_on_constants::AssertionsOnConstants)); - store.register_late_pass(|| Box::new(assertions_on_result_states::AssertionsOnResultStates)); - store.register_late_pass(|| Box::new(inherent_to_string::InherentToString)); + store.register_late_pass(|_| Box::new(suspicious_trait_impl::SuspiciousImpl)); + store.register_late_pass(|_| Box::new(map_unit_fn::MapUnit)); + store.register_late_pass(|_| Box::new(inherent_impl::MultipleInherentImpl)); + store.register_late_pass(|_| Box::new(neg_cmp_op_on_partial_ord::NoNegCompOpForPartialOrd)); + store.register_late_pass(|_| Box::new(unwrap::Unwrap)); + store.register_late_pass(|_| Box::new(indexing_slicing::IndexingSlicing)); + store.register_late_pass(|_| Box::new(non_copy_const::NonCopyConst)); + store.register_late_pass(|_| Box::new(ptr_offset_with_cast::PtrOffsetWithCast)); + store.register_late_pass(|_| Box::new(redundant_clone::RedundantClone)); + store.register_late_pass(|_| Box::new(slow_vector_initialization::SlowVectorInit)); + store.register_late_pass(move |_| Box::new(unnecessary_wraps::UnnecessaryWraps::new(avoid_breaking_exported_api))); + store.register_late_pass(|_| Box::new(assertions_on_constants::AssertionsOnConstants)); + store.register_late_pass(|_| Box::new(assertions_on_result_states::AssertionsOnResultStates)); + store.register_late_pass(|_| Box::new(inherent_to_string::InherentToString)); let max_trait_bounds = conf.max_trait_bounds; - store.register_late_pass(move || Box::new(trait_bounds::TraitBounds::new(max_trait_bounds))); - store.register_late_pass(|| Box::new(comparison_chain::ComparisonChain)); - store.register_late_pass(|| Box::new(mut_key::MutableKeyType)); + store.register_late_pass(move |_| Box::new(trait_bounds::TraitBounds::new(max_trait_bounds))); + store.register_late_pass(|_| Box::new(comparison_chain::ComparisonChain)); + store.register_late_pass(|_| Box::new(mut_key::MutableKeyType)); store.register_early_pass(|| Box::new(reference::DerefAddrOf)); store.register_early_pass(|| Box::new(double_parens::DoubleParens)); - store.register_late_pass(|| Box::new(format_impl::FormatImpl::new())); + store.register_late_pass(|_| Box::new(format_impl::FormatImpl::new())); store.register_early_pass(|| Box::new(unsafe_removed_from_name::UnsafeNameRemoval)); store.register_early_pass(|| Box::new(else_if_without_else::ElseIfWithoutElse)); store.register_early_pass(|| Box::new(int_plus_one::IntPlusOne)); store.register_early_pass(|| Box::new(formatting::Formatting)); store.register_early_pass(|| Box::new(misc_early::MiscEarlyLints)); store.register_early_pass(|| Box::new(redundant_closure_call::RedundantClosureCall)); - store.register_late_pass(|| Box::new(redundant_closure_call::RedundantClosureCall)); + store.register_late_pass(|_| Box::new(redundant_closure_call::RedundantClosureCall)); store.register_early_pass(|| Box::new(unused_unit::UnusedUnit)); - store.register_late_pass(|| Box::new(returns::Return)); + store.register_late_pass(|_| Box::new(returns::Return)); store.register_early_pass(|| Box::new(collapsible_if::CollapsibleIf)); store.register_early_pass(|| Box::new(items_after_statements::ItemsAfterStatements)); store.register_early_pass(|| Box::new(precedence::Precedence)); - store.register_late_pass(|| Box::new(needless_parens_on_range_literals::NeedlessParensOnRangeLiterals)); + store.register_late_pass(|_| Box::new(needless_parens_on_range_literals::NeedlessParensOnRangeLiterals)); store.register_early_pass(|| Box::new(needless_continue::NeedlessContinue)); store.register_early_pass(|| Box::new(redundant_else::RedundantElse)); - store.register_late_pass(|| Box::new(create_dir::CreateDir)); + store.register_late_pass(|_| Box::new(create_dir::CreateDir)); store.register_early_pass(|| Box::new(needless_arbitrary_self_type::NeedlessArbitrarySelfType)); let literal_representation_lint_fraction_readability = conf.unreadable_literal_lint_fractions; store.register_early_pass(move || { @@ -759,7 +759,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: )) }); let enum_variant_name_threshold = conf.enum_variant_name_threshold; - store.register_late_pass(move || { + store.register_late_pass(move |_| { Box::new(enum_variants::EnumVariantNames::new( enum_variant_name_threshold, avoid_breaking_exported_api, @@ -767,23 +767,23 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: }); store.register_early_pass(|| Box::new(tabs_in_doc_comments::TabsInDocComments)); let upper_case_acronyms_aggressive = conf.upper_case_acronyms_aggressive; - store.register_late_pass(move || { + store.register_late_pass(move |_| { Box::new(upper_case_acronyms::UpperCaseAcronyms::new( avoid_breaking_exported_api, upper_case_acronyms_aggressive, )) }); - store.register_late_pass(|| Box::new(default::Default::default())); - store.register_late_pass(move || Box::new(unused_self::UnusedSelf::new(avoid_breaking_exported_api))); - store.register_late_pass(|| Box::new(mutable_debug_assertion::DebugAssertWithMutCall)); - store.register_late_pass(|| Box::new(exit::Exit)); - store.register_late_pass(|| Box::new(to_digit_is_some::ToDigitIsSome)); + store.register_late_pass(|_| Box::new(default::Default::default())); + store.register_late_pass(move |_| Box::new(unused_self::UnusedSelf::new(avoid_breaking_exported_api))); + store.register_late_pass(|_| Box::new(mutable_debug_assertion::DebugAssertWithMutCall)); + store.register_late_pass(|_| Box::new(exit::Exit)); + store.register_late_pass(|_| Box::new(to_digit_is_some::ToDigitIsSome)); let array_size_threshold = conf.array_size_threshold; - store.register_late_pass(move || Box::new(large_stack_arrays::LargeStackArrays::new(array_size_threshold))); - store.register_late_pass(move || Box::new(large_const_arrays::LargeConstArrays::new(array_size_threshold))); - store.register_late_pass(|| Box::new(floating_point_arithmetic::FloatingPointArithmetic)); + store.register_late_pass(move |_| Box::new(large_stack_arrays::LargeStackArrays::new(array_size_threshold))); + store.register_late_pass(move |_| Box::new(large_const_arrays::LargeConstArrays::new(array_size_threshold))); + store.register_late_pass(|_| Box::new(floating_point_arithmetic::FloatingPointArithmetic)); store.register_early_pass(|| Box::new(as_conversions::AsConversions)); - store.register_late_pass(|| Box::new(let_underscore::LetUnderscore)); + store.register_late_pass(|_| Box::new(let_underscore::LetUnderscore)); store.register_early_pass(|| Box::new(single_component_path_imports::SingleComponentPathImports)); let max_fn_params_bools = conf.max_fn_params_bools; let max_struct_bools = conf.max_struct_bools; @@ -795,17 +795,17 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: }); store.register_early_pass(|| Box::new(option_env_unwrap::OptionEnvUnwrap)); let warn_on_all_wildcard_imports = conf.warn_on_all_wildcard_imports; - store.register_late_pass(move || Box::new(wildcard_imports::WildcardImports::new(warn_on_all_wildcard_imports))); - store.register_late_pass(|| Box::new(redundant_pub_crate::RedundantPubCrate::default())); - store.register_late_pass(|| Box::new(unnamed_address::UnnamedAddress)); - store.register_late_pass(move || Box::new(dereference::Dereferencing::new(msrv))); - store.register_late_pass(|| Box::new(option_if_let_else::OptionIfLetElse)); - store.register_late_pass(|| Box::new(future_not_send::FutureNotSend)); - store.register_late_pass(|| Box::new(if_let_mutex::IfLetMutex)); - store.register_late_pass(|| Box::new(if_not_else::IfNotElse)); - store.register_late_pass(|| Box::new(equatable_if_let::PatternEquality)); - store.register_late_pass(|| Box::new(manual_async_fn::ManualAsyncFn)); - store.register_late_pass(|| Box::new(panic_in_result_fn::PanicInResultFn)); + store.register_late_pass(move |_| Box::new(wildcard_imports::WildcardImports::new(warn_on_all_wildcard_imports))); + store.register_late_pass(|_| Box::new(redundant_pub_crate::RedundantPubCrate::default())); + store.register_late_pass(|_| Box::new(unnamed_address::UnnamedAddress)); + store.register_late_pass(move |_| Box::new(dereference::Dereferencing::new(msrv))); + store.register_late_pass(|_| Box::new(option_if_let_else::OptionIfLetElse)); + store.register_late_pass(|_| Box::new(future_not_send::FutureNotSend)); + store.register_late_pass(|_| Box::new(if_let_mutex::IfLetMutex)); + store.register_late_pass(|_| Box::new(if_not_else::IfNotElse)); + store.register_late_pass(|_| Box::new(equatable_if_let::PatternEquality)); + store.register_late_pass(|_| Box::new(manual_async_fn::ManualAsyncFn)); + store.register_late_pass(|_| Box::new(panic_in_result_fn::PanicInResultFn)); let single_char_binding_names_threshold = conf.single_char_binding_names_threshold; store.register_early_pass(move || { Box::new(non_expressive_names::NonExpressiveNames { @@ -814,92 +814,92 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: }); let macro_matcher = conf.standard_macro_braces.iter().cloned().collect::>(); store.register_early_pass(move || Box::new(nonstandard_macro_braces::MacroBraces::new(¯o_matcher))); - store.register_late_pass(|| Box::new(macro_use::MacroUseImports::default())); - store.register_late_pass(|| Box::new(pattern_type_mismatch::PatternTypeMismatch)); - store.register_late_pass(|| Box::new(unwrap_in_result::UnwrapInResult)); - store.register_late_pass(|| Box::new(semicolon_if_nothing_returned::SemicolonIfNothingReturned)); - store.register_late_pass(|| Box::new(async_yields_async::AsyncYieldsAsync)); + store.register_late_pass(|_| Box::new(macro_use::MacroUseImports::default())); + store.register_late_pass(|_| Box::new(pattern_type_mismatch::PatternTypeMismatch)); + store.register_late_pass(|_| Box::new(unwrap_in_result::UnwrapInResult)); + store.register_late_pass(|_| Box::new(semicolon_if_nothing_returned::SemicolonIfNothingReturned)); + store.register_late_pass(|_| Box::new(async_yields_async::AsyncYieldsAsync)); let disallowed_methods = conf.disallowed_methods.clone(); - store.register_late_pass(move || Box::new(disallowed_methods::DisallowedMethods::new(disallowed_methods.clone()))); + store.register_late_pass(move |_| Box::new(disallowed_methods::DisallowedMethods::new(disallowed_methods.clone()))); store.register_early_pass(|| Box::new(asm_syntax::InlineAsmX86AttSyntax)); store.register_early_pass(|| Box::new(asm_syntax::InlineAsmX86IntelSyntax)); - store.register_late_pass(|| Box::new(empty_drop::EmptyDrop)); - store.register_late_pass(|| Box::new(strings::StrToString)); - store.register_late_pass(|| Box::new(strings::StringToString)); - store.register_late_pass(|| Box::new(zero_sized_map_values::ZeroSizedMapValues)); - store.register_late_pass(|| Box::new(vec_init_then_push::VecInitThenPush::default())); - store.register_late_pass(|| Box::new(redundant_slicing::RedundantSlicing)); - store.register_late_pass(|| Box::new(from_str_radix_10::FromStrRadix10)); - store.register_late_pass(move || Box::new(if_then_some_else_none::IfThenSomeElseNone::new(msrv))); - store.register_late_pass(|| Box::new(bool_assert_comparison::BoolAssertComparison)); + store.register_late_pass(|_| Box::new(empty_drop::EmptyDrop)); + store.register_late_pass(|_| Box::new(strings::StrToString)); + store.register_late_pass(|_| Box::new(strings::StringToString)); + store.register_late_pass(|_| Box::new(zero_sized_map_values::ZeroSizedMapValues)); + store.register_late_pass(|_| Box::new(vec_init_then_push::VecInitThenPush::default())); + store.register_late_pass(|_| Box::new(redundant_slicing::RedundantSlicing)); + store.register_late_pass(|_| Box::new(from_str_radix_10::FromStrRadix10)); + store.register_late_pass(move |_| Box::new(if_then_some_else_none::IfThenSomeElseNone::new(msrv))); + store.register_late_pass(|_| Box::new(bool_assert_comparison::BoolAssertComparison)); store.register_early_pass(move || Box::new(module_style::ModStyle)); - store.register_late_pass(|| Box::new(unused_async::UnusedAsync)); + store.register_late_pass(|_| Box::new(unused_async::UnusedAsync)); let disallowed_types = conf.disallowed_types.clone(); - store.register_late_pass(move || Box::new(disallowed_types::DisallowedTypes::new(disallowed_types.clone()))); + store.register_late_pass(move |_| Box::new(disallowed_types::DisallowedTypes::new(disallowed_types.clone()))); let import_renames = conf.enforced_import_renames.clone(); - store.register_late_pass(move || { + store.register_late_pass(move |_| { Box::new(missing_enforced_import_rename::ImportRename::new( import_renames.clone(), )) }); let scripts = conf.allowed_scripts.clone(); store.register_early_pass(move || Box::new(disallowed_script_idents::DisallowedScriptIdents::new(&scripts))); - store.register_late_pass(|| Box::new(strlen_on_c_strings::StrlenOnCStrings)); - store.register_late_pass(move || Box::new(self_named_constructors::SelfNamedConstructors)); - store.register_late_pass(move || Box::new(iter_not_returning_iterator::IterNotReturningIterator)); - store.register_late_pass(move || Box::new(manual_assert::ManualAssert)); + store.register_late_pass(|_| Box::new(strlen_on_c_strings::StrlenOnCStrings)); + store.register_late_pass(move |_| Box::new(self_named_constructors::SelfNamedConstructors)); + store.register_late_pass(move |_| Box::new(iter_not_returning_iterator::IterNotReturningIterator)); + store.register_late_pass(move |_| Box::new(manual_assert::ManualAssert)); let enable_raw_pointer_heuristic_for_send = conf.enable_raw_pointer_heuristic_for_send; - store.register_late_pass(move || { + store.register_late_pass(move |_| { Box::new(non_send_fields_in_send_ty::NonSendFieldInSendTy::new( enable_raw_pointer_heuristic_for_send, )) }); - store.register_late_pass(move || Box::new(undocumented_unsafe_blocks::UndocumentedUnsafeBlocks)); - store.register_late_pass(move || Box::new(format_args::FormatArgs)); - store.register_late_pass(|| Box::new(trailing_empty_array::TrailingEmptyArray)); + store.register_late_pass(move |_| Box::new(undocumented_unsafe_blocks::UndocumentedUnsafeBlocks)); + store.register_late_pass(move |_| Box::new(format_args::FormatArgs)); + store.register_late_pass(|_| Box::new(trailing_empty_array::TrailingEmptyArray)); store.register_early_pass(|| Box::new(octal_escapes::OctalEscapes)); - store.register_late_pass(|| Box::new(needless_late_init::NeedlessLateInit)); - store.register_late_pass(|| Box::new(return_self_not_must_use::ReturnSelfNotMustUse)); - store.register_late_pass(|| Box::new(init_numbered_fields::NumberedFields)); + store.register_late_pass(|_| Box::new(needless_late_init::NeedlessLateInit)); + store.register_late_pass(|_| Box::new(return_self_not_must_use::ReturnSelfNotMustUse)); + store.register_late_pass(|_| Box::new(init_numbered_fields::NumberedFields)); store.register_early_pass(|| Box::new(single_char_lifetime_names::SingleCharLifetimeNames)); - store.register_late_pass(move || Box::new(manual_bits::ManualBits::new(msrv))); - store.register_late_pass(|| Box::new(default_union_representation::DefaultUnionRepresentation)); + store.register_late_pass(move |_| Box::new(manual_bits::ManualBits::new(msrv))); + store.register_late_pass(|_| Box::new(default_union_representation::DefaultUnionRepresentation)); store.register_early_pass(|| Box::new(doc_link_with_quotes::DocLinkWithQuotes)); - store.register_late_pass(|| Box::new(only_used_in_recursion::OnlyUsedInRecursion::default())); + store.register_late_pass(|_| Box::new(only_used_in_recursion::OnlyUsedInRecursion::default())); let allow_dbg_in_tests = conf.allow_dbg_in_tests; - store.register_late_pass(move || Box::new(dbg_macro::DbgMacro::new(allow_dbg_in_tests))); + store.register_late_pass(move |_| Box::new(dbg_macro::DbgMacro::new(allow_dbg_in_tests))); let cargo_ignore_publish = conf.cargo_ignore_publish; - store.register_late_pass(move || { + store.register_late_pass(move |_| { Box::new(cargo::Cargo { ignore_publish: cargo_ignore_publish, }) }); store.register_early_pass(|| Box::new(crate_in_macro_def::CrateInMacroDef)); store.register_early_pass(|| Box::new(empty_structs_with_brackets::EmptyStructsWithBrackets)); - store.register_late_pass(|| Box::new(unnecessary_owned_empty_strings::UnnecessaryOwnedEmptyStrings)); + store.register_late_pass(|_| Box::new(unnecessary_owned_empty_strings::UnnecessaryOwnedEmptyStrings)); store.register_early_pass(|| Box::new(pub_use::PubUse)); - store.register_late_pass(|| Box::new(format_push_string::FormatPushString)); + store.register_late_pass(|_| Box::new(format_push_string::FormatPushString)); let max_include_file_size = conf.max_include_file_size; - store.register_late_pass(move || Box::new(large_include_file::LargeIncludeFile::new(max_include_file_size))); - store.register_late_pass(|| Box::new(strings::TrimSplitWhitespace)); - store.register_late_pass(|| Box::new(rc_clone_in_vec_init::RcCloneInVecInit)); + store.register_late_pass(move |_| Box::new(large_include_file::LargeIncludeFile::new(max_include_file_size))); + store.register_late_pass(|_| Box::new(strings::TrimSplitWhitespace)); + store.register_late_pass(|_| Box::new(rc_clone_in_vec_init::RcCloneInVecInit)); store.register_early_pass(|| Box::new(duplicate_mod::DuplicateMod::default())); store.register_early_pass(|| Box::new(unused_rounding::UnusedRounding)); store.register_early_pass(move || Box::new(almost_complete_letter_range::AlmostCompleteLetterRange::new(msrv))); - store.register_late_pass(|| Box::new(swap_ptr_to_ref::SwapPtrToRef)); - store.register_late_pass(|| Box::new(mismatching_type_param_order::TypeParamMismatch)); - store.register_late_pass(|| Box::new(read_zero_byte_vec::ReadZeroByteVec)); - store.register_late_pass(|| Box::new(default_instead_of_iter_empty::DefaultIterEmpty)); - store.register_late_pass(move || Box::new(manual_rem_euclid::ManualRemEuclid::new(msrv))); - store.register_late_pass(move || Box::new(manual_retain::ManualRetain::new(msrv))); + store.register_late_pass(|_| Box::new(swap_ptr_to_ref::SwapPtrToRef)); + store.register_late_pass(|_| Box::new(mismatching_type_param_order::TypeParamMismatch)); + store.register_late_pass(|_| Box::new(read_zero_byte_vec::ReadZeroByteVec)); + store.register_late_pass(|_| Box::new(default_instead_of_iter_empty::DefaultIterEmpty)); + store.register_late_pass(move |_| Box::new(manual_rem_euclid::ManualRemEuclid::new(msrv))); + store.register_late_pass(move |_| Box::new(manual_retain::ManualRetain::new(msrv))); let verbose_bit_mask_threshold = conf.verbose_bit_mask_threshold; - store.register_late_pass(move || Box::new(operators::Operators::new(verbose_bit_mask_threshold))); - store.register_late_pass(|| Box::new(invalid_utf8_in_unchecked::InvalidUtf8InUnchecked)); - store.register_late_pass(|| Box::new(std_instead_of_core::StdReexports::default())); - store.register_late_pass(|| Box::new(manual_instant_elapsed::ManualInstantElapsed)); - store.register_late_pass(|| Box::new(partialeq_to_none::PartialeqToNone)); - store.register_late_pass(|| Box::new(manual_string_new::ManualStringNew)); - store.register_late_pass(|| Box::new(unused_peekable::UnusedPeekable)); + store.register_late_pass(move |_| Box::new(operators::Operators::new(verbose_bit_mask_threshold))); + store.register_late_pass(|_| Box::new(invalid_utf8_in_unchecked::InvalidUtf8InUnchecked)); + store.register_late_pass(|_| Box::new(std_instead_of_core::StdReexports::default())); + store.register_late_pass(|_| Box::new(manual_instant_elapsed::ManualInstantElapsed)); + store.register_late_pass(|_| Box::new(partialeq_to_none::PartialeqToNone)); + store.register_late_pass(|_| Box::new(manual_string_new::ManualStringNew)); + store.register_late_pass(|_| Box::new(unused_peekable::UnusedPeekable)); store.register_early_pass(|| Box::new(multi_assignments::MultiAssignments)); // add lints here, do not remove this comment, it's used in `new_lint` }