Complete diagnostics in ty lowering groundwork

Implement diagnostics in all places left: generics (predicates, defaults, const params' types), fields, and type aliases.

Unfortunately this results in a 20mb addition in `analysis-stats .` due to many type methods returning an addition diagnostics result now (even if it's `None` in most cases). I'm not sure if this can be improved.

An alternative strategy that can prevent the memory usage growth is to never produce diagnostics in hir-ty methods. Instead, lower all types in the hir crate when computing diagnostics from scratch (with diagnostics this time). But this has two serious disadvantages:
 1. This can cause code duplication (although it can probably be not that bad, it will still mean a lot more code).
 2. I believe we eventually want to compute diagnostics for the *entire* workspace (either on-type or on-save or something alike), so users can know when they have diagnostics even in inactive files. Choosing this approach will mean we lose all precomputed salsa queries. For one file this is fine, for the whole workspace this will be very slow.
This commit is contained in:
Chayim Refael Friedman 2024-11-21 02:21:16 +02:00
parent 5f25ae3d1b
commit 21ad3b5b87
8 changed files with 621 additions and 103 deletions

View file

@ -68,6 +68,9 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::GenericArgsProhibited) -> Option
#[cfg(test)]
mod tests {
// This diagnostic was the first to be emitted in ty lowering, so the tests here also test
// diagnostics in ty lowering in general (which is why there are so many of them).
use crate::tests::{check_diagnostics, check_fix};
#[test]
@ -239,4 +242,201 @@ fn foo() {
}"#,
);
}
#[test]
fn in_fields() {
check_diagnostics(
r#"
struct A(bool<i32>);
// ^^^^^ 💡 error: generic arguments are not allowed on builtin types
struct B { v: bool<(), 1> }
// ^^^^^^^ 💡 error: generic arguments are not allowed on builtin types
union C {
a: bool<i32>,
// ^^^^^ 💡 error: generic arguments are not allowed on builtin types
b: i32<bool>,
// ^^^^^^ 💡 error: generic arguments are not allowed on builtin types
}
enum D {
A(bool<i32>),
// ^^^^^ 💡 error: generic arguments are not allowed on builtin types
B { v: i32<bool> },
// ^^^^^^ 💡 error: generic arguments are not allowed on builtin types
}
"#,
);
}
#[test]
fn in_generics() {
check_diagnostics(
r#"
mod foo {
pub trait Trait {}
}
struct A<A: foo::<()>::Trait>(A)
// ^^^^^^ 💡 error: generic arguments are not allowed on modules
where bool<i32>: foo::Trait;
// ^^^^^ 💡 error: generic arguments are not allowed on builtin types
union B<A: foo::<()>::Trait>
// ^^^^^^ 💡 error: generic arguments are not allowed on modules
where bool<i32>: foo::Trait
// ^^^^^ 💡 error: generic arguments are not allowed on builtin types
{ a: A }
enum C<A: foo::<()>::Trait>
// ^^^^^^ 💡 error: generic arguments are not allowed on modules
where bool<i32>: foo::Trait
// ^^^^^ 💡 error: generic arguments are not allowed on builtin types
{}
fn f<A: foo::<()>::Trait>()
// ^^^^^^ 💡 error: generic arguments are not allowed on modules
where bool<i32>: foo::Trait
// ^^^^^ 💡 error: generic arguments are not allowed on builtin types
{}
type D<A: foo::<()>::Trait> = A
// ^^^^^^ 💡 error: generic arguments are not allowed on modules
where bool<i32>: foo::Trait;
// ^^^^^ 💡 error: generic arguments are not allowed on builtin types
trait E<A: foo::<()>::Trait>
// ^^^^^^ 💡 error: generic arguments are not allowed on modules
where bool<i32>: foo::Trait
// ^^^^^ 💡 error: generic arguments are not allowed on builtin types
{
fn f<B: foo::<()>::Trait>()
// ^^^^^^ 💡 error: generic arguments are not allowed on modules
where bool<i32>: foo::Trait
// ^^^^^ 💡 error: generic arguments are not allowed on builtin types
{}
type D<B: foo::<()>::Trait> = A
// ^^^^^^ 💡 error: generic arguments are not allowed on modules
where bool<i32>: foo::Trait;
// ^^^^^ 💡 error: generic arguments are not allowed on builtin types
}
impl<A: foo::<()>::Trait> E for ()
// ^^^^^^ 💡 error: generic arguments are not allowed on modules
where bool<i32>: foo::Trait
// ^^^^^ 💡 error: generic arguments are not allowed on builtin types
{
fn f<B: foo::<()>::Trait>()
// ^^^^^^ 💡 error: generic arguments are not allowed on modules
where bool<i32>: foo::Trait
// ^^^^^ 💡 error: generic arguments are not allowed on builtin types
{}
type D<B: foo::<()>::Trait> = A
// ^^^^^^ 💡 error: generic arguments are not allowed on modules
where bool<i32>: foo::Trait;
// ^^^^^ 💡 error: generic arguments are not allowed on builtin types
}
"#,
);
}
#[test]
fn assoc_items() {
check_diagnostics(
r#"
struct Foo;
trait Trait {
fn f() -> bool<i32> { true }
// ^^^^^ 💡 error: generic arguments are not allowed on builtin types
type T = i32<bool>;
// ^^^^^^ 💡 error: generic arguments are not allowed on builtin types
}
impl Trait for Foo {
fn f() -> bool<i32> { true }
// ^^^^^ 💡 error: generic arguments are not allowed on builtin types
type T = i32<bool>;
// ^^^^^^ 💡 error: generic arguments are not allowed on builtin types
}
impl Foo {
fn f() -> bool<i32> { true }
// ^^^^^ 💡 error: generic arguments are not allowed on builtin types
type T = i32<bool>;
// ^^^^^^ 💡 error: generic arguments are not allowed on builtin types
}
"#,
);
}
#[test]
fn const_param_ty() {
check_diagnostics(
r#"
fn foo<
const A: bool<i32>,
// ^^^^^ 💡 error: generic arguments are not allowed on builtin types
B,
C,
const D: bool<i32>,
// ^^^^^ 💡 error: generic arguments are not allowed on builtin types
const E: bool<i32>,
// ^^^^^ 💡 error: generic arguments are not allowed on builtin types
>() {}
"#,
);
}
#[test]
fn generic_defaults() {
check_diagnostics(
r#"
struct Foo<A = bool<i32>>(A);
// ^^^^^ 💡 error: generic arguments are not allowed on builtin types
"#,
);
}
#[test]
fn impl_self_ty() {
check_diagnostics(
r#"
struct Foo<A>(A);
trait Trait {}
impl Foo<bool<i32>> {}
// ^^^^^ 💡 error: generic arguments are not allowed on builtin types
impl Trait for Foo<bool<i32>> {}
// ^^^^^ 💡 error: generic arguments are not allowed on builtin types
"#,
);
}
#[test]
fn impl_trait() {
check_diagnostics(
r#"
mod foo {
pub trait Trait {}
}
impl foo::<()>::Trait for () {}
// ^^^^^^ 💡 error: generic arguments are not allowed on modules
"#,
);
}
#[test]
fn type_alias() {
check_diagnostics(
r#"
pub trait Trait {
type Assoc;
}
type T = bool<i32>;
// ^^^^^ 💡 error: generic arguments are not allowed on builtin types
impl Trait for () {
type Assoc = i32<bool>;
// ^^^^^^ 💡 error: generic arguments are not allowed on builtin types
}
"#,
);
}
}