Unnamed repository; edit this file 'description' to name the repository.
| -rw-r--r-- | crates/hir-ty/src/lower/diagnostics.rs | 5 | ||||
| -rw-r--r-- | crates/hir-ty/src/lower/path.rs | 6 | ||||
| -rw-r--r-- | crates/hir/src/diagnostics.rs | 12 | ||||
| -rw-r--r-- | crates/ide-diagnostics/src/handlers/generic_default_refers_to_self.rs | 43 | ||||
| -rw-r--r-- | crates/ide-diagnostics/src/lib.rs | 2 |
5 files changed, 66 insertions, 2 deletions
diff --git a/crates/hir-ty/src/lower/diagnostics.rs b/crates/hir-ty/src/lower/diagnostics.rs index 009f047109..2565fb46ce 100644 --- a/crates/hir-ty/src/lower/diagnostics.rs +++ b/crates/hir-ty/src/lower/diagnostics.rs @@ -81,6 +81,11 @@ pub enum PathLoweringDiagnostic { def: GenericDefId, expected_count: u32, }, + /// Generic defaults are not allowed to refer to `Self`. + GenericDefaultRefersToSelf { + /// Index of the `Self` segment. + segment: u32, + }, } #[derive(Debug, Clone, Copy, PartialEq, Eq)] diff --git a/crates/hir-ty/src/lower/path.rs b/crates/hir-ty/src/lower/path.rs index 4f70732178..a364894539 100644 --- a/crates/hir-ty/src/lower/path.rs +++ b/crates/hir-ty/src/lower/path.rs @@ -300,8 +300,10 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { prohibit_generics_on_resolved(GenericArgsProhibitedReason::SelfTy); if self.ctx.lowering_param_default.is_some() { - // Generic defaults are not allowed to refer to `Self`. - // FIXME: Emit an error. + let segment = self.current_segment_u32(); + self.on_diagnostic(PathLoweringDiagnostic::GenericDefaultRefersToSelf { + segment, + }); return false; } } diff --git a/crates/hir/src/diagnostics.rs b/crates/hir/src/diagnostics.rs index 6cfb79d5a1..e0cab2d82c 100644 --- a/crates/hir/src/diagnostics.rs +++ b/crates/hir/src/diagnostics.rs @@ -57,6 +57,7 @@ diagnostics![AnyDiagnostic<'db> -> BreakOutsideOfLoop, CastToUnsized<'db>, ExpectedFunction<'db>, + GenericDefaultRefersToSelf, InactiveCode, IncoherentImpl, IncorrectCase, @@ -465,6 +466,12 @@ pub struct IncorrectGenericsOrder { pub expected_kind: GenericArgKind, } +#[derive(Debug)] +pub struct GenericDefaultRefersToSelf { + /// The `Self` segment. + pub segment: InFile<AstPtr<ast::PathSegment>>, +} + impl<'db> AnyDiagnostic<'db> { pub(crate) fn body_validation_diagnostic( db: &'db dyn HirDatabase, @@ -894,6 +901,11 @@ impl<'db> AnyDiagnostic<'db> { } .into() } + PathLoweringDiagnostic::GenericDefaultRefersToSelf { segment } => { + let segment = hir_segment_to_ast_segment(&path.value, segment)?; + let segment = path.with_value(AstPtr::new(&segment)); + GenericDefaultRefersToSelf { segment }.into() + } }) } diff --git a/crates/ide-diagnostics/src/handlers/generic_default_refers_to_self.rs b/crates/ide-diagnostics/src/handlers/generic_default_refers_to_self.rs new file mode 100644 index 0000000000..3d38159c4f --- /dev/null +++ b/crates/ide-diagnostics/src/handlers/generic_default_refers_to_self.rs @@ -0,0 +1,43 @@ +use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext}; + +// Diagnostic: generic-default-refers-to-self +// +// This diagnostic is shown when a generic default refers to `Self` +pub(crate) fn generic_default_refers_to_self( + ctx: &DiagnosticsContext<'_>, + d: &hir::GenericDefaultRefersToSelf, +) -> Diagnostic { + Diagnostic::new_with_syntax_node_ptr( + ctx, + DiagnosticCode::RustcHardError("E0735"), + "generic parameters cannot use `Self` in their defaults", + d.segment.map(Into::into), + ) + .stable() +} + +#[cfg(test)] +mod tests { + use crate::tests::check_diagnostics; + + #[test] + fn plain_self() { + check_diagnostics( + r#" +struct Foo<T = Self>(T); + // ^^^^ error: generic parameters cannot use `Self` in their defaults +"#, + ); + } + + #[test] + fn self_as_generic() { + check_diagnostics( + r#" +struct Wrapper<T>(T); +struct Foo<T = Wrapper<Self>>(T); + // ^^^^ error: generic parameters cannot use `Self` in their defaults +"#, + ); + } +} diff --git a/crates/ide-diagnostics/src/lib.rs b/crates/ide-diagnostics/src/lib.rs index 09c9f8eab0..54af3a35f4 100644 --- a/crates/ide-diagnostics/src/lib.rs +++ b/crates/ide-diagnostics/src/lib.rs @@ -35,6 +35,7 @@ mod handlers { pub(crate) mod elided_lifetimes_in_path; pub(crate) mod expected_function; pub(crate) mod generic_args_prohibited; + pub(crate) mod generic_default_refers_to_self; pub(crate) mod inactive_code; pub(crate) mod incoherent_impl; pub(crate) mod incorrect_case; @@ -477,6 +478,7 @@ pub fn semantic_diagnostics( 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), + AnyDiagnostic::GenericDefaultRefersToSelf(d) => handlers::generic_default_refers_to_self::generic_default_refers_to_self(&ctx, &d), }; res.push(d) } |