diff options
| author | Lukas Wirth <lukastw97@gmail.com> | 2025-03-25 07:49:45 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-03-25 07:49:45 +0000 |
| commit | c7509abf6f776e4277f6a9721a85fe5d99f9c53e (patch) | |
| tree | f7821ab624bbf90937540a0deff5483aa8862584 /src/tools/rust-analyzer | |
| parent | 51d3d8cfb1445eeaa9db819acfb3fe333b085eaa (diff) | |
| parent | d59743101d06c026cee1edeac2683558dd6484c3 (diff) | |
| download | rust-c7509abf6f776e4277f6a9721a85fe5d99f9c53e.tar.gz rust-c7509abf6f776e4277f6a9721a85fe5d99f9c53e.zip | |
Merge pull request #19347 from Shourya742/2025-03-13-add-diagnostic-for-dnagling-impl-with-lifetime
Add diagnostic for missing ambiguity error for impl trait
Diffstat (limited to 'src/tools/rust-analyzer')
5 files changed, 99 insertions, 1 deletions
diff --git a/src/tools/rust-analyzer/crates/syntax/src/validation.rs b/src/tools/rust-analyzer/crates/syntax/src/validation.rs index 14df485a9d4..12894a2bda8 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/validation.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/validation.rs @@ -363,11 +363,40 @@ fn validate_trait_object_ty(ty: ast::DynTraitType) -> Option<SyntaxError> { } fn validate_impl_object_ty(ty: ast::ImplTraitType, errors: &mut Vec<SyntaxError>) { - if ty.type_bound_list().map_or(0, |tbl| tbl.bounds().count()) == 0 { + let Some(bound_list) = ty.type_bound_list() else { errors.push(SyntaxError::new( "At least one trait must be specified", ty.syntax().text_range(), )); + return; + }; + + let bounds: Vec<_> = bound_list.bounds().collect(); + + if !bounds.iter().any(|b| !matches!(b.kind(), ast::TypeBoundKind::Lifetime(_))) { + errors.push(SyntaxError::new( + "At least one trait must be specified", + ty.syntax().text_range(), + )); + return; + } + + if bounds.len() == 1 { + return; + } + + let Some(preceding_token) = ty + .impl_token() + .and_then(|token| token.prev_token()) + .and_then(|prev| algo::skip_trivia_token(prev, Direction::Prev)) + else { + return; + }; + + if !matches!(preceding_token.kind(), T!['('] | T![<] | T![=]) + && matches!(preceding_token.kind(), T![&]) + { + errors.push(SyntaxError::new("ambiguous `+` in a type", ty.syntax().text_range())); } } diff --git a/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0261_dangling_impl_undeclared_lifetime.rast b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0261_dangling_impl_undeclared_lifetime.rast new file mode 100644 index 00000000000..bd71c61cada --- /dev/null +++ b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0261_dangling_impl_undeclared_lifetime.rast @@ -0,0 +1,38 @@ +SOURCE_FILE@0..28 + FN@0..28 + FN_KW@0..2 "fn" + WHITESPACE@2..3 " " + NAME@3..4 + IDENT@3..4 "f" + PARAM_LIST@4..25 + L_PAREN@4..5 "(" + PARAM@5..24 + WILDCARD_PAT@5..6 + UNDERSCORE@5..6 "_" + COLON@6..7 ":" + WHITESPACE@7..8 " " + REF_TYPE@8..24 + AMP@8..9 "&" + IMPL_TRAIT_TYPE@9..24 + IMPL_KW@9..13 "impl" + WHITESPACE@13..14 " " + TYPE_BOUND_LIST@14..24 + TYPE_BOUND@14..16 + LIFETIME@14..16 + LIFETIME_IDENT@14..16 "'a" + WHITESPACE@16..17 " " + PLUS@17..18 "+" + WHITESPACE@18..19 " " + TYPE_BOUND@19..24 + PATH_TYPE@19..24 + PATH@19..24 + PATH_SEGMENT@19..24 + NAME_REF@19..24 + IDENT@19..24 "Sized" + R_PAREN@24..25 ")" + WHITESPACE@25..26 " " + BLOCK_EXPR@26..28 + STMT_LIST@26..28 + L_CURLY@26..27 "{" + R_CURLY@27..28 "}" +error 9..24: ambiguous `+` in a type diff --git a/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0261_dangling_impl_undeclared_lifetime.rs b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0261_dangling_impl_undeclared_lifetime.rs new file mode 100644 index 00000000000..670a6f0ea7c --- /dev/null +++ b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0261_dangling_impl_undeclared_lifetime.rs @@ -0,0 +1 @@ +fn f(_: &impl 'a + Sized) {} \ No newline at end of file diff --git a/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/impl_trait_lifetime_only.rast b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/impl_trait_lifetime_only.rast new file mode 100644 index 00000000000..98aa862bc88 --- /dev/null +++ b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/impl_trait_lifetime_only.rast @@ -0,0 +1,29 @@ +SOURCE_FILE@0..20 + FN@0..20 + FN_KW@0..2 "fn" + WHITESPACE@2..3 " " + NAME@3..4 + IDENT@3..4 "f" + PARAM_LIST@4..17 + L_PAREN@4..5 "(" + PARAM@5..16 + WILDCARD_PAT@5..6 + UNDERSCORE@5..6 "_" + COLON@6..7 ":" + WHITESPACE@7..8 " " + REF_TYPE@8..16 + AMP@8..9 "&" + IMPL_TRAIT_TYPE@9..16 + IMPL_KW@9..13 "impl" + WHITESPACE@13..14 " " + TYPE_BOUND_LIST@14..16 + TYPE_BOUND@14..16 + LIFETIME@14..16 + LIFETIME_IDENT@14..16 "'a" + R_PAREN@16..17 ")" + WHITESPACE@17..18 " " + BLOCK_EXPR@18..20 + STMT_LIST@18..20 + L_CURLY@18..19 "{" + R_CURLY@19..20 "}" +error 9..16: At least one trait must be specified diff --git a/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/impl_trait_lifetime_only.rs b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/impl_trait_lifetime_only.rs new file mode 100644 index 00000000000..5b18a54ef5a --- /dev/null +++ b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/impl_trait_lifetime_only.rs @@ -0,0 +1 @@ +fn f(_: &impl 'a) {} \ No newline at end of file |
