Emit `'_` for lifetime generics in `HirDisplay`

This commit is contained in:
hkalbasi 2023-06-05 10:55:47 +03:30
parent b4907a531f
commit 5531d46c95
4 changed files with 49 additions and 22 deletions

View File

@ -1223,7 +1223,8 @@ fn hir_fmt_generics(
generic_def: Option<hir_def::GenericDefId>, generic_def: Option<hir_def::GenericDefId>,
) -> Result<(), HirDisplayError> { ) -> Result<(), HirDisplayError> {
let db = f.db; let db = f.db;
if parameters.len(Interner) > 0 { let lifetime_args_count = generic_def.map_or(0, |g| db.generic_params(g).lifetimes.len());
if parameters.len(Interner) + lifetime_args_count > 0 {
let parameters_to_write = if f.display_target.is_source_code() || f.omit_verbose_types() { let parameters_to_write = if f.display_target.is_source_code() || f.omit_verbose_types() {
match generic_def match generic_def
.map(|generic_def_id| db.generic_defaults(generic_def_id)) .map(|generic_def_id| db.generic_defaults(generic_def_id))
@ -1268,26 +1269,28 @@ fn hir_fmt_generics(
} else { } else {
parameters.as_slice(Interner) parameters.as_slice(Interner)
}; };
if !parameters_to_write.is_empty() { if !parameters_to_write.is_empty() || lifetime_args_count != 0 {
write!(f, "<")?; write!(f, "<")?;
let mut first = true;
if f.display_target.is_source_code() { for _ in 0..lifetime_args_count {
let mut first = true; if !first {
for generic_arg in parameters_to_write { write!(f, ", ")?;
if !first { }
write!(f, ", ")?; first = false;
} write!(f, "'_")?;
first = false; }
for generic_arg in parameters_to_write {
if generic_arg.ty(Interner).map(|ty| ty.kind(Interner)) == Some(&TyKind::Error) if !first {
{ write!(f, ", ")?;
write!(f, "_")?; }
} else { first = false;
generic_arg.hir_fmt(f)?; if f.display_target.is_source_code()
} && generic_arg.ty(Interner).map(|ty| ty.kind(Interner)) == Some(&TyKind::Error)
{
write!(f, "_")?;
} else {
generic_arg.hir_fmt(f)?;
} }
} else {
f.write_joined(parameters_to_write, ", ")?;
} }
write!(f, ">")?; write!(f, ">")?;

View File

@ -1109,7 +1109,7 @@ fn var_args() {
#[lang = "va_list"] #[lang = "va_list"]
pub struct VaListImpl<'f>; pub struct VaListImpl<'f>;
fn my_fn(foo: ...) {} fn my_fn(foo: ...) {}
//^^^ VaListImpl //^^^ VaListImpl<'_>
"#, "#,
); );
} }

View File

@ -896,13 +896,13 @@ fn flush(&self) {
"#, "#,
expect![[r#" expect![[r#"
123..127 'self': &Mutex<T> 123..127 'self': &Mutex<T>
150..152 '{}': MutexGuard<T> 150..152 '{}': MutexGuard<'_, T>
234..238 'self': &{unknown} 234..238 'self': &{unknown}
240..290 '{ ...()); }': () 240..290 '{ ...()); }': ()
250..251 'w': &Mutex<BufWriter> 250..251 'w': &Mutex<BufWriter>
276..287 '*(w.lock())': BufWriter 276..287 '*(w.lock())': BufWriter
278..279 'w': &Mutex<BufWriter> 278..279 'w': &Mutex<BufWriter>
278..286 'w.lock()': MutexGuard<BufWriter> 278..286 'w.lock()': MutexGuard<'_, BufWriter>
"#]], "#]],
); );
} }

View File

@ -5478,6 +5478,30 @@ fn $0fun_name<T: Debug>(i: T) {
); );
} }
#[test]
fn dont_emit_type_with_hidden_lifetime_parameter() {
// FIXME: We should emit a `<T: Debug>` generic argument for the generated function
check_assist(
extract_function,
r#"
struct Struct<'a, T>(&'a T);
fn func<T: Debug>(i: Struct<'_, T>) {
$0foo(i);$0
}
"#,
r#"
struct Struct<'a, T>(&'a T);
fn func<T: Debug>(i: Struct<'_, T>) {
fun_name(i);
}
fn $0fun_name(i: Struct<'_, T>) {
foo(i);
}
"#,
);
}
#[test] #[test]
fn preserve_generics_from_body() { fn preserve_generics_from_body() {
check_assist( check_assist(