diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs index 42d25b512f5c9..9c550b5ee57f1 100644 --- a/compiler/rustc_ast_lowering/src/delegation.rs +++ b/compiler/rustc_ast_lowering/src/delegation.rs @@ -44,6 +44,7 @@ use hir::{BodyId, HirId}; use rustc_abi::ExternAbi; use rustc_ast::*; use rustc_errors::ErrorGuaranteed; +use rustc_hir::TySource; use rustc_hir::def_id::DefId; use rustc_middle::span_bug; use rustc_middle::ty::{Asyncness, ResolverAstLowering}; @@ -174,12 +175,14 @@ impl<'hir> LoweringContext<'_, 'hir> { hir_id: self.next_id(), kind: hir::TyKind::InferDelegation(sig_id, hir::InferDelegationKind::Input(arg)), span, + source: TySource::Other, })); let output = self.arena.alloc(hir::Ty { hir_id: self.next_id(), kind: hir::TyKind::InferDelegation(sig_id, hir::InferDelegationKind::Output), span, + source: TySource::Other, }); self.arena.alloc(hir::FnDecl { diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 537d4a2a6af6a..484b77455f735 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -5,9 +5,8 @@ use rustc_ast::ptr::P as AstP; use rustc_ast::*; use rustc_ast_pretty::pprust::expr_to_string; use rustc_data_structures::stack::ensure_sufficient_stack; -use rustc_hir as hir; -use rustc_hir::HirId; use rustc_hir::def::{DefKind, Res}; +use rustc_hir::{self as hir, HirId, TySource}; use rustc_middle::span_bug; use rustc_middle::ty::TyCtxt; use rustc_session::errors::report_lit_error; @@ -761,6 +760,7 @@ impl<'hir> LoweringContext<'_, 'hir> { hir_id: self.next_id(), kind: hir::TyKind::Path(resume_ty), span: unstable_span, + source: TySource::Other, }; let inputs = arena_vec![self; input_ty]; diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 64d4a00ea4d8e..c95ea57db476d 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -55,7 +55,7 @@ use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res}; use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId}; use rustc_hir::{ self as hir, AngleBrackets, ConstArg, GenericArg, HirId, ItemLocalMap, LangItem, - LifetimeSource, LifetimeSyntax, ParamName, TraitCandidate, + LifetimeSource, LifetimeSyntax, ParamName, TraitCandidate, TySource, }; use rustc_index::{Idx, IndexSlice, IndexVec}; use rustc_macros::extension; @@ -1181,7 +1181,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { bounds, TaggedRef::new(lifetime_bound, TraitObjectSyntax::None), ); - return hir::Ty { kind, span: self.lower_span(t.span), hir_id: self.next_id() }; + return hir::Ty { + kind, + span: self.lower_span(t.span), + hir_id: self.next_id(), + source: TySource::Other, + }; } let id = self.lower_node_id(t.id); @@ -1198,7 +1203,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } fn ty(&mut self, span: Span, kind: hir::TyKind<'hir>) -> hir::Ty<'hir> { - hir::Ty { hir_id: self.next_id(), kind, span: self.lower_span(span) } + hir::Ty { + hir_id: self.next_id(), + kind, + span: self.lower_span(span), + source: TySource::Other, + } } fn ty_tup(&mut self, span: Span, tys: &'hir [hir::Ty<'hir>]) -> hir::Ty<'hir> { @@ -1219,7 +1229,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let lifetime = self.lower_ty_direct_lifetime(t, *region); let kind = hir::TyKind::Ref(lifetime, self.lower_mt(mt, itctx)); let span = self.lower_span(t.span); - let arg = hir::Ty { kind, span, hir_id: self.next_id() }; + let arg = hir::Ty { kind, span, hir_id: self.next_id(), source: TySource::Other }; let args = self.arena.alloc(hir::GenericArgs { args: self.arena.alloc([hir::GenericArg::Type(self.arena.alloc(arg))]), constraints: &[], @@ -1384,7 +1394,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { TyKind::Dummy => panic!("`TyKind::Dummy` should never be lowered"), }; - hir::Ty { kind, span: self.lower_span(t.span), hir_id: self.lower_node_id(t.id) } + hir::Ty { + kind, + span: self.lower_span(t.span), + hir_id: self.lower_node_id(t.id), + source: TySource::Other, + } } fn lower_ty_direct_lifetime( @@ -2382,7 +2397,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } - fn ty_path(&mut self, mut hir_id: HirId, span: Span, qpath: hir::QPath<'hir>) -> hir::Ty<'hir> { + fn ty_path(&mut self, hir_id: HirId, span: Span, qpath: hir::QPath<'hir>) -> hir::Ty<'hir> { + self.ty_path_with_source(hir_id, span, qpath, TySource::Other) + } + + fn ty_path_with_source( + &mut self, + mut hir_id: HirId, + span: Span, + qpath: hir::QPath<'hir>, + source: TySource, + ) -> hir::Ty<'hir> { let kind = match qpath { hir::QPath::Resolved(None, path) => { // Turn trait object paths into `TyKind::TraitObject` instead. @@ -2409,7 +2434,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { _ => hir::TyKind::Path(qpath), }; - hir::Ty { hir_id, kind, span: self.lower_span(span) } + hir::Ty { hir_id, kind, span: self.lower_span(span), source } } /// Invoked to create the lifetime argument(s) for an elided trait object diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index c80ef275c801a..d7fe02a6e82a5 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use rustc_ast::{self as ast, *}; use rustc_hir::def::{DefKind, PartialRes, PerNS, Res}; use rustc_hir::def_id::DefId; -use rustc_hir::{self as hir, GenericArg}; +use rustc_hir::{self as hir, GenericArg, TySource}; use rustc_middle::{span_bug, ty}; use rustc_session::parse::add_feature_diagnostics; use rustc_span::{BytePos, DUMMY_SP, DesugaringKind, Ident, Span, Symbol, sym}; @@ -169,7 +169,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // e.g., `Vec` in `Vec::new` or `::Item` in // `::Item::default`. let new_id = self.next_id(); - self.arena.alloc(self.ty_path(new_id, path.span, hir::QPath::Resolved(qself, path))) + self.arena.alloc(self.ty_path_with_source( + new_id, + path.span, + hir::QPath::Resolved(qself, path), + TySource::ImplicitSelf, + )) }; // Anything after the base path are associated "extensions", diff --git a/compiler/rustc_baked_icu_data/src/lib.rs b/compiler/rustc_baked_icu_data/src/lib.rs index f3f6522f57587..05ad644af1a26 100644 --- a/compiler/rustc_baked_icu_data/src/lib.rs +++ b/compiler/rustc_baked_icu_data/src/lib.rs @@ -21,13 +21,14 @@ //! ``` // tidy-alphabetical-start -#![allow(elided_lifetimes_in_paths)] #![allow(internal_features)] #![allow(unreachable_pub)] // because this crate is mostly generated code #![doc(rust_logo)] #![feature(rustdoc_internals)] // #![warn(unreachable_pub)] // don't use because this crate is mostly generated code // tidy-alphabetical-end +#![cfg_attr(bootstrap, allow(elided_lifetimes_in_paths))] +#![cfg_attr(not(bootstrap), allow(hidden_lifetimes_in_paths))] mod data { include!("data/mod.rs"); diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 6f288bb39b953..6c56c0653852e 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -498,7 +498,12 @@ pub struct InferArg { impl InferArg { pub fn to_ty(&self) -> Ty<'static> { - Ty { kind: TyKind::Infer(()), span: self.span, hir_id: self.hir_id } + Ty { + kind: TyKind::Infer(()), + span: self.span, + hir_id: self.hir_id, + source: TySource::Other, + } } } @@ -3274,6 +3279,16 @@ impl<'hir> AssocItemConstraintKind<'hir> { } } +#[derive(Debug, Clone, Copy, PartialEq, HashStable_Generic)] +pub enum TySource { + /// `Vec` in `Vec::new` + ImplicitSelf, + + /// Details not yet needed. Feel free to give useful + /// categorization to these usages. + Other, +} + /// An uninhabited enum used to make `Infer` variants on [`Ty`] and [`ConstArg`] be /// unreachable. Zero-Variant enums are guaranteed to have the same layout as the never /// type. @@ -3293,6 +3308,7 @@ pub struct Ty<'hir, Unambig = ()> { pub hir_id: HirId, pub span: Span, pub kind: TyKind<'hir, Unambig>, + pub source: TySource, } impl<'hir> Ty<'hir, AmbigArg> { @@ -4991,7 +5007,7 @@ mod size_asserts { static_assert_size!(StmtKind<'_>, 16); static_assert_size!(TraitItem<'_>, 88); static_assert_size!(TraitItemKind<'_>, 48); - static_assert_size!(Ty<'_>, 48); + static_assert_size!(Ty<'_>, 56); static_assert_size!(TyKind<'_>, 32); // tidy-alphabetical-end } diff --git a/compiler/rustc_hir/src/hir/tests.rs b/compiler/rustc_hir/src/hir/tests.rs index 1fd793bc1616f..099485a0aee36 100644 --- a/compiler/rustc_hir/src/hir/tests.rs +++ b/compiler/rustc_hir/src/hir/tests.rs @@ -20,10 +20,10 @@ macro_rules! define_tests { define_tests! { cast_never TyKind Never {} - cast_tup TyKind Tup { 0: &[Ty { span: DUMMY_SP, hir_id: HirId::INVALID, kind: TyKind::Never }] } - cast_ptr TyKind Ptr { 0: MutTy { ty: &Ty { span: DUMMY_SP, hir_id: HirId::INVALID, kind: TyKind::Never }, mutbl: Mutability::Not }} + cast_tup TyKind Tup { 0: &[Ty { span: DUMMY_SP, hir_id: HirId::INVALID, kind: TyKind::Never, source: TySource::Other }] } + cast_ptr TyKind Ptr { 0: MutTy { ty: &Ty { span: DUMMY_SP, hir_id: HirId::INVALID, kind: TyKind::Never, source: TySource::Other }, mutbl: Mutability::Not }} cast_array TyKind Array { - 0: &Ty { span: DUMMY_SP, hir_id: HirId::INVALID, kind: TyKind::Never }, + 0: &Ty { span: DUMMY_SP, hir_id: HirId::INVALID, kind: TyKind::Never, source: TySource::Other }, 1: &ConstArg { hir_id: HirId::INVALID, kind: ConstArgKind::Anon(&AnonConst { hir_id: HirId::INVALID, def_id: LocalDefId { local_def_index: DefIndex::ZERO }, diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index bebac3a4b7820..e4201c48faefc 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -978,7 +978,7 @@ pub fn walk_unambig_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) -> match typ.try_as_ambig_ty() { Some(ambig_ty) => visitor.visit_ty(ambig_ty), None => { - let Ty { hir_id, span, kind: _ } = typ; + let Ty { hir_id, span, kind: _, source: _ } = typ; try_visit!(visitor.visit_id(*hir_id)); visitor.visit_infer(*hir_id, *span, InferKind::Ty(typ)) } @@ -986,7 +986,7 @@ pub fn walk_unambig_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) -> } pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v, AmbigArg>) -> V::Result { - let Ty { hir_id, span: _, kind } = typ; + let Ty { hir_id, span: _, kind, source: _ } = typ; try_visit!(visitor.visit_id(*hir_id)); match *kind { diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index fd2e2ba39acec..fe4a67cada181 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -289,7 +289,11 @@ lint_hidden_glob_reexport = private item shadows public glob re-export .note_glob_reexport = the name `{$name}` in the {$namespace} namespace is supposed to be publicly re-exported here .note_private_item = but the private item here shadows it -lint_hidden_lifetime_parameters = hidden lifetime parameters in types are deprecated +lint_hidden_lifetime_in_path = + paths containing hidden lifetime parameters are deprecated + +lint_hidden_lifetime_in_path_suggestion = + indicate the anonymous lifetime lint_hidden_unicode_codepoints = unicode codepoint changing visible direction of text present in {$label} .label = this {$label} contains {$count -> diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 5679d4566dcd4..32d9b09bd789d 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -287,6 +287,26 @@ impl LintStore { self.by_name.insert(old_name.to_string(), Renamed(new_name.to_string(), target)); } + #[track_caller] + pub fn register_renamed_group(&mut self, old_name: &'static str, new_name: &'static str) { + let prev_lint = self.lint_groups.insert( + old_name, + LintGroup { + lint_ids: vec![], + is_externally_loaded: false, + depr: Some(LintAlias { name: new_name, silent: false }), + }, + ); + + if prev_lint.is_some() { + bug!("The lint group {old_name} has already been registered"); + } + + if !self.lint_groups.contains_key(new_name) { + bug!("The lint group {new_name} has not been registered"); + } + } + pub fn register_removed(&mut self, name: &str, reason: &str) { self.by_name.insert(name.into(), Removed(reason.into())); } diff --git a/compiler/rustc_lint/src/early/diagnostics.rs b/compiler/rustc_lint/src/early/diagnostics.rs index 60c477dd6c749..c7ab53df53951 100644 --- a/compiler/rustc_lint/src/early/diagnostics.rs +++ b/compiler/rustc_lint/src/early/diagnostics.rs @@ -4,9 +4,7 @@ use std::borrow::Cow; use rustc_ast::util::unicode::TEXT_FLOW_CONTROL_CHARS; -use rustc_errors::{ - Applicability, Diag, DiagArgValue, LintDiagnostic, elided_lifetime_in_path_suggestion, -}; +use rustc_errors::{Applicability, Diag, DiagArgValue, LintDiagnostic}; use rustc_middle::middle::stability; use rustc_middle::ty::TyCtxt; use rustc_session::Session; @@ -75,19 +73,6 @@ pub fn decorate_builtin_lint( lints::MacroExpandedMacroExportsAccessedByAbsolutePaths { definition: span_def } .decorate_lint(diag) } - - BuiltinLintDiag::ElidedLifetimesInPaths(n, path_span, incl_angl_brckt, insertion_span) => { - lints::ElidedLifetimesInPaths { - subdiag: elided_lifetime_in_path_suggestion( - sess.source_map(), - n, - path_span, - incl_angl_brckt, - insertion_span, - ), - } - .decorate_lint(diag); - } BuiltinLintDiag::UnknownCrateTypes { span, candidate } => { let sugg = candidate.map(|candidate| lints::UnknownCrateTypesSub { span, candidate }); lints::UnknownCrateTypes { sugg }.decorate_lint(diag); diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index c86f66cc9b09b..0dd9e2f7a9778 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -249,6 +249,7 @@ late_lint_methods!( UnqualifiedLocalImports: UnqualifiedLocalImports, CheckTransmutes: CheckTransmutes, LifetimeSyntax: LifetimeSyntax, + HiddenLifetimesInTypePaths: HiddenLifetimesInTypePaths::default(), ] ] ); @@ -269,7 +270,7 @@ pub fn new_lint_store(internal_lints: bool) -> LintStore { /// `rustc_session::lint::builtin`). fn register_builtins(store: &mut LintStore) { macro_rules! add_lint_group { - ($name:expr, $($lint:ident),*) => ( + ($name:expr, $($lint:ident),* $(,)?) => ( store.register_group(false, $name, None, vec![$(LintId::of($lint)),*]); ) } @@ -284,7 +285,7 @@ fn register_builtins(store: &mut LintStore) { "nonstandard_style", NON_CAMEL_CASE_TYPES, NON_SNAKE_CASE, - NON_UPPER_CASE_GLOBALS + NON_UPPER_CASE_GLOBALS, ); add_lint_group!( @@ -310,7 +311,7 @@ fn register_builtins(store: &mut LintStore) { UNUSED_PARENS, UNUSED_BRACES, REDUNDANT_SEMICOLONS, - MAP_UNIT_FN + MAP_UNIT_FN, ); add_lint_group!("let_underscore", LET_UNDERSCORE_DROP, LET_UNDERSCORE_LOCK); @@ -320,14 +321,16 @@ fn register_builtins(store: &mut LintStore) { BARE_TRAIT_OBJECTS, UNUSED_EXTERN_CRATES, ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, - ELIDED_LIFETIMES_IN_PATHS, - EXPLICIT_OUTLIVES_REQUIREMENTS // FIXME(#52665, #47816) not always applicable and not all - // macros are ready for this yet. - // UNREACHABLE_PUB, - - // FIXME macro crates are not up for this yet, too much - // breakage is seen if we try to encourage this lint. - // MACRO_USE_EXTERN_CRATE + HIDDEN_LIFETIMES_IN_OUTPUT_PATHS, + HIDDEN_LIFETIMES_IN_INPUT_PATHS, + HIDDEN_LIFETIMES_IN_TYPE_PATHS, + EXPLICIT_OUTLIVES_REQUIREMENTS, + // FIXME(#52665, #47816) not always applicable and not all + // macros are ready for this yet. + // UNREACHABLE_PUB, + // FIXME macro crates are not up for this yet, too much + // breakage is seen if we try to encourage this lint. + // MACRO_USE_EXTERN_CRATE ); add_lint_group!("keyword_idents", KEYWORD_IDENTS_2018, KEYWORD_IDENTS_2024); @@ -340,9 +343,15 @@ fn register_builtins(store: &mut LintStore) { add_lint_group!("deprecated_safe", DEPRECATED_SAFE_2024); + add_lint_group!( + "hidden_lifetimes_in_paths", + HIDDEN_LIFETIMES_IN_OUTPUT_PATHS, + HIDDEN_LIFETIMES_IN_INPUT_PATHS, + HIDDEN_LIFETIMES_IN_TYPE_PATHS, + ); + // Register renamed and removed lints. store.register_renamed("single_use_lifetime", "single_use_lifetimes"); - store.register_renamed("elided_lifetime_in_path", "elided_lifetimes_in_paths"); store.register_renamed("bare_trait_object", "bare_trait_objects"); store.register_renamed("unstable_name_collision", "unstable_name_collisions"); store.register_renamed("unused_doc_comment", "unused_doc_comments"); @@ -358,6 +367,10 @@ fn register_builtins(store: &mut LintStore) { store.register_renamed("temporary_cstring_as_ptr", "dangling_pointers_from_temporaries"); store.register_renamed("elided_named_lifetimes", "mismatched_lifetime_syntaxes"); + // Register renamed lint groups + store.register_renamed_group("elided_lifetime_in_path", "hidden_lifetimes_in_paths"); + store.register_renamed_group("elided_lifetimes_in_paths", "hidden_lifetimes_in_paths"); + // These were moved to tool lints, but rustc still sees them when compiling normally, before // tool lints are registered, so `check_tool_name_for_backwards_compat` doesn't work. Use // `register_removed` explicitly. diff --git a/compiler/rustc_lint/src/lifetime_syntax.rs b/compiler/rustc_lint/src/lifetime_syntax.rs index 31b038e6a467d..87b46073124ab 100644 --- a/compiler/rustc_lint/src/lifetime_syntax.rs +++ b/compiler/rustc_lint/src/lifetime_syntax.rs @@ -1,7 +1,10 @@ +use std::slice; + use rustc_data_structures::fx::FxIndexMap; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{self as hir, LifetimeSource}; -use rustc_session::{declare_lint, declare_lint_pass}; +use rustc_session::lint::Lint; +use rustc_session::{declare_lint, declare_lint_pass, impl_lint_pass}; use rustc_span::Span; use tracing::instrument; @@ -71,7 +74,82 @@ declare_lint! { "detects when a lifetime uses different syntax between arguments and return values" } -declare_lint_pass!(LifetimeSyntax => [MISMATCHED_LIFETIME_SYNTAXES]); +declare_lint! { + /// The `hidden_lifetimes_in_input_paths` lint detects the use of + /// hidden lifetime parameters in types occurring as a function + /// argument. + /// + /// ### Example + /// + /// ```rust,compile_fail + /// struct ContainsLifetime<'a>(&'a i32); + /// + /// #[deny(hidden_lifetimes_in_input_paths)] + /// fn foo(x: ContainsLifetime) {} + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// Hidden lifetime parameters can make it difficult to see at a + /// glance that borrowing is occurring. + /// + /// This lint ensures that lifetime parameters are always + /// explicitly stated, even if it is the `'_` [placeholder + /// lifetime]. + /// + /// This lint is "allow" by default as function arguments by + /// themselves do not usually cause much confusion. + /// + /// [placeholder lifetime]: https://doc.rust-lang.org/reference/lifetime-elision.html#lifetime-elision-in-functions + pub HIDDEN_LIFETIMES_IN_INPUT_PATHS, + Allow, + "hidden lifetime parameters in types in function arguments may be confusing" +} + +declare_lint! { + /// The `hidden_lifetimes_in_output_paths` lint detects the use + /// of hidden lifetime parameters in types occurring as a function + /// return value. + /// + /// ### Example + /// + /// ```rust,compile_fail + /// struct ContainsLifetime<'a>(&'a i32); + /// + /// #[deny(hidden_lifetimes_in_output_paths)] + /// fn foo(x: &i32) -> ContainsLifetime { + /// ContainsLifetime(x) + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// Hidden lifetime parameters can make it difficult to see at a + /// glance that borrowing is occurring. This is especially true + /// when a type is used as a function's return value: lifetime + /// elision will link the return value's lifetime to an argument's + /// lifetime, but no syntax in the function signature indicates + /// that. + /// + /// This lint ensures that lifetime parameters are always + /// explicitly stated, even if it is the `'_` [placeholder + /// lifetime]. + /// + /// [placeholder lifetime]: https://doc.rust-lang.org/reference/lifetime-elision.html#lifetime-elision-in-functions + pub HIDDEN_LIFETIMES_IN_OUTPUT_PATHS, + Allow, + "hidden lifetime parameters in types in function return values are deprecated" +} + +declare_lint_pass!(LifetimeSyntax => [ + MISMATCHED_LIFETIME_SYNTAXES, + HIDDEN_LIFETIMES_IN_INPUT_PATHS, + HIDDEN_LIFETIMES_IN_OUTPUT_PATHS, +]); impl<'tcx> LateLintPass<'tcx> for LifetimeSyntax { #[instrument(skip_all)] @@ -96,6 +174,8 @@ impl<'tcx> LateLintPass<'tcx> for LifetimeSyntax { } report_mismatches(cx, &input_map, &output_map); + report_hidden_in_paths(cx, &input_map, HIDDEN_LIFETIMES_IN_INPUT_PATHS); + report_hidden_in_paths(cx, &output_map, HIDDEN_LIFETIMES_IN_OUTPUT_PATHS); } } @@ -407,6 +487,50 @@ fn build_mismatch_suggestion( } } +fn report_hidden_in_paths<'tcx>( + cx: &LateContext<'tcx>, + info_map: &LifetimeInfoMap<'tcx>, + lint: &'static Lint, +) { + let relevant_lifetimes = info_map + .iter() + .filter(|&(&&res, _)| reportable_lifetime_resolution(res)) + .flat_map(|(_, info)| info) + .filter(|info| { + matches!(info.lifetime.source, LifetimeSource::Path { .. }) + && info.lifetime.is_implicit() + }); + + let mut reporting_spans = Vec::new(); + let mut suggestions = Vec::new(); + + for info in relevant_lifetimes { + reporting_spans.push(info.reporting_span()); + suggestions.push(info.suggestion("'_")); + } + + if reporting_spans.is_empty() { + return; + } + + cx.emit_span_lint( + lint, + reporting_spans, + lints::HiddenLifetimeInPath { + suggestions: lints::HiddenLifetimeInPathSuggestion { suggestions }, + }, + ); +} + +/// We don't care about errors, nor do we care about the lifetime +/// inside of a trait object. +fn reportable_lifetime_resolution(kind: hir::LifetimeKind) -> bool { + matches!( + kind, + hir::LifetimeKind::Param(..) | hir::LifetimeKind::Infer | hir::LifetimeKind::Static + ) +} + #[derive(Debug)] struct Info<'tcx> { type_span: Span, @@ -501,3 +625,114 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeInfoCollector<'a, 'tcx> { self.referenced_type_span = old_referenced_type_span; } } + +declare_lint! { + /// The `hidden_lifetimes_in_type_paths` lint detects the use of + /// hidden lifetime parameters in types not part of a function's + /// arguments or return values. + /// + /// ### Example + /// + /// ```rust,compile_fail + /// struct ContainsLifetime<'a>(&'a i32); + /// + /// #[deny(hidden_lifetimes_in_type_paths)] + /// static FOO: ContainsLifetime = ContainsLifetime(&42); + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// Hidden lifetime parameters can make it difficult to see at a + /// glance that borrowing is occurring. + /// + /// This lint ensures that lifetime parameters are always + /// explicitly stated, even if it is the `'_` [placeholder + /// lifetime]. + /// + /// [placeholder lifetime]: https://doc.rust-lang.org/reference/lifetime-elision.html#lifetime-elision-in-functions + pub HIDDEN_LIFETIMES_IN_TYPE_PATHS, + Allow, + "hidden lifetime parameters in types outside function signatures are discouraged" +} + +#[derive(Default)] +pub(crate) struct HiddenLifetimesInTypePaths { + inside_fn_signature: bool, +} + +impl_lint_pass!(HiddenLifetimesInTypePaths => [HIDDEN_LIFETIMES_IN_TYPE_PATHS]); + +impl<'tcx> LateLintPass<'tcx> for HiddenLifetimesInTypePaths { + #[instrument(skip(self, cx))] + fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx hir::Ty<'tcx, hir::AmbigArg>) { + if self.inside_fn_signature { + return; + } + + // Do not lint about usages like `ContainsLifetime::method` or + // `ContainsLifetimeAndType::::method`. + if ty.source == hir::TySource::ImplicitSelf { + return; + } + + let hir::TyKind::Path(path) = ty.kind else { return }; + + let path_segments = match path { + hir::QPath::Resolved(_ty, path) => path.segments, + + hir::QPath::TypeRelative(_ty, path_segment) => slice::from_ref(path_segment), + + hir::QPath::LangItem(..) => &[], + }; + + let mut suggestions = Vec::new(); + + for path_segment in path_segments { + for arg in path_segment.args().args { + if let hir::GenericArg::Lifetime(lifetime) = arg + && lifetime.is_implicit() + && reportable_lifetime_resolution(lifetime.kind) + { + suggestions.push(lifetime.suggestion("'_")) + } + } + } + + if suggestions.is_empty() { + return; + } + + cx.emit_span_lint( + HIDDEN_LIFETIMES_IN_TYPE_PATHS, + ty.span, + lints::HiddenLifetimeInPath { + suggestions: lints::HiddenLifetimeInPathSuggestion { suggestions }, + }, + ); + } + + #[instrument(skip_all)] + fn check_fn( + &mut self, + _: &LateContext<'tcx>, + _: hir::intravisit::FnKind<'tcx>, + _: &'tcx hir::FnDecl<'tcx>, + _: &'tcx hir::Body<'tcx>, + _: rustc_span::Span, + _: rustc_span::def_id::LocalDefId, + ) { + // We make the assumption that we will visit the function + // declaration first, before visiting the body. + self.inside_fn_signature = true; + } + + // This may be a function's body, which would indicate that we are + // no longer in the signature. Even if it's not, a body cannot + // occur inside a function signature. + #[instrument(skip_all)] + fn check_body(&mut self, _: &LateContext<'tcx>, _: &hir::Body<'tcx>) { + self.inside_fn_signature = false; + } +} diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 9d3c74a9a2b80..b62d96814fb6a 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -5,8 +5,8 @@ use std::num::NonZero; use rustc_abi::ExternAbi; use rustc_errors::codes::*; use rustc_errors::{ - Applicability, Diag, DiagArgValue, DiagMessage, DiagStyledString, ElidedLifetimeInPathSubdiag, - EmissionGuarantee, LintDiagnostic, MultiSpan, Subdiagnostic, SuggestionStyle, + Applicability, Diag, DiagArgValue, DiagMessage, DiagStyledString, EmissionGuarantee, + LintDiagnostic, MultiSpan, Subdiagnostic, SuggestionStyle, }; use rustc_hir as hir; use rustc_hir::def::Namespace; @@ -2745,13 +2745,6 @@ pub(crate) struct MacroExpandedMacroExportsAccessedByAbsolutePaths { pub definition: Span, } -#[derive(LintDiagnostic)] -#[diag(lint_hidden_lifetime_parameters)] -pub(crate) struct ElidedLifetimesInPaths { - #[subdiagnostic] - pub subdiag: ElidedLifetimeInPathSubdiag, -} - #[derive(LintDiagnostic)] #[diag(lint_invalid_crate_type_value)] pub(crate) struct UnknownCrateTypes { @@ -3314,3 +3307,24 @@ impl Subdiagnostic for MismatchedLifetimeSyntaxesSuggestion { } } } + +#[derive(LintDiagnostic)] +#[diag(lint_hidden_lifetime_in_path)] +pub(crate) struct HiddenLifetimeInPath { + #[subdiagnostic] + pub suggestions: HiddenLifetimeInPathSuggestion, +} + +pub(crate) struct HiddenLifetimeInPathSuggestion { + pub suggestions: Vec<(Span, String)>, +} + +impl Subdiagnostic for HiddenLifetimeInPathSuggestion { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { + diag.multipart_suggestion_verbose( + fluent::lint_hidden_lifetime_in_path_suggestion, + self.suggestions, + Applicability::MachineApplicable, + ); + } +} diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 843d577842130..dd94e52b3de95 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -39,7 +39,6 @@ declare_lint_pass! { DEPRECATED_WHERE_CLAUSE_LOCATION, DUPLICATE_MACRO_ATTRIBUTES, ELIDED_LIFETIMES_IN_ASSOCIATED_CONSTANT, - ELIDED_LIFETIMES_IN_PATHS, EXPLICIT_BUILTIN_CFGS_IN_FLAGS, EXPORTED_PRIVATE_DEPENDENCIES, FFI_UNWIND_CALLS, @@ -1796,41 +1795,6 @@ declare_lint! { }; } -declare_lint! { - /// The `elided_lifetimes_in_paths` lint detects the use of hidden - /// lifetime parameters. - /// - /// ### Example - /// - /// ```rust,compile_fail - /// #![deny(elided_lifetimes_in_paths)] - /// #![deny(warnings)] - /// struct Foo<'a> { - /// x: &'a u32 - /// } - /// - /// fn foo(x: &Foo) { - /// } - /// ``` - /// - /// {{produces}} - /// - /// ### Explanation - /// - /// Elided lifetime parameters can make it difficult to see at a glance - /// that borrowing is occurring. This lint ensures that lifetime - /// parameters are always explicitly stated, even if it is the `'_` - /// [placeholder lifetime]. - /// - /// This lint is "allow" by default because it has some known issues, and - /// may require a significant transition for old code. - /// - /// [placeholder lifetime]: https://doc.rust-lang.org/reference/lifetime-elision.html#lifetime-elision-in-functions - pub ELIDED_LIFETIMES_IN_PATHS, - Allow, - "hidden lifetime parameters in types are deprecated" -} - declare_lint! { /// The `bare_trait_objects` lint suggests using `dyn Trait` for trait /// objects. diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 1d9b7a7fcb948..496acb589002e 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -621,7 +621,6 @@ pub enum BuiltinLintDiag { ident: Ident, }, MacroExpandedMacroExportsAccessedByAbsolutePaths(Span), - ElidedLifetimesInPaths(usize, Span, bool, Span), UnknownCrateTypes { span: Span, candidate: Option, diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 3dc285fdab690..0fc841f9b9b8a 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -2104,7 +2104,6 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { kind, count: expected_lifetimes, }; - let mut should_lint = true; for rib in self.lifetime_ribs.iter().rev() { match rib.kind { // In create-parameter mode we error here because we don't want to support @@ -2127,7 +2126,6 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { span: path_span, subdiag, }); - should_lint = false; for id in node_ids { self.record_lifetime_res( @@ -2196,20 +2194,6 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } } } - - if should_lint { - self.r.lint_buffer.buffer_lint( - lint::builtin::ELIDED_LIFETIMES_IN_PATHS, - segment_id, - elided_lifetime_span, - lint::BuiltinLintDiag::ElidedLifetimesInPaths( - expected_lifetimes, - path_span, - !segment.has_generic_args, - elided_lifetime_span, - ), - ); - } } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index e8cf25b190621..adee4415b6426 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1650,7 +1650,7 @@ fn first_non_private<'tcx>( } fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type { - let hir::Ty { hir_id, span, ref kind } = *hir_ty; + let hir::Ty { hir_id, span, ref kind, source: _ } = *hir_ty; let hir::TyKind::Path(qpath) = kind else { unreachable!() }; match qpath { diff --git a/src/tools/lint-docs/src/groups.rs b/src/tools/lint-docs/src/groups.rs index 78d4f87ed0de6..11ef265f351eb 100644 --- a/src/tools/lint-docs/src/groups.rs +++ b/src/tools/lint-docs/src/groups.rs @@ -12,6 +12,7 @@ static GROUP_DESCRIPTIONS: &[(&str, &str)] = &[ ("let-underscore", "Lints that detect wildcard let bindings that are likely to be invalid"), ("rustdoc", "Rustdoc-specific lints"), ("rust-2018-idioms", "Lints to nudge you toward idiomatic features of Rust 2018"), + ("hidden-lifetimes-in-paths", "Lints that detect the use of hidden lifetime parameters"), ("nonstandard-style", "Violation of standard naming conventions"), ("future-incompatible", "Lints that detect code that has future-compatibility problems"), ("rust-2018-compatibility", "Lints used to transition code from the 2015 edition to 2018"), @@ -28,6 +29,10 @@ static GROUP_DESCRIPTIONS: &[(&str, &str)] = &[ ("deprecated-safe", "Lints for functions which were erroneously marked as safe in the past"), ]; +pub fn exists(name: &str) -> bool { + GROUP_DESCRIPTIONS.iter().any(|&(n, _)| n == name) +} + type LintGroups = BTreeMap>; impl<'a> LintExtractor<'a> { diff --git a/src/tools/lint-docs/src/lib.rs b/src/tools/lint-docs/src/lib.rs index 6bb18c2bced70..c0d7ad814bc81 100644 --- a/src/tools/lint-docs/src/lib.rs +++ b/src/tools/lint-docs/src/lib.rs @@ -24,7 +24,7 @@ static RENAMES: &[(Level, &[(&str, &str)])] = &[ Level::Allow, &[ ("single-use-lifetime", "single-use-lifetimes"), - ("elided-lifetime-in-path", "elided-lifetimes-in-paths"), + ("elided-lifetime-in-path", "hidden-lifetimes-in-paths"), ("async-idents", "keyword-idents"), ("disjoint-capture-migration", "rust-2021-incompatible-closure-captures"), ("keyword-idents", "keyword-idents-2018"), @@ -584,9 +584,15 @@ impl<'a> LintExtractor<'a> { fn add_renamed_lints(lints: &mut Vec) { for (level, names) in RENAMES { for (from, to) in *names { + let doc = if groups::exists(to) { + format!("The lint `{from}` has been renamed to the group `{to}`.") + } else { + format!("The lint `{from}` has been renamed to [`{to}`](#{to}).") + }; + lints.push(Lint { name: from.to_string(), - doc: vec![format!("The lint `{from}` has been renamed to [`{to}`](#{to}).")], + doc: vec![doc], level: *level, path: PathBuf::new(), lineno: 0, diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt index 3e9d79224fdde..0b81fb84b2b38 100644 --- a/src/tools/tidy/src/issues.txt +++ b/src/tools/tidy/src/issues.txt @@ -2619,7 +2619,6 @@ ui/let-else/issue-100103.rs ui/let-else/issue-102317.rs ui/let-else/issue-94176.rs ui/let-else/issue-99975.rs -ui/lifetimes/auxiliary/issue-91763-aux.rs ui/lifetimes/issue-103582-hint-for-missing-lifetime-bound-on-trait-object-using-type-alias.rs ui/lifetimes/issue-104432-unused-lifetimes-in-expansion.rs ui/lifetimes/issue-105227.rs @@ -2652,7 +2651,6 @@ ui/lifetimes/issue-84398.rs ui/lifetimes/issue-84604.rs ui/lifetimes/issue-90170-elision-mismatch.rs ui/lifetimes/issue-90600-expected-return-static-indirect.rs -ui/lifetimes/issue-91763.rs ui/lifetimes/issue-93911.rs ui/lifetimes/issue-95023.rs ui/lifetimes/issue-97193.rs diff --git a/tests/ui/lifetimes/auxiliary/issue-91763-aux.rs b/tests/ui/lifetimes/auxiliary/issue-91763-aux.rs deleted file mode 100644 index 4e4b7f61f1ef4..0000000000000 --- a/tests/ui/lifetimes/auxiliary/issue-91763-aux.rs +++ /dev/null @@ -1,42 +0,0 @@ -//#![feature(proc_macro_diagnostic, proc_macro_span, proc_macro_def_site)] - -extern crate proc_macro; - -use proc_macro::{Delimiter, Group, Ident, Punct, Spacing, Span, TokenStream, TokenTree}; -use std::iter::FromIterator; - -#[proc_macro_attribute] -pub fn repro(_args: TokenStream, input: TokenStream) -> TokenStream { - let call_site = Span::call_site(); - let span = input.into_iter().nth(8).unwrap().span(); - - //fn f(_: &::std::fmt::Formatter) {} - TokenStream::from_iter([ - TokenTree::Ident(Ident::new("fn", call_site)), - TokenTree::Ident(Ident::new("f", call_site)), - TokenTree::Group(Group::new( - Delimiter::Parenthesis, - TokenStream::from_iter([ - TokenTree::Ident(Ident::new("_", call_site)), - TokenTree::Punct(punct(':', Spacing::Alone, call_site)), - TokenTree::Punct(punct('&', Spacing::Alone, call_site)), - TokenTree::Punct(punct(':', Spacing::Joint, span)), - TokenTree::Punct(punct(':', Spacing::Alone, span)), - TokenTree::Ident(Ident::new("std", span)), - TokenTree::Punct(punct(':', Spacing::Joint, span)), - TokenTree::Punct(punct(':', Spacing::Alone, span)), - TokenTree::Ident(Ident::new("fmt", span)), - TokenTree::Punct(punct(':', Spacing::Joint, span)), - TokenTree::Punct(punct(':', Spacing::Alone, span)), - TokenTree::Ident(Ident::new("Formatter", span)), - ]), - )), - TokenTree::Group(Group::new(Delimiter::Brace, TokenStream::new())), - ]) -} - -fn punct(ch: char, spacing: Spacing, span: Span) -> Punct { - let mut punct = Punct::new(ch, spacing); - punct.set_span(span); - punct -} diff --git a/tests/ui/lifetimes/elided-lint-in-mod.rs b/tests/ui/lifetimes/elided-lint-in-mod.rs deleted file mode 100644 index afe85cb607d40..0000000000000 --- a/tests/ui/lifetimes/elided-lint-in-mod.rs +++ /dev/null @@ -1,11 +0,0 @@ -struct Foo<'a>(&'a ()); - -fn test(_: Foo) {} - -#[deny(elided_lifetimes_in_paths)] -mod w { - fn test2(_: super::Foo) {} - //~^ ERROR hidden lifetime parameters in types are deprecated -} - -fn main() {} diff --git a/tests/ui/lifetimes/elided-lint-in-mod.stderr b/tests/ui/lifetimes/elided-lint-in-mod.stderr deleted file mode 100644 index 1fee18028c66f..0000000000000 --- a/tests/ui/lifetimes/elided-lint-in-mod.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error: hidden lifetime parameters in types are deprecated - --> $DIR/elided-lint-in-mod.rs:7:24 - | -LL | fn test2(_: super::Foo) {} - | -------^^^ - | | - | expected lifetime parameter - | -note: the lint level is defined here - --> $DIR/elided-lint-in-mod.rs:5:8 - | -LL | #[deny(elided_lifetimes_in_paths)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ -help: indicate the anonymous lifetime - | -LL | fn test2(_: super::Foo<'_>) {} - | ++++ - -error: aborting due to 1 previous error - diff --git a/tests/ui/lifetimes/hidden-lifetimes-in-mod.rs b/tests/ui/lifetimes/hidden-lifetimes-in-mod.rs new file mode 100644 index 0000000000000..470431b8407a0 --- /dev/null +++ b/tests/ui/lifetimes/hidden-lifetimes-in-mod.rs @@ -0,0 +1,11 @@ +struct Foo<'a>(&'a ()); + +fn test(_: Foo) {} + +#[deny(hidden_lifetimes_in_paths)] +mod w { + fn test2(_: super::Foo) {} + //~^ ERROR paths containing hidden lifetime parameters are deprecated +} + +fn main() {} diff --git a/tests/ui/lifetimes/hidden-lifetimes-in-mod.stderr b/tests/ui/lifetimes/hidden-lifetimes-in-mod.stderr new file mode 100644 index 0000000000000..679f511376326 --- /dev/null +++ b/tests/ui/lifetimes/hidden-lifetimes-in-mod.stderr @@ -0,0 +1,19 @@ +error: paths containing hidden lifetime parameters are deprecated + --> $DIR/hidden-lifetimes-in-mod.rs:7:17 + | +LL | fn test2(_: super::Foo) {} + | ^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/hidden-lifetimes-in-mod.rs:5:8 + | +LL | #[deny(hidden_lifetimes_in_paths)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: `#[deny(hidden_lifetimes_in_input_paths)]` implied by `#[deny(hidden_lifetimes_in_paths)]` +help: indicate the anonymous lifetime + | +LL | fn test2(_: super::Foo<'_>) {} + | ++++ + +error: aborting due to 1 previous error + diff --git a/tests/ui/lifetimes/hidden-lifetimes-in-type-paths.rs b/tests/ui/lifetimes/hidden-lifetimes-in-type-paths.rs new file mode 100644 index 0000000000000..26fcf278f5dd0 --- /dev/null +++ b/tests/ui/lifetimes/hidden-lifetimes-in-type-paths.rs @@ -0,0 +1,52 @@ +#![deny(hidden_lifetimes_in_type_paths)] + +struct ContainsLifetime<'a>(&'a u8); + +impl<'a> ContainsLifetime<'a> { + fn use_it() {} +} + +struct ContainsLifetimeAndType<'a, T>(&'a T); + +impl<'a, T> ContainsLifetimeAndType<'a, T> { + fn use_it() {} +} + +fn use_via_turbofish() {} + +trait UseViaTrait { + fn use_it() {} +} + +impl UseViaTrait for ContainsLifetime<'_> {} + +trait TraitWithLifetime<'a> { + fn use_it() {} +} + +impl<'a> TraitWithLifetime<'a> for u8 {} + +// ========== + +static USE_VIA_STATIC: ContainsLifetime = ContainsLifetime(&42); +//~^ ERROR hidden lifetime parameters + +fn main() { + use_via_turbofish::(); + //~^ ERROR hidden lifetime parameters + + let _use_via_binding: ContainsLifetime; + //~^ ERROR hidden lifetime parameters + + ::use_it(); + //~^ ERROR hidden lifetime parameters + + ::use_it(); + //~^ ERROR hidden lifetime parameters + + ContainsLifetime::use_it(); + + ContainsLifetimeAndType::::use_it(); + + ::use_it(); +} diff --git a/tests/ui/lifetimes/hidden-lifetimes-in-type-paths.stderr b/tests/ui/lifetimes/hidden-lifetimes-in-type-paths.stderr new file mode 100644 index 0000000000000..5eae5a87cd413 --- /dev/null +++ b/tests/ui/lifetimes/hidden-lifetimes-in-type-paths.stderr @@ -0,0 +1,62 @@ +error: paths containing hidden lifetime parameters are deprecated + --> $DIR/hidden-lifetimes-in-type-paths.rs:31:24 + | +LL | static USE_VIA_STATIC: ContainsLifetime = ContainsLifetime(&42); + | ^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/hidden-lifetimes-in-type-paths.rs:1:9 + | +LL | #![deny(hidden_lifetimes_in_type_paths)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: indicate the anonymous lifetime + | +LL | static USE_VIA_STATIC: ContainsLifetime<'_> = ContainsLifetime(&42); + | ++++ + +error: paths containing hidden lifetime parameters are deprecated + --> $DIR/hidden-lifetimes-in-type-paths.rs:35:25 + | +LL | use_via_turbofish::(); + | ^^^^^^^^^^^^^^^^ + | +help: indicate the anonymous lifetime + | +LL | use_via_turbofish::>(); + | ++++ + +error: paths containing hidden lifetime parameters are deprecated + --> $DIR/hidden-lifetimes-in-type-paths.rs:38:27 + | +LL | let _use_via_binding: ContainsLifetime; + | ^^^^^^^^^^^^^^^^ + | +help: indicate the anonymous lifetime + | +LL | let _use_via_binding: ContainsLifetime<'_>; + | ++++ + +error: paths containing hidden lifetime parameters are deprecated + --> $DIR/hidden-lifetimes-in-type-paths.rs:41:6 + | +LL | ::use_it(); + | ^^^^^^^^^^^^^^^^ + | +help: indicate the anonymous lifetime + | +LL | as UseViaTrait>::use_it(); + | ++++ + +error: paths containing hidden lifetime parameters are deprecated + --> $DIR/hidden-lifetimes-in-type-paths.rs:44:6 + | +LL | ::use_it(); + | ^^^^^^^^^^^^^^^^ + | +help: indicate the anonymous lifetime + | +LL | >::use_it(); + | ++++ + +error: aborting due to 5 previous errors + diff --git a/tests/ui/lifetimes/issue-91763.rs b/tests/ui/lifetimes/issue-91763.rs deleted file mode 100644 index 6abb64db5feba..0000000000000 --- a/tests/ui/lifetimes/issue-91763.rs +++ /dev/null @@ -1,11 +0,0 @@ -//@ proc-macro: issue-91763-aux.rs - -#![deny(elided_lifetimes_in_paths)] - -extern crate issue_91763_aux; - -#[issue_91763_aux::repro] -fn f() -> Ptr; -//~^ ERROR hidden lifetime parameters in types are deprecated - -fn main() {} diff --git a/tests/ui/lifetimes/issue-91763.stderr b/tests/ui/lifetimes/issue-91763.stderr deleted file mode 100644 index f7293ed809c3a..0000000000000 --- a/tests/ui/lifetimes/issue-91763.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error: hidden lifetime parameters in types are deprecated - --> $DIR/issue-91763.rs:8:20 - | -LL | fn f() -> Ptr; - | ^ expected lifetime parameter - | -note: the lint level is defined here - --> $DIR/issue-91763.rs:3:9 - | -LL | #![deny(elided_lifetimes_in_paths)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ -help: indicate the anonymous lifetime - | -LL | fn f() -> Ptr<'_>; - | ++++ - -error: aborting due to 1 previous error - diff --git a/tests/ui/lint/force-warn/allowed-by-default-lint.rs b/tests/ui/lint/force-warn/allowed-by-default-lint.rs index f0c9663c0d3a2..7f290dac230c2 100644 --- a/tests/ui/lint/force-warn/allowed-by-default-lint.rs +++ b/tests/ui/lint/force-warn/allowed-by-default-lint.rs @@ -1,5 +1,5 @@ // --force-warn $LINT causes $LINT (which is allow-by-default) to warn -//@ compile-flags: --force-warn elided_lifetimes_in_paths +//@ compile-flags: --force-warn hidden_lifetimes_in_paths //@ check-pass struct Foo<'a> { @@ -7,6 +7,6 @@ struct Foo<'a> { } fn foo(x: &Foo) {} -//~^ WARN hidden lifetime parameters in types are deprecated +//~^ WARN paths containing hidden lifetime parameters are deprecated fn main() {} diff --git a/tests/ui/lint/force-warn/allowed-by-default-lint.stderr b/tests/ui/lint/force-warn/allowed-by-default-lint.stderr index ac98b5896ca7b..26dae7dbe7e73 100644 --- a/tests/ui/lint/force-warn/allowed-by-default-lint.stderr +++ b/tests/ui/lint/force-warn/allowed-by-default-lint.stderr @@ -1,10 +1,10 @@ -warning: hidden lifetime parameters in types are deprecated +warning: paths containing hidden lifetime parameters are deprecated --> $DIR/allowed-by-default-lint.rs:9:12 | LL | fn foo(x: &Foo) {} - | ^^^ expected lifetime parameter + | ^^^ | - = note: requested on the command line with `--force-warn elided-lifetimes-in-paths` + = note: `--force-warn hidden-lifetimes-in-input-paths` implied by `--force-warn hidden-lifetimes-in-paths` help: indicate the anonymous lifetime | LL | fn foo(x: &Foo<'_>) {} diff --git a/tests/ui/lint/reasons-erroneous.rs b/tests/ui/lint/reasons-erroneous.rs index 0aa46953bf1ac..3a17245750a78 100644 --- a/tests/ui/lint/reasons-erroneous.rs +++ b/tests/ui/lint/reasons-erroneous.rs @@ -12,7 +12,7 @@ #![warn(unsafe_code, blerp = "or in league with robbers have reversed the signposts")] //~^ ERROR malformed lint attribute //~| NOTE bad attribute argument -#![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))] +#![warn(hidden_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))] //~^ ERROR malformed lint attribute //~| NOTE bad attribute argument #![warn(ellipsis_inclusive_range_patterns, reason = "born barren", reason = "a freak growth")] diff --git a/tests/ui/lint/reasons-erroneous.stderr b/tests/ui/lint/reasons-erroneous.stderr index fcff88d8e0fa7..5dccd64f77927 100644 --- a/tests/ui/lint/reasons-erroneous.stderr +++ b/tests/ui/lint/reasons-erroneous.stderr @@ -25,7 +25,7 @@ LL | #![warn(unsafe_code, blerp = "or in league with robbers have reversed the s error[E0452]: malformed lint attribute input --> $DIR/reasons-erroneous.rs:15:36 | -LL | #![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))] +LL | #![warn(hidden_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument error[E0452]: malformed lint attribute input diff --git a/tests/ui/lint/reasons.rs b/tests/ui/lint/reasons.rs index 917e7539aaed3..f75d27aa2e883 100644 --- a/tests/ui/lint/reasons.rs +++ b/tests/ui/lint/reasons.rs @@ -1,6 +1,6 @@ //@ check-pass -#![warn(elided_lifetimes_in_paths, +#![warn(hidden_lifetimes_in_paths, //~^ NOTE the lint level is defined here reason = "explicit anonymous lifetimes aid reasoning about ownership")] #![warn( @@ -17,8 +17,8 @@ pub struct CheaterDetectionMechanism {} impl fmt::Debug for CheaterDetectionMechanism { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - //~^ WARN hidden lifetime parameters in types are deprecated - //~| NOTE expected lifetime parameter + //~^ WARN paths containing hidden lifetime parameters are deprecated + //~| NOTE implied by //~| NOTE explicit anonymous lifetimes aid //~| HELP indicate the anonymous lifetime fmt.debug_struct("CheaterDetectionMechanism").finish() diff --git a/tests/ui/lint/reasons.stderr b/tests/ui/lint/reasons.stderr index 8028785ab94be..4fb73d474bc99 100644 --- a/tests/ui/lint/reasons.stderr +++ b/tests/ui/lint/reasons.stderr @@ -1,17 +1,16 @@ -warning: hidden lifetime parameters in types are deprecated - --> $DIR/reasons.rs:19:34 +warning: paths containing hidden lifetime parameters are deprecated + --> $DIR/reasons.rs:19:29 | LL | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - | -----^^^^^^^^^ - | | - | expected lifetime parameter + | ^^^^^^^^^^^^^^ | = note: explicit anonymous lifetimes aid reasoning about ownership note: the lint level is defined here --> $DIR/reasons.rs:3:9 | -LL | #![warn(elided_lifetimes_in_paths, +LL | #![warn(hidden_lifetimes_in_paths, | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: `#[warn(hidden_lifetimes_in_input_paths)]` implied by `#[warn(hidden_lifetimes_in_paths)]` help: indicate the anonymous lifetime | LL | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/tests/ui/stats/input-stats.stderr b/tests/ui/stats/input-stats.stderr index f2598bd7eaf85..fb360d4e98449 100644 --- a/tests/ui/stats/input-stats.stderr +++ b/tests/ui/stats/input-stats.stderr @@ -95,10 +95,6 @@ hir-stats - Wild 72 (NN.N%) 1 hir-stats - Binding 216 (NN.N%) 3 hir-stats GenericParam 400 (NN.N%) 5 80 hir-stats Generics 560 (NN.N%) 10 56 -hir-stats Ty 720 (NN.N%) 15 48 -hir-stats - Ptr 48 (NN.N%) 1 -hir-stats - Ref 48 (NN.N%) 1 -hir-stats - Path 624 (NN.N%) 13 hir-stats Expr 768 (NN.N%) 12 64 hir-stats - InlineAsm 64 (NN.N%) 1 hir-stats - Match 64 (NN.N%) 1 @@ -106,6 +102,10 @@ hir-stats - Path 64 (NN.N%) 1 hir-stats - Struct 64 (NN.N%) 1 hir-stats - Lit 128 (NN.N%) 2 hir-stats - Block 384 (NN.N%) 6 +hir-stats Ty 840 (NN.N%) 15 56 +hir-stats - Ptr 56 (NN.N%) 1 +hir-stats - Ref 56 (NN.N%) 1 +hir-stats - Path 728 (NN.N%) 13 hir-stats Item 968 (NN.N%) 11 88 hir-stats - Enum 88 (NN.N%) 1 hir-stats - ExternCrate 88 (NN.N%) 1 @@ -117,5 +117,5 @@ hir-stats - Use 352 (NN.N%) 4 hir-stats Path 1_040 (NN.N%) 26 40 hir-stats PathSegment 1_776 (NN.N%) 37 48 hir-stats ---------------------------------------------------------------- -hir-stats Total 8_644 172 +hir-stats Total 8_764 172 hir-stats