diff options
| author | Jake Goulding <jake.goulding@gmail.com> | 2025-06-06 14:18:32 -0400 |
|---|---|---|
| committer | Jake Goulding <jake.goulding@gmail.com> | 2025-06-06 16:27:16 -0400 |
| commit | 9c6320abb4bbe51f876e5e918a600e9a5c9dd11b (patch) | |
| tree | 5536d0146f5ea8219eeeb6663675f923af03912a | |
| parent | d00435f223dc3a88d8c5f472b10ba948b7959cc6 (diff) | |
| download | rust-9c6320abb4bbe51f876e5e918a600e9a5c9dd11b.tar.gz rust-9c6320abb4bbe51f876e5e918a600e9a5c9dd11b.zip | |
Apply `mismatched-lifetime-syntaxes` to trait and extern functions
5 files changed, 140 insertions, 10 deletions
diff --git a/compiler/rustc_lint/src/lifetime_syntax.rs b/compiler/rustc_lint/src/lifetime_syntax.rs index 31b038e6a46..95b7b69bd5a 100644 --- a/compiler/rustc_lint/src/lifetime_syntax.rs +++ b/compiler/rustc_lint/src/lifetime_syntax.rs @@ -84,19 +84,45 @@ impl<'tcx> LateLintPass<'tcx> for LifetimeSyntax { _: rustc_span::Span, _: rustc_span::def_id::LocalDefId, ) { - let mut input_map = Default::default(); - let mut output_map = Default::default(); + check_fn_like(cx, fd); + } - for input in fd.inputs { - LifetimeInfoCollector::collect(input, &mut input_map); + #[instrument(skip_all)] + fn check_trait_item(&mut self, cx: &LateContext<'tcx>, ti: &'tcx hir::TraitItem<'tcx>) { + match ti.kind { + hir::TraitItemKind::Const(..) => {} + hir::TraitItemKind::Fn(fn_sig, _trait_fn) => check_fn_like(cx, fn_sig.decl), + hir::TraitItemKind::Type(..) => {} } + } - if let hir::FnRetTy::Return(output) = fd.output { - LifetimeInfoCollector::collect(output, &mut output_map); + #[instrument(skip_all)] + fn check_foreign_item( + &mut self, + cx: &LateContext<'tcx>, + fi: &'tcx rustc_hir::ForeignItem<'tcx>, + ) { + match fi.kind { + hir::ForeignItemKind::Fn(fn_sig, _idents, _generics) => check_fn_like(cx, fn_sig.decl), + hir::ForeignItemKind::Static(..) => {} + hir::ForeignItemKind::Type => {} } + } +} + +fn check_fn_like<'tcx>(cx: &LateContext<'tcx>, fd: &'tcx hir::FnDecl<'tcx>) { + let mut input_map = Default::default(); + let mut output_map = Default::default(); - report_mismatches(cx, &input_map, &output_map); + for input in fd.inputs { + LifetimeInfoCollector::collect(input, &mut input_map); } + + if let hir::FnRetTy::Return(output) = fd.output { + LifetimeInfoCollector::collect(output, &mut output_map); + } + + report_mismatches(cx, &input_map, &output_map); } #[instrument(skip_all)] diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-1.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-1.rs index e00a31e26aa..cca60852efd 100644 --- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-1.rs +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-1.rs @@ -20,7 +20,7 @@ where Self: Sized, { type I: for<'a> FamilyLt<'a>; - fn inject(_: &()) -> <Self::I as FamilyLt>::Out; + fn inject(_: &()) -> <Self::I as FamilyLt<'_>>::Out; } impl<T: 'static> Inject for RefMutFamily<T> { diff --git a/tests/ui/lifetimes/mismatched-lifetime-syntaxes.rs b/tests/ui/lifetimes/mismatched-lifetime-syntaxes.rs index 6d8487b99c6..b98423afb17 100644 --- a/tests/ui/lifetimes/mismatched-lifetime-syntaxes.rs +++ b/tests/ui/lifetimes/mismatched-lifetime-syntaxes.rs @@ -220,6 +220,45 @@ mod diagnostic_output { } } +/// Trait functions are represented differently in the HIR. Make sure +/// we visit them. +mod trait_functions { + #[derive(Copy, Clone)] + struct ContainsLifetime<'a>(&'a u8); + + trait TheTrait { + fn implicit_ref_to_implicit_path(v: &u8) -> ContainsLifetime; + //~^ ERROR lifetime flowing from input to output with different syntax + + fn method_implicit_ref_to_implicit_path(&self) -> ContainsLifetime; + //~^ ERROR lifetime flowing from input to output with different syntax + } + + impl TheTrait for &u8 { + fn implicit_ref_to_implicit_path(v: &u8) -> ContainsLifetime { + //~^ ERROR lifetime flowing from input to output with different syntax + ContainsLifetime(v) + } + + fn method_implicit_ref_to_implicit_path(&self) -> ContainsLifetime { + //~^ ERROR lifetime flowing from input to output with different syntax + ContainsLifetime(self) + } + } +} + +/// Extern functions are represented differently in the HIR. Make sure +/// we visit them. +mod foreign_functions { + #[derive(Copy, Clone)] + struct ContainsLifetime<'a>(&'a u8); + + extern "Rust" { + fn implicit_ref_to_implicit_path(v: &u8) -> ContainsLifetime; + //~^ ERROR lifetime flowing from input to output with different syntax + } +} + /// These usages are expected to **not** trigger the lint mod acceptable_uses { #[derive(Copy, Clone)] diff --git a/tests/ui/lifetimes/mismatched-lifetime-syntaxes.stderr b/tests/ui/lifetimes/mismatched-lifetime-syntaxes.stderr index 0ec16a266b6..108b3f14169 100644 --- a/tests/ui/lifetimes/mismatched-lifetime-syntaxes.stderr +++ b/tests/ui/lifetimes/mismatched-lifetime-syntaxes.stderr @@ -469,5 +469,70 @@ help: one option is to consistently use `'a` LL | fn multiple_outputs<'a>(v: &'a u8) -> (&'a u8, &'a u8) { | ++ ++ -error: aborting due to 34 previous errors +error: lifetime flowing from input to output with different syntax can be confusing + --> $DIR/mismatched-lifetime-syntaxes.rs:230:45 + | +LL | fn implicit_ref_to_implicit_path(v: &u8) -> ContainsLifetime; + | ^^^ ---------------- the lifetime gets resolved as `'_` + | | + | this lifetime flows to the output + | +help: one option is to remove the lifetime for references and use the anonymous lifetime for paths + | +LL | fn implicit_ref_to_implicit_path(v: &u8) -> ContainsLifetime<'_>; + | ++++ + +error: lifetime flowing from input to output with different syntax can be confusing + --> $DIR/mismatched-lifetime-syntaxes.rs:233:49 + | +LL | fn method_implicit_ref_to_implicit_path(&self) -> ContainsLifetime; + | ^^^^^ ---------------- the lifetime gets resolved as `'_` + | | + | this lifetime flows to the output + | +help: one option is to remove the lifetime for references and use the anonymous lifetime for paths + | +LL | fn method_implicit_ref_to_implicit_path(&self) -> ContainsLifetime<'_>; + | ++++ + +error: lifetime flowing from input to output with different syntax can be confusing + --> $DIR/mismatched-lifetime-syntaxes.rs:238:45 + | +LL | fn implicit_ref_to_implicit_path(v: &u8) -> ContainsLifetime { + | ^^^ ---------------- the lifetime gets resolved as `'_` + | | + | this lifetime flows to the output + | +help: one option is to remove the lifetime for references and use the anonymous lifetime for paths + | +LL | fn implicit_ref_to_implicit_path(v: &u8) -> ContainsLifetime<'_> { + | ++++ + +error: lifetime flowing from input to output with different syntax can be confusing + --> $DIR/mismatched-lifetime-syntaxes.rs:243:49 + | +LL | fn method_implicit_ref_to_implicit_path(&self) -> ContainsLifetime { + | ^^^^^ ---------------- the lifetime gets resolved as `'_` + | | + | this lifetime flows to the output + | +help: one option is to remove the lifetime for references and use the anonymous lifetime for paths + | +LL | fn method_implicit_ref_to_implicit_path(&self) -> ContainsLifetime<'_> { + | ++++ + +error: lifetime flowing from input to output with different syntax can be confusing + --> $DIR/mismatched-lifetime-syntaxes.rs:257:45 + | +LL | fn implicit_ref_to_implicit_path(v: &u8) -> ContainsLifetime; + | ^^^ ---------------- the lifetime gets resolved as `'_` + | | + | this lifetime flows to the output + | +help: one option is to remove the lifetime for references and use the anonymous lifetime for paths + | +LL | fn implicit_ref_to_implicit_path(v: &u8) -> ContainsLifetime<'_>; + | ++++ + +error: aborting due to 39 previous errors diff --git a/tests/ui/traits/associated_type_bound/hrtb-associated.rs b/tests/ui/traits/associated_type_bound/hrtb-associated.rs index 59e5a09c0cb..bf9f59c05e3 100644 --- a/tests/ui/traits/associated_type_bound/hrtb-associated.rs +++ b/tests/ui/traits/associated_type_bound/hrtb-associated.rs @@ -10,7 +10,7 @@ pub trait Provides<'a> { pub trait Selector: for<'a> Provides<'a> { type Namespace: PartialEq + for<'a> PartialEq<<Self as Provides<'a>>::Item>; - fn get_namespace(&self) -> <Self as Provides>::Item; + fn get_namespace(&self) -> <Self as Provides<'_>>::Item; } pub struct MySelector; |
