Rollup merge of #97720 - cjgillot:all-fresh, r=petrochenkov
Always create elided lifetime parameters for functions Anonymous and elided lifetimes in functions are sometimes (async fns) --and sometimes not (regular fns)-- desugared to implicit generic parameters. This difference of treatment makes it some downstream analyses more complicated to handle. This step is a pre-requisite to perform lifetime elision resolution on AST. There is currently an inconsistency in the treatment of argument-position impl-trait for functions and async fns: ```rust trait Foo<'a> {} fn foo(t: impl Foo<'_>) {} //~ ERROR missing lifetime specifier async fn async_foo(t: impl Foo<'_>) {} //~ OK fn bar(t: impl Iterator<Item = &'_ u8>) {} //~ ERROR missing lifetime specifier async fn async_bar(t: impl Iterator<Item = &'_ u8>) {} //~ OK ``` The current implementation reports "missing lifetime specifier" on `foo`, but **accepts it** in `async_foo`. This PR **proposes to accept** the anonymous lifetime in both cases as an extra generic lifetime parameter. This change would be insta-stable, so let's ping t-lang. Anonymous lifetimes in GAT bindings keep being forbidden: ```rust fn foo(t: impl Foo<Assoc<'_> = Bar<'_>>) {} ^^ ^^ forbidden ok ``` I started a discussion here: https://rust-lang.zulipchat.com/#narrow/stream/213817-t-lang/topic/Anonymous.20lifetimes.20in.20universal.20impl-trait/near/284968606 r? ``@petrochenkov``
This commit is contained in:
commit
f5e9cb53ab
20 changed files with 163 additions and 56 deletions
|
@ -148,6 +148,8 @@ declare_features! (
|
||||||
/// below (it has to be checked before expansion possibly makes
|
/// below (it has to be checked before expansion possibly makes
|
||||||
/// macros disappear).
|
/// macros disappear).
|
||||||
(active, allow_internal_unstable, "1.0.0", None, None),
|
(active, allow_internal_unstable, "1.0.0", None, None),
|
||||||
|
/// Allows using anonymous lifetimes in argument-position impl-trait.
|
||||||
|
(active, anonymous_lifetime_in_impl_trait, "1.63.0", None, None),
|
||||||
/// Allows identifying the `compiler_builtins` crate.
|
/// Allows identifying the `compiler_builtins` crate.
|
||||||
(active, compiler_builtins, "1.13.0", None, None),
|
(active, compiler_builtins, "1.13.0", None, None),
|
||||||
/// Outputs useful `assert!` messages
|
/// Outputs useful `assert!` messages
|
||||||
|
|
|
@ -758,7 +758,10 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
|
||||||
// We don't need to deal with patterns in parameters, because
|
// We don't need to deal with patterns in parameters, because
|
||||||
// they are not possible for foreign or bodiless functions.
|
// they are not possible for foreign or bodiless functions.
|
||||||
self.with_lifetime_rib(
|
self.with_lifetime_rib(
|
||||||
LifetimeRibKind::AnonymousPassThrough(fn_id, false),
|
LifetimeRibKind::AnonymousCreateParameter {
|
||||||
|
binder: fn_id,
|
||||||
|
report_in_path: false,
|
||||||
|
},
|
||||||
|this| walk_list!(this, visit_param, &sig.decl.inputs),
|
|this| walk_list!(this, visit_param, &sig.decl.inputs),
|
||||||
);
|
);
|
||||||
self.with_lifetime_rib(
|
self.with_lifetime_rib(
|
||||||
|
@ -792,18 +795,13 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
|
||||||
// generic parameters. This is especially useful for `async fn`, where
|
// generic parameters. This is especially useful for `async fn`, where
|
||||||
// these fresh generic parameters can be applied to the opaque `impl Trait`
|
// these fresh generic parameters can be applied to the opaque `impl Trait`
|
||||||
// return type.
|
// return type.
|
||||||
let rib = if async_node_id.is_some() {
|
this.with_lifetime_rib(
|
||||||
// Only emit a hard error for `async fn`, since this kind of
|
|
||||||
// elision has always been allowed in regular `fn`s.
|
|
||||||
LifetimeRibKind::AnonymousCreateParameter {
|
LifetimeRibKind::AnonymousCreateParameter {
|
||||||
binder: fn_id,
|
binder: fn_id,
|
||||||
report_in_path: true,
|
// Only emit a hard error for `async fn`, since this kind of
|
||||||
}
|
// elision has always been allowed in regular `fn`s.
|
||||||
} else {
|
report_in_path: async_node_id.is_some(),
|
||||||
LifetimeRibKind::AnonymousPassThrough(fn_id, false)
|
},
|
||||||
};
|
|
||||||
this.with_lifetime_rib(
|
|
||||||
rib,
|
|
||||||
// Add each argument to the rib.
|
// Add each argument to the rib.
|
||||||
|this| this.resolve_params(&declaration.inputs),
|
|this| this.resolve_params(&declaration.inputs),
|
||||||
);
|
);
|
||||||
|
|
|
@ -1677,7 +1677,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
||||||
break None;
|
break None;
|
||||||
}
|
}
|
||||||
|
|
||||||
Scope::Binder { ref lifetimes, scope_type, s, .. } => {
|
Scope::Binder { ref lifetimes, scope_type, s, where_bound_origin, .. } => {
|
||||||
if let Some(&def) = lifetimes.get(®ion_def_id) {
|
if let Some(&def) = lifetimes.get(®ion_def_id) {
|
||||||
break Some(def.shifted(late_depth));
|
break Some(def.shifted(late_depth));
|
||||||
}
|
}
|
||||||
|
@ -1685,6 +1685,21 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
||||||
BinderScopeType::Normal => late_depth += 1,
|
BinderScopeType::Normal => late_depth += 1,
|
||||||
BinderScopeType::Concatenating => {}
|
BinderScopeType::Concatenating => {}
|
||||||
}
|
}
|
||||||
|
// Fresh lifetimes in APIT used to be allowed in async fns and forbidden in
|
||||||
|
// regular fns.
|
||||||
|
if let Some(hir::PredicateOrigin::ImplTrait) = where_bound_origin
|
||||||
|
&& let hir::LifetimeName::Param(_, hir::ParamName::Fresh) = lifetime_ref.name
|
||||||
|
&& let hir::IsAsync::NotAsync = self.tcx.asyncness(lifetime_ref.hir_id.owner)
|
||||||
|
&& !self.tcx.features().anonymous_lifetime_in_impl_trait
|
||||||
|
{
|
||||||
|
rustc_session::parse::feature_err(
|
||||||
|
&self.tcx.sess.parse_sess,
|
||||||
|
sym::anonymous_lifetime_in_impl_trait,
|
||||||
|
lifetime_ref.span,
|
||||||
|
"anonymous lifetimes in `impl Trait` are unstable",
|
||||||
|
).emit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
scope = s;
|
scope = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -341,6 +341,7 @@ symbols! {
|
||||||
always,
|
always,
|
||||||
and,
|
and,
|
||||||
and_then,
|
and_then,
|
||||||
|
anonymous_lifetime_in_impl_trait,
|
||||||
any,
|
any,
|
||||||
append_const_msg,
|
append_const_msg,
|
||||||
arbitrary_enum_discriminant,
|
arbitrary_enum_discriminant,
|
||||||
|
|
|
@ -93,7 +93,7 @@ impl CustomStruct {
|
||||||
|
|
||||||
fn test_alias(
|
fn test_alias(
|
||||||
value: CustomAlias,
|
value: CustomAlias,
|
||||||
reference: &CustomAlias, //~ ERROR passing `CustomAlias<>` by reference
|
reference: &CustomAlias, //~ ERROR passing `CustomAlias<'_>` by reference
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,11 +94,11 @@ error: passing `CustomStruct` by reference
|
||||||
LL | reference: &CustomStruct,
|
LL | reference: &CustomStruct,
|
||||||
| ^^^^^^^^^^^^^ help: try passing by value: `CustomStruct`
|
| ^^^^^^^^^^^^^ help: try passing by value: `CustomStruct`
|
||||||
|
|
||||||
error: passing `CustomAlias<>` by reference
|
error: passing `CustomAlias<'_>` by reference
|
||||||
--> $DIR/rustc_pass_by_value.rs:96:20
|
--> $DIR/rustc_pass_by_value.rs:96:20
|
||||||
|
|
|
|
||||||
LL | reference: &CustomAlias,
|
LL | reference: &CustomAlias,
|
||||||
| ^^^^^^^^^^^^ help: try passing by value: `CustomAlias<>`
|
| ^^^^^^^^^^^^ help: try passing by value: `CustomAlias<'_>`
|
||||||
|
|
||||||
error: passing `WithParameters<T, 1>` by reference
|
error: passing `WithParameters<T, 1>` by reference
|
||||||
--> $DIR/rustc_pass_by_value.rs:110:20
|
--> $DIR/rustc_pass_by_value.rs:110:20
|
||||||
|
|
|
@ -4,12 +4,12 @@ error[E0478]: lifetime bound not satisfied
|
||||||
LL | fn do_sth(_: u32) {}
|
LL | fn do_sth(_: u32) {}
|
||||||
| ^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
note: lifetime parameter instantiated with the anonymous lifetime #2 defined here
|
note: lifetime parameter instantiated with the anonymous lifetime as defined here
|
||||||
--> $DIR/issue-87748.rs:18:5
|
--> $DIR/issue-87748.rs:18:5
|
||||||
|
|
|
|
||||||
LL | fn do_sth(_: u32) {}
|
LL | fn do_sth(_: u32) {}
|
||||||
| ^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^
|
||||||
note: but lifetime parameter must outlive the anonymous lifetime #1 defined here
|
note: but lifetime parameter must outlive the anonymous lifetime as defined here
|
||||||
--> $DIR/issue-87748.rs:18:5
|
--> $DIR/issue-87748.rs:18:5
|
||||||
|
|
|
|
||||||
LL | fn do_sth(_: u32) {}
|
LL | fn do_sth(_: u32) {}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
// at some point in the future.
|
// at some point in the future.
|
||||||
|
|
||||||
#![feature(generic_associated_types)]
|
#![feature(generic_associated_types)]
|
||||||
|
#![feature(anonymous_lifetime_in_impl_trait)]
|
||||||
trait Foo {
|
trait Foo {
|
||||||
type Item<'a>;
|
type Item<'a>;
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,10 @@ trait Foo {
|
||||||
fn foo(x: &impl Foo<Item<'_> = u32>) { }
|
fn foo(x: &impl Foo<Item<'_> = u32>) { }
|
||||||
//~^ ERROR `'_` cannot be used here [E0637]
|
//~^ ERROR `'_` cannot be used here [E0637]
|
||||||
|
|
||||||
|
// Ok: the anonymous lifetime is bound to the function.
|
||||||
fn bar(x: &impl for<'a> Foo<Item<'a> = &'_ u32>) { }
|
fn bar(x: &impl for<'a> Foo<Item<'a> = &'_ u32>) { }
|
||||||
//~^ ERROR missing lifetime specifier
|
|
||||||
|
// Ok: the anonymous lifetime is bound to the function.
|
||||||
|
fn baz(x: &impl for<'a> Foo<Item<'a> = &u32>) { }
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -4,18 +4,6 @@ error[E0637]: `'_` cannot be used here
|
||||||
LL | fn foo(x: &impl Foo<Item<'_> = u32>) { }
|
LL | fn foo(x: &impl Foo<Item<'_> = u32>) { }
|
||||||
| ^^ `'_` is a reserved lifetime name
|
| ^^ `'_` is a reserved lifetime name
|
||||||
|
|
||||||
error[E0106]: missing lifetime specifier
|
error: aborting due to previous error
|
||||||
--> $DIR/issue-95305.rs:14:41
|
|
||||||
|
|
|
||||||
LL | fn bar(x: &impl for<'a> Foo<Item<'a> = &'_ u32>) { }
|
|
||||||
| ^^ expected named lifetime parameter
|
|
||||||
|
|
|
||||||
help: consider using the `'a` lifetime
|
|
||||||
|
|
|
||||||
LL | fn bar(x: &impl for<'a> Foo<Item<'a> = &'a u32>) { }
|
|
||||||
| ~~
|
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
For more information about this error, try `rustc --explain E0637`.
|
||||||
|
|
||||||
Some errors have detailed explanations: E0106, E0637.
|
|
||||||
For more information about an error, try `rustc --explain E0106`.
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ LL | fn next(&'a mut self) -> Option<Self::Item>
|
||||||
|
|
|
|
||||||
= note: expected fn pointer `fn(&mut RepeatMut<'a, T>) -> Option<_>`
|
= note: expected fn pointer `fn(&mut RepeatMut<'a, T>) -> Option<_>`
|
||||||
found fn pointer `fn(&'a mut RepeatMut<'a, T>) -> Option<_>`
|
found fn pointer `fn(&'a mut RepeatMut<'a, T>) -> Option<_>`
|
||||||
note: the anonymous lifetime #1 defined here...
|
note: the anonymous lifetime as defined here...
|
||||||
--> $DIR/issue-37884.rs:6:5
|
--> $DIR/issue-37884.rs:6:5
|
||||||
|
|
|
|
||||||
LL | fn next(&'a mut self) -> Option<Self::Item>
|
LL | fn next(&'a mut self) -> Option<Self::Item>
|
||||||
|
|
|
@ -2,14 +2,14 @@ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appea
|
||||||
--> $DIR/impl-trait-captures.rs:11:5
|
--> $DIR/impl-trait-captures.rs:11:5
|
||||||
|
|
|
|
||||||
LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> {
|
LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> {
|
||||||
| -- hidden type `&ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrAnon(0)) T` captures the anonymous lifetime defined here
|
| -- hidden type `&ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:13 ~ impl_trait_captures[1afc]::foo::'_), '_)) T` captures the anonymous lifetime defined here
|
||||||
LL | x
|
LL | x
|
||||||
| ^
|
| ^
|
||||||
|
|
|
|
||||||
help: to declare that the `impl Trait` captures `ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrAnon(0))`, you can add an explicit `ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrAnon(0))` lifetime bound
|
help: to declare that the `impl Trait` captures `ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:13 ~ impl_trait_captures[1afc]::foo::'_), '_))`, you can add an explicit `ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:13 ~ impl_trait_captures[1afc]::foo::'_), '_))` lifetime bound
|
||||||
|
|
|
|
||||||
LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> + ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrAnon(0)) {
|
LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> + ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:13 ~ impl_trait_captures[1afc]::foo::'_), '_)) {
|
||||||
| ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
| ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
21
src/test/ui/suggestions/impl-trait-missing-lifetime-gated.rs
Normal file
21
src/test/ui/suggestions/impl-trait-missing-lifetime-gated.rs
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
// edition:2021
|
||||||
|
// gate-test-anonymous_lifetime_in_impl_trait
|
||||||
|
// Verify the behaviour of `feature(anonymous_lifetime_in_impl_trait)`.
|
||||||
|
|
||||||
|
fn f(_: impl Iterator<Item = &'_ ()>) {}
|
||||||
|
//~^ ERROR anonymous lifetimes in `impl Trait` are unstable
|
||||||
|
|
||||||
|
fn g(x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
|
||||||
|
//~^ ERROR anonymous lifetimes in `impl Trait` are unstable
|
||||||
|
//~| ERROR missing lifetime specifier
|
||||||
|
|
||||||
|
// Anonymous lifetimes in async fn are already allowed.
|
||||||
|
// This is understood as `fn foo<'_1>(_: impl Iterator<Item = &'_1 ()>) {}`.
|
||||||
|
async fn h(_: impl Iterator<Item = &'_ ()>) {}
|
||||||
|
|
||||||
|
// Anonymous lifetimes in async fn are already allowed.
|
||||||
|
// But that lifetime does not participate in resolution.
|
||||||
|
async fn i(x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
|
||||||
|
//~^ ERROR missing lifetime specifier
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,44 @@
|
||||||
|
error[E0658]: anonymous lifetimes in `impl Trait` are unstable
|
||||||
|
--> $DIR/impl-trait-missing-lifetime-gated.rs:5:31
|
||||||
|
|
|
||||||
|
LL | fn f(_: impl Iterator<Item = &'_ ()>) {}
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
= help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable
|
||||||
|
|
||||||
|
error[E0106]: missing lifetime specifier
|
||||||
|
--> $DIR/impl-trait-missing-lifetime-gated.rs:8:50
|
||||||
|
|
|
||||||
|
LL | fn g(x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
|
||||||
|
| ^^ expected named lifetime parameter
|
||||||
|
|
|
||||||
|
= help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments
|
||||||
|
help: consider using the `'static` lifetime
|
||||||
|
|
|
||||||
|
LL | fn g(x: impl Iterator<Item = &'_ ()>) -> Option<&'static ()> { x.next() }
|
||||||
|
| ~~~~~~~
|
||||||
|
|
||||||
|
error[E0658]: anonymous lifetimes in `impl Trait` are unstable
|
||||||
|
--> $DIR/impl-trait-missing-lifetime-gated.rs:8:31
|
||||||
|
|
|
||||||
|
LL | fn g(x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
= help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable
|
||||||
|
|
||||||
|
error[E0106]: missing lifetime specifier
|
||||||
|
--> $DIR/impl-trait-missing-lifetime-gated.rs:18:56
|
||||||
|
|
|
||||||
|
LL | async fn i(x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
|
||||||
|
| ^^ expected named lifetime parameter
|
||||||
|
|
|
||||||
|
= help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments
|
||||||
|
help: consider using the `'static` lifetime
|
||||||
|
|
|
||||||
|
LL | async fn i(x: impl Iterator<Item = &'_ ()>) -> Option<&'static ()> { x.next() }
|
||||||
|
| ~~~~~~~
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
|
Some errors have detailed explanations: E0106, E0658.
|
||||||
|
For more information about an error, try `rustc --explain E0106`.
|
|
@ -1,2 +1,19 @@
|
||||||
fn f(_: impl Iterator<Item = &'_ ()>) {} //~ ERROR missing lifetime specifier
|
// edition:2021
|
||||||
|
|
||||||
|
#![feature(anonymous_lifetime_in_impl_trait)]
|
||||||
|
|
||||||
|
// This is understood as `fn foo<'_1>(_: impl Iterator<Item = &'_1 ()>) {}`.
|
||||||
|
fn f(_: impl Iterator<Item = &'_ ()>) {}
|
||||||
|
|
||||||
|
// But that lifetime does not participate in resolution.
|
||||||
|
fn g(x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
|
||||||
|
//~^ ERROR missing lifetime specifier
|
||||||
|
|
||||||
|
// This is understood as `fn foo<'_1>(_: impl Iterator<Item = &'_1 ()>) {}`.
|
||||||
|
async fn h(_: impl Iterator<Item = &'_ ()>) {}
|
||||||
|
|
||||||
|
// But that lifetime does not participate in resolution.
|
||||||
|
async fn i(x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
|
||||||
|
//~^ ERROR missing lifetime specifier
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -1,14 +1,27 @@
|
||||||
error[E0106]: missing lifetime specifier
|
error[E0106]: missing lifetime specifier
|
||||||
--> $DIR/impl-trait-missing-lifetime.rs:1:31
|
--> $DIR/impl-trait-missing-lifetime.rs:9:50
|
||||||
|
|
|
|
||||||
LL | fn f(_: impl Iterator<Item = &'_ ()>) {}
|
LL | fn g(x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
|
||||||
| ^^ expected named lifetime parameter
|
| ^^ expected named lifetime parameter
|
||||||
|
|
|
|
||||||
help: consider introducing a named lifetime parameter
|
= help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments
|
||||||
|
help: consider using the `'static` lifetime
|
||||||
|
|
|
|
||||||
LL | fn f<'a>(_: impl Iterator<Item = &'a ()>) {}
|
LL | fn g(x: impl Iterator<Item = &'_ ()>) -> Option<&'static ()> { x.next() }
|
||||||
| ++++ ~~
|
| ~~~~~~~
|
||||||
|
|
||||||
error: aborting due to previous error
|
error[E0106]: missing lifetime specifier
|
||||||
|
--> $DIR/impl-trait-missing-lifetime.rs:16:56
|
||||||
|
|
|
||||||
|
LL | async fn i(x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
|
||||||
|
| ^^ expected named lifetime parameter
|
||||||
|
|
|
||||||
|
= help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments
|
||||||
|
help: consider using the `'static` lifetime
|
||||||
|
|
|
||||||
|
LL | async fn i(x: impl Iterator<Item = &'_ ()>) -> Option<&'static ()> { x.next() }
|
||||||
|
| ~~~~~~~
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0106`.
|
For more information about this error, try `rustc --explain E0106`.
|
||||||
|
|
|
@ -21,11 +21,11 @@ note: because this has an unmet lifetime requirement
|
||||||
|
|
|
|
||||||
LL | pub struct Wrapper<T: Trait>(T);
|
LL | pub struct Wrapper<T: Trait>(T);
|
||||||
| ^^^^^ introduces a `'static` lifetime requirement
|
| ^^^^^ introduces a `'static` lifetime requirement
|
||||||
note: the anonymous lifetime #1 defined here...
|
note: the anonymous lifetime as defined here...
|
||||||
--> $DIR/wf-in-foreign-fn-decls-issue-80468.rs:16:5
|
--> $DIR/wf-in-foreign-fn-decls-issue-80468.rs:16:29
|
||||||
|
|
|
|
||||||
LL | pub fn repro(_: Wrapper<Ref>);
|
LL | pub fn repro(_: Wrapper<Ref>);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^
|
||||||
note: ...does not necessarily outlive the static lifetime introduced by the compatible `impl`
|
note: ...does not necessarily outlive the static lifetime introduced by the compatible `impl`
|
||||||
--> $DIR/wf-in-foreign-fn-decls-issue-80468.rs:13:1
|
--> $DIR/wf-in-foreign-fn-decls-issue-80468.rs:13:1
|
||||||
|
|
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_help;
|
||||||
use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
|
use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
|
||||||
use clippy_utils::{get_trait_def_id, paths, return_ty, trait_ref_of_method};
|
use clippy_utils::{get_trait_def_id, paths, return_ty, trait_ref_of_method};
|
||||||
use if_chain::if_chain;
|
use if_chain::if_chain;
|
||||||
use rustc_hir::{ImplItem, ImplItemKind};
|
use rustc_hir::{GenericParamKind, ImplItem, ImplItemKind};
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||||
use rustc_span::sym;
|
use rustc_span::sym;
|
||||||
|
@ -102,7 +102,7 @@ impl<'tcx> LateLintPass<'tcx> for InherentToString {
|
||||||
let decl = &signature.decl;
|
let decl = &signature.decl;
|
||||||
if decl.implicit_self.has_implicit_self();
|
if decl.implicit_self.has_implicit_self();
|
||||||
if decl.inputs.len() == 1;
|
if decl.inputs.len() == 1;
|
||||||
if impl_item.generics.params.is_empty();
|
if impl_item.generics.params.iter().all(|p| matches!(p.kind, GenericParamKind::Lifetime { .. }));
|
||||||
|
|
||||||
// Check if return type is String
|
// Check if return type is String
|
||||||
if is_type_diagnostic_item(cx, return_ty(cx, impl_item.hir_id()), sym::String);
|
if is_type_diagnostic_item(cx, return_ty(cx, impl_item.hir_id()), sym::String);
|
||||||
|
|
|
@ -9,8 +9,8 @@ use rustc_hir::intravisit::{
|
||||||
use rustc_hir::FnRetTy::Return;
|
use rustc_hir::FnRetTy::Return;
|
||||||
use rustc_hir::{
|
use rustc_hir::{
|
||||||
BareFnTy, BodyId, FnDecl, GenericArg, GenericBound, GenericParam, GenericParamKind, Generics, Impl, ImplItem,
|
BareFnTy, BodyId, FnDecl, GenericArg, GenericBound, GenericParam, GenericParamKind, Generics, Impl, ImplItem,
|
||||||
ImplItemKind, Item, ItemKind, LangItem, Lifetime, LifetimeName, ParamName, PolyTraitRef, PredicateOrigin,
|
ImplItemKind, Item, ItemKind, LangItem, Lifetime, LifetimeName, LifetimeParamKind, ParamName, PolyTraitRef,
|
||||||
TraitBoundModifier, TraitFn, TraitItem, TraitItemKind, Ty, TyKind, WherePredicate,
|
PredicateOrigin, TraitBoundModifier, TraitFn, TraitItem, TraitItemKind, Ty, TyKind, WherePredicate,
|
||||||
};
|
};
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
use rustc_middle::hir::nested_filter as middle_nested_filter;
|
use rustc_middle::hir::nested_filter as middle_nested_filter;
|
||||||
|
@ -338,7 +338,10 @@ fn could_use_elision<'tcx>(
|
||||||
fn allowed_lts_from(named_generics: &[GenericParam<'_>]) -> FxHashSet<RefLt> {
|
fn allowed_lts_from(named_generics: &[GenericParam<'_>]) -> FxHashSet<RefLt> {
|
||||||
let mut allowed_lts = FxHashSet::default();
|
let mut allowed_lts = FxHashSet::default();
|
||||||
for par in named_generics.iter() {
|
for par in named_generics.iter() {
|
||||||
if let GenericParamKind::Lifetime { .. } = par.kind {
|
if let GenericParamKind::Lifetime {
|
||||||
|
kind: LifetimeParamKind::Explicit,
|
||||||
|
} = par.kind
|
||||||
|
{
|
||||||
allowed_lts.insert(RefLt::Named(par.name.ident().name));
|
allowed_lts.insert(RefLt::Named(par.name.ident().name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -379,6 +382,7 @@ impl<'a, 'tcx> RefVisitor<'a, 'tcx> {
|
||||||
self.lts.push(RefLt::Static);
|
self.lts.push(RefLt::Static);
|
||||||
} else if let LifetimeName::Param(_, ParamName::Fresh) = lt.name {
|
} else if let LifetimeName::Param(_, ParamName::Fresh) = lt.name {
|
||||||
// Fresh lifetimes generated should be ignored.
|
// Fresh lifetimes generated should be ignored.
|
||||||
|
self.lts.push(RefLt::Unnamed);
|
||||||
} else if lt.is_elided() {
|
} else if lt.is_elided() {
|
||||||
self.lts.push(RefLt::Unnamed);
|
self.lts.push(RefLt::Unnamed);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -495,12 +495,13 @@ fn check_mut_from_ref<'tcx>(cx: &LateContext<'tcx>, sig: &FnSig<'_>, body: Optio
|
||||||
if let FnRetTy::Return(ty) = sig.decl.output
|
if let FnRetTy::Return(ty) = sig.decl.output
|
||||||
&& let Some((out, Mutability::Mut, _)) = get_rptr_lm(ty)
|
&& let Some((out, Mutability::Mut, _)) = get_rptr_lm(ty)
|
||||||
{
|
{
|
||||||
|
let out_region = cx.tcx.named_region(out.hir_id);
|
||||||
let args: Option<Vec<_>> = sig
|
let args: Option<Vec<_>> = sig
|
||||||
.decl
|
.decl
|
||||||
.inputs
|
.inputs
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(get_rptr_lm)
|
.filter_map(get_rptr_lm)
|
||||||
.filter(|&(lt, _, _)| lt.name == out.name)
|
.filter(|&(lt, _, _)| cx.tcx.named_region(lt.hir_id) == out_region)
|
||||||
.map(|(_, mutability, span)| (mutability == Mutability::Not).then(|| span))
|
.map(|(_, mutability, span)| (mutability == Mutability::Not).then(|| span))
|
||||||
.collect();
|
.collect();
|
||||||
if let Some(args) = args
|
if let Some(args) = args
|
||||||
|
|
|
@ -31,7 +31,7 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, lt: &Lifetime, m
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let ltopt = if lt.is_elided() {
|
let ltopt = if lt.name.is_anonymous() {
|
||||||
String::new()
|
String::new()
|
||||||
} else {
|
} else {
|
||||||
format!("{} ", lt.name.ident().as_str())
|
format!("{} ", lt.name.ident().as_str())
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue