aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_ty')
-rw-r--r--crates/hir_ty/src/diagnostics.rs55
-rw-r--r--crates/hir_ty/src/diagnostics/decl_check.rs28
-rw-r--r--crates/hir_ty/src/diagnostics/decl_check/case_conv.rs9
-rw-r--r--crates/hir_ty/src/diagnostics/unsafe_check.rs18
-rw-r--r--crates/hir_ty/src/traits.rs30
5 files changed, 130 insertions, 10 deletions
diff --git a/crates/hir_ty/src/diagnostics.rs b/crates/hir_ty/src/diagnostics.rs
index dfe98571e..b58fe0ed7 100644
--- a/crates/hir_ty/src/diagnostics.rs
+++ b/crates/hir_ty/src/diagnostics.rs
@@ -36,6 +36,9 @@ pub fn validate_body(db: &dyn HirDatabase, owner: DefWithBodyId, sink: &mut Diag
36 validator.validate_body(db); 36 validator.validate_body(db);
37} 37}
38 38
39// Diagnostic: no-such-field
40//
41// This diagnostic is triggered if created structure does not have field provided in record.
39#[derive(Debug)] 42#[derive(Debug)]
40pub struct NoSuchField { 43pub struct NoSuchField {
41 pub file: HirFileId, 44 pub file: HirFileId,
@@ -60,6 +63,17 @@ impl Diagnostic for NoSuchField {
60 } 63 }
61} 64}
62 65
66// Diagnostic: missing-structure-fields
67//
68// This diagnostic is triggered if record lacks some fields that exist in the corresponding structure.
69//
70// Example:
71//
72// ```rust
73// struct A { a: u8, b: u8 }
74//
75// let a = A { a: 10 };
76// ```
63#[derive(Debug)] 77#[derive(Debug)]
64pub struct MissingFields { 78pub struct MissingFields {
65 pub file: HirFileId, 79 pub file: HirFileId,
@@ -96,6 +110,21 @@ impl Diagnostic for MissingFields {
96 } 110 }
97} 111}
98 112
113// Diagnostic: missing-pat-fields
114//
115// This diagnostic is triggered if pattern lacks some fields that exist in the corresponding structure.
116//
117// Example:
118//
119// ```rust
120// struct A { a: u8, b: u8 }
121//
122// let a = A { a: 10, b: 20 };
123//
124// if let A { a } = a {
125// // ...
126// }
127// ```
99#[derive(Debug)] 128#[derive(Debug)]
100pub struct MissingPatFields { 129pub struct MissingPatFields {
101 pub file: HirFileId, 130 pub file: HirFileId,
@@ -130,6 +159,9 @@ impl Diagnostic for MissingPatFields {
130 } 159 }
131} 160}
132 161
162// Diagnostic: missing-match-arm
163//
164// This diagnostic is triggered if `match` block is missing one or more match arms.
133#[derive(Debug)] 165#[derive(Debug)]
134pub struct MissingMatchArms { 166pub struct MissingMatchArms {
135 pub file: HirFileId, 167 pub file: HirFileId,
@@ -152,6 +184,17 @@ impl Diagnostic for MissingMatchArms {
152 } 184 }
153} 185}
154 186
187// Diagnostic: missing-ok-in-tail-expr
188//
189// This diagnostic is triggered if block that should return `Result` returns a value not wrapped in `Ok`.
190//
191// Example:
192//
193// ```rust
194// fn foo() -> Result<u8, ()> {
195// 10
196// }
197// ```
155#[derive(Debug)] 198#[derive(Debug)]
156pub struct MissingOkInTailExpr { 199pub struct MissingOkInTailExpr {
157 pub file: HirFileId, 200 pub file: HirFileId,
@@ -173,6 +216,9 @@ impl Diagnostic for MissingOkInTailExpr {
173 } 216 }
174} 217}
175 218
219// Diagnostic: break-outside-of-loop
220//
221// This diagnostic is triggered if `break` keyword is used outside of a loop.
176#[derive(Debug)] 222#[derive(Debug)]
177pub struct BreakOutsideOfLoop { 223pub struct BreakOutsideOfLoop {
178 pub file: HirFileId, 224 pub file: HirFileId,
@@ -194,6 +240,9 @@ impl Diagnostic for BreakOutsideOfLoop {
194 } 240 }
195} 241}
196 242
243// Diagnostic: missing-unsafe
244//
245// This diagnostic is triggered if operation marked as `unsafe` is used outside of `unsafe` function or block.
197#[derive(Debug)] 246#[derive(Debug)]
198pub struct MissingUnsafe { 247pub struct MissingUnsafe {
199 pub file: HirFileId, 248 pub file: HirFileId,
@@ -215,6 +264,9 @@ impl Diagnostic for MissingUnsafe {
215 } 264 }
216} 265}
217 266
267// Diagnostic: mismatched-arg-count
268//
269// This diagnostic is triggered if function is invoked with an incorrect amount of arguments.
218#[derive(Debug)] 270#[derive(Debug)]
219pub struct MismatchedArgCount { 271pub struct MismatchedArgCount {
220 pub file: HirFileId, 272 pub file: HirFileId,
@@ -264,6 +316,9 @@ impl fmt::Display for CaseType {
264 } 316 }
265} 317}
266 318
319// Diagnostic: incorrect-ident-case
320//
321// This diagnostic is triggered if item name doesn't follow https://doc.rust-lang.org/1.0.0/style/style/naming/README.html[Rust naming convention].
267#[derive(Debug)] 322#[derive(Debug)]
268pub struct IncorrectCase { 323pub struct IncorrectCase {
269 pub file: HirFileId, 324 pub file: HirFileId,
diff --git a/crates/hir_ty/src/diagnostics/decl_check.rs b/crates/hir_ty/src/diagnostics/decl_check.rs
index f987636fe..f179c62b7 100644
--- a/crates/hir_ty/src/diagnostics/decl_check.rs
+++ b/crates/hir_ty/src/diagnostics/decl_check.rs
@@ -708,11 +708,23 @@ fn foo() {
708 } 708 }
709 709
710 #[test] 710 #[test]
711 fn incorrect_struct_name() { 711 fn incorrect_struct_names() {
712 check_diagnostics( 712 check_diagnostics(
713 r#" 713 r#"
714struct non_camel_case_name {} 714struct non_camel_case_name {}
715 // ^^^^^^^^^^^^^^^^^^^ Structure `non_camel_case_name` should have CamelCase name, e.g. `NonCamelCaseName` 715 // ^^^^^^^^^^^^^^^^^^^ Structure `non_camel_case_name` should have CamelCase name, e.g. `NonCamelCaseName`
716
717struct SCREAMING_CASE {}
718 // ^^^^^^^^^^^^^^ Structure `SCREAMING_CASE` should have CamelCase name, e.g. `ScreamingCase`
719"#,
720 );
721 }
722
723 #[test]
724 fn no_diagnostic_for_camel_cased_acronyms_in_struct_name() {
725 check_diagnostics(
726 r#"
727struct AABB {}
716"#, 728"#,
717 ); 729 );
718 } 730 }
@@ -728,11 +740,23 @@ struct SomeStruct { SomeField: u8 }
728 } 740 }
729 741
730 #[test] 742 #[test]
731 fn incorrect_enum_name() { 743 fn incorrect_enum_names() {
732 check_diagnostics( 744 check_diagnostics(
733 r#" 745 r#"
734enum some_enum { Val(u8) } 746enum some_enum { Val(u8) }
735 // ^^^^^^^^^ Enum `some_enum` should have CamelCase name, e.g. `SomeEnum` 747 // ^^^^^^^^^ Enum `some_enum` should have CamelCase name, e.g. `SomeEnum`
748
749enum SOME_ENUM
750 // ^^^^^^^^^ Enum `SOME_ENUM` should have CamelCase name, e.g. `SomeEnum`
751"#,
752 );
753 }
754
755 #[test]
756 fn no_diagnostic_for_camel_cased_acronyms_in_enum_name() {
757 check_diagnostics(
758 r#"
759enum AABB {}
736"#, 760"#,
737 ); 761 );
738 } 762 }
diff --git a/crates/hir_ty/src/diagnostics/decl_check/case_conv.rs b/crates/hir_ty/src/diagnostics/decl_check/case_conv.rs
index 3800f2a6b..324d60765 100644
--- a/crates/hir_ty/src/diagnostics/decl_check/case_conv.rs
+++ b/crates/hir_ty/src/diagnostics/decl_check/case_conv.rs
@@ -29,7 +29,13 @@ fn detect_case(ident: &str) -> DetectedCase {
29 29
30 if has_uppercase { 30 if has_uppercase {
31 if !has_lowercase { 31 if !has_lowercase {
32 DetectedCase::UpperSnakeCase 32 if has_underscore {
33 DetectedCase::UpperSnakeCase
34 } else {
35 // It has uppercase only and no underscores. Ex: "AABB"
36 // This is a camel cased acronym.
37 DetectedCase::UpperCamelCase
38 }
33 } else if !has_underscore { 39 } else if !has_underscore {
34 if first_lowercase { 40 if first_lowercase {
35 DetectedCase::LowerCamelCase 41 DetectedCase::LowerCamelCase
@@ -180,6 +186,7 @@ mod tests {
180 check(to_camel_case, "Weird_Case", expect![["WeirdCase"]]); 186 check(to_camel_case, "Weird_Case", expect![["WeirdCase"]]);
181 check(to_camel_case, "name", expect![["Name"]]); 187 check(to_camel_case, "name", expect![["Name"]]);
182 check(to_camel_case, "A", expect![[""]]); 188 check(to_camel_case, "A", expect![[""]]);
189 check(to_camel_case, "AABB", expect![[""]]);
183 } 190 }
184 191
185 #[test] 192 #[test]
diff --git a/crates/hir_ty/src/diagnostics/unsafe_check.rs b/crates/hir_ty/src/diagnostics/unsafe_check.rs
index 21a121aad..2da9688ca 100644
--- a/crates/hir_ty/src/diagnostics/unsafe_check.rs
+++ b/crates/hir_ty/src/diagnostics/unsafe_check.rs
@@ -202,4 +202,22 @@ fn main() {
202"#, 202"#,
203 ); 203 );
204 } 204 }
205
206 #[test]
207 fn no_missing_unsafe_diagnostic_with_safe_intrinsic() {
208 check_diagnostics(
209 r#"
210extern "rust-intrinsic" {
211 pub fn bitreverse(x: u32) -> u32; // Safe intrinsic
212 pub fn floorf32(x: f32) -> f32; // Unsafe intrinsic
213}
214
215fn main() {
216 let _ = bitreverse(12);
217 let _ = floorf32(12.0);
218 //^^^^^^^^^^^^^^ This operation is unsafe and requires an unsafe function or block
219}
220"#,
221 );
222 }
205} 223}
diff --git a/crates/hir_ty/src/traits.rs b/crates/hir_ty/src/traits.rs
index 14cd3a2b4..ce1174cbe 100644
--- a/crates/hir_ty/src/traits.rs
+++ b/crates/hir_ty/src/traits.rs
@@ -5,6 +5,7 @@ use base_db::CrateId;
5use chalk_ir::cast::Cast; 5use chalk_ir::cast::Cast;
6use chalk_solve::{logging_db::LoggingRustIrDatabase, Solver}; 6use chalk_solve::{logging_db::LoggingRustIrDatabase, Solver};
7use hir_def::{lang_item::LangItemTarget, TraitId}; 7use hir_def::{lang_item::LangItemTarget, TraitId};
8use stdx::panic_context;
8 9
9use crate::{db::HirDatabase, DebruijnIndex, Substs}; 10use crate::{db::HirDatabase, DebruijnIndex, Substs};
10 11
@@ -168,14 +169,23 @@ fn solve(
168 }; 169 };
169 170
170 let mut solve = || { 171 let mut solve = || {
171 if is_chalk_print() { 172 let _ctx = if is_chalk_debug() || is_chalk_print() {
172 let logging_db = LoggingRustIrDatabase::new(context); 173 Some(panic_context::enter(format!("solving {:?}", goal)))
173 let solution = solver.solve_limited(&logging_db, goal, &should_continue); 174 } else {
174 log::debug!("chalk program:\n{}", logging_db); 175 None
176 };
177 let solution = if is_chalk_print() {
178 let logging_db =
179 LoggingRustIrDatabaseLoggingOnDrop(LoggingRustIrDatabase::new(context));
180 let solution = solver.solve_limited(&logging_db.0, goal, &should_continue);
175 solution 181 solution
176 } else { 182 } else {
177 solver.solve_limited(&context, goal, &should_continue) 183 solver.solve_limited(&context, goal, &should_continue)
178 } 184 };
185
186 log::debug!("solve({:?}) => {:?}", goal, solution);
187
188 solution
179 }; 189 };
180 190
181 // don't set the TLS for Chalk unless Chalk debugging is active, to make 191 // don't set the TLS for Chalk unless Chalk debugging is active, to make
@@ -183,11 +193,17 @@ fn solve(
183 let solution = 193 let solution =
184 if is_chalk_debug() { chalk::tls::set_current_program(db, solve) } else { solve() }; 194 if is_chalk_debug() { chalk::tls::set_current_program(db, solve) } else { solve() };
185 195
186 log::debug!("solve({:?}) => {:?}", goal, solution);
187
188 solution 196 solution
189} 197}
190 198
199struct LoggingRustIrDatabaseLoggingOnDrop<'a>(LoggingRustIrDatabase<Interner, ChalkContext<'a>>);
200
201impl<'a> Drop for LoggingRustIrDatabaseLoggingOnDrop<'a> {
202 fn drop(&mut self) {
203 eprintln!("chalk program:\n{}", self.0);
204 }
205}
206
191fn is_chalk_debug() -> bool { 207fn is_chalk_debug() -> bool {
192 std::env::var("CHALK_DEBUG").is_ok() 208 std::env::var("CHALK_DEBUG").is_ok()
193} 209}