From afe6e5ba0f81963b4af17d5e4f9fa85a3d7b9fc9 Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Sun, 2 Mar 2025 19:41:39 +0530 Subject: [PATCH 1/3] add diagnostic for dangling dyn --- crates/syntax/src/validation.rs | 24 ++++++++++++------ .../parser/validation/0224_dangling_dyn.rast | 25 +++++++++++++++++++ .../parser/validation/0224_dangling_dyn.rs | 1 + 3 files changed, 42 insertions(+), 8 deletions(-) create mode 100644 crates/syntax/test_data/parser/validation/0224_dangling_dyn.rast create mode 100644 crates/syntax/test_data/parser/validation/0224_dangling_dyn.rs diff --git a/crates/syntax/src/validation.rs b/crates/syntax/src/validation.rs index 13d352d3c6..2dc86411e4 100644 --- a/crates/syntax/src/validation.rs +++ b/crates/syntax/src/validation.rs @@ -340,17 +340,25 @@ fn validate_trait_object_fn_ptr_ret_ty(ty: ast::FnPtrType, errors: &mut Vec Option { let tbl = ty.type_bound_list()?; + let bounds_count = tbl.bounds().count(); - if tbl.bounds().count() > 1 { - let dyn_token = ty.dyn_token()?; - let potential_parenthesis = - algo::skip_trivia_token(dyn_token.prev_token()?, Direction::Prev)?; - let kind = potential_parenthesis.kind(); - if !matches!(kind, T!['('] | T![<] | T![=]) { - return Some(SyntaxError::new("ambiguous `+` in a type", ty.syntax().text_range())); + match bounds_count { + 0 => Some(SyntaxError::new( + "At least one trait is required for an object type", + ty.syntax().text_range(), + )), + _ if bounds_count > 1 => { + let dyn_token = ty.dyn_token()?; + let preceding_token = + algo::skip_trivia_token(dyn_token.prev_token()?, Direction::Prev)?; + + if !matches!(preceding_token.kind(), T!['('] | T![<] | T![=]) { + return Some(SyntaxError::new("ambiguous `+` in a type", ty.syntax().text_range())); + } + None } + _ => None, } - None } fn validate_macro_rules(mac: ast::MacroRules, errors: &mut Vec) { diff --git a/crates/syntax/test_data/parser/validation/0224_dangling_dyn.rast b/crates/syntax/test_data/parser/validation/0224_dangling_dyn.rast new file mode 100644 index 0000000000..b31af5fbc6 --- /dev/null +++ b/crates/syntax/test_data/parser/validation/0224_dangling_dyn.rast @@ -0,0 +1,25 @@ +SOURCE_FILE@0..16 + FN@0..16 + FN_KW@0..2 "fn" + WHITESPACE@2..3 " " + NAME@3..4 + IDENT@3..4 "f" + PARAM_LIST@4..13 + L_PAREN@4..5 "(" + PARAM@5..12 + WILDCARD_PAT@5..6 + UNDERSCORE@5..6 "_" + COLON@6..7 ":" + WHITESPACE@7..8 " " + REF_TYPE@8..12 + AMP@8..9 "&" + DYN_TRAIT_TYPE@9..12 + DYN_KW@9..12 "dyn" + TYPE_BOUND_LIST@12..12 + R_PAREN@12..13 ")" + WHITESPACE@13..14 " " + BLOCK_EXPR@14..16 + STMT_LIST@14..16 + L_CURLY@14..15 "{" + R_CURLY@15..16 "}" +error 9..12: At least one trait is required for an object type diff --git a/crates/syntax/test_data/parser/validation/0224_dangling_dyn.rs b/crates/syntax/test_data/parser/validation/0224_dangling_dyn.rs new file mode 100644 index 0000000000..2fdbb42846 --- /dev/null +++ b/crates/syntax/test_data/parser/validation/0224_dangling_dyn.rs @@ -0,0 +1 @@ +fn f(_: &dyn) {} \ No newline at end of file From 0b97ae26bfef0c894abfabaf7ebab361a4a289d7 Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Sun, 2 Mar 2025 19:42:42 +0530 Subject: [PATCH 2/3] add diagnostic for dangling impl --- crates/syntax/src/validation.rs | 17 ++++++++++--- .../parser/validation/dangling_impl.rast | 25 +++++++++++++++++++ .../parser/validation/dangling_impl.rs | 1 + 3 files changed, 40 insertions(+), 3 deletions(-) create mode 100644 crates/syntax/test_data/parser/validation/dangling_impl.rast create mode 100644 crates/syntax/test_data/parser/validation/dangling_impl.rs diff --git a/crates/syntax/src/validation.rs b/crates/syntax/src/validation.rs index 2dc86411e4..0377e7c0e6 100644 --- a/crates/syntax/src/validation.rs +++ b/crates/syntax/src/validation.rs @@ -315,10 +315,21 @@ fn validate_path_keywords(segment: ast::PathSegment, errors: &mut Vec) { - if let Some(ast::Type::DynTraitType(ty)) = ty.ty() { - if let Some(err) = validate_trait_object_ty(ty) { - errors.push(err); + match ty.ty() { + Some(ast::Type::DynTraitType(ty)) => { + if let Some(err) = validate_trait_object_ty(ty) { + errors.push(err); + } } + Some(ast::Type::ImplTraitType(ty)) => { + if ty.type_bound_list().map_or(0, |tbl| tbl.bounds().count()) == 0 { + errors.push(SyntaxError::new( + "At least one trait must be specified", + ty.syntax().text_range(), + )); + } + } + _ => {} } } diff --git a/crates/syntax/test_data/parser/validation/dangling_impl.rast b/crates/syntax/test_data/parser/validation/dangling_impl.rast new file mode 100644 index 0000000000..dbe6535ac6 --- /dev/null +++ b/crates/syntax/test_data/parser/validation/dangling_impl.rast @@ -0,0 +1,25 @@ +SOURCE_FILE@0..17 + FN@0..17 + FN_KW@0..2 "fn" + WHITESPACE@2..3 " " + NAME@3..4 + IDENT@3..4 "f" + PARAM_LIST@4..14 + L_PAREN@4..5 "(" + PARAM@5..13 + WILDCARD_PAT@5..6 + UNDERSCORE@5..6 "_" + COLON@6..7 ":" + WHITESPACE@7..8 " " + REF_TYPE@8..13 + AMP@8..9 "&" + IMPL_TRAIT_TYPE@9..13 + IMPL_KW@9..13 "impl" + TYPE_BOUND_LIST@13..13 + R_PAREN@13..14 ")" + WHITESPACE@14..15 " " + BLOCK_EXPR@15..17 + STMT_LIST@15..17 + L_CURLY@15..16 "{" + R_CURLY@16..17 "}" +error 9..13: At least one trait must be specified diff --git a/crates/syntax/test_data/parser/validation/dangling_impl.rs b/crates/syntax/test_data/parser/validation/dangling_impl.rs new file mode 100644 index 0000000000..0b440b4c5a --- /dev/null +++ b/crates/syntax/test_data/parser/validation/dangling_impl.rs @@ -0,0 +1 @@ +fn f(_: &impl) {} \ No newline at end of file From af959f90313760db226e03570c7364b5c7674d21 Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Mon, 3 Mar 2025 15:58:33 +0530 Subject: [PATCH 3/3] Add dangling impl - Adds dangling impl diagnostics - Rename validation test from dangling_impl to dangling_iml_ref --- crates/syntax/src/validation.rs | 27 ++++++++--------- .../parser/validation/dangling_impl.rast | 30 +++++++++---------- .../parser/validation/dangling_impl.rs | 2 +- .../validation/dangling_impl_reference.rast | 25 ++++++++++++++++ .../validation/dangling_impl_reference.rs | 1 + 5 files changed, 54 insertions(+), 31 deletions(-) create mode 100644 crates/syntax/test_data/parser/validation/dangling_impl_reference.rast create mode 100644 crates/syntax/test_data/parser/validation/dangling_impl_reference.rs diff --git a/crates/syntax/src/validation.rs b/crates/syntax/src/validation.rs index 0377e7c0e6..85eefac734 100644 --- a/crates/syntax/src/validation.rs +++ b/crates/syntax/src/validation.rs @@ -37,6 +37,7 @@ pub(crate) fn validate(root: &SyntaxNode, errors: &mut Vec) { ast::FnPtrType(it) => validate_trait_object_fn_ptr_ret_ty(it, errors), ast::MacroRules(it) => validate_macro_rules(it, errors), ast::LetExpr(it) => validate_let_expr(it, errors), + ast::ImplTraitType(it) => validate_impl_object_ty(it, errors), _ => (), } } @@ -315,21 +316,10 @@ fn validate_path_keywords(segment: ast::PathSegment, errors: &mut Vec) { - match ty.ty() { - Some(ast::Type::DynTraitType(ty)) => { - if let Some(err) = validate_trait_object_ty(ty) { - errors.push(err); - } + if let Some(ast::Type::DynTraitType(ty)) = ty.ty() { + if let Some(err) = validate_trait_object_ty(ty) { + errors.push(err); } - Some(ast::Type::ImplTraitType(ty)) => { - if ty.type_bound_list().map_or(0, |tbl| tbl.bounds().count()) == 0 { - errors.push(SyntaxError::new( - "At least one trait must be specified", - ty.syntax().text_range(), - )); - } - } - _ => {} } } @@ -372,6 +362,15 @@ fn validate_trait_object_ty(ty: ast::DynTraitType) -> Option { } } +fn validate_impl_object_ty(ty: ast::ImplTraitType, errors: &mut Vec) { + if ty.type_bound_list().map_or(0, |tbl| tbl.bounds().count()) == 0 { + errors.push(SyntaxError::new( + "At least one trait must be specified", + ty.syntax().text_range(), + )); + } +} + fn validate_macro_rules(mac: ast::MacroRules, errors: &mut Vec) { if let Some(vis) = mac.visibility() { errors.push(SyntaxError::new( diff --git a/crates/syntax/test_data/parser/validation/dangling_impl.rast b/crates/syntax/test_data/parser/validation/dangling_impl.rast index dbe6535ac6..2db07ae12a 100644 --- a/crates/syntax/test_data/parser/validation/dangling_impl.rast +++ b/crates/syntax/test_data/parser/validation/dangling_impl.rast @@ -1,25 +1,23 @@ -SOURCE_FILE@0..17 - FN@0..17 +SOURCE_FILE@0..16 + FN@0..16 FN_KW@0..2 "fn" WHITESPACE@2..3 " " NAME@3..4 IDENT@3..4 "f" - PARAM_LIST@4..14 + PARAM_LIST@4..13 L_PAREN@4..5 "(" - PARAM@5..13 + PARAM@5..12 WILDCARD_PAT@5..6 UNDERSCORE@5..6 "_" COLON@6..7 ":" WHITESPACE@7..8 " " - REF_TYPE@8..13 - AMP@8..9 "&" - IMPL_TRAIT_TYPE@9..13 - IMPL_KW@9..13 "impl" - TYPE_BOUND_LIST@13..13 - R_PAREN@13..14 ")" - WHITESPACE@14..15 " " - BLOCK_EXPR@15..17 - STMT_LIST@15..17 - L_CURLY@15..16 "{" - R_CURLY@16..17 "}" -error 9..13: At least one trait must be specified + IMPL_TRAIT_TYPE@8..12 + IMPL_KW@8..12 "impl" + TYPE_BOUND_LIST@12..12 + R_PAREN@12..13 ")" + WHITESPACE@13..14 " " + BLOCK_EXPR@14..16 + STMT_LIST@14..16 + L_CURLY@14..15 "{" + R_CURLY@15..16 "}" +error 8..12: At least one trait must be specified diff --git a/crates/syntax/test_data/parser/validation/dangling_impl.rs b/crates/syntax/test_data/parser/validation/dangling_impl.rs index 0b440b4c5a..61706d9e41 100644 --- a/crates/syntax/test_data/parser/validation/dangling_impl.rs +++ b/crates/syntax/test_data/parser/validation/dangling_impl.rs @@ -1 +1 @@ -fn f(_: &impl) {} \ No newline at end of file +fn f(_: impl) {} \ No newline at end of file diff --git a/crates/syntax/test_data/parser/validation/dangling_impl_reference.rast b/crates/syntax/test_data/parser/validation/dangling_impl_reference.rast new file mode 100644 index 0000000000..dbe6535ac6 --- /dev/null +++ b/crates/syntax/test_data/parser/validation/dangling_impl_reference.rast @@ -0,0 +1,25 @@ +SOURCE_FILE@0..17 + FN@0..17 + FN_KW@0..2 "fn" + WHITESPACE@2..3 " " + NAME@3..4 + IDENT@3..4 "f" + PARAM_LIST@4..14 + L_PAREN@4..5 "(" + PARAM@5..13 + WILDCARD_PAT@5..6 + UNDERSCORE@5..6 "_" + COLON@6..7 ":" + WHITESPACE@7..8 " " + REF_TYPE@8..13 + AMP@8..9 "&" + IMPL_TRAIT_TYPE@9..13 + IMPL_KW@9..13 "impl" + TYPE_BOUND_LIST@13..13 + R_PAREN@13..14 ")" + WHITESPACE@14..15 " " + BLOCK_EXPR@15..17 + STMT_LIST@15..17 + L_CURLY@15..16 "{" + R_CURLY@16..17 "}" +error 9..13: At least one trait must be specified diff --git a/crates/syntax/test_data/parser/validation/dangling_impl_reference.rs b/crates/syntax/test_data/parser/validation/dangling_impl_reference.rs new file mode 100644 index 0000000000..0b440b4c5a --- /dev/null +++ b/crates/syntax/test_data/parser/validation/dangling_impl_reference.rs @@ -0,0 +1 @@ +fn f(_: &impl) {} \ No newline at end of file