mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-11-02 04:48:13 +00:00
Properly handle lifetimes when checking generic arguments len
And also, prepare for correct lowering of lifetime. We still don't handle most lifetimes correctly, but a bit more of the foundation to lifetime elision is now implemented.
This commit is contained in:
parent
3d00e247dd
commit
adcf699ea3
16 changed files with 858 additions and 226 deletions
112
crates/ide-diagnostics/src/handlers/elided_lifetimes_in_path.rs
Normal file
112
crates/ide-diagnostics/src/handlers/elided_lifetimes_in_path.rs
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext};
|
||||
|
||||
// Diagnostic: elided-lifetimes-in-path
|
||||
//
|
||||
// This diagnostic is triggered when lifetimes are elided in paths. It is a lint only for some cases,
|
||||
// and a hard error for others.
|
||||
pub(crate) fn elided_lifetimes_in_path(
|
||||
ctx: &DiagnosticsContext<'_>,
|
||||
d: &hir::ElidedLifetimesInPath,
|
||||
) -> Diagnostic {
|
||||
if d.hard_error {
|
||||
Diagnostic::new_with_syntax_node_ptr(
|
||||
ctx,
|
||||
DiagnosticCode::RustcHardError("E0726"),
|
||||
"implicit elided lifetime not allowed here",
|
||||
d.generics_or_segment.map(Into::into),
|
||||
)
|
||||
.experimental()
|
||||
} else {
|
||||
Diagnostic::new_with_syntax_node_ptr(
|
||||
ctx,
|
||||
DiagnosticCode::RustcLint("elided_lifetimes_in_paths"),
|
||||
"hidden lifetime parameters in types are deprecated",
|
||||
d.generics_or_segment.map(Into::into),
|
||||
)
|
||||
.experimental()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::tests::check_diagnostics;
|
||||
|
||||
#[test]
|
||||
fn fn_() {
|
||||
check_diagnostics(
|
||||
r#"
|
||||
#![warn(elided_lifetimes_in_paths)]
|
||||
|
||||
struct Foo<'a>(&'a ());
|
||||
|
||||
fn foo(_: Foo) {}
|
||||
// ^^^ warn: hidden lifetime parameters in types are deprecated
|
||||
"#,
|
||||
);
|
||||
check_diagnostics(
|
||||
r#"
|
||||
#![warn(elided_lifetimes_in_paths)]
|
||||
|
||||
struct Foo<'a>(&'a ());
|
||||
|
||||
fn foo(_: Foo<'_>) -> Foo { loop {} }
|
||||
// ^^^ warn: hidden lifetime parameters in types are deprecated
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn async_fn() {
|
||||
check_diagnostics(
|
||||
r#"
|
||||
struct Foo<'a>(&'a ());
|
||||
|
||||
async fn foo(_: Foo) {}
|
||||
// ^^^ error: implicit elided lifetime not allowed here
|
||||
"#,
|
||||
);
|
||||
check_diagnostics(
|
||||
r#"
|
||||
#![warn(elided_lifetimes_in_paths)]
|
||||
|
||||
struct Foo<'a>(&'a ());
|
||||
|
||||
fn foo(_: Foo<'_>) -> Foo { loop {} }
|
||||
// ^^^ warn: hidden lifetime parameters in types are deprecated
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn no_error_when_explicitly_elided() {
|
||||
check_diagnostics(
|
||||
r#"
|
||||
#![warn(elided_lifetimes_in_paths)]
|
||||
|
||||
struct Foo<'a>(&'a ());
|
||||
trait Trait<'a> {}
|
||||
|
||||
fn foo(_: Foo<'_>) -> Foo<'_> { loop {} }
|
||||
async fn bar(_: Foo<'_>) -> Foo<'_> { loop {} }
|
||||
impl Foo<'_> {}
|
||||
impl Trait<'_> for Foo<'_> {}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn impl_() {
|
||||
check_diagnostics(
|
||||
r#"
|
||||
struct Foo<'a>(&'a ());
|
||||
trait Trait<'a> {}
|
||||
|
||||
impl Foo {}
|
||||
// ^^^ error: implicit elided lifetime not allowed here
|
||||
|
||||
impl Trait for Foo<'_> {}
|
||||
// ^^^^^ error: implicit elided lifetime not allowed here
|
||||
"#,
|
||||
);
|
||||
}
|
||||
}
|
||||
92
crates/ide-diagnostics/src/handlers/missing_lifetime.rs
Normal file
92
crates/ide-diagnostics/src/handlers/missing_lifetime.rs
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext};
|
||||
|
||||
// Diagnostic: missing-lifetime
|
||||
//
|
||||
// This diagnostic is triggered when a lifetime argument is missing.
|
||||
pub(crate) fn missing_lifetime(
|
||||
ctx: &DiagnosticsContext<'_>,
|
||||
d: &hir::MissingLifetime,
|
||||
) -> Diagnostic {
|
||||
Diagnostic::new_with_syntax_node_ptr(
|
||||
ctx,
|
||||
DiagnosticCode::RustcHardError("E0106"),
|
||||
"missing lifetime specifier",
|
||||
d.generics_or_segment.map(Into::into),
|
||||
)
|
||||
.experimental()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::tests::check_diagnostics;
|
||||
|
||||
#[test]
|
||||
fn in_fields() {
|
||||
check_diagnostics(
|
||||
r#"
|
||||
struct Foo<'a>(&'a ());
|
||||
struct Bar(Foo);
|
||||
// ^^^ error: missing lifetime specifier
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bounds() {
|
||||
check_diagnostics(
|
||||
r#"
|
||||
struct Foo<'a, T>(&'a T);
|
||||
trait Trait<'a> {
|
||||
type Assoc;
|
||||
}
|
||||
|
||||
fn foo<'a, T: Trait>(
|
||||
// ^^^^^ error: missing lifetime specifier
|
||||
_: impl Trait<'a, Assoc: Trait>,
|
||||
// ^^^^^ error: missing lifetime specifier
|
||||
)
|
||||
where
|
||||
Foo<T>: Trait<'a>,
|
||||
// ^^^ error: missing lifetime specifier
|
||||
{
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn generic_defaults() {
|
||||
check_diagnostics(
|
||||
r#"
|
||||
struct Foo<'a>(&'a ());
|
||||
|
||||
struct Bar<T = Foo>(T);
|
||||
// ^^^ error: missing lifetime specifier
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn type_alias_type() {
|
||||
check_diagnostics(
|
||||
r#"
|
||||
struct Foo<'a>(&'a ());
|
||||
|
||||
type Bar = Foo;
|
||||
// ^^^ error: missing lifetime specifier
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn const_param_ty() {
|
||||
check_diagnostics(
|
||||
r#"
|
||||
struct Foo<'a>(&'a ());
|
||||
|
||||
fn bar<const F: Foo>() {}
|
||||
// ^^^ error: missing lifetime specifier
|
||||
"#,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -27,6 +27,7 @@ mod handlers {
|
|||
pub(crate) mod await_outside_of_async;
|
||||
pub(crate) mod bad_rtn;
|
||||
pub(crate) mod break_outside_of_loop;
|
||||
pub(crate) mod elided_lifetimes_in_path;
|
||||
pub(crate) mod expected_function;
|
||||
pub(crate) mod generic_args_prohibited;
|
||||
pub(crate) mod inactive_code;
|
||||
|
|
@ -40,6 +41,7 @@ mod handlers {
|
|||
pub(crate) mod malformed_derive;
|
||||
pub(crate) mod mismatched_arg_count;
|
||||
pub(crate) mod missing_fields;
|
||||
pub(crate) mod missing_lifetime;
|
||||
pub(crate) mod missing_match_arms;
|
||||
pub(crate) mod missing_unsafe;
|
||||
pub(crate) mod moved_out_of_ref;
|
||||
|
|
@ -503,6 +505,8 @@ pub fn semantic_diagnostics(
|
|||
AnyDiagnostic::BadRtn(d) => handlers::bad_rtn::bad_rtn(&ctx, &d),
|
||||
AnyDiagnostic::IncorrectGenericsLen(d) => handlers::incorrect_generics_len::incorrect_generics_len(&ctx, &d),
|
||||
AnyDiagnostic::IncorrectGenericsOrder(d) => handlers::incorrect_generics_order::incorrect_generics_order(&ctx, &d),
|
||||
AnyDiagnostic::MissingLifetime(d) => handlers::missing_lifetime::missing_lifetime(&ctx, &d),
|
||||
AnyDiagnostic::ElidedLifetimesInPath(d) => handlers::elided_lifetimes_in_path::elided_lifetimes_in_path(&ctx, &d),
|
||||
};
|
||||
res.push(d)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue