From cc857180a244582c949b243b05c15afdbae9192e Mon Sep 17 00:00:00 2001 From: Jake Goulding Date: Thu, 8 Feb 2024 13:41:00 -0500 Subject: [PATCH] Split `elided_lifetime_in_paths` into tied and untied Types that contain a reference can be confusing when lifetime elision occurs: ```rust // Confusing fn foo(_: &u8) -> Bar { todo!() } // Less confusing fn foo(_: &u8) -> Bar<'_> { todo!() } ``` However, the previous lint did not distinguish when these types were not "tying" lifetimes across the function inputs / outputs: ```rust // Maybe a little confusing fn foo(_: Bar) {} // More explicit but noisier with less obvious value fn foo(_: Bar<'_>) {} ``` We now report different lints for each case, hopefully paving the way to marking the first case (when lifetimes are tied together) as warn-by-default. --- compiler/rustc_lint/src/lib.rs | 9 +- compiler/rustc_lint_defs/src/builtin.rs | 54 +++++- compiler/rustc_resolve/src/late.rs | 119 ++++++++++--- src/tools/lint-docs/src/groups.rs | 1 + .../elided-lifetime-in-path-details.rs | 168 ++++++++++++++++++ ...lided-lifetime-in-path-details.tied.stderr | 161 +++++++++++++++++ ...ded-lifetime-in-path-details.untied.stderr | 62 +++++++ tests/ui/lifetimes/issue-91763.stderr | 1 + .../force-warn/allowed-by-default-lint.stderr | 3 +- tests/ui/lint/reasons.rs | 1 + tests/ui/lint/reasons.stderr | 3 +- 11 files changed, 553 insertions(+), 29 deletions(-) create mode 100644 tests/ui/lifetimes/elided-lifetime-in-path-details.rs create mode 100644 tests/ui/lifetimes/elided-lifetime-in-path-details.tied.stderr create mode 100644 tests/ui/lifetimes/elided-lifetime-in-path-details.untied.stderr diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index a855bada34b69..5a9dbbe114fb8 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -303,7 +303,8 @@ fn register_builtins(store: &mut LintStore) { BARE_TRAIT_OBJECTS, UNUSED_EXTERN_CRATES, ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, - ELIDED_LIFETIMES_IN_PATHS, + ELIDED_LIFETIMES_IN_PATHS_TIED, + ELIDED_LIFETIMES_IN_PATHS_UNTIED, EXPLICIT_OUTLIVES_REQUIREMENTS, // FIXME(#52665, #47816) not always applicable and not all // macros are ready for this yet. @@ -313,6 +314,12 @@ fn register_builtins(store: &mut LintStore) { // MACRO_USE_EXTERN_CRATE ); + add_lint_group!( + "elided_lifetimes_in_paths", + ELIDED_LIFETIMES_IN_PATHS_TIED, + ELIDED_LIFETIMES_IN_PATHS_UNTIED, + ); + // 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"); diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 6a2a2c1e48e2a..e933d1ebc6837 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -40,7 +40,8 @@ declare_lint_pass! { DEPRECATED_WHERE_CLAUSE_LOCATION, DUPLICATE_MACRO_ATTRIBUTES, ELIDED_LIFETIMES_IN_ASSOCIATED_CONSTANT, - ELIDED_LIFETIMES_IN_PATHS, + ELIDED_LIFETIMES_IN_PATHS_TIED, + ELIDED_LIFETIMES_IN_PATHS_UNTIED, EXPORTED_PRIVATE_DEPENDENCIES, FFI_UNWIND_CALLS, FORBIDDEN_LINT_GROUPS, @@ -1701,19 +1702,21 @@ declare_lint! { } declare_lint! { - /// The `elided_lifetimes_in_paths` lint detects the use of hidden - /// lifetime parameters. + /// The `elided_lifetimes_in_paths_tied` lint detects the use of + /// hidden lifetime parameters when those lifetime parameters tie + /// an input lifetime parameter to an output lifetime parameter. /// /// ### Example /// /// ```rust,compile_fail - /// #![deny(elided_lifetimes_in_paths)] + /// #![deny(elided_lifetimes_in_paths_tied)] /// #![deny(warnings)] /// struct Foo<'a> { /// x: &'a u32 /// } /// - /// fn foo(x: &Foo) { + /// fn foo(x: Foo) -> &u32 { + /// &x.0 /// } /// ``` /// @@ -1730,12 +1733,51 @@ declare_lint! { /// 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, + pub ELIDED_LIFETIMES_IN_PATHS_TIED, Allow, "hidden lifetime parameters in types are deprecated", crate_level_only } +declare_lint! { + /// The `elided_lifetimes_in_paths_untied` lint detects the use of + /// hidden lifetime parameters when those lifetime parameters do + /// not tie an input lifetime parameter to an output lifetime + /// parameter. + /// + /// ### Example + /// + /// ```rust,compile_fail + /// #![deny(elided_lifetimes_in_paths_untied)] + /// #![deny(warnings)] + /// struct Foo<'a> { + /// x: &'a u32 + /// } + /// + /// fn foo(x: Foo) -> u32 { + /// x.0 + /// } + /// ``` + /// + /// {{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_UNTIED, + Allow, + "hidden lifetime parameters in types make it hard to tell when borrowing is happening", + crate_level_only +} + declare_lint! { /// The `bare_trait_objects` lint suggests using `dyn Trait` for trait /// objects. diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 8fa873a9381c9..ae6fe1ee0374d 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -646,7 +646,24 @@ struct DiagnosticMetadata<'ast> { } #[derive(Debug)] -struct ResolvedNestedElisionTarget { +enum ResolvedElisionTarget { + /// Elision in `&u8` -> `&'_ u8` + TopLevel(NodeId), + /// Elision in `Foo` -> `Foo<'_>` + Nested(NestedResolvedElisionTarget), +} + +impl ResolvedElisionTarget { + fn node_id(&self) -> NodeId { + match *self { + Self::TopLevel(n) => n, + Self::Nested(NestedResolvedElisionTarget { segment_id, .. }) => segment_id, + } + } +} + +#[derive(Debug)] +struct NestedResolvedElisionTarget { segment_id: NodeId, elided_lifetime_span: Span, diagnostic: lint::BuiltinLintDiagnostics, @@ -694,7 +711,7 @@ struct LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { lifetime_uses: FxHashMap, /// Track which types participated in lifetime elision - resolved_lifetime_elisions: Vec, + resolved_lifetime_elisions: Vec, } /// Walks the whole crate in DFS order, visiting each item, resolving names as it goes. @@ -1745,6 +1762,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { LifetimeElisionCandidate::Ignore, ); self.resolve_anonymous_lifetime(<, true); + + self.resolved_lifetime_elisions.push(ResolvedElisionTarget::TopLevel(anchor_id)); } #[instrument(level = "debug", skip(self))] @@ -1957,16 +1976,18 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { } if should_lint { - self.resolved_lifetime_elisions.push(ResolvedNestedElisionTarget { - segment_id, - elided_lifetime_span, - diagnostic: lint::BuiltinLintDiagnostics::ElidedLifetimesInPaths( - expected_lifetimes, - path_span, - !segment.has_generic_args, + self.resolved_lifetime_elisions.push(ResolvedElisionTarget::Nested( + NestedResolvedElisionTarget { + segment_id, elided_lifetime_span, - ), - }); + diagnostic: lint::BuiltinLintDiagnostics::ElidedLifetimesInPaths( + expected_lifetimes, + path_span, + !segment.has_generic_args, + elided_lifetime_span, + ), + }, + )); } } } @@ -2028,22 +2049,80 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { let elision_failures = replace(&mut self.diagnostic_metadata.current_elision_failures, outer_failures); - if !elision_failures.is_empty() { - let Err(failure_info) = elision_lifetime else { bug!() }; - self.report_missing_lifetime_specifiers(elision_failures, Some(failure_info)); - } + + let elision_lifetime = match (elision_failures.is_empty(), elision_lifetime) { + (true, Ok(lifetime)) => Some(lifetime), + + (true, Err(_)) => None, + + (false, Ok(_)) => bug!(), + + (false, Err(failure_info)) => { + self.report_missing_lifetime_specifiers(elision_failures, Some(failure_info)); + None + } + }; + + // We've recorded all elisions that occurred in the params and + // outputs, categorized by top-level or nested. + // + // Our primary lint case is when an output lifetime is tied to + // an input lifetime. In that case, we want to warn about any + // parameters that had a nested elision. + // + // The secondary case is for nested elisions that are not part + // of the tied lifetime relationship. let output_resolved_lifetime_elisions = replace(&mut self.resolved_lifetime_elisions, outer_resolved_lifetime_elisions); - let resolved_lifetime_elisions = - param_resolved_lifetime_elisions.into_iter().chain(output_resolved_lifetime_elisions); + match (output_resolved_lifetime_elisions.is_empty(), elision_lifetime) { + (true, _) | (_, None) => { + // Treat all parameters as untied + self.report_elided_lifetimes_in_paths( + param_resolved_lifetime_elisions, + lint::builtin::ELIDED_LIFETIMES_IN_PATHS_UNTIED, + ); + } + (false, Some(elision_lifetime)) => { + let (primary, secondary): (Vec<_>, Vec<_>) = + param_resolved_lifetime_elisions.into_iter().partition(|re| { + // Recover the `NodeId` of an elided lifetime + let lvl1 = &self.r.lifetimes_res_map[&re.node_id()]; + let lvl2 = match lvl1 { + LifetimeRes::ElidedAnchor { start, .. } => { + &self.r.lifetimes_res_map[&start] + } + o => o, + }; + + lvl2 == &elision_lifetime + }); + + self.report_elided_lifetimes_in_paths( + primary.into_iter().chain(output_resolved_lifetime_elisions), + lint::builtin::ELIDED_LIFETIMES_IN_PATHS_TIED, + ); + self.report_elided_lifetimes_in_paths( + secondary, + lint::builtin::ELIDED_LIFETIMES_IN_PATHS_UNTIED, + ); + } + } + } + + fn report_elided_lifetimes_in_paths( + &mut self, + resolved_elisions: impl IntoIterator, + lint: &'static lint::Lint, + ) { + for re in resolved_elisions { + let ResolvedElisionTarget::Nested(d) = re else { continue }; - for re in resolved_lifetime_elisions { - let ResolvedNestedElisionTarget { segment_id, elided_lifetime_span, diagnostic } = re; + let NestedResolvedElisionTarget { segment_id, elided_lifetime_span, diagnostic } = d; self.r.lint_buffer.buffer_lint_with_diagnostic( - lint::builtin::ELIDED_LIFETIMES_IN_PATHS, + lint, segment_id, elided_lifetime_span, "hidden lifetime parameters in types are deprecated", diff --git a/src/tools/lint-docs/src/groups.rs b/src/tools/lint-docs/src/groups.rs index c5cd30ccc3437..84db26f955171 100644 --- a/src/tools/lint-docs/src/groups.rs +++ b/src/tools/lint-docs/src/groups.rs @@ -11,6 +11,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"), + ("elided-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"), diff --git a/tests/ui/lifetimes/elided-lifetime-in-path-details.rs b/tests/ui/lifetimes/elided-lifetime-in-path-details.rs new file mode 100644 index 0000000000000..5db22c48a8929 --- /dev/null +++ b/tests/ui/lifetimes/elided-lifetime-in-path-details.rs @@ -0,0 +1,168 @@ +// revisions: tied untied + +#![cfg_attr(tied, deny(elided_lifetimes_in_paths_tied))] +#![cfg_attr(untied, deny(elided_lifetimes_in_paths_untied))] + +struct ContainsLifetime<'a>(&'a u8); + +// ========== +// Core desired functionality + +fn top_level_to_nested(v: &u8) -> + ContainsLifetime + //[tied]~^ ERROR hidden lifetime parameters +{ + ContainsLifetime(v) +} + +fn nested_to_top_level( + v: ContainsLifetime, + //[tied]~^ ERROR hidden lifetime parameters +) -> &u8 +{ + v.0 +} + +fn nested_to_nested( + v: ContainsLifetime, + //[tied]~^ ERROR hidden lifetime parameters +) -> ContainsLifetime + //[tied]~^ ERROR hidden lifetime parameters +{ + v +} + +fn top_level_to_top_level(v: &u8) -> &u8 { + v +} + +// ========== +// Mixed named and elided lifetimes + +fn named_top_level_to_nested<'a>(v: &'a u8) -> + ContainsLifetime + //[tied]~^ ERROR hidden lifetime parameters +{ + ContainsLifetime(v) +} + +// ========== +// Using named lifetimes everywhere should not report + +fn named_top_level_to_named_nested<'a>(v: &'a u8) -> ContainsLifetime<'a> { + ContainsLifetime(v) +} + +fn named_nested_to_named_top_level<'a>(v: ContainsLifetime<'a>) -> &'a u8 { + v.0 +} + +fn named_nested_to_named_nested<'a>(v: ContainsLifetime<'a>) -> ContainsLifetime<'a> { + v +} + +// ========== +// Lifetimes with nothing to tie to + +fn top_level_parameter(v: &u8) {} + +fn nested_parameter(v: ContainsLifetime) {} +//[untied]~^ ERROR hidden lifetime parameters + +fn top_level_nested_parameter(v: &ContainsLifetime) {} +//[untied]~^ ERROR hidden lifetime parameters + +// ========== +// More complicated types + +fn top_level_to_multiple_nested(v: &u8) -> ( + ContainsLifetime, + //[tied]~^ ERROR hidden lifetime parameters + ContainsLifetime, + //[tied]~^ ERROR hidden lifetime parameters +) +{ + (ContainsLifetime(v), ContainsLifetime(v)) +} + +// ---------- + +struct AsAMethod(u8); + +impl AsAMethod { + fn top_level_to_nested(v: &u8) -> + ContainsLifetime + //[tied]~^ ERROR hidden lifetime parameters + { + ContainsLifetime(v) + } + + fn nested_to_top_level( + v: ContainsLifetime, + //[tied]~^ ERROR hidden lifetime parameters + ) -> &u8 + { + v.0 + } + + fn nested_to_nested( + v: ContainsLifetime, + //[tied]~^ ERROR hidden lifetime parameters + ) -> ContainsLifetime + //[tied]~^ ERROR hidden lifetime parameters + { + v + } + + fn top_level_to_top_level(v: &u8) -> &u8 { + v + } + + fn self_to_nested(&self) -> + ContainsLifetime + //[tied]~^ ERROR hidden lifetime parameters + { + ContainsLifetime(&self.0) + } + + fn self_to_nested_with_irrelevant_top_level_parameter(&self, _: &u8) -> + ContainsLifetime + //[tied]~^ ERROR hidden lifetime parameters + { + ContainsLifetime(&self.0) + } + + fn self_to_nested_with_irrelevant_nested_parameter( + &self, + _: ContainsLifetime, + //[untied]~^ ERROR hidden lifetime parameters + ) -> ContainsLifetime + //[tied]~^ ERROR hidden lifetime parameters + { + ContainsLifetime(&self.0) + } + + fn nested_in_parameter( + &self, + v: ContainsLifetime, + //[untied]~^ ERROR hidden lifetime parameters + ) {} + + fn nested_in_parameter_with_return( + &self, + v: ContainsLifetime, + //[untied]~^ ERROR hidden lifetime parameters + ) -> &u8 + { + &self.0 + } +} + +// // Do we need to worry about nested function signatures? +// // fn outer(_: fn(&) -> &) + +// // Do we need to worry about closures? + +// // Do we need to write tests for `self: Foo` syntax? + +fn main() {} diff --git a/tests/ui/lifetimes/elided-lifetime-in-path-details.tied.stderr b/tests/ui/lifetimes/elided-lifetime-in-path-details.tied.stderr new file mode 100644 index 0000000000000..cad9042183b3c --- /dev/null +++ b/tests/ui/lifetimes/elided-lifetime-in-path-details.tied.stderr @@ -0,0 +1,161 @@ +error: hidden lifetime parameters in types are deprecated + --> $DIR/elided-lifetime-in-path-details.rs:12:5 + | +LL | ContainsLifetime + | ^^^^^^^^^^^^^^^^ expected lifetime parameter + | +note: the lint level is defined here + --> $DIR/elided-lifetime-in-path-details.rs:3:24 + | +LL | #![cfg_attr(tied, deny(elided_lifetimes_in_paths_tied))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: indicate the anonymous lifetime + | +LL | ContainsLifetime<'_> + | ++++ + +error: hidden lifetime parameters in types are deprecated + --> $DIR/elided-lifetime-in-path-details.rs:19:8 + | +LL | v: ContainsLifetime, + | ^^^^^^^^^^^^^^^^ expected lifetime parameter + | +help: indicate the anonymous lifetime + | +LL | v: ContainsLifetime<'_>, + | ++++ + +error: hidden lifetime parameters in types are deprecated + --> $DIR/elided-lifetime-in-path-details.rs:27:8 + | +LL | v: ContainsLifetime, + | ^^^^^^^^^^^^^^^^ expected lifetime parameter + | +help: indicate the anonymous lifetime + | +LL | v: ContainsLifetime<'_>, + | ++++ + +error: hidden lifetime parameters in types are deprecated + --> $DIR/elided-lifetime-in-path-details.rs:29:6 + | +LL | ) -> ContainsLifetime + | ^^^^^^^^^^^^^^^^ expected lifetime parameter + | +help: indicate the anonymous lifetime + | +LL | ) -> ContainsLifetime<'_> + | ++++ + +error: hidden lifetime parameters in types are deprecated + --> $DIR/elided-lifetime-in-path-details.rs:43:5 + | +LL | ContainsLifetime + | ^^^^^^^^^^^^^^^^ expected lifetime parameter + | +help: indicate the anonymous lifetime + | +LL | ContainsLifetime<'_> + | ++++ + +error: hidden lifetime parameters in types are deprecated + --> $DIR/elided-lifetime-in-path-details.rs:79:5 + | +LL | ContainsLifetime, + | ^^^^^^^^^^^^^^^^ expected lifetime parameter + | +help: indicate the anonymous lifetime + | +LL | ContainsLifetime<'_>, + | ++++ + +error: hidden lifetime parameters in types are deprecated + --> $DIR/elided-lifetime-in-path-details.rs:81:5 + | +LL | ContainsLifetime, + | ^^^^^^^^^^^^^^^^ expected lifetime parameter + | +help: indicate the anonymous lifetime + | +LL | ContainsLifetime<'_>, + | ++++ + +error: hidden lifetime parameters in types are deprecated + --> $DIR/elided-lifetime-in-path-details.rs:94:9 + | +LL | ContainsLifetime + | ^^^^^^^^^^^^^^^^ expected lifetime parameter + | +help: indicate the anonymous lifetime + | +LL | ContainsLifetime<'_> + | ++++ + +error: hidden lifetime parameters in types are deprecated + --> $DIR/elided-lifetime-in-path-details.rs:101:12 + | +LL | v: ContainsLifetime, + | ^^^^^^^^^^^^^^^^ expected lifetime parameter + | +help: indicate the anonymous lifetime + | +LL | v: ContainsLifetime<'_>, + | ++++ + +error: hidden lifetime parameters in types are deprecated + --> $DIR/elided-lifetime-in-path-details.rs:109:12 + | +LL | v: ContainsLifetime, + | ^^^^^^^^^^^^^^^^ expected lifetime parameter + | +help: indicate the anonymous lifetime + | +LL | v: ContainsLifetime<'_>, + | ++++ + +error: hidden lifetime parameters in types are deprecated + --> $DIR/elided-lifetime-in-path-details.rs:111:10 + | +LL | ) -> ContainsLifetime + | ^^^^^^^^^^^^^^^^ expected lifetime parameter + | +help: indicate the anonymous lifetime + | +LL | ) -> ContainsLifetime<'_> + | ++++ + +error: hidden lifetime parameters in types are deprecated + --> $DIR/elided-lifetime-in-path-details.rs:122:9 + | +LL | ContainsLifetime + | ^^^^^^^^^^^^^^^^ expected lifetime parameter + | +help: indicate the anonymous lifetime + | +LL | ContainsLifetime<'_> + | ++++ + +error: hidden lifetime parameters in types are deprecated + --> $DIR/elided-lifetime-in-path-details.rs:129:9 + | +LL | ContainsLifetime + | ^^^^^^^^^^^^^^^^ expected lifetime parameter + | +help: indicate the anonymous lifetime + | +LL | ContainsLifetime<'_> + | ++++ + +error: hidden lifetime parameters in types are deprecated + --> $DIR/elided-lifetime-in-path-details.rs:139:10 + | +LL | ) -> ContainsLifetime + | ^^^^^^^^^^^^^^^^ expected lifetime parameter + | +help: indicate the anonymous lifetime + | +LL | ) -> ContainsLifetime<'_> + | ++++ + +error: aborting due to 14 previous errors + diff --git a/tests/ui/lifetimes/elided-lifetime-in-path-details.untied.stderr b/tests/ui/lifetimes/elided-lifetime-in-path-details.untied.stderr new file mode 100644 index 0000000000000..a3a0af5881b5e --- /dev/null +++ b/tests/ui/lifetimes/elided-lifetime-in-path-details.untied.stderr @@ -0,0 +1,62 @@ +error: hidden lifetime parameters in types are deprecated + --> $DIR/elided-lifetime-in-path-details.rs:69:24 + | +LL | fn nested_parameter(v: ContainsLifetime) {} + | ^^^^^^^^^^^^^^^^ expected lifetime parameter + | +note: the lint level is defined here + --> $DIR/elided-lifetime-in-path-details.rs:4:26 + | +LL | #![cfg_attr(untied, deny(elided_lifetimes_in_paths_untied))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: indicate the anonymous lifetime + | +LL | fn nested_parameter(v: ContainsLifetime<'_>) {} + | ++++ + +error: hidden lifetime parameters in types are deprecated + --> $DIR/elided-lifetime-in-path-details.rs:72:35 + | +LL | fn top_level_nested_parameter(v: &ContainsLifetime) {} + | ^^^^^^^^^^^^^^^^ expected lifetime parameter + | +help: indicate the anonymous lifetime + | +LL | fn top_level_nested_parameter(v: &ContainsLifetime<'_>) {} + | ++++ + +error: hidden lifetime parameters in types are deprecated + --> $DIR/elided-lifetime-in-path-details.rs:137:12 + | +LL | _: ContainsLifetime, + | ^^^^^^^^^^^^^^^^ expected lifetime parameter + | +help: indicate the anonymous lifetime + | +LL | _: ContainsLifetime<'_>, + | ++++ + +error: hidden lifetime parameters in types are deprecated + --> $DIR/elided-lifetime-in-path-details.rs:147:12 + | +LL | v: ContainsLifetime, + | ^^^^^^^^^^^^^^^^ expected lifetime parameter + | +help: indicate the anonymous lifetime + | +LL | v: ContainsLifetime<'_>, + | ++++ + +error: hidden lifetime parameters in types are deprecated + --> $DIR/elided-lifetime-in-path-details.rs:153:12 + | +LL | v: ContainsLifetime, + | ^^^^^^^^^^^^^^^^ expected lifetime parameter + | +help: indicate the anonymous lifetime + | +LL | v: ContainsLifetime<'_>, + | ++++ + +error: aborting due to 5 previous errors + diff --git a/tests/ui/lifetimes/issue-91763.stderr b/tests/ui/lifetimes/issue-91763.stderr index f7293ed809c3a..6d5d219b5b236 100644 --- a/tests/ui/lifetimes/issue-91763.stderr +++ b/tests/ui/lifetimes/issue-91763.stderr @@ -9,6 +9,7 @@ note: the lint level is defined here | LL | #![deny(elided_lifetimes_in_paths)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: `#[deny(elided_lifetimes_in_paths_untied)]` implied by `#[deny(elided_lifetimes_in_paths)]` help: indicate the anonymous lifetime | LL | fn f() -> Ptr<'_>; 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..6f95ff999cf6c 100644 --- a/tests/ui/lint/force-warn/allowed-by-default-lint.stderr +++ b/tests/ui/lint/force-warn/allowed-by-default-lint.stderr @@ -4,7 +4,8 @@ warning: hidden lifetime parameters in types are deprecated LL | fn foo(x: &Foo) {} | ^^^ expected lifetime parameter | - = note: requested on the command line with `--force-warn elided-lifetimes-in-paths` + = note: `--force-warn elided-lifetimes-in-paths-untied` implied by `--force-warn elided-lifetimes-in-paths` + = help: to override `--force-warn elided-lifetimes-in-paths` add `#[allow(elided_lifetimes_in_paths_untied)]` help: indicate the anonymous lifetime | LL | fn foo(x: &Foo<'_>) {} diff --git a/tests/ui/lint/reasons.rs b/tests/ui/lint/reasons.rs index da1c740c4a344..ddff1711bc1d8 100644 --- a/tests/ui/lint/reasons.rs +++ b/tests/ui/lint/reasons.rs @@ -19,6 +19,7 @@ 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 implied by //~| NOTE expected lifetime parameter //~| NOTE explicit anonymous lifetimes aid //~| HELP indicate the anonymous lifetime diff --git a/tests/ui/lint/reasons.stderr b/tests/ui/lint/reasons.stderr index cd8412153f101..878e61d0757d0 100644 --- a/tests/ui/lint/reasons.stderr +++ b/tests/ui/lint/reasons.stderr @@ -12,13 +12,14 @@ note: the lint level is defined here | LL | #![warn(elided_lifetimes_in_paths, | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: `#[warn(elided_lifetimes_in_paths_untied)]` implied by `#[warn(elided_lifetimes_in_paths)]` help: indicate the anonymous lifetime | LL | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { | ++++ warning: variable `Social_exchange_psychology` should have a snake case name - --> $DIR/reasons.rs:30:9 + --> $DIR/reasons.rs:31:9 | LL | let Social_exchange_psychology = CheaterDetectionMechanism {}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert the identifier to snake case (notice the capitalization): `social_exchange_psychology`