Skip to content

Commit

Permalink
Rename elided_lifetimes_in_paths to lifetimes_hidden_in_paths
Browse files Browse the repository at this point in the history
Technically, `&u8` has a hidden lifetime that becomes the anonymous
lifetime `&'_ u8` which may then participate in elision in a function
signature. We specifically don't want to warn about usages of the
anonymous lifetime when it is part of elision.
  • Loading branch information
shepmaster committed Mar 11, 2024
1 parent f6d1275 commit 88dd6fc
Show file tree
Hide file tree
Showing 16 changed files with 74 additions and 73 deletions.
3 changes: 2 additions & 1 deletion compiler/rustc_baked_icu_data/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
#![allow(internal_features)]
#![feature(rustdoc_internals)]
#![doc(rust_logo)]
#![allow(elided_lifetimes_in_paths)]
#![cfg_attr(bootstrap, allow(elided_lifetimes_in_paths))]
#![cfg_attr(not(bootstrap), allow(lifetimes_hidden_in_paths))]

mod data {
include!("data/mod.rs");
Expand Down
13 changes: 7 additions & 6 deletions compiler/rustc_lint/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -303,8 +303,8 @@ fn register_builtins(store: &mut LintStore) {
BARE_TRAIT_OBJECTS,
UNUSED_EXTERN_CRATES,
ELLIPSIS_INCLUSIVE_RANGE_PATTERNS,
ELIDED_LIFETIMES_IN_PATHS_TIED,
ELIDED_LIFETIMES_IN_PATHS_UNTIED,
TIED_LIFETIMES_HIDDEN_IN_PATHS,
UNTIED_LIFETIMES_HIDDEN_IN_PATHS,
EXPLICIT_OUTLIVES_REQUIREMENTS,
// FIXME(#52665, #47816) not always applicable and not all
// macros are ready for this yet.
Expand All @@ -315,9 +315,9 @@ fn register_builtins(store: &mut LintStore) {
);

add_lint_group!(
"elided_lifetimes_in_paths",
ELIDED_LIFETIMES_IN_PATHS_TIED,
ELIDED_LIFETIMES_IN_PATHS_UNTIED,
"lifetimes_hidden_in_paths",
TIED_LIFETIMES_HIDDEN_IN_PATHS,
UNTIED_LIFETIMES_HIDDEN_IN_PATHS,
);

// Register renamed and removed lints.
Expand All @@ -336,7 +336,8 @@ fn register_builtins(store: &mut LintStore) {
store.register_renamed("static_mut_ref", "static_mut_refs");

// Register renamed lint groups
store.register_renamed_group("elided_lifetime_in_path", "elided_lifetimes_in_paths");
store.register_renamed_group("elided_lifetime_in_path", "lifetimes_hidden_in_paths");
store.register_renamed_group("elided_lifetimes_in_paths", "lifetimes_hidden_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
Expand Down
20 changes: 10 additions & 10 deletions compiler/rustc_lint_defs/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@ declare_lint_pass! {
DEPRECATED_WHERE_CLAUSE_LOCATION,
DUPLICATE_MACRO_ATTRIBUTES,
ELIDED_LIFETIMES_IN_ASSOCIATED_CONSTANT,
ELIDED_LIFETIMES_IN_PATHS_TIED,
ELIDED_LIFETIMES_IN_PATHS_UNTIED,
EXPORTED_PRIVATE_DEPENDENCIES,
FFI_UNWIND_CALLS,
FORBIDDEN_LINT_GROUPS,
Expand Down Expand Up @@ -93,6 +91,7 @@ declare_lint_pass! {
STATIC_MUT_REFS,
TEST_UNSTABLE_LINT,
TEXT_DIRECTION_CODEPOINT_IN_COMMENT,
TIED_LIFETIMES_HIDDEN_IN_PATHS,
TRIVIAL_CASTS,
TRIVIAL_NUMERIC_CASTS,
TYVAR_BEHIND_RAW_POINTER,
Expand All @@ -113,6 +112,7 @@ declare_lint_pass! {
UNSTABLE_NAME_COLLISIONS,
UNSTABLE_SYNTAX_PRE_EXPANSION,
UNSUPPORTED_CALLING_CONVENTIONS,
UNTIED_LIFETIMES_HIDDEN_IN_PATHS,
UNUSED_ASSIGNMENTS,
UNUSED_ASSOCIATED_TYPE_BOUNDS,
UNUSED_ATTRIBUTES,
Expand Down Expand Up @@ -1731,14 +1731,14 @@ declare_lint! {
}

declare_lint! {
/// The `elided_lifetimes_in_paths_tied` lint detects the use of
/// The `tied_lifetimes_hidden_in_paths` 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_tied)]
/// #![deny(tied_lifetimes_hidden_in_paths)]
/// #![deny(warnings)]
/// struct Foo<'a> {
/// x: &'a u32
Expand All @@ -1753,7 +1753,7 @@ declare_lint! {
///
/// ### Explanation
///
/// Elided lifetime parameters can make it difficult to see at a glance
/// 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].
Expand All @@ -1762,22 +1762,22 @@ 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_TIED,
pub TIED_LIFETIMES_HIDDEN_IN_PATHS,
Allow,
"hidden lifetime parameters in types are deprecated",
crate_level_only
}

declare_lint! {
/// The `elided_lifetimes_in_paths_untied` lint detects the use of
/// The `untied_lifetimes_hidden_in_paths` 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(untied_lifetimes_hidden_in_paths)]
/// #![deny(warnings)]
/// struct Foo<'a> {
/// x: &'a u32
Expand All @@ -1792,7 +1792,7 @@ declare_lint! {
///
/// ### Explanation
///
/// Elided lifetime parameters can make it difficult to see at a glance
/// 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].
Expand All @@ -1801,7 +1801,7 @@ 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_UNTIED,
pub UNTIED_LIFETIMES_HIDDEN_IN_PATHS,
Allow,
"hidden lifetime parameters in types make it hard to tell when borrowing is happening",
crate_level_only
Expand Down
79 changes: 39 additions & 40 deletions compiler/rustc_resolve/src/late.rs
Original file line number Diff line number Diff line change
Expand Up @@ -646,26 +646,26 @@ struct DiagMetadata<'ast> {
}

#[derive(Debug)]
enum ResolvedElisionTarget {
/// Elision in `&u8` -> `&'_ u8`
enum HiddenLifetimeTarget {
/// Lifetime in `&u8` is hidden (becomes `&'_ u8`)
TopLevel(NodeId),
/// Elision in `Foo` -> `Foo<'_>`
Nested(NestedResolvedElisionTarget),
/// Lifetime in `Foo` is hidden (becomes `Foo<'_>`)
Nested(NestedHiddenLifetimeTarget),
}

impl ResolvedElisionTarget {
impl HiddenLifetimeTarget {
fn node_id(&self) -> NodeId {
match *self {
Self::TopLevel(n) => n,
Self::Nested(NestedResolvedElisionTarget { segment_id, .. }) => segment_id,
Self::Nested(NestedHiddenLifetimeTarget { segment_id, .. }) => segment_id,
}
}
}

#[derive(Debug)]
struct NestedResolvedElisionTarget {
struct NestedHiddenLifetimeTarget {
segment_id: NodeId,
elided_lifetime_span: Span,
lifetime_span: Span,
diagnostic: lint::BuiltinLintDiag,
}

Expand Down Expand Up @@ -710,8 +710,8 @@ struct LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
/// Count the number of places a lifetime is used.
lifetime_uses: FxHashMap<LocalDefId, LifetimeUseSet>,

/// Track which types participated in lifetime elision
resolved_lifetime_elisions: Vec<ResolvedElisionTarget>,
/// Track which parameters/return values had hidden lifetimes.
hidden_lifetimes: Vec<HiddenLifetimeTarget>,
}

/// Walks the whole crate in DFS order, visiting each item, resolving names as it goes.
Expand Down Expand Up @@ -1325,7 +1325,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
// errors at module scope should always be reported
in_func_body: false,
lifetime_uses: Default::default(),
resolved_lifetime_elisions: Vec::new(),
hidden_lifetimes: Vec::new(),
}
}

Expand Down Expand Up @@ -1760,7 +1760,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
);
self.resolve_anonymous_lifetime(&lt, true);

self.resolved_lifetime_elisions.push(ResolvedElisionTarget::TopLevel(anchor_id));
self.hidden_lifetimes.push(HiddenLifetimeTarget::TopLevel(anchor_id));
}

#[instrument(level = "debug", skip(self))]
Expand Down Expand Up @@ -1972,10 +1972,10 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
}

if should_lint {
self.resolved_lifetime_elisions.push(ResolvedElisionTarget::Nested(
NestedResolvedElisionTarget {
self.hidden_lifetimes.push(HiddenLifetimeTarget::Nested(
NestedHiddenLifetimeTarget {
segment_id,
elided_lifetime_span,
lifetime_span: elided_lifetime_span,
diagnostic: lint::BuiltinLintDiag::ElidedLifetimesInPaths(
expected_lifetimes,
path_span,
Expand Down Expand Up @@ -2026,12 +2026,12 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
inputs: impl Iterator<Item = (Option<&'ast Pat>, &'ast Ty)> + Clone,
output_ty: &'ast FnRetTy,
) {
let outer_resolved_lifetime_elisions = take(&mut self.resolved_lifetime_elisions);
let outer_hidden_lifetimes = take(&mut self.hidden_lifetimes);

// Add each argument to the rib.
let elision_lifetime = self.resolve_fn_params(has_self, inputs);
debug!(?elision_lifetime);
let param_resolved_lifetime_elisions = take(&mut self.resolved_lifetime_elisions);
let param_hidden_lifetimes = take(&mut self.hidden_lifetimes);

let outer_failures = take(&mut self.diag_metadata.current_elision_failures);

Expand Down Expand Up @@ -2059,31 +2059,30 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
}
};

// We've recorded all elisions that occurred in the params and
// outputs, categorized by top-level or nested.
// We've recorded all hidden lifetimes 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
// nested hidden lifetimes in those params or outputs.
//
// The secondary case is for nested elisions that are not part
// of the tied lifetime relationship.
// The secondary case is for nested hidden lifetimes 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 output_hidden_lifetimes = replace(&mut self.hidden_lifetimes, outer_hidden_lifetimes);

match (output_resolved_lifetime_elisions.is_empty(), elision_lifetime) {
match (output_hidden_lifetimes.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,
self.report_lifetimes_hidden_in_paths(
param_hidden_lifetimes,
lint::builtin::UNTIED_LIFETIMES_HIDDEN_IN_PATHS,
);
}
(false, Some(elision_lifetime)) => {
let (primary, secondary): (Vec<_>, Vec<_>) =
param_resolved_lifetime_elisions.into_iter().partition(|re| {
// Recover the `NodeId` of an elided lifetime
param_hidden_lifetimes.into_iter().partition(|re| {
// Recover the `NodeId` of a hidden lifetime
let lvl1 = &self.r.lifetimes_res_map[&re.node_id()];
let lvl2 = match lvl1 {
LifetimeRes::ElidedAnchor { start, .. } => {
Expand All @@ -2095,32 +2094,32 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
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_lifetimes_hidden_in_paths(
primary.into_iter().chain(output_hidden_lifetimes),
lint::builtin::TIED_LIFETIMES_HIDDEN_IN_PATHS,
);
self.report_elided_lifetimes_in_paths(
self.report_lifetimes_hidden_in_paths(
secondary,
lint::builtin::ELIDED_LIFETIMES_IN_PATHS_UNTIED,
lint::builtin::UNTIED_LIFETIMES_HIDDEN_IN_PATHS,
);
}
}
}

fn report_elided_lifetimes_in_paths(
fn report_lifetimes_hidden_in_paths(
&mut self,
resolved_elisions: impl IntoIterator<Item = ResolvedElisionTarget>,
hidden_lifetimes: impl IntoIterator<Item = HiddenLifetimeTarget>,
lint: &'static lint::Lint,
) {
for re in resolved_elisions {
let ResolvedElisionTarget::Nested(d) = re else { continue };
for hl in hidden_lifetimes {
let HiddenLifetimeTarget::Nested(n) = hl else { continue };

let NestedResolvedElisionTarget { segment_id, elided_lifetime_span, diagnostic } = d;
let NestedHiddenLifetimeTarget { segment_id, lifetime_span, diagnostic } = n;

self.r.lint_buffer.buffer_lint_with_diagnostic(
lint,
segment_id,
elided_lifetime_span,
lifetime_span,
"hidden lifetime parameters in types are deprecated",
diagnostic,
);
Expand Down
2 changes: 1 addition & 1 deletion src/tools/lint-docs/src/groups.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +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"),
("lifetimes-hidden-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"),
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/lifetimes/elided-lifetime-in-path-details.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//@revisions: tied untied

#![cfg_attr(tied, deny(elided_lifetimes_in_paths_tied))]
#![cfg_attr(untied, deny(elided_lifetimes_in_paths_untied))]
#![cfg_attr(tied, deny(tied_lifetimes_hidden_in_paths))]
#![cfg_attr(untied, deny(untied_lifetimes_hidden_in_paths))]

struct ContainsLifetime<'a>(&'a u8);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ LL | ContainsLifetime
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))]
LL | #![cfg_attr(tied, deny(tied_lifetimes_hidden_in_paths))]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: indicate the anonymous lifetime
|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ LL | fn nested_parameter(v: ContainsLifetime) {}
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))]
LL | #![cfg_attr(untied, deny(untied_lifetimes_hidden_in_paths))]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: indicate the anonymous lifetime
|
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/lifetimes/issue-91763.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//@ aux-build:issue-91763-aux.rs

#![deny(elided_lifetimes_in_paths)]
#![deny(lifetimes_hidden_in_paths)]

extern crate issue_91763_aux;

Expand Down
4 changes: 2 additions & 2 deletions tests/ui/lifetimes/issue-91763.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ LL | fn f() -> Ptr<Thing>;
note: the lint level is defined here
--> $DIR/issue-91763.rs:3:9
|
LL | #![deny(elided_lifetimes_in_paths)]
LL | #![deny(lifetimes_hidden_in_paths)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
= note: `#[deny(elided_lifetimes_in_paths_untied)]` implied by `#[deny(elided_lifetimes_in_paths)]`
= note: `#[deny(untied_lifetimes_hidden_in_paths)]` implied by `#[deny(lifetimes_hidden_in_paths)]`
help: indicate the anonymous lifetime
|
LL | fn f() -> Ptr<Thing><'_>;
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/lint/force-warn/allowed-by-default-lint.rs
Original file line number Diff line number Diff line change
@@ -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 lifetimes_hidden_in_paths
//@ check-pass

struct Foo<'a> {
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/lint/force-warn/allowed-by-default-lint.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ warning: hidden lifetime parameters in types are deprecated
LL | fn foo(x: &Foo) {}
| ^^^ expected lifetime parameter
|
= 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)]`
= note: `--force-warn untied-lifetimes-hidden-in-paths` implied by `--force-warn lifetimes-hidden-in-paths`
= help: to override `--force-warn lifetimes-hidden-in-paths` add `#[allow(untied_lifetimes_hidden_in_paths)]`
help: indicate the anonymous lifetime
|
LL | fn foo(x: &Foo<'_>) {}
Expand Down
Loading

0 comments on commit 88dd6fc

Please sign in to comment.