aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_ty/src')
-rw-r--r--crates/hir_ty/src/diagnostics/decl_check.rs126
-rw-r--r--crates/hir_ty/src/diagnostics/decl_check/case_conv.rs255
-rw-r--r--crates/hir_ty/src/diagnostics/expr.rs15
-rw-r--r--crates/hir_ty/src/diagnostics/unsafe_check.rs8
-rw-r--r--crates/hir_ty/src/display.rs149
-rw-r--r--crates/hir_ty/src/infer.rs8
-rw-r--r--crates/hir_ty/src/infer/expr.rs2
-rw-r--r--crates/hir_ty/src/infer/unify.rs37
-rw-r--r--crates/hir_ty/src/lib.rs3
-rw-r--r--crates/hir_ty/src/method_resolution.rs13
-rw-r--r--crates/hir_ty/src/test_db.rs6
-rw-r--r--crates/hir_ty/src/tests.rs8
-rw-r--r--crates/hir_ty/src/traits/chalk.rs23
-rw-r--r--crates/hir_ty/src/traits/chalk/interner.rs37
-rw-r--r--crates/hir_ty/src/traits/chalk/mapping.rs369
-rw-r--r--crates/hir_ty/src/traits/chalk/tls.rs162
16 files changed, 610 insertions, 611 deletions
diff --git a/crates/hir_ty/src/diagnostics/decl_check.rs b/crates/hir_ty/src/diagnostics/decl_check.rs
index f179c62b7..4b3e2fa8f 100644
--- a/crates/hir_ty/src/diagnostics/decl_check.rs
+++ b/crates/hir_ty/src/diagnostics/decl_check.rs
@@ -16,7 +16,7 @@ use hir_def::{
16 adt::VariantData, 16 adt::VariantData,
17 expr::{Pat, PatId}, 17 expr::{Pat, PatId},
18 src::HasSource, 18 src::HasSource,
19 AdtId, ConstId, EnumId, FunctionId, Lookup, ModuleDefId, StaticId, StructId, 19 AdtId, AttrDefId, ConstId, EnumId, FunctionId, Lookup, ModuleDefId, StaticId, StructId,
20}; 20};
21use hir_expand::{ 21use hir_expand::{
22 diagnostics::DiagnosticSink, 22 diagnostics::DiagnosticSink,
@@ -32,6 +32,12 @@ use crate::{
32 diagnostics::{decl_check::case_conv::*, CaseType, IncorrectCase}, 32 diagnostics::{decl_check::case_conv::*, CaseType, IncorrectCase},
33}; 33};
34 34
35mod allow {
36 pub(super) const NON_SNAKE_CASE: &str = "non_snake_case";
37 pub(super) const NON_UPPER_CASE_GLOBAL: &str = "non_upper_case_globals";
38 pub(super) const NON_CAMEL_CASE_TYPES: &str = "non_camel_case_types";
39}
40
35pub(super) struct DeclValidator<'a, 'b: 'a> { 41pub(super) struct DeclValidator<'a, 'b: 'a> {
36 owner: ModuleDefId, 42 owner: ModuleDefId,
37 sink: &'a mut DiagnosticSink<'b>, 43 sink: &'a mut DiagnosticSink<'b>,
@@ -72,11 +78,29 @@ impl<'a, 'b> DeclValidator<'a, 'b> {
72 } 78 }
73 } 79 }
74 80
81 /// Checks whether not following the convention is allowed for this item.
82 ///
83 /// Currently this method doesn't check parent attributes.
84 fn allowed(&self, db: &dyn HirDatabase, id: AttrDefId, allow_name: &str) -> bool {
85 db.attrs(id).by_key("allow").tt_values().any(|tt| tt.to_string().contains(allow_name))
86 }
87
75 fn validate_func(&mut self, db: &dyn HirDatabase, func: FunctionId) { 88 fn validate_func(&mut self, db: &dyn HirDatabase, func: FunctionId) {
76 let data = db.function_data(func); 89 let data = db.function_data(func);
77 let body = db.body(func.into()); 90 let body = db.body(func.into());
78 91
79 // 1. Check the function name. 92 // Recursively validate inner scope items, such as static variables and constants.
93 for (item_id, _) in body.item_scope.values() {
94 let mut validator = DeclValidator::new(item_id, self.sink);
95 validator.validate_item(db);
96 }
97
98 // Check whether non-snake case identifiers are allowed for this function.
99 if self.allowed(db, func.into(), allow::NON_SNAKE_CASE) {
100 return;
101 }
102
103 // Check the function name.
80 let function_name = data.name.to_string(); 104 let function_name = data.name.to_string();
81 let fn_name_replacement = if let Some(new_name) = to_lower_snake_case(&function_name) { 105 let fn_name_replacement = if let Some(new_name) = to_lower_snake_case(&function_name) {
82 let replacement = Replacement { 106 let replacement = Replacement {
@@ -89,7 +113,7 @@ impl<'a, 'b> DeclValidator<'a, 'b> {
89 None 113 None
90 }; 114 };
91 115
92 // 2. Check the param names. 116 // Check the param names.
93 let mut fn_param_replacements = Vec::new(); 117 let mut fn_param_replacements = Vec::new();
94 118
95 for pat_id in body.params.iter().cloned() { 119 for pat_id in body.params.iter().cloned() {
@@ -111,7 +135,7 @@ impl<'a, 'b> DeclValidator<'a, 'b> {
111 } 135 }
112 } 136 }
113 137
114 // 3. Check the patterns inside the function body. 138 // Check the patterns inside the function body.
115 let mut pats_replacements = Vec::new(); 139 let mut pats_replacements = Vec::new();
116 140
117 for (pat_idx, pat) in body.pats.iter() { 141 for (pat_idx, pat) in body.pats.iter() {
@@ -136,7 +160,7 @@ impl<'a, 'b> DeclValidator<'a, 'b> {
136 } 160 }
137 } 161 }
138 162
139 // 4. If there is at least one element to spawn a warning on, go to the source map and generate a warning. 163 // If there is at least one element to spawn a warning on, go to the source map and generate a warning.
140 self.create_incorrect_case_diagnostic_for_func( 164 self.create_incorrect_case_diagnostic_for_func(
141 func, 165 func,
142 db, 166 db,
@@ -144,12 +168,6 @@ impl<'a, 'b> DeclValidator<'a, 'b> {
144 fn_param_replacements, 168 fn_param_replacements,
145 ); 169 );
146 self.create_incorrect_case_diagnostic_for_variables(func, db, pats_replacements); 170 self.create_incorrect_case_diagnostic_for_variables(func, db, pats_replacements);
147
148 // 5. Recursively validate inner scope items, such as static variables and constants.
149 for (item_id, _) in body.item_scope.values() {
150 let mut validator = DeclValidator::new(item_id, self.sink);
151 validator.validate_item(db);
152 }
153 } 171 }
154 172
155 /// Given the information about incorrect names in the function declaration, looks up into the source code 173 /// Given the information about incorrect names in the function declaration, looks up into the source code
@@ -169,7 +187,7 @@ impl<'a, 'b> DeclValidator<'a, 'b> {
169 let fn_loc = func.lookup(db.upcast()); 187 let fn_loc = func.lookup(db.upcast());
170 let fn_src = fn_loc.source(db.upcast()); 188 let fn_src = fn_loc.source(db.upcast());
171 189
172 // 1. Diagnostic for function name. 190 // Diagnostic for function name.
173 if let Some(replacement) = fn_name_replacement { 191 if let Some(replacement) = fn_name_replacement {
174 let ast_ptr = match fn_src.value.name() { 192 let ast_ptr = match fn_src.value.name() {
175 Some(name) => name, 193 Some(name) => name,
@@ -196,7 +214,7 @@ impl<'a, 'b> DeclValidator<'a, 'b> {
196 self.sink.push(diagnostic); 214 self.sink.push(diagnostic);
197 } 215 }
198 216
199 // 2. Diagnostics for function params. 217 // Diagnostics for function params.
200 let fn_params_list = match fn_src.value.param_list() { 218 let fn_params_list = match fn_src.value.param_list() {
201 Some(params) => params, 219 Some(params) => params,
202 None => { 220 None => {
@@ -312,7 +330,11 @@ impl<'a, 'b> DeclValidator<'a, 'b> {
312 fn validate_struct(&mut self, db: &dyn HirDatabase, struct_id: StructId) { 330 fn validate_struct(&mut self, db: &dyn HirDatabase, struct_id: StructId) {
313 let data = db.struct_data(struct_id); 331 let data = db.struct_data(struct_id);
314 332
315 // 1. Check the structure name. 333 let non_camel_case_allowed =
334 self.allowed(db, struct_id.into(), allow::NON_CAMEL_CASE_TYPES);
335 let non_snake_case_allowed = self.allowed(db, struct_id.into(), allow::NON_SNAKE_CASE);
336
337 // Check the structure name.
316 let struct_name = data.name.to_string(); 338 let struct_name = data.name.to_string();
317 let struct_name_replacement = if let Some(new_name) = to_camel_case(&struct_name) { 339 let struct_name_replacement = if let Some(new_name) = to_camel_case(&struct_name) {
318 let replacement = Replacement { 340 let replacement = Replacement {
@@ -320,29 +342,35 @@ impl<'a, 'b> DeclValidator<'a, 'b> {
320 suggested_text: new_name, 342 suggested_text: new_name,
321 expected_case: CaseType::UpperCamelCase, 343 expected_case: CaseType::UpperCamelCase,
322 }; 344 };
323 Some(replacement) 345 if non_camel_case_allowed {
346 None
347 } else {
348 Some(replacement)
349 }
324 } else { 350 } else {
325 None 351 None
326 }; 352 };
327 353
328 // 2. Check the field names. 354 // Check the field names.
329 let mut struct_fields_replacements = Vec::new(); 355 let mut struct_fields_replacements = Vec::new();
330 356
331 if let VariantData::Record(fields) = data.variant_data.as_ref() { 357 if !non_snake_case_allowed {
332 for (_, field) in fields.iter() { 358 if let VariantData::Record(fields) = data.variant_data.as_ref() {
333 let field_name = field.name.to_string(); 359 for (_, field) in fields.iter() {
334 if let Some(new_name) = to_lower_snake_case(&field_name) { 360 let field_name = field.name.to_string();
335 let replacement = Replacement { 361 if let Some(new_name) = to_lower_snake_case(&field_name) {
336 current_name: field.name.clone(), 362 let replacement = Replacement {
337 suggested_text: new_name, 363 current_name: field.name.clone(),
338 expected_case: CaseType::LowerSnakeCase, 364 suggested_text: new_name,
339 }; 365 expected_case: CaseType::LowerSnakeCase,
340 struct_fields_replacements.push(replacement); 366 };
367 struct_fields_replacements.push(replacement);
368 }
341 } 369 }
342 } 370 }
343 } 371 }
344 372
345 // 3. If there is at least one element to spawn a warning on, go to the source map and generate a warning. 373 // If there is at least one element to spawn a warning on, go to the source map and generate a warning.
346 self.create_incorrect_case_diagnostic_for_struct( 374 self.create_incorrect_case_diagnostic_for_struct(
347 struct_id, 375 struct_id,
348 db, 376 db,
@@ -442,7 +470,12 @@ impl<'a, 'b> DeclValidator<'a, 'b> {
442 fn validate_enum(&mut self, db: &dyn HirDatabase, enum_id: EnumId) { 470 fn validate_enum(&mut self, db: &dyn HirDatabase, enum_id: EnumId) {
443 let data = db.enum_data(enum_id); 471 let data = db.enum_data(enum_id);
444 472
445 // 1. Check the enum name. 473 // Check whether non-camel case names are allowed for this enum.
474 if self.allowed(db, enum_id.into(), allow::NON_CAMEL_CASE_TYPES) {
475 return;
476 }
477
478 // Check the enum name.
446 let enum_name = data.name.to_string(); 479 let enum_name = data.name.to_string();
447 let enum_name_replacement = if let Some(new_name) = to_camel_case(&enum_name) { 480 let enum_name_replacement = if let Some(new_name) = to_camel_case(&enum_name) {
448 let replacement = Replacement { 481 let replacement = Replacement {
@@ -455,7 +488,7 @@ impl<'a, 'b> DeclValidator<'a, 'b> {
455 None 488 None
456 }; 489 };
457 490
458 // 2. Check the field names. 491 // Check the field names.
459 let mut enum_fields_replacements = Vec::new(); 492 let mut enum_fields_replacements = Vec::new();
460 493
461 for (_, variant) in data.variants.iter() { 494 for (_, variant) in data.variants.iter() {
@@ -470,7 +503,7 @@ impl<'a, 'b> DeclValidator<'a, 'b> {
470 } 503 }
471 } 504 }
472 505
473 // 3. If there is at least one element to spawn a warning on, go to the source map and generate a warning. 506 // If there is at least one element to spawn a warning on, go to the source map and generate a warning.
474 self.create_incorrect_case_diagnostic_for_enum( 507 self.create_incorrect_case_diagnostic_for_enum(
475 enum_id, 508 enum_id,
476 db, 509 db,
@@ -572,6 +605,10 @@ impl<'a, 'b> DeclValidator<'a, 'b> {
572 fn validate_const(&mut self, db: &dyn HirDatabase, const_id: ConstId) { 605 fn validate_const(&mut self, db: &dyn HirDatabase, const_id: ConstId) {
573 let data = db.const_data(const_id); 606 let data = db.const_data(const_id);
574 607
608 if self.allowed(db, const_id.into(), allow::NON_UPPER_CASE_GLOBAL) {
609 return;
610 }
611
575 let name = match &data.name { 612 let name = match &data.name {
576 Some(name) => name, 613 Some(name) => name,
577 None => return, 614 None => return,
@@ -612,6 +649,10 @@ impl<'a, 'b> DeclValidator<'a, 'b> {
612 fn validate_static(&mut self, db: &dyn HirDatabase, static_id: StaticId) { 649 fn validate_static(&mut self, db: &dyn HirDatabase, static_id: StaticId) {
613 let data = db.static_data(static_id); 650 let data = db.static_data(static_id);
614 651
652 if self.allowed(db, static_id.into(), allow::NON_UPPER_CASE_GLOBAL) {
653 return;
654 }
655
615 let name = match &data.name { 656 let name = match &data.name {
616 Some(name) => name, 657 Some(name) => name,
617 None => return, 658 None => return,
@@ -854,4 +895,29 @@ fn main() {
854"#, 895"#,
855 ); 896 );
856 } 897 }
898
899 #[test]
900 fn allow_attributes() {
901 check_diagnostics(
902 r#"
903 #[allow(non_snake_case)]
904 fn NonSnakeCaseName(SOME_VAR: u8) -> u8{
905 let OtherVar = SOME_VAR + 1;
906 OtherVar
907 }
908
909 #[allow(non_snake_case, non_camel_case_types)]
910 pub struct some_type {
911 SOME_FIELD: u8,
912 SomeField: u16,
913 }
914
915 #[allow(non_upper_case_globals)]
916 pub const some_const: u8 = 10;
917
918 #[allow(non_upper_case_globals)]
919 pub static SomeStatic: u8 = 10;
920 "#,
921 );
922 }
857} 923}
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 324d60765..14e4d92f0 100644
--- a/crates/hir_ty/src/diagnostics/decl_check/case_conv.rs
+++ b/crates/hir_ty/src/diagnostics/decl_check/case_conv.rs
@@ -1,156 +1,145 @@
1//! Functions for string case manipulation, such as detecting the identifier case, 1//! Functions for string case manipulation, such as detecting the identifier case,
2//! and converting it into appropriate form. 2//! and converting it into appropriate form.
3 3
4#[derive(Debug)] 4// Code that was taken from rustc was taken at commit 89fdb30,
5enum DetectedCase { 5// from file /compiler/rustc_lint/src/nonstandard_style.rs
6 LowerCamelCase,
7 UpperCamelCase,
8 LowerSnakeCase,
9 UpperSnakeCase,
10 Unknown,
11}
12
13fn detect_case(ident: &str) -> DetectedCase {
14 let trimmed_ident = ident.trim_matches('_');
15 let first_lowercase = trimmed_ident.starts_with(|chr: char| chr.is_ascii_lowercase());
16 let mut has_lowercase = first_lowercase;
17 let mut has_uppercase = false;
18 let mut has_underscore = false;
19
20 for chr in trimmed_ident.chars() {
21 if chr == '_' {
22 has_underscore = true;
23 } else if chr.is_ascii_uppercase() {
24 has_uppercase = true;
25 } else if chr.is_ascii_lowercase() {
26 has_lowercase = true;
27 }
28 }
29
30 if has_uppercase {
31 if !has_lowercase {
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 }
39 } else if !has_underscore {
40 if first_lowercase {
41 DetectedCase::LowerCamelCase
42 } else {
43 DetectedCase::UpperCamelCase
44 }
45 } else {
46 // It has uppercase, it has lowercase, it has underscore.
47 // No assumptions here
48 DetectedCase::Unknown
49 }
50 } else {
51 DetectedCase::LowerSnakeCase
52 }
53}
54 6
55/// Converts an identifier to an UpperCamelCase form. 7/// Converts an identifier to an UpperCamelCase form.
56/// Returns `None` if the string is already is UpperCamelCase. 8/// Returns `None` if the string is already is UpperCamelCase.
57pub fn to_camel_case(ident: &str) -> Option<String> { 9pub(crate) fn to_camel_case(ident: &str) -> Option<String> {
58 let detected_case = detect_case(ident); 10 if is_camel_case(ident) {
59 11 return None;
60 match detected_case {
61 DetectedCase::UpperCamelCase => return None,
62 DetectedCase::LowerCamelCase => {
63 let mut first_capitalized = false;
64 let output = ident
65 .chars()
66 .map(|chr| {
67 if !first_capitalized && chr.is_ascii_lowercase() {
68 first_capitalized = true;
69 chr.to_ascii_uppercase()
70 } else {
71 chr
72 }
73 })
74 .collect();
75 return Some(output);
76 }
77 _ => {}
78 } 12 }
79 13
80 let mut output = String::with_capacity(ident.len()); 14 // Taken from rustc.
81 15 let ret = ident
82 let mut capital_added = false; 16 .trim_matches('_')
83 for chr in ident.chars() { 17 .split('_')
84 if chr.is_alphabetic() { 18 .filter(|component| !component.is_empty())
85 if !capital_added { 19 .map(|component| {
86 output.push(chr.to_ascii_uppercase()); 20 let mut camel_cased_component = String::new();
87 capital_added = true; 21
88 } else { 22 let mut new_word = true;
89 output.push(chr.to_ascii_lowercase()); 23 let mut prev_is_lower_case = true;
24
25 for c in component.chars() {
26 // Preserve the case if an uppercase letter follows a lowercase letter, so that
27 // `camelCase` is converted to `CamelCase`.
28 if prev_is_lower_case && c.is_uppercase() {
29 new_word = true;
30 }
31
32 if new_word {
33 camel_cased_component.push_str(&c.to_uppercase().to_string());
34 } else {
35 camel_cased_component.push_str(&c.to_lowercase().to_string());
36 }
37
38 prev_is_lower_case = c.is_lowercase();
39 new_word = false;
90 } 40 }
91 } else if chr == '_' {
92 // Skip this character and make the next one capital.
93 capital_added = false;
94 } else {
95 // Put the characted as-is.
96 output.push(chr);
97 }
98 }
99 41
100 if output == ident { 42 camel_cased_component
101 // While we didn't detect the correct case at the beginning, there 43 })
102 // may be special cases: e.g. `A` is both valid CamelCase and UPPER_SNAKE_CASE. 44 .fold((String::new(), None), |(acc, prev): (String, Option<String>), next| {
103 None 45 // separate two components with an underscore if their boundary cannot
104 } else { 46 // be distinguished using a uppercase/lowercase case distinction
105 Some(output) 47 let join = if let Some(prev) = prev {
106 } 48 let l = prev.chars().last().unwrap();
49 let f = next.chars().next().unwrap();
50 !char_has_case(l) && !char_has_case(f)
51 } else {
52 false
53 };
54 (acc + if join { "_" } else { "" } + &next, Some(next))
55 })
56 .0;
57 Some(ret)
107} 58}
108 59
109/// Converts an identifier to a lower_snake_case form. 60/// Converts an identifier to a lower_snake_case form.
110/// Returns `None` if the string is already in lower_snake_case. 61/// Returns `None` if the string is already in lower_snake_case.
111pub fn to_lower_snake_case(ident: &str) -> Option<String> { 62pub(crate) fn to_lower_snake_case(ident: &str) -> Option<String> {
112 // First, assume that it's UPPER_SNAKE_CASE. 63 if is_lower_snake_case(ident) {
113 match detect_case(ident) { 64 return None;
114 DetectedCase::LowerSnakeCase => return None, 65 } else if is_upper_snake_case(ident) {
115 DetectedCase::UpperSnakeCase => { 66 return Some(ident.to_lowercase());
116 return Some(ident.chars().map(|chr| chr.to_ascii_lowercase()).collect())
117 }
118 _ => {}
119 } 67 }
120 68
121 // Otherwise, assume that it's CamelCase. 69 Some(stdx::to_lower_snake_case(ident))
122 let lower_snake_case = stdx::to_lower_snake_case(ident);
123
124 if lower_snake_case == ident {
125 // While we didn't detect the correct case at the beginning, there
126 // may be special cases: e.g. `a` is both valid camelCase and snake_case.
127 None
128 } else {
129 Some(lower_snake_case)
130 }
131} 70}
132 71
133/// Converts an identifier to an UPPER_SNAKE_CASE form. 72/// Converts an identifier to an UPPER_SNAKE_CASE form.
134/// Returns `None` if the string is already is UPPER_SNAKE_CASE. 73/// Returns `None` if the string is already is UPPER_SNAKE_CASE.
135pub fn to_upper_snake_case(ident: &str) -> Option<String> { 74pub(crate) fn to_upper_snake_case(ident: &str) -> Option<String> {
136 match detect_case(ident) { 75 if is_upper_snake_case(ident) {
137 DetectedCase::UpperSnakeCase => return None, 76 return None;
138 DetectedCase::LowerSnakeCase => { 77 } else if is_lower_snake_case(ident) {
139 return Some(ident.chars().map(|chr| chr.to_ascii_uppercase()).collect()) 78 return Some(ident.to_uppercase());
140 } 79 }
141 _ => {} 80
81 Some(stdx::to_upper_snake_case(ident))
82}
83
84// Taken from rustc.
85// Modified by replacing the use of unstable feature `array_windows`.
86fn is_camel_case(name: &str) -> bool {
87 let name = name.trim_matches('_');
88 if name.is_empty() {
89 return true;
142 } 90 }
143 91
144 // Normalize the string from whatever form it's in currently, and then just make it uppercase. 92 let mut fst = None;
145 let upper_snake_case = stdx::to_upper_snake_case(ident); 93 // start with a non-lowercase letter rather than non-uppercase
94 // ones (some scripts don't have a concept of upper/lowercase)
95 !name.chars().next().unwrap().is_lowercase()
96 && !name.contains("__")
97 && !name.chars().any(|snd| {
98 let ret = match (fst, snd) {
99 (None, _) => false,
100 (Some(fst), snd) => {
101 char_has_case(fst) && snd == '_' || char_has_case(snd) && fst == '_'
102 }
103 };
104 fst = Some(snd);
105
106 ret
107 })
108}
109
110fn is_lower_snake_case(ident: &str) -> bool {
111 is_snake_case(ident, char::is_uppercase)
112}
146 113
147 if upper_snake_case == ident { 114fn is_upper_snake_case(ident: &str) -> bool {
148 // While we didn't detect the correct case at the beginning, there 115 is_snake_case(ident, char::is_lowercase)
149 // may be special cases: e.g. `A` is both valid CamelCase and UPPER_SNAKE_CASE. 116}
150 None 117
151 } else { 118// Taken from rustc.
152 Some(upper_snake_case) 119// Modified to allow checking for both upper and lower snake case.
120fn is_snake_case<F: Fn(char) -> bool>(ident: &str, wrong_case: F) -> bool {
121 if ident.is_empty() {
122 return true;
153 } 123 }
124 let ident = ident.trim_matches('_');
125
126 let mut allow_underscore = true;
127 ident.chars().all(|c| {
128 allow_underscore = match c {
129 '_' if !allow_underscore => return false,
130 '_' => false,
131 // It would be more obvious to check for the correct case,
132 // but some characters do not have a case.
133 c if !wrong_case(c) => true,
134 _ => return false,
135 };
136 true
137 })
138}
139
140// Taken from rustc.
141fn char_has_case(c: char) -> bool {
142 c.is_lowercase() || c.is_uppercase()
154} 143}
155 144
156#[cfg(test)] 145#[cfg(test)]
@@ -173,6 +162,7 @@ mod tests {
173 check(to_lower_snake_case, "CamelCase", expect![["camel_case"]]); 162 check(to_lower_snake_case, "CamelCase", expect![["camel_case"]]);
174 check(to_lower_snake_case, "lowerCamelCase", expect![["lower_camel_case"]]); 163 check(to_lower_snake_case, "lowerCamelCase", expect![["lower_camel_case"]]);
175 check(to_lower_snake_case, "a", expect![[""]]); 164 check(to_lower_snake_case, "a", expect![[""]]);
165 check(to_lower_snake_case, "abc", expect![[""]]);
176 } 166 }
177 167
178 #[test] 168 #[test]
@@ -187,6 +177,11 @@ mod tests {
187 check(to_camel_case, "name", expect![["Name"]]); 177 check(to_camel_case, "name", expect![["Name"]]);
188 check(to_camel_case, "A", expect![[""]]); 178 check(to_camel_case, "A", expect![[""]]);
189 check(to_camel_case, "AABB", expect![[""]]); 179 check(to_camel_case, "AABB", expect![[""]]);
180 // Taken from rustc: /compiler/rustc_lint/src/nonstandard_style/tests.rs
181 check(to_camel_case, "X86_64", expect![[""]]);
182 check(to_camel_case, "x86__64", expect![["X86_64"]]);
183 check(to_camel_case, "Abc_123", expect![["Abc123"]]);
184 check(to_camel_case, "A1_b2_c3", expect![["A1B2C3"]]);
190 } 185 }
191 186
192 #[test] 187 #[test]
@@ -197,5 +192,7 @@ mod tests {
197 check(to_upper_snake_case, "CamelCase", expect![["CAMEL_CASE"]]); 192 check(to_upper_snake_case, "CamelCase", expect![["CAMEL_CASE"]]);
198 check(to_upper_snake_case, "lowerCamelCase", expect![["LOWER_CAMEL_CASE"]]); 193 check(to_upper_snake_case, "lowerCamelCase", expect![["LOWER_CAMEL_CASE"]]);
199 check(to_upper_snake_case, "A", expect![[""]]); 194 check(to_upper_snake_case, "A", expect![[""]]);
195 check(to_upper_snake_case, "ABC", expect![[""]]);
196 check(to_upper_snake_case, "X86_64", expect![[""]]);
200 } 197 }
201} 198}
diff --git a/crates/hir_ty/src/diagnostics/expr.rs b/crates/hir_ty/src/diagnostics/expr.rs
index 278a4b947..434b19354 100644
--- a/crates/hir_ty/src/diagnostics/expr.rs
+++ b/crates/hir_ty/src/diagnostics/expr.rs
@@ -17,17 +17,10 @@ use crate::{
17 ApplicationTy, InferenceResult, Ty, TypeCtor, 17 ApplicationTy, InferenceResult, Ty, TypeCtor,
18}; 18};
19 19
20pub use hir_def::{ 20pub(crate) use hir_def::{
21 body::{ 21 body::{Body, BodySourceMap},
22 scope::{ExprScopes, ScopeEntry, ScopeId}, 22 expr::{Expr, ExprId, MatchArm, Pat, PatId},
23 Body, BodySourceMap, ExprPtr, ExprSource, PatPtr, PatSource, 23 LocalFieldId, VariantId,
24 },
25 expr::{
26 ArithOp, Array, BinaryOp, BindingAnnotation, CmpOp, Expr, ExprId, Literal, LogicOp,
27 MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, Statement, UnaryOp,
28 },
29 src::HasSource,
30 LocalFieldId, Lookup, VariantId,
31}; 24};
32 25
33pub(super) struct ExprValidator<'a, 'b: 'a> { 26pub(super) struct ExprValidator<'a, 'b: 'a> {
diff --git a/crates/hir_ty/src/diagnostics/unsafe_check.rs b/crates/hir_ty/src/diagnostics/unsafe_check.rs
index 2da9688ca..6dc862826 100644
--- a/crates/hir_ty/src/diagnostics/unsafe_check.rs
+++ b/crates/hir_ty/src/diagnostics/unsafe_check.rs
@@ -59,12 +59,12 @@ impl<'a, 'b> UnsafeValidator<'a, 'b> {
59 } 59 }
60} 60}
61 61
62pub struct UnsafeExpr { 62pub(crate) struct UnsafeExpr {
63 pub expr: ExprId, 63 pub(crate) expr: ExprId,
64 pub inside_unsafe_block: bool, 64 pub(crate) inside_unsafe_block: bool,
65} 65}
66 66
67pub fn unsafe_expressions( 67pub(crate) fn unsafe_expressions(
68 db: &dyn HirDatabase, 68 db: &dyn HirDatabase,
69 infer: &InferenceResult, 69 infer: &InferenceResult,
70 def: DefWithBodyId, 70 def: DefWithBodyId,
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs
index d2e151f25..14e8c0633 100644
--- a/crates/hir_ty/src/display.rs
+++ b/crates/hir_ty/src/display.rs
@@ -26,6 +26,20 @@ pub trait HirDisplay {
26 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError>; 26 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError>;
27 27
28 /// Returns a `Display`able type that is human-readable. 28 /// Returns a `Display`able type that is human-readable.
29 fn into_displayable<'a>(
30 &'a self,
31 db: &'a dyn HirDatabase,
32 max_size: Option<usize>,
33 omit_verbose_types: bool,
34 display_target: DisplayTarget,
35 ) -> HirDisplayWrapper<'a, Self>
36 where
37 Self: Sized,
38 {
39 HirDisplayWrapper { db, t: self, max_size, omit_verbose_types, display_target }
40 }
41
42 /// Returns a `Display`able type that is human-readable.
29 /// Use this for showing types to the user (e.g. diagnostics) 43 /// Use this for showing types to the user (e.g. diagnostics)
30 fn display<'a>(&'a self, db: &'a dyn HirDatabase) -> HirDisplayWrapper<'a, Self> 44 fn display<'a>(&'a self, db: &'a dyn HirDatabase) -> HirDisplayWrapper<'a, Self>
31 where 45 where
@@ -82,6 +96,20 @@ pub trait HirDisplay {
82 }; 96 };
83 Ok(result) 97 Ok(result)
84 } 98 }
99
100 /// Returns a String representation of `self` for test purposes
101 fn display_test<'a>(&'a self, db: &'a dyn HirDatabase) -> HirDisplayWrapper<'a, Self>
102 where
103 Self: Sized,
104 {
105 HirDisplayWrapper {
106 db,
107 t: self,
108 max_size: None,
109 omit_verbose_types: false,
110 display_target: DisplayTarget::Test,
111 }
112 }
85} 113}
86 114
87impl<'a> HirFormatter<'a> { 115impl<'a> HirFormatter<'a> {
@@ -126,7 +154,7 @@ impl<'a> HirFormatter<'a> {
126} 154}
127 155
128#[derive(Clone, Copy)] 156#[derive(Clone, Copy)]
129enum DisplayTarget { 157pub enum DisplayTarget {
130 /// Display types for inlays, doc popups, autocompletion, etc... 158 /// Display types for inlays, doc popups, autocompletion, etc...
131 /// Showing `{unknown}` or not qualifying paths is fine here. 159 /// Showing `{unknown}` or not qualifying paths is fine here.
132 /// There's no reason for this to fail. 160 /// There's no reason for this to fail.
@@ -134,12 +162,17 @@ enum DisplayTarget {
134 /// Display types for inserting them in source files. 162 /// Display types for inserting them in source files.
135 /// The generated code should compile, so paths need to be qualified. 163 /// The generated code should compile, so paths need to be qualified.
136 SourceCode { module_id: ModuleId }, 164 SourceCode { module_id: ModuleId },
165 /// Only for test purpose to keep real types
166 Test,
137} 167}
138 168
139impl DisplayTarget { 169impl DisplayTarget {
140 fn is_source_code(&self) -> bool { 170 fn is_source_code(&self) -> bool {
141 matches!(self, Self::SourceCode {..}) 171 matches!(self, Self::SourceCode {..})
142 } 172 }
173 fn is_test(&self) -> bool {
174 matches!(self, Self::Test)
175 }
143} 176}
144 177
145#[derive(Debug)] 178#[derive(Debug)]
@@ -213,32 +246,32 @@ impl HirDisplay for ApplicationTy {
213 TypeCtor::Str => write!(f, "str")?, 246 TypeCtor::Str => write!(f, "str")?,
214 TypeCtor::Slice => { 247 TypeCtor::Slice => {
215 let t = self.parameters.as_single(); 248 let t = self.parameters.as_single();
216 write!(f, "[{}]", t.display(f.db))?; 249 write!(f, "[")?;
250 t.hir_fmt(f)?;
251 write!(f, "]")?;
217 } 252 }
218 TypeCtor::Array => { 253 TypeCtor::Array => {
219 let t = self.parameters.as_single(); 254 let t = self.parameters.as_single();
220 write!(f, "[{}; _]", t.display(f.db))?; 255 write!(f, "[")?;
256 t.hir_fmt(f)?;
257 write!(f, "; _]")?;
221 } 258 }
222 TypeCtor::RawPtr(m) => { 259 TypeCtor::RawPtr(m) => {
223 let t = self.parameters.as_single(); 260 let t = self.parameters.as_single();
224 let ty_display = t.display(f.db);
225 261
226 write!(f, "*{}", m.as_keyword_for_ptr())?; 262 write!(f, "*{}", m.as_keyword_for_ptr())?;
227 if matches!(t, Ty::Dyn(predicates) if predicates.len() > 1) { 263 if matches!(t, Ty::Dyn(predicates) if predicates.len() > 1) {
228 write!(f, "(")?; 264 write!(f, "(")?;
229 write!(f, "{}", ty_display)?; 265 t.hir_fmt(f)?;
230 write!(f, ")")?; 266 write!(f, ")")?;
231 } else { 267 } else {
232 write!(f, "{}", ty_display)?; 268 t.hir_fmt(f)?;
233 } 269 }
234 } 270 }
235 TypeCtor::Ref(m) => { 271 TypeCtor::Ref(m) => {
236 let t = self.parameters.as_single(); 272 let t = self.parameters.as_single();
237 let ty_display = if f.omit_verbose_types() { 273 let ty_display =
238 t.display_truncated(f.db, f.max_size) 274 t.into_displayable(f.db, f.max_size, f.omit_verbose_types, f.display_target);
239 } else {
240 t.display(f.db)
241 };
242 275
243 write!(f, "&{}", m.as_keyword_for_ref())?; 276 write!(f, "&{}", m.as_keyword_for_ref())?;
244 if matches!(t, Ty::Dyn(predicates) if predicates.len() > 1) { 277 if matches!(t, Ty::Dyn(predicates) if predicates.len() > 1) {
@@ -253,7 +286,9 @@ impl HirDisplay for ApplicationTy {
253 TypeCtor::Tuple { .. } => { 286 TypeCtor::Tuple { .. } => {
254 let ts = &self.parameters; 287 let ts = &self.parameters;
255 if ts.len() == 1 { 288 if ts.len() == 1 {
256 write!(f, "({},)", ts[0].display(f.db))?; 289 write!(f, "(")?;
290 ts[0].hir_fmt(f)?;
291 write!(f, ",)")?;
257 } else { 292 } else {
258 write!(f, "(")?; 293 write!(f, "(")?;
259 f.write_joined(&*ts.0, ", ")?; 294 f.write_joined(&*ts.0, ", ")?;
@@ -274,11 +309,12 @@ impl HirDisplay for ApplicationTy {
274 write!(f, ")")?; 309 write!(f, ")")?;
275 let ret = sig.ret(); 310 let ret = sig.ret();
276 if *ret != Ty::unit() { 311 if *ret != Ty::unit() {
277 let ret_display = if f.omit_verbose_types() { 312 let ret_display = ret.into_displayable(
278 ret.display_truncated(f.db, f.max_size) 313 f.db,
279 } else { 314 f.max_size,
280 ret.display(f.db) 315 f.omit_verbose_types,
281 }; 316 f.display_target,
317 );
282 write!(f, " -> {}", ret_display)?; 318 write!(f, " -> {}", ret_display)?;
283 } 319 }
284 } 320 }
@@ -310,17 +346,19 @@ impl HirDisplay for ApplicationTy {
310 write!(f, ")")?; 346 write!(f, ")")?;
311 let ret = sig.ret(); 347 let ret = sig.ret();
312 if *ret != Ty::unit() { 348 if *ret != Ty::unit() {
313 let ret_display = if f.omit_verbose_types() { 349 let ret_display = ret.into_displayable(
314 ret.display_truncated(f.db, f.max_size) 350 f.db,
315 } else { 351 f.max_size,
316 ret.display(f.db) 352 f.omit_verbose_types,
317 }; 353 f.display_target,
354 );
355
318 write!(f, " -> {}", ret_display)?; 356 write!(f, " -> {}", ret_display)?;
319 } 357 }
320 } 358 }
321 TypeCtor::Adt(def_id) => { 359 TypeCtor::Adt(def_id) => {
322 match f.display_target { 360 match f.display_target {
323 DisplayTarget::Diagnostics => { 361 DisplayTarget::Diagnostics | DisplayTarget::Test => {
324 let name = match def_id { 362 let name = match def_id {
325 AdtId::StructId(it) => f.db.struct_data(it).name.clone(), 363 AdtId::StructId(it) => f.db.struct_data(it).name.clone(),
326 AdtId::UnionId(it) => f.db.union_data(it).name.clone(), 364 AdtId::UnionId(it) => f.db.union_data(it).name.clone(),
@@ -389,12 +427,23 @@ impl HirDisplay for ApplicationTy {
389 _ => panic!("not an associated type"), 427 _ => panic!("not an associated type"),
390 }; 428 };
391 let trait_ = f.db.trait_data(trait_); 429 let trait_ = f.db.trait_data(trait_);
392 let type_alias = f.db.type_alias_data(type_alias); 430 let type_alias_data = f.db.type_alias_data(type_alias);
393 write!(f, "{}::{}", trait_.name, type_alias.name)?; 431
394 if self.parameters.len() > 0 { 432 // Use placeholder associated types when the target is test (https://rust-lang.github.io/chalk/book/clauses/type_equality.html#placeholder-associated-types)
395 write!(f, "<")?; 433 if f.display_target.is_test() {
396 f.write_joined(&*self.parameters.0, ", ")?; 434 write!(f, "{}::{}", trait_.name, type_alias_data.name)?;
397 write!(f, ">")?; 435 if self.parameters.len() > 0 {
436 write!(f, "<")?;
437 f.write_joined(&*self.parameters.0, ", ")?;
438 write!(f, ">")?;
439 }
440 } else {
441 let projection_ty = ProjectionTy {
442 associated_ty: type_alias,
443 parameters: self.parameters.clone(),
444 };
445
446 projection_ty.hir_fmt(f)?;
398 } 447 }
399 } 448 }
400 TypeCtor::ForeignType(type_alias) => { 449 TypeCtor::ForeignType(type_alias) => {
@@ -439,11 +488,12 @@ impl HirDisplay for ApplicationTy {
439 write!(f, "|")?; 488 write!(f, "|")?;
440 }; 489 };
441 490
442 let ret_display = if f.omit_verbose_types() { 491 let ret_display = sig.ret().into_displayable(
443 sig.ret().display_truncated(f.db, f.max_size) 492 f.db,
444 } else { 493 f.max_size,
445 sig.ret().display(f.db) 494 f.omit_verbose_types,
446 }; 495 f.display_target,
496 );
447 write!(f, " -> {}", ret_display)?; 497 write!(f, " -> {}", ret_display)?;
448 } else { 498 } else {
449 write!(f, "{{closure}}")?; 499 write!(f, "{{closure}}")?;
@@ -461,7 +511,13 @@ impl HirDisplay for ProjectionTy {
461 } 511 }
462 512
463 let trait_ = f.db.trait_data(self.trait_(f.db)); 513 let trait_ = f.db.trait_data(self.trait_(f.db));
464 write!(f, "<{} as {}", self.parameters[0].display(f.db), trait_.name)?; 514 let first_parameter = self.parameters[0].into_displayable(
515 f.db,
516 f.max_size,
517 f.omit_verbose_types,
518 f.display_target,
519 );
520 write!(f, "<{} as {}", first_parameter, trait_.name)?;
465 if self.parameters.len() > 1 { 521 if self.parameters.len() > 1 {
466 write!(f, "<")?; 522 write!(f, "<")?;
467 f.write_joined(&self.parameters[1..], ", ")?; 523 f.write_joined(&self.parameters[1..], ", ")?;
@@ -640,10 +696,10 @@ impl HirDisplay for GenericPredicate {
640 projection_pred.projection_ty.trait_ref(f.db).hir_fmt_ext(f, true)?; 696 projection_pred.projection_ty.trait_ref(f.db).hir_fmt_ext(f, true)?;
641 write!( 697 write!(
642 f, 698 f,
643 ">::{} = {}", 699 ">::{} = ",
644 f.db.type_alias_data(projection_pred.projection_ty.associated_ty).name, 700 f.db.type_alias_data(projection_pred.projection_ty.associated_ty).name,
645 projection_pred.ty.display(f.db)
646 )?; 701 )?;
702 projection_pred.ty.hir_fmt(f)?;
647 } 703 }
648 GenericPredicate::Error => write!(f, "{{error}}")?, 704 GenericPredicate::Error => write!(f, "{{error}}")?,
649 } 705 }
@@ -654,13 +710,18 @@ impl HirDisplay for GenericPredicate {
654impl HirDisplay for Obligation { 710impl HirDisplay for Obligation {
655 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { 711 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
656 match self { 712 match self {
657 Obligation::Trait(tr) => write!(f, "Implements({})", tr.display(f.db)), 713 Obligation::Trait(tr) => {
658 Obligation::Projection(proj) => write!( 714 write!(f, "Implements(")?;
659 f, 715 tr.hir_fmt(f)?;
660 "Normalize({} => {})", 716 write!(f, ")")
661 proj.projection_ty.display(f.db), 717 }
662 proj.ty.display(f.db) 718 Obligation::Projection(proj) => {
663 ), 719 write!(f, "Normalize(")?;
720 proj.projection_ty.hir_fmt(f)?;
721 write!(f, " => ")?;
722 proj.ty.hir_fmt(f)?;
723 write!(f, ")")
724 }
664 } 725 }
665 } 726 }
666} 727}
diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs
index 644ebd42d..a14d67c06 100644
--- a/crates/hir_ty/src/infer.rs
+++ b/crates/hir_ty/src/infer.rs
@@ -94,7 +94,7 @@ enum BindingMode {
94} 94}
95 95
96impl BindingMode { 96impl BindingMode {
97 pub fn convert(annotation: BindingAnnotation) -> BindingMode { 97 fn convert(annotation: BindingAnnotation) -> BindingMode {
98 match annotation { 98 match annotation {
99 BindingAnnotation::Unannotated | BindingAnnotation::Mutable => BindingMode::Move, 99 BindingAnnotation::Unannotated | BindingAnnotation::Mutable => BindingMode::Move,
100 BindingAnnotation::Ref => BindingMode::Ref(Mutability::Shared), 100 BindingAnnotation::Ref => BindingMode::Ref(Mutability::Shared),
@@ -214,9 +214,9 @@ struct InferenceContext<'a> {
214 214
215#[derive(Clone, Debug)] 215#[derive(Clone, Debug)]
216struct BreakableContext { 216struct BreakableContext {
217 pub may_break: bool, 217 may_break: bool,
218 pub break_ty: Ty, 218 break_ty: Ty,
219 pub label: Option<name::Name>, 219 label: Option<name::Name>,
220} 220}
221 221
222fn find_breakable<'c>( 222fn find_breakable<'c>(
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs
index 8ac4cf89a..605951b10 100644
--- a/crates/hir_ty/src/infer/expr.rs
+++ b/crates/hir_ty/src/infer/expr.rs
@@ -107,7 +107,7 @@ impl<'a> InferenceContext<'a> {
107 } 107 }
108 } 108 }
109 109
110 pub fn callable_sig(&mut self, ty: &Ty, num_args: usize) -> Option<(Vec<Ty>, Ty)> { 110 pub(crate) fn callable_sig(&mut self, ty: &Ty, num_args: usize) -> Option<(Vec<Ty>, Ty)> {
111 match ty.callable_sig(self.db) { 111 match ty.callable_sig(self.db) {
112 Some(sig) => Some((sig.params().to_vec(), sig.ret().clone())), 112 Some(sig) => Some((sig.params().to_vec(), sig.ret().clone())),
113 None => self.callable_sig_from_fn_trait(ty, num_args), 113 None => self.callable_sig_from_fn_trait(ty, num_args),
diff --git a/crates/hir_ty/src/infer/unify.rs b/crates/hir_ty/src/infer/unify.rs
index 2e895d911..76984242e 100644
--- a/crates/hir_ty/src/infer/unify.rs
+++ b/crates/hir_ty/src/infer/unify.rs
@@ -35,7 +35,7 @@ where
35 35
36#[derive(Debug)] 36#[derive(Debug)]
37pub(super) struct Canonicalized<T> { 37pub(super) struct Canonicalized<T> {
38 pub value: Canonical<T>, 38 pub(super) value: Canonical<T>,
39 free_vars: Vec<InferTy>, 39 free_vars: Vec<InferTy>,
40} 40}
41 41
@@ -127,7 +127,7 @@ where
127} 127}
128 128
129impl<T> Canonicalized<T> { 129impl<T> Canonicalized<T> {
130 pub fn decanonicalize_ty(&self, mut ty: Ty) -> Ty { 130 pub(super) fn decanonicalize_ty(&self, mut ty: Ty) -> Ty {
131 ty.walk_mut_binders( 131 ty.walk_mut_binders(
132 &mut |ty, binders| { 132 &mut |ty, binders| {
133 if let &mut Ty::Bound(bound) = ty { 133 if let &mut Ty::Bound(bound) = ty {
@@ -141,7 +141,11 @@ impl<T> Canonicalized<T> {
141 ty 141 ty
142 } 142 }
143 143
144 pub fn apply_solution(&self, ctx: &mut InferenceContext<'_>, solution: Canonical<Substs>) { 144 pub(super) fn apply_solution(
145 &self,
146 ctx: &mut InferenceContext<'_>,
147 solution: Canonical<Substs>,
148 ) {
145 // the solution may contain new variables, which we need to convert to new inference vars 149 // the solution may contain new variables, which we need to convert to new inference vars
146 let new_vars = Substs( 150 let new_vars = Substs(
147 solution 151 solution
@@ -164,7 +168,7 @@ impl<T> Canonicalized<T> {
164 } 168 }
165} 169}
166 170
167pub fn unify(tys: &Canonical<(Ty, Ty)>) -> Option<Substs> { 171pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option<Substs> {
168 let mut table = InferenceTable::new(); 172 let mut table = InferenceTable::new();
169 let vars = Substs( 173 let vars = Substs(
170 tys.kinds 174 tys.kinds
@@ -199,41 +203,46 @@ pub(crate) struct InferenceTable {
199} 203}
200 204
201impl InferenceTable { 205impl InferenceTable {
202 pub fn new() -> Self { 206 pub(crate) fn new() -> Self {
203 InferenceTable { var_unification_table: InPlaceUnificationTable::new() } 207 InferenceTable { var_unification_table: InPlaceUnificationTable::new() }
204 } 208 }
205 209
206 pub fn new_type_var(&mut self) -> Ty { 210 pub(crate) fn new_type_var(&mut self) -> Ty {
207 Ty::Infer(InferTy::TypeVar(self.var_unification_table.new_key(TypeVarValue::Unknown))) 211 Ty::Infer(InferTy::TypeVar(self.var_unification_table.new_key(TypeVarValue::Unknown)))
208 } 212 }
209 213
210 pub fn new_integer_var(&mut self) -> Ty { 214 pub(crate) fn new_integer_var(&mut self) -> Ty {
211 Ty::Infer(InferTy::IntVar(self.var_unification_table.new_key(TypeVarValue::Unknown))) 215 Ty::Infer(InferTy::IntVar(self.var_unification_table.new_key(TypeVarValue::Unknown)))
212 } 216 }
213 217
214 pub fn new_float_var(&mut self) -> Ty { 218 pub(crate) fn new_float_var(&mut self) -> Ty {
215 Ty::Infer(InferTy::FloatVar(self.var_unification_table.new_key(TypeVarValue::Unknown))) 219 Ty::Infer(InferTy::FloatVar(self.var_unification_table.new_key(TypeVarValue::Unknown)))
216 } 220 }
217 221
218 pub fn new_maybe_never_type_var(&mut self) -> Ty { 222 pub(crate) fn new_maybe_never_type_var(&mut self) -> Ty {
219 Ty::Infer(InferTy::MaybeNeverTypeVar( 223 Ty::Infer(InferTy::MaybeNeverTypeVar(
220 self.var_unification_table.new_key(TypeVarValue::Unknown), 224 self.var_unification_table.new_key(TypeVarValue::Unknown),
221 )) 225 ))
222 } 226 }
223 227
224 pub fn resolve_ty_completely(&mut self, ty: Ty) -> Ty { 228 pub(crate) fn resolve_ty_completely(&mut self, ty: Ty) -> Ty {
225 self.resolve_ty_completely_inner(&mut Vec::new(), ty) 229 self.resolve_ty_completely_inner(&mut Vec::new(), ty)
226 } 230 }
227 231
228 pub fn resolve_ty_as_possible(&mut self, ty: Ty) -> Ty { 232 pub(crate) fn resolve_ty_as_possible(&mut self, ty: Ty) -> Ty {
229 self.resolve_ty_as_possible_inner(&mut Vec::new(), ty) 233 self.resolve_ty_as_possible_inner(&mut Vec::new(), ty)
230 } 234 }
231 235
232 pub fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool { 236 pub(crate) fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool {
233 self.unify_inner(ty1, ty2, 0) 237 self.unify_inner(ty1, ty2, 0)
234 } 238 }
235 239
236 pub fn unify_substs(&mut self, substs1: &Substs, substs2: &Substs, depth: usize) -> bool { 240 pub(crate) fn unify_substs(
241 &mut self,
242 substs1: &Substs,
243 substs2: &Substs,
244 depth: usize,
245 ) -> bool {
237 substs1.0.iter().zip(substs2.0.iter()).all(|(t1, t2)| self.unify_inner(t1, t2, depth)) 246 substs1.0.iter().zip(substs2.0.iter()).all(|(t1, t2)| self.unify_inner(t1, t2, depth))
238 } 247 }
239 248
@@ -331,7 +340,7 @@ impl InferenceTable {
331 340
332 /// If `ty` is a type variable with known type, returns that type; 341 /// If `ty` is a type variable with known type, returns that type;
333 /// otherwise, return ty. 342 /// otherwise, return ty.
334 pub fn resolve_ty_shallow<'b>(&mut self, ty: &'b Ty) -> Cow<'b, Ty> { 343 pub(crate) fn resolve_ty_shallow<'b>(&mut self, ty: &'b Ty) -> Cow<'b, Ty> {
335 let mut ty = Cow::Borrowed(ty); 344 let mut ty = Cow::Borrowed(ty);
336 // The type variable could resolve to a int/float variable. Hence try 345 // The type variable could resolve to a int/float variable. Hence try
337 // resolving up to three times; each type of variable shouldn't occur 346 // resolving up to three times; each type of variable shouldn't occur
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs
index 768d95eff..5a8c97198 100644
--- a/crates/hir_ty/src/lib.rs
+++ b/crates/hir_ty/src/lib.rs
@@ -1,6 +1,5 @@
1//! The type system. We currently use this to infer types for completion, hover 1//! The type system. We currently use this to infer types for completion, hover
2//! information and various assists. 2//! information and various assists.
3
4#[allow(unused)] 3#[allow(unused)]
5macro_rules! eprintln { 4macro_rules! eprintln {
6 ($($tt:tt)*) => { stdx::eprintln!($($tt)*) }; 5 ($($tt:tt)*) => { stdx::eprintln!($($tt)*) };
@@ -1115,5 +1114,5 @@ pub struct ReturnTypeImplTraits {
1115 1114
1116#[derive(Clone, PartialEq, Eq, Debug, Hash)] 1115#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1117pub(crate) struct ReturnTypeImplTrait { 1116pub(crate) struct ReturnTypeImplTrait {
1118 pub bounds: Binders<Vec<GenericPredicate>>, 1117 pub(crate) bounds: Binders<Vec<GenericPredicate>>,
1119} 1118}
diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs
index 8961df404..5a6f0c67f 100644
--- a/crates/hir_ty/src/method_resolution.rs
+++ b/crates/hir_ty/src/method_resolution.rs
@@ -740,6 +740,19 @@ pub fn implements_trait(
740 solution.is_some() 740 solution.is_some()
741} 741}
742 742
743pub fn implements_trait_unique(
744 ty: &Canonical<Ty>,
745 db: &dyn HirDatabase,
746 env: Arc<TraitEnvironment>,
747 krate: CrateId,
748 trait_: TraitId,
749) -> bool {
750 let goal = generic_implements_goal(db, env, trait_, ty.clone());
751 let solution = db.trait_solve(krate, goal);
752
753 matches!(solution, Some(crate::traits::Solution::Unique(_)))
754}
755
743/// This creates Substs for a trait with the given Self type and type variables 756/// This creates Substs for a trait with the given Self type and type variables
744/// for all other parameters, to query Chalk with it. 757/// for all other parameters, to query Chalk with it.
745fn generic_implements_goal( 758fn generic_implements_goal(
diff --git a/crates/hir_ty/src/test_db.rs b/crates/hir_ty/src/test_db.rs
index 15b8435e9..22254b765 100644
--- a/crates/hir_ty/src/test_db.rs
+++ b/crates/hir_ty/src/test_db.rs
@@ -21,7 +21,7 @@ use test_utils::extract_annotations;
21 crate::db::HirDatabaseStorage 21 crate::db::HirDatabaseStorage
22)] 22)]
23#[derive(Default)] 23#[derive(Default)]
24pub struct TestDB { 24pub(crate) struct TestDB {
25 storage: salsa::Storage<TestDB>, 25 storage: salsa::Storage<TestDB>,
26 events: Mutex<Option<Vec<salsa::Event>>>, 26 events: Mutex<Option<Vec<salsa::Event>>>,
27} 27}
@@ -113,13 +113,13 @@ impl TestDB {
113} 113}
114 114
115impl TestDB { 115impl TestDB {
116 pub fn log(&self, f: impl FnOnce()) -> Vec<salsa::Event> { 116 pub(crate) fn log(&self, f: impl FnOnce()) -> Vec<salsa::Event> {
117 *self.events.lock().unwrap() = Some(Vec::new()); 117 *self.events.lock().unwrap() = Some(Vec::new());
118 f(); 118 f();
119 self.events.lock().unwrap().take().unwrap() 119 self.events.lock().unwrap().take().unwrap()
120 } 120 }
121 121
122 pub fn log_executed(&self, f: impl FnOnce()) -> Vec<String> { 122 pub(crate) fn log_executed(&self, f: impl FnOnce()) -> Vec<String> {
123 let events = self.log(f); 123 let events = self.log(f);
124 events 124 events
125 .into_iter() 125 .into_iter()
diff --git a/crates/hir_ty/src/tests.rs b/crates/hir_ty/src/tests.rs
index 0445efc9e..104ef334c 100644
--- a/crates/hir_ty/src/tests.rs
+++ b/crates/hir_ty/src/tests.rs
@@ -74,7 +74,7 @@ fn check_types_impl(ra_fixture: &str, display_source: bool) {
74 let module = db.module_for_file(file_id); 74 let module = db.module_for_file(file_id);
75 ty.display_source_code(&db, module).unwrap() 75 ty.display_source_code(&db, module).unwrap()
76 } else { 76 } else {
77 ty.display(&db).to_string() 77 ty.display_test(&db).to_string()
78 }; 78 };
79 assert_eq!(expected, actual); 79 assert_eq!(expected, actual);
80 checked_one = true; 80 checked_one = true;
@@ -163,7 +163,7 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
163 macro_prefix, 163 macro_prefix,
164 range, 164 range,
165 ellipsize(text, 15), 165 ellipsize(text, 15),
166 ty.display(&db) 166 ty.display_test(&db)
167 ); 167 );
168 } 168 }
169 if include_mismatches { 169 if include_mismatches {
@@ -179,8 +179,8 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
179 "{}{:?}: expected {}, got {}\n", 179 "{}{:?}: expected {}, got {}\n",
180 macro_prefix, 180 macro_prefix,
181 range, 181 range,
182 mismatch.expected.display(&db), 182 mismatch.expected.display_test(&db),
183 mismatch.actual.display(&db), 183 mismatch.actual.display_test(&db),
184 ); 184 );
185 } 185 }
186 } 186 }
diff --git a/crates/hir_ty/src/traits/chalk.rs b/crates/hir_ty/src/traits/chalk.rs
index cbe5cd7dd..55e2c3a3e 100644
--- a/crates/hir_ty/src/traits/chalk.rs
+++ b/crates/hir_ty/src/traits/chalk.rs
@@ -3,7 +3,7 @@ use std::sync::Arc;
3 3
4use log::debug; 4use log::debug;
5 5
6use chalk_ir::{fold::shift::Shift, CanonicalVarKinds, GenericArg, TypeName}; 6use chalk_ir::{fold::shift::Shift, CanonicalVarKinds, GenericArg};
7use chalk_solve::rust_ir::{self, OpaqueTyDatumBound, WellKnownTrait}; 7use chalk_solve::rust_ir::{self, OpaqueTyDatumBound, WellKnownTrait};
8 8
9use base_db::{salsa::InternKey, CrateId}; 9use base_db::{salsa::InternKey, CrateId};
@@ -27,7 +27,7 @@ use mapping::{
27 TypeAliasAsValue, 27 TypeAliasAsValue,
28}; 28};
29 29
30pub use self::interner::*; 30pub(crate) use self::interner::*;
31 31
32pub(super) mod tls; 32pub(super) mod tls;
33mod interner; 33mod interner;
@@ -81,7 +81,10 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
81 81
82 let ty: Ty = from_chalk(self.db, parameters[0].assert_ty_ref(&Interner).clone()); 82 let ty: Ty = from_chalk(self.db, parameters[0].assert_ty_ref(&Interner).clone());
83 83
84 fn binder_kind(ty: &Ty, binders: &CanonicalVarKinds<Interner>) -> Option<chalk_ir::TyKind> { 84 fn binder_kind(
85 ty: &Ty,
86 binders: &CanonicalVarKinds<Interner>,
87 ) -> Option<chalk_ir::TyVariableKind> {
85 if let Ty::Bound(bv) = ty { 88 if let Ty::Bound(bv) = ty {
86 let binders = binders.as_slice(&Interner); 89 let binders = binders.as_slice(&Interner);
87 if bv.debruijn == DebruijnIndex::INNERMOST { 90 if bv.debruijn == DebruijnIndex::INNERMOST {
@@ -95,8 +98,8 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
95 98
96 let self_ty_fp = TyFingerprint::for_impl(&ty); 99 let self_ty_fp = TyFingerprint::for_impl(&ty);
97 let fps: &[TyFingerprint] = match binder_kind(&ty, binders) { 100 let fps: &[TyFingerprint] = match binder_kind(&ty, binders) {
98 Some(chalk_ir::TyKind::Integer) => &ALL_INT_FPS, 101 Some(chalk_ir::TyVariableKind::Integer) => &ALL_INT_FPS,
99 Some(chalk_ir::TyKind::Float) => &ALL_FLOAT_FPS, 102 Some(chalk_ir::TyVariableKind::Float) => &ALL_FLOAT_FPS,
100 _ => self_ty_fp.as_ref().map(std::slice::from_ref).unwrap_or(&[]), 103 _ => self_ty_fp.as_ref().map(std::slice::from_ref).unwrap_or(&[]),
101 }; 104 };
102 105
@@ -129,12 +132,8 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
129 debug!("impls_for_trait returned {} impls", result.len()); 132 debug!("impls_for_trait returned {} impls", result.len());
130 result 133 result
131 } 134 }
132 fn impl_provided_for( 135 fn impl_provided_for(&self, auto_trait_id: TraitId, kind: &chalk_ir::TyKind<Interner>) -> bool {
133 &self, 136 debug!("impl_provided_for {:?}, {:?}", auto_trait_id, kind);
134 auto_trait_id: TraitId,
135 application_ty: &chalk_ir::ApplicationTy<Interner>,
136 ) -> bool {
137 debug!("impl_provided_for {:?}, {:?}", auto_trait_id, application_ty);
138 false // FIXME 137 false // FIXME
139 } 138 }
140 fn associated_ty_value(&self, id: AssociatedTyValueId) -> Arc<AssociatedTyValue> { 139 fn associated_ty_value(&self, id: AssociatedTyValueId) -> Arc<AssociatedTyValue> {
@@ -466,7 +465,7 @@ pub(crate) fn struct_datum_query(
466 struct_id: AdtId, 465 struct_id: AdtId,
467) -> Arc<StructDatum> { 466) -> Arc<StructDatum> {
468 debug!("struct_datum {:?}", struct_id); 467 debug!("struct_datum {:?}", struct_id);
469 let type_ctor: TypeCtor = from_chalk(db, TypeName::Adt(struct_id)); 468 let type_ctor = TypeCtor::Adt(from_chalk(db, struct_id));
470 debug!("struct {:?} = {:?}", struct_id, type_ctor); 469 debug!("struct {:?} = {:?}", struct_id, type_ctor);
471 let num_params = type_ctor.num_ty_params(db); 470 let num_params = type_ctor.num_ty_params(db);
472 let upstream = type_ctor.krate(db) != Some(krate); 471 let upstream = type_ctor.krate(db) != Some(krate);
diff --git a/crates/hir_ty/src/traits/chalk/interner.rs b/crates/hir_ty/src/traits/chalk/interner.rs
index f9304b7d0..39569e690 100644
--- a/crates/hir_ty/src/traits/chalk/interner.rs
+++ b/crates/hir_ty/src/traits/chalk/interner.rs
@@ -10,21 +10,21 @@ use std::{fmt, sync::Arc};
10#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)] 10#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]
11pub struct Interner; 11pub struct Interner;
12 12
13pub type AssocTypeId = chalk_ir::AssocTypeId<Interner>; 13pub(crate) type AssocTypeId = chalk_ir::AssocTypeId<Interner>;
14pub type AssociatedTyDatum = chalk_solve::rust_ir::AssociatedTyDatum<Interner>; 14pub(crate) type AssociatedTyDatum = chalk_solve::rust_ir::AssociatedTyDatum<Interner>;
15pub type ForeignDefId = chalk_ir::ForeignDefId<Interner>; 15pub(crate) type ForeignDefId = chalk_ir::ForeignDefId<Interner>;
16pub type TraitId = chalk_ir::TraitId<Interner>; 16pub(crate) type TraitId = chalk_ir::TraitId<Interner>;
17pub type TraitDatum = chalk_solve::rust_ir::TraitDatum<Interner>; 17pub(crate) type TraitDatum = chalk_solve::rust_ir::TraitDatum<Interner>;
18pub type AdtId = chalk_ir::AdtId<Interner>; 18pub(crate) type AdtId = chalk_ir::AdtId<Interner>;
19pub type StructDatum = chalk_solve::rust_ir::AdtDatum<Interner>; 19pub(crate) type StructDatum = chalk_solve::rust_ir::AdtDatum<Interner>;
20pub type ImplId = chalk_ir::ImplId<Interner>; 20pub(crate) type ImplId = chalk_ir::ImplId<Interner>;
21pub type ImplDatum = chalk_solve::rust_ir::ImplDatum<Interner>; 21pub(crate) type ImplDatum = chalk_solve::rust_ir::ImplDatum<Interner>;
22pub type AssociatedTyValueId = chalk_solve::rust_ir::AssociatedTyValueId<Interner>; 22pub(crate) type AssociatedTyValueId = chalk_solve::rust_ir::AssociatedTyValueId<Interner>;
23pub type AssociatedTyValue = chalk_solve::rust_ir::AssociatedTyValue<Interner>; 23pub(crate) type AssociatedTyValue = chalk_solve::rust_ir::AssociatedTyValue<Interner>;
24pub type FnDefId = chalk_ir::FnDefId<Interner>; 24pub(crate) type FnDefId = chalk_ir::FnDefId<Interner>;
25pub type FnDefDatum = chalk_solve::rust_ir::FnDefDatum<Interner>; 25pub(crate) type FnDefDatum = chalk_solve::rust_ir::FnDefDatum<Interner>;
26pub type OpaqueTyId = chalk_ir::OpaqueTyId<Interner>; 26pub(crate) type OpaqueTyId = chalk_ir::OpaqueTyId<Interner>;
27pub type OpaqueTyDatum = chalk_solve::rust_ir::OpaqueTyDatum<Interner>; 27pub(crate) type OpaqueTyDatum = chalk_solve::rust_ir::OpaqueTyDatum<Interner>;
28 28
29impl chalk_ir::interner::Interner for Interner { 29impl chalk_ir::interner::Interner for Interner {
30 type InternedType = Arc<chalk_ir::TyData<Self>>; 30 type InternedType = Arc<chalk_ir::TyData<Self>>;
@@ -122,13 +122,6 @@ impl chalk_ir::interner::Interner for Interner {
122 tls::with_current_program(|prog| Some(prog?.debug_program_clause_implication(pci, fmt))) 122 tls::with_current_program(|prog| Some(prog?.debug_program_clause_implication(pci, fmt)))
123 } 123 }
124 124
125 fn debug_application_ty(
126 application_ty: &chalk_ir::ApplicationTy<Interner>,
127 fmt: &mut fmt::Formatter<'_>,
128 ) -> Option<fmt::Result> {
129 tls::with_current_program(|prog| Some(prog?.debug_application_ty(application_ty, fmt)))
130 }
131
132 fn debug_substitution( 125 fn debug_substitution(
133 substitution: &chalk_ir::Substitution<Interner>, 126 substitution: &chalk_ir::Substitution<Interner>,
134 fmt: &mut fmt::Formatter<'_>, 127 fmt: &mut fmt::Formatter<'_>,
diff --git a/crates/hir_ty/src/traits/chalk/mapping.rs b/crates/hir_ty/src/traits/chalk/mapping.rs
index be3301313..86cbc4c7e 100644
--- a/crates/hir_ty/src/traits/chalk/mapping.rs
+++ b/crates/hir_ty/src/traits/chalk/mapping.rs
@@ -4,7 +4,7 @@
4//! conversions. 4//! conversions.
5 5
6use chalk_ir::{ 6use chalk_ir::{
7 cast::Cast, fold::shift::Shift, interner::HasInterner, PlaceholderIndex, Scalar, TypeName, 7 cast::Cast, fold::shift::Shift, interner::HasInterner, LifetimeData, PlaceholderIndex, Scalar,
8 UniverseIndex, 8 UniverseIndex,
9}; 9};
10use chalk_solve::rust_ir; 10use chalk_solve::rust_ir;
@@ -32,7 +32,7 @@ impl ToChalk for Ty {
32 TypeCtor::Array => array_to_chalk(db, apply_ty.parameters), 32 TypeCtor::Array => array_to_chalk(db, apply_ty.parameters),
33 TypeCtor::FnPtr { num_args: _, is_varargs } => { 33 TypeCtor::FnPtr { num_args: _, is_varargs } => {
34 let substitution = apply_ty.parameters.to_chalk(db).shifted_in(&Interner); 34 let substitution = apply_ty.parameters.to_chalk(db).shifted_in(&Interner);
35 chalk_ir::TyData::Function(chalk_ir::FnPointer { 35 chalk_ir::TyKind::Function(chalk_ir::FnPointer {
36 num_binders: 0, 36 num_binders: 0,
37 sig: chalk_ir::FnSig { 37 sig: chalk_ir::FnSig {
38 abi: (), 38 abi: (),
@@ -43,10 +43,68 @@ impl ToChalk for Ty {
43 }) 43 })
44 .intern(&Interner) 44 .intern(&Interner)
45 } 45 }
46 _ => { 46 TypeCtor::AssociatedType(type_alias) => {
47 let name = apply_ty.ctor.to_chalk(db); 47 let assoc_type = TypeAliasAsAssocType(type_alias);
48 let assoc_type_id = assoc_type.to_chalk(db);
48 let substitution = apply_ty.parameters.to_chalk(db); 49 let substitution = apply_ty.parameters.to_chalk(db);
49 chalk_ir::ApplicationTy { name, substitution }.cast(&Interner).intern(&Interner) 50 chalk_ir::TyKind::AssociatedType(assoc_type_id, substitution).intern(&Interner)
51 }
52
53 TypeCtor::OpaqueType(impl_trait_id) => {
54 let id = impl_trait_id.to_chalk(db);
55 let substitution = apply_ty.parameters.to_chalk(db);
56 chalk_ir::TyKind::OpaqueType(id, substitution).intern(&Interner)
57 }
58
59 TypeCtor::ForeignType(type_alias) => {
60 let foreign_type = TypeAliasAsForeignType(type_alias);
61 let foreign_type_id = foreign_type.to_chalk(db);
62 chalk_ir::TyKind::Foreign(foreign_type_id).intern(&Interner)
63 }
64
65 TypeCtor::Bool => chalk_ir::TyKind::Scalar(Scalar::Bool).intern(&Interner),
66 TypeCtor::Char => chalk_ir::TyKind::Scalar(Scalar::Char).intern(&Interner),
67 TypeCtor::Int(int_ty) => {
68 chalk_ir::TyKind::Scalar(int_ty_to_chalk(int_ty)).intern(&Interner)
69 }
70 TypeCtor::Float(FloatTy { bitness: FloatBitness::X32 }) => {
71 chalk_ir::TyKind::Scalar(Scalar::Float(chalk_ir::FloatTy::F32))
72 .intern(&Interner)
73 }
74 TypeCtor::Float(FloatTy { bitness: FloatBitness::X64 }) => {
75 chalk_ir::TyKind::Scalar(Scalar::Float(chalk_ir::FloatTy::F64))
76 .intern(&Interner)
77 }
78
79 TypeCtor::Tuple { cardinality } => {
80 let substitution = apply_ty.parameters.to_chalk(db);
81 chalk_ir::TyKind::Tuple(cardinality.into(), substitution).intern(&Interner)
82 }
83 TypeCtor::RawPtr(mutability) => {
84 let ty = apply_ty.parameters[0].clone().to_chalk(db);
85 chalk_ir::TyKind::Raw(mutability.to_chalk(db), ty).intern(&Interner)
86 }
87 TypeCtor::Slice => {
88 chalk_ir::TyKind::Slice(apply_ty.parameters[0].clone().to_chalk(db))
89 .intern(&Interner)
90 }
91 TypeCtor::Str => chalk_ir::TyKind::Str.intern(&Interner),
92 TypeCtor::FnDef(callable_def) => {
93 let id = callable_def.to_chalk(db);
94 let substitution = apply_ty.parameters.to_chalk(db);
95 chalk_ir::TyKind::FnDef(id, substitution).intern(&Interner)
96 }
97 TypeCtor::Never => chalk_ir::TyKind::Never.intern(&Interner),
98
99 TypeCtor::Closure { def, expr } => {
100 let closure_id = db.intern_closure((def, expr));
101 let substitution = apply_ty.parameters.to_chalk(db);
102 chalk_ir::TyKind::Closure(closure_id.into(), substitution).intern(&Interner)
103 }
104
105 TypeCtor::Adt(adt_id) => {
106 let substitution = apply_ty.parameters.to_chalk(db);
107 chalk_ir::TyKind::Adt(chalk_ir::AdtId(adt_id), substitution).intern(&Interner)
50 } 108 }
51 }, 109 },
52 Ty::Projection(proj_ty) => { 110 Ty::Projection(proj_ty) => {
@@ -67,7 +125,7 @@ impl ToChalk for Ty {
67 } 125 }
68 .to_ty::<Interner>(&Interner) 126 .to_ty::<Interner>(&Interner)
69 } 127 }
70 Ty::Bound(idx) => chalk_ir::TyData::BoundVar(idx).intern(&Interner), 128 Ty::Bound(idx) => chalk_ir::TyKind::BoundVar(idx).intern(&Interner),
71 Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"), 129 Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"),
72 Ty::Dyn(predicates) => { 130 Ty::Dyn(predicates) => {
73 let where_clauses = chalk_ir::QuantifiedWhereClauses::from_iter( 131 let where_clauses = chalk_ir::QuantifiedWhereClauses::from_iter(
@@ -76,57 +134,47 @@ impl ToChalk for Ty {
76 ); 134 );
77 let bounded_ty = chalk_ir::DynTy { 135 let bounded_ty = chalk_ir::DynTy {
78 bounds: make_binders(where_clauses, 1), 136 bounds: make_binders(where_clauses, 1),
79 lifetime: FAKE_PLACEHOLDER.to_lifetime(&Interner), 137 lifetime: LifetimeData::Static.intern(&Interner),
80 }; 138 };
81 chalk_ir::TyData::Dyn(bounded_ty).intern(&Interner) 139 chalk_ir::TyKind::Dyn(bounded_ty).intern(&Interner)
82 } 140 }
83 Ty::Opaque(opaque_ty) => { 141 Ty::Opaque(opaque_ty) => {
84 let opaque_ty_id = opaque_ty.opaque_ty_id.to_chalk(db); 142 let opaque_ty_id = opaque_ty.opaque_ty_id.to_chalk(db);
85 let substitution = opaque_ty.parameters.to_chalk(db); 143 let substitution = opaque_ty.parameters.to_chalk(db);
86 chalk_ir::TyData::Alias(chalk_ir::AliasTy::Opaque(chalk_ir::OpaqueTy { 144 chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Opaque(chalk_ir::OpaqueTy {
87 opaque_ty_id, 145 opaque_ty_id,
88 substitution, 146 substitution,
89 })) 147 }))
90 .intern(&Interner) 148 .intern(&Interner)
91 } 149 }
92 Ty::Unknown => { 150 Ty::Unknown => chalk_ir::TyKind::Error.intern(&Interner),
93 let substitution = chalk_ir::Substitution::empty(&Interner);
94 let name = TypeName::Error;
95 chalk_ir::ApplicationTy { name, substitution }.cast(&Interner).intern(&Interner)
96 }
97 } 151 }
98 } 152 }
99 fn from_chalk(db: &dyn HirDatabase, chalk: chalk_ir::Ty<Interner>) -> Self { 153 fn from_chalk(db: &dyn HirDatabase, chalk: chalk_ir::Ty<Interner>) -> Self {
100 match chalk.data(&Interner).clone() { 154 match chalk.data(&Interner).kind.clone() {
101 chalk_ir::TyData::Apply(apply_ty) => match apply_ty.name { 155 chalk_ir::TyKind::Error => Ty::Unknown,
102 TypeName::Error => Ty::Unknown, 156 chalk_ir::TyKind::Array(ty, _size) => {
103 TypeName::Ref(m) => ref_from_chalk(db, m, apply_ty.substitution), 157 Ty::apply(TypeCtor::Array, Substs::single(from_chalk(db, ty)))
104 TypeName::Array => array_from_chalk(db, apply_ty.substitution), 158 }
105 _ => { 159 chalk_ir::TyKind::Placeholder(idx) => {
106 let ctor = from_chalk(db, apply_ty.name);
107 let parameters = from_chalk(db, apply_ty.substitution);
108 Ty::Apply(ApplicationTy { ctor, parameters })
109 }
110 },
111 chalk_ir::TyData::Placeholder(idx) => {
112 assert_eq!(idx.ui, UniverseIndex::ROOT); 160 assert_eq!(idx.ui, UniverseIndex::ROOT);
113 let interned_id = crate::db::GlobalTypeParamId::from_intern_id( 161 let interned_id = crate::db::GlobalTypeParamId::from_intern_id(
114 crate::salsa::InternId::from(idx.idx), 162 crate::salsa::InternId::from(idx.idx),
115 ); 163 );
116 Ty::Placeholder(db.lookup_intern_type_param_id(interned_id)) 164 Ty::Placeholder(db.lookup_intern_type_param_id(interned_id))
117 } 165 }
118 chalk_ir::TyData::Alias(chalk_ir::AliasTy::Projection(proj)) => { 166 chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Projection(proj)) => {
119 let associated_ty = 167 let associated_ty =
120 from_chalk::<TypeAliasAsAssocType, _>(db, proj.associated_ty_id).0; 168 from_chalk::<TypeAliasAsAssocType, _>(db, proj.associated_ty_id).0;
121 let parameters = from_chalk(db, proj.substitution); 169 let parameters = from_chalk(db, proj.substitution);
122 Ty::Projection(ProjectionTy { associated_ty, parameters }) 170 Ty::Projection(ProjectionTy { associated_ty, parameters })
123 } 171 }
124 chalk_ir::TyData::Alias(chalk_ir::AliasTy::Opaque(opaque_ty)) => { 172 chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Opaque(opaque_ty)) => {
125 let impl_trait_id = from_chalk(db, opaque_ty.opaque_ty_id); 173 let impl_trait_id = from_chalk(db, opaque_ty.opaque_ty_id);
126 let parameters = from_chalk(db, opaque_ty.substitution); 174 let parameters = from_chalk(db, opaque_ty.substitution);
127 Ty::Opaque(OpaqueTy { opaque_ty_id: impl_trait_id, parameters }) 175 Ty::Opaque(OpaqueTy { opaque_ty_id: impl_trait_id, parameters })
128 } 176 }
129 chalk_ir::TyData::Function(chalk_ir::FnPointer { 177 chalk_ir::TyKind::Function(chalk_ir::FnPointer {
130 num_binders, 178 num_binders,
131 sig: chalk_ir::FnSig { variadic, .. }, 179 sig: chalk_ir::FnSig { variadic, .. },
132 substitution, 180 substitution,
@@ -145,9 +193,9 @@ impl ToChalk for Ty {
145 parameters, 193 parameters,
146 }) 194 })
147 } 195 }
148 chalk_ir::TyData::BoundVar(idx) => Ty::Bound(idx), 196 chalk_ir::TyKind::BoundVar(idx) => Ty::Bound(idx),
149 chalk_ir::TyData::InferenceVar(_iv, _kind) => Ty::Unknown, 197 chalk_ir::TyKind::InferenceVar(_iv, _kind) => Ty::Unknown,
150 chalk_ir::TyData::Dyn(where_clauses) => { 198 chalk_ir::TyKind::Dyn(where_clauses) => {
151 assert_eq!(where_clauses.bounds.binders.len(&Interner), 1); 199 assert_eq!(where_clauses.bounds.binders.len(&Interner), 1);
152 let predicates = where_clauses 200 let predicates = where_clauses
153 .bounds 201 .bounds
@@ -157,12 +205,75 @@ impl ToChalk for Ty {
157 .collect(); 205 .collect();
158 Ty::Dyn(predicates) 206 Ty::Dyn(predicates)
159 } 207 }
208
209 chalk_ir::TyKind::Adt(struct_id, subst) => {
210 apply_ty_from_chalk(db, TypeCtor::Adt(struct_id.0), subst)
211 }
212 chalk_ir::TyKind::AssociatedType(type_id, subst) => apply_ty_from_chalk(
213 db,
214 TypeCtor::AssociatedType(from_chalk::<TypeAliasAsAssocType, _>(db, type_id).0),
215 subst,
216 ),
217 chalk_ir::TyKind::OpaqueType(opaque_type_id, subst) => {
218 apply_ty_from_chalk(db, TypeCtor::OpaqueType(from_chalk(db, opaque_type_id)), subst)
219 }
220
221 chalk_ir::TyKind::Scalar(Scalar::Bool) => Ty::simple(TypeCtor::Bool),
222 chalk_ir::TyKind::Scalar(Scalar::Char) => Ty::simple(TypeCtor::Char),
223 chalk_ir::TyKind::Scalar(Scalar::Int(int_ty)) => Ty::simple(TypeCtor::Int(IntTy {
224 signedness: Signedness::Signed,
225 bitness: bitness_from_chalk_int(int_ty),
226 })),
227 chalk_ir::TyKind::Scalar(Scalar::Uint(uint_ty)) => Ty::simple(TypeCtor::Int(IntTy {
228 signedness: Signedness::Unsigned,
229 bitness: bitness_from_chalk_uint(uint_ty),
230 })),
231 chalk_ir::TyKind::Scalar(Scalar::Float(chalk_ir::FloatTy::F32)) => {
232 Ty::simple(TypeCtor::Float(FloatTy { bitness: FloatBitness::X32 }))
233 }
234 chalk_ir::TyKind::Scalar(Scalar::Float(chalk_ir::FloatTy::F64)) => {
235 Ty::simple(TypeCtor::Float(FloatTy { bitness: FloatBitness::X64 }))
236 }
237 chalk_ir::TyKind::Tuple(cardinality, subst) => {
238 apply_ty_from_chalk(db, TypeCtor::Tuple { cardinality: cardinality as u16 }, subst)
239 }
240 chalk_ir::TyKind::Raw(mutability, ty) => {
241 Ty::apply_one(TypeCtor::RawPtr(from_chalk(db, mutability)), from_chalk(db, ty))
242 }
243 chalk_ir::TyKind::Slice(ty) => Ty::apply_one(TypeCtor::Slice, from_chalk(db, ty)),
244 chalk_ir::TyKind::Ref(mutability, _lifetime, ty) => {
245 Ty::apply_one(TypeCtor::Ref(from_chalk(db, mutability)), from_chalk(db, ty))
246 }
247 chalk_ir::TyKind::Str => Ty::simple(TypeCtor::Str),
248 chalk_ir::TyKind::Never => Ty::simple(TypeCtor::Never),
249
250 chalk_ir::TyKind::FnDef(fn_def_id, subst) => {
251 let callable_def = from_chalk(db, fn_def_id);
252 apply_ty_from_chalk(db, TypeCtor::FnDef(callable_def), subst)
253 }
254
255 chalk_ir::TyKind::Closure(id, subst) => {
256 let id: crate::db::ClosureId = id.into();
257 let (def, expr) = db.lookup_intern_closure(id);
258 apply_ty_from_chalk(db, TypeCtor::Closure { def, expr }, subst)
259 }
260
261 chalk_ir::TyKind::Foreign(foreign_def_id) => Ty::simple(TypeCtor::ForeignType(
262 from_chalk::<TypeAliasAsForeignType, _>(db, foreign_def_id).0,
263 )),
264 chalk_ir::TyKind::Generator(_, _) => unimplemented!(), // FIXME
265 chalk_ir::TyKind::GeneratorWitness(_, _) => unimplemented!(), // FIXME
160 } 266 }
161 } 267 }
162} 268}
163 269
164const FAKE_PLACEHOLDER: PlaceholderIndex = 270fn apply_ty_from_chalk(
165 PlaceholderIndex { ui: UniverseIndex::ROOT, idx: usize::MAX }; 271 db: &dyn HirDatabase,
272 ctor: TypeCtor,
273 subst: chalk_ir::Substitution<Interner>,
274) -> Ty {
275 Ty::Apply(ApplicationTy { ctor, parameters: from_chalk(db, subst) })
276}
166 277
167/// We currently don't model lifetimes, but Chalk does. So, we have to insert a 278/// We currently don't model lifetimes, but Chalk does. So, we have to insert a
168/// fake lifetime here, because Chalks built-in logic may expect it to be there. 279/// fake lifetime here, because Chalks built-in logic may expect it to be there.
@@ -172,57 +283,22 @@ fn ref_to_chalk(
172 subst: Substs, 283 subst: Substs,
173) -> chalk_ir::Ty<Interner> { 284) -> chalk_ir::Ty<Interner> {
174 let arg = subst[0].clone().to_chalk(db); 285 let arg = subst[0].clone().to_chalk(db);
175 let lifetime = FAKE_PLACEHOLDER.to_lifetime(&Interner); 286 let lifetime = LifetimeData::Static.intern(&Interner);
176 chalk_ir::ApplicationTy { 287 chalk_ir::TyKind::Ref(mutability.to_chalk(db), lifetime, arg).intern(&Interner)
177 name: TypeName::Ref(mutability.to_chalk(db)),
178 substitution: chalk_ir::Substitution::from_iter(
179 &Interner,
180 vec![lifetime.cast(&Interner), arg.cast(&Interner)],
181 ),
182 }
183 .intern(&Interner)
184}
185
186/// Here we remove the lifetime from the type we got from Chalk.
187fn ref_from_chalk(
188 db: &dyn HirDatabase,
189 mutability: chalk_ir::Mutability,
190 subst: chalk_ir::Substitution<Interner>,
191) -> Ty {
192 let tys = subst
193 .iter(&Interner)
194 .filter_map(|p| Some(from_chalk(db, p.ty(&Interner)?.clone())))
195 .collect();
196 Ty::apply(TypeCtor::Ref(from_chalk(db, mutability)), Substs(tys))
197} 288}
198 289
199/// We currently don't model constants, but Chalk does. So, we have to insert a 290/// We currently don't model constants, but Chalk does. So, we have to insert a
200/// fake constant here, because Chalks built-in logic may expect it to be there. 291/// fake constant here, because Chalks built-in logic may expect it to be there.
201fn array_to_chalk(db: &dyn HirDatabase, subst: Substs) -> chalk_ir::Ty<Interner> { 292fn array_to_chalk(db: &dyn HirDatabase, subst: Substs) -> chalk_ir::Ty<Interner> {
202 let arg = subst[0].clone().to_chalk(db); 293 let arg = subst[0].clone().to_chalk(db);
203 let usize_ty = chalk_ir::ApplicationTy { 294 let usize_ty =
204 name: TypeName::Scalar(Scalar::Uint(chalk_ir::UintTy::Usize)), 295 chalk_ir::TyKind::Scalar(Scalar::Uint(chalk_ir::UintTy::Usize)).intern(&Interner);
205 substitution: chalk_ir::Substitution::empty(&Interner), 296 let const_ = chalk_ir::ConstData {
297 ty: usize_ty,
298 value: chalk_ir::ConstValue::Concrete(chalk_ir::ConcreteConst { interned: () }),
206 } 299 }
207 .intern(&Interner); 300 .intern(&Interner);
208 let const_ = FAKE_PLACEHOLDER.to_const(&Interner, usize_ty); 301 chalk_ir::TyKind::Array(arg, const_).intern(&Interner)
209 chalk_ir::ApplicationTy {
210 name: TypeName::Array,
211 substitution: chalk_ir::Substitution::from_iter(
212 &Interner,
213 vec![arg.cast(&Interner), const_.cast(&Interner)],
214 ),
215 }
216 .intern(&Interner)
217}
218
219/// Here we remove the const from the type we got from Chalk.
220fn array_from_chalk(db: &dyn HirDatabase, subst: chalk_ir::Substitution<Interner>) -> Ty {
221 let tys = subst
222 .iter(&Interner)
223 .filter_map(|p| Some(from_chalk(db, p.ty(&Interner)?.clone())))
224 .collect();
225 Ty::apply(TypeCtor::Array, Substs(tys))
226} 302}
227 303
228impl ToChalk for Substs { 304impl ToChalk for Substs {
@@ -287,124 +363,6 @@ impl ToChalk for OpaqueTyId {
287 } 363 }
288} 364}
289 365
290impl ToChalk for TypeCtor {
291 type Chalk = TypeName<Interner>;
292
293 fn to_chalk(self, db: &dyn HirDatabase) -> TypeName<Interner> {
294 match self {
295 TypeCtor::AssociatedType(type_alias) => {
296 let assoc_type = TypeAliasAsAssocType(type_alias);
297 let assoc_type_id = assoc_type.to_chalk(db);
298 TypeName::AssociatedType(assoc_type_id)
299 }
300
301 TypeCtor::OpaqueType(impl_trait_id) => {
302 let id = impl_trait_id.to_chalk(db);
303 TypeName::OpaqueType(id)
304 }
305
306 TypeCtor::ForeignType(type_alias) => {
307 let foreign_type = TypeAliasAsForeignType(type_alias);
308 let foreign_type_id = foreign_type.to_chalk(db);
309 TypeName::Foreign(foreign_type_id)
310 }
311
312 TypeCtor::Bool => TypeName::Scalar(Scalar::Bool),
313 TypeCtor::Char => TypeName::Scalar(Scalar::Char),
314 TypeCtor::Int(int_ty) => TypeName::Scalar(int_ty_to_chalk(int_ty)),
315 TypeCtor::Float(FloatTy { bitness: FloatBitness::X32 }) => {
316 TypeName::Scalar(Scalar::Float(chalk_ir::FloatTy::F32))
317 }
318 TypeCtor::Float(FloatTy { bitness: FloatBitness::X64 }) => {
319 TypeName::Scalar(Scalar::Float(chalk_ir::FloatTy::F64))
320 }
321
322 TypeCtor::Tuple { cardinality } => TypeName::Tuple(cardinality.into()),
323 TypeCtor::RawPtr(mutability) => TypeName::Raw(mutability.to_chalk(db)),
324 TypeCtor::Slice => TypeName::Slice,
325 TypeCtor::Array => TypeName::Array,
326 TypeCtor::Ref(mutability) => TypeName::Ref(mutability.to_chalk(db)),
327 TypeCtor::Str => TypeName::Str,
328 TypeCtor::FnDef(callable_def) => {
329 let id = callable_def.to_chalk(db);
330 TypeName::FnDef(id)
331 }
332 TypeCtor::Never => TypeName::Never,
333
334 TypeCtor::Closure { def, expr } => {
335 let closure_id = db.intern_closure((def, expr));
336 TypeName::Closure(closure_id.into())
337 }
338
339 TypeCtor::Adt(adt_id) => TypeName::Adt(chalk_ir::AdtId(adt_id)),
340
341 TypeCtor::FnPtr { .. } => {
342 // This should not be reached, since Chalk doesn't represent
343 // function pointers with TypeName
344 unreachable!()
345 }
346 }
347 }
348
349 fn from_chalk(db: &dyn HirDatabase, type_name: TypeName<Interner>) -> TypeCtor {
350 match type_name {
351 TypeName::Adt(struct_id) => TypeCtor::Adt(struct_id.0),
352 TypeName::AssociatedType(type_id) => {
353 TypeCtor::AssociatedType(from_chalk::<TypeAliasAsAssocType, _>(db, type_id).0)
354 }
355 TypeName::OpaqueType(opaque_type_id) => {
356 TypeCtor::OpaqueType(from_chalk(db, opaque_type_id))
357 }
358
359 TypeName::Scalar(Scalar::Bool) => TypeCtor::Bool,
360 TypeName::Scalar(Scalar::Char) => TypeCtor::Char,
361 TypeName::Scalar(Scalar::Int(int_ty)) => TypeCtor::Int(IntTy {
362 signedness: Signedness::Signed,
363 bitness: bitness_from_chalk_int(int_ty),
364 }),
365 TypeName::Scalar(Scalar::Uint(uint_ty)) => TypeCtor::Int(IntTy {
366 signedness: Signedness::Unsigned,
367 bitness: bitness_from_chalk_uint(uint_ty),
368 }),
369 TypeName::Scalar(Scalar::Float(chalk_ir::FloatTy::F32)) => {
370 TypeCtor::Float(FloatTy { bitness: FloatBitness::X32 })
371 }
372 TypeName::Scalar(Scalar::Float(chalk_ir::FloatTy::F64)) => {
373 TypeCtor::Float(FloatTy { bitness: FloatBitness::X64 })
374 }
375 TypeName::Tuple(cardinality) => TypeCtor::Tuple { cardinality: cardinality as u16 },
376 TypeName::Raw(mutability) => TypeCtor::RawPtr(from_chalk(db, mutability)),
377 TypeName::Slice => TypeCtor::Slice,
378 TypeName::Ref(mutability) => TypeCtor::Ref(from_chalk(db, mutability)),
379 TypeName::Str => TypeCtor::Str,
380 TypeName::Never => TypeCtor::Never,
381
382 TypeName::FnDef(fn_def_id) => {
383 let callable_def = from_chalk(db, fn_def_id);
384 TypeCtor::FnDef(callable_def)
385 }
386 TypeName::Array => TypeCtor::Array,
387
388 TypeName::Closure(id) => {
389 let id: crate::db::ClosureId = id.into();
390 let (def, expr) = db.lookup_intern_closure(id);
391 TypeCtor::Closure { def, expr }
392 }
393
394 TypeName::Foreign(foreign_def_id) => {
395 TypeCtor::ForeignType(from_chalk::<TypeAliasAsForeignType, _>(db, foreign_def_id).0)
396 }
397
398 TypeName::Error => {
399 // this should not be reached, since we don't represent TypeName::Error with TypeCtor
400 unreachable!()
401 }
402 TypeName::Generator(_) => unimplemented!(), // FIXME
403 TypeName::GeneratorWitness(_) => unimplemented!(), // FIXME
404 }
405 }
406}
407
408fn bitness_from_chalk_uint(uint_ty: chalk_ir::UintTy) -> IntBitness { 366fn bitness_from_chalk_uint(uint_ty: chalk_ir::UintTy) -> IntBitness {
409 use chalk_ir::UintTy; 367 use chalk_ir::UintTy;
410 368
@@ -506,7 +464,7 @@ impl ToChalk for CallableDefId {
506 } 464 }
507} 465}
508 466
509pub struct TypeAliasAsAssocType(pub TypeAliasId); 467pub(crate) struct TypeAliasAsAssocType(pub(crate) TypeAliasId);
510 468
511impl ToChalk for TypeAliasAsAssocType { 469impl ToChalk for TypeAliasAsAssocType {
512 type Chalk = AssocTypeId; 470 type Chalk = AssocTypeId;
@@ -520,7 +478,7 @@ impl ToChalk for TypeAliasAsAssocType {
520 } 478 }
521} 479}
522 480
523pub struct TypeAliasAsForeignType(pub TypeAliasId); 481pub(crate) struct TypeAliasAsForeignType(pub(crate) TypeAliasId);
524 482
525impl ToChalk for TypeAliasAsForeignType { 483impl ToChalk for TypeAliasAsForeignType {
526 type Chalk = ForeignDefId; 484 type Chalk = ForeignDefId;
@@ -534,7 +492,7 @@ impl ToChalk for TypeAliasAsForeignType {
534 } 492 }
535} 493}
536 494
537pub struct TypeAliasAsValue(pub TypeAliasId); 495pub(crate) struct TypeAliasAsValue(pub(crate) TypeAliasId);
538 496
539impl ToChalk for TypeAliasAsValue { 497impl ToChalk for TypeAliasAsValue {
540 type Chalk = AssociatedTyValueId; 498 type Chalk = AssociatedTyValueId;
@@ -676,9 +634,9 @@ where
676 .kinds 634 .kinds
677 .iter() 635 .iter()
678 .map(|k| match k { 636 .map(|k| match k {
679 TyKind::General => chalk_ir::TyKind::General, 637 TyKind::General => chalk_ir::TyVariableKind::General,
680 TyKind::Integer => chalk_ir::TyKind::Integer, 638 TyKind::Integer => chalk_ir::TyVariableKind::Integer,
681 TyKind::Float => chalk_ir::TyKind::Float, 639 TyKind::Float => chalk_ir::TyVariableKind::Float,
682 }) 640 })
683 .map(|tk| { 641 .map(|tk| {
684 chalk_ir::CanonicalVarKind::new( 642 chalk_ir::CanonicalVarKind::new(
@@ -699,9 +657,9 @@ where
699 .iter(&Interner) 657 .iter(&Interner)
700 .map(|k| match k.kind { 658 .map(|k| match k.kind {
701 chalk_ir::VariableKind::Ty(tk) => match tk { 659 chalk_ir::VariableKind::Ty(tk) => match tk {
702 chalk_ir::TyKind::General => TyKind::General, 660 chalk_ir::TyVariableKind::General => TyKind::General,
703 chalk_ir::TyKind::Integer => TyKind::Integer, 661 chalk_ir::TyVariableKind::Integer => TyKind::Integer,
704 chalk_ir::TyKind::Float => TyKind::Float, 662 chalk_ir::TyVariableKind::Float => TyKind::Float,
705 }, 663 },
706 chalk_ir::VariableKind::Lifetime => panic!("unexpected lifetime from Chalk"), 664 chalk_ir::VariableKind::Lifetime => panic!("unexpected lifetime from Chalk"),
707 chalk_ir::VariableKind::Const(_) => panic!("unexpected const from Chalk"), 665 chalk_ir::VariableKind::Const(_) => panic!("unexpected const from Chalk"),
@@ -767,7 +725,8 @@ where
767 chalk_ir::Binders::new( 725 chalk_ir::Binders::new(
768 chalk_ir::VariableKinds::from_iter( 726 chalk_ir::VariableKinds::from_iter(
769 &Interner, 727 &Interner,
770 std::iter::repeat(chalk_ir::VariableKind::Ty(chalk_ir::TyKind::General)).take(num_vars), 728 std::iter::repeat(chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General))
729 .take(num_vars),
771 ), 730 ),
772 value, 731 value,
773 ) 732 )
diff --git a/crates/hir_ty/src/traits/chalk/tls.rs b/crates/hir_ty/src/traits/chalk/tls.rs
index b4568cff6..75b16172e 100644
--- a/crates/hir_ty/src/traits/chalk/tls.rs
+++ b/crates/hir_ty/src/traits/chalk/tls.rs
@@ -1,114 +1,32 @@
1//! Implementation of Chalk debug helper functions using TLS. 1//! Implementation of Chalk debug helper functions using TLS.
2use std::fmt; 2use std::fmt;
3 3
4use chalk_ir::{AliasTy, GenericArg, Goal, Goals, Lifetime, ProgramClauseImplication, TypeName}; 4use chalk_ir::{AliasTy, GenericArg, Goal, Goals, Lifetime, ProgramClauseImplication};
5use itertools::Itertools; 5use itertools::Itertools;
6 6
7use super::{from_chalk, Interner, TypeAliasAsAssocType}; 7use super::{from_chalk, Interner, TypeAliasAsAssocType};
8use crate::{db::HirDatabase, CallableDefId, TypeCtor}; 8use crate::{db::HirDatabase, CallableDefId};
9use hir_def::{AdtId, AssocContainerId, DefWithBodyId, Lookup, TypeAliasId}; 9use hir_def::{AdtId, AssocContainerId, Lookup, TypeAliasId};
10 10
11pub use unsafe_tls::{set_current_program, with_current_program}; 11pub(crate) use unsafe_tls::{set_current_program, with_current_program};
12 12
13pub struct DebugContext<'a>(&'a dyn HirDatabase); 13pub(crate) struct DebugContext<'a>(&'a dyn HirDatabase);
14 14
15impl DebugContext<'_> { 15impl DebugContext<'_> {
16 pub fn debug_struct_id( 16 pub(crate) fn debug_struct_id(
17 &self, 17 &self,
18 id: super::AdtId, 18 id: super::AdtId,
19 f: &mut fmt::Formatter<'_>, 19 f: &mut fmt::Formatter<'_>,
20 ) -> Result<(), fmt::Error> { 20 ) -> Result<(), fmt::Error> {
21 let type_ctor: TypeCtor = from_chalk(self.0, TypeName::Adt(id)); 21 let name = match id.0 {
22 match type_ctor { 22 AdtId::StructId(it) => self.0.struct_data(it).name.clone(),
23 TypeCtor::Bool => write!(f, "bool")?, 23 AdtId::UnionId(it) => self.0.union_data(it).name.clone(),
24 TypeCtor::Char => write!(f, "char")?, 24 AdtId::EnumId(it) => self.0.enum_data(it).name.clone(),
25 TypeCtor::Int(t) => write!(f, "{}", t)?, 25 };
26 TypeCtor::Float(t) => write!(f, "{}", t)?, 26 write!(f, "{}", name)
27 TypeCtor::Str => write!(f, "str")?,
28 TypeCtor::Slice => write!(f, "slice")?,
29 TypeCtor::Array => write!(f, "array")?,
30 TypeCtor::RawPtr(m) => write!(f, "*{}", m.as_keyword_for_ptr())?,
31 TypeCtor::Ref(m) => write!(f, "&{}", m.as_keyword_for_ref())?,
32 TypeCtor::Never => write!(f, "!")?,
33 TypeCtor::Tuple { .. } => {
34 write!(f, "()")?;
35 }
36 TypeCtor::FnPtr { .. } => {
37 write!(f, "fn")?;
38 }
39 TypeCtor::FnDef(def) => {
40 let name = match def {
41 CallableDefId::FunctionId(ff) => self.0.function_data(ff).name.clone(),
42 CallableDefId::StructId(s) => self.0.struct_data(s).name.clone(),
43 CallableDefId::EnumVariantId(e) => {
44 let enum_data = self.0.enum_data(e.parent);
45 enum_data.variants[e.local_id].name.clone()
46 }
47 };
48 match def {
49 CallableDefId::FunctionId(_) => write!(f, "{{fn {}}}", name)?,
50 CallableDefId::StructId(_) | CallableDefId::EnumVariantId(_) => {
51 write!(f, "{{ctor {}}}", name)?
52 }
53 }
54 }
55 TypeCtor::Adt(def_id) => {
56 let name = match def_id {
57 AdtId::StructId(it) => self.0.struct_data(it).name.clone(),
58 AdtId::UnionId(it) => self.0.union_data(it).name.clone(),
59 AdtId::EnumId(it) => self.0.enum_data(it).name.clone(),
60 };
61 write!(f, "{}", name)?;
62 }
63 TypeCtor::AssociatedType(type_alias) => {
64 let trait_ = match type_alias.lookup(self.0.upcast()).container {
65 AssocContainerId::TraitId(it) => it,
66 _ => panic!("not an associated type"),
67 };
68 let trait_name = self.0.trait_data(trait_).name.clone();
69 let name = self.0.type_alias_data(type_alias).name.clone();
70 write!(f, "{}::{}", trait_name, name)?;
71 }
72 TypeCtor::OpaqueType(opaque_ty_id) => match opaque_ty_id {
73 crate::OpaqueTyId::ReturnTypeImplTrait(func, idx) => {
74 write!(f, "{{impl trait {} of {:?}}}", idx, func)?;
75 }
76 crate::OpaqueTyId::AsyncBlockTypeImplTrait(def, idx) => {
77 write!(f, "{{impl trait of async block {} of {:?}}}", idx.into_raw(), def)?;
78 }
79 },
80 TypeCtor::ForeignType(type_alias) => {
81 let name = self.0.type_alias_data(type_alias).name.clone();
82 write!(f, "{}", name)?;
83 }
84 TypeCtor::Closure { def, expr } => {
85 write!(f, "{{closure {:?} in ", expr.into_raw())?;
86 match def {
87 DefWithBodyId::FunctionId(func) => {
88 write!(f, "fn {}", self.0.function_data(func).name)?
89 }
90 DefWithBodyId::StaticId(s) => {
91 if let Some(name) = self.0.static_data(s).name.as_ref() {
92 write!(f, "body of static {}", name)?;
93 } else {
94 write!(f, "body of unnamed static {:?}", s)?;
95 }
96 }
97 DefWithBodyId::ConstId(c) => {
98 if let Some(name) = self.0.const_data(c).name.as_ref() {
99 write!(f, "body of const {}", name)?;
100 } else {
101 write!(f, "body of unnamed const {:?}", c)?;
102 }
103 }
104 };
105 write!(f, "}}")?;
106 }
107 }
108 Ok(())
109 } 27 }
110 28
111 pub fn debug_trait_id( 29 pub(crate) fn debug_trait_id(
112 &self, 30 &self,
113 id: super::TraitId, 31 id: super::TraitId,
114 fmt: &mut fmt::Formatter<'_>, 32 fmt: &mut fmt::Formatter<'_>,
@@ -118,7 +36,7 @@ impl DebugContext<'_> {
118 write!(fmt, "{}", trait_data.name) 36 write!(fmt, "{}", trait_data.name)
119 } 37 }
120 38
121 pub fn debug_assoc_type_id( 39 pub(crate) fn debug_assoc_type_id(
122 &self, 40 &self,
123 id: super::AssocTypeId, 41 id: super::AssocTypeId,
124 fmt: &mut fmt::Formatter<'_>, 42 fmt: &mut fmt::Formatter<'_>,
@@ -133,7 +51,7 @@ impl DebugContext<'_> {
133 write!(fmt, "{}::{}", trait_data.name, type_alias_data.name) 51 write!(fmt, "{}::{}", trait_data.name, type_alias_data.name)
134 } 52 }
135 53
136 pub fn debug_opaque_ty_id( 54 pub(crate) fn debug_opaque_ty_id(
137 &self, 55 &self,
138 opaque_ty_id: chalk_ir::OpaqueTyId<Interner>, 56 opaque_ty_id: chalk_ir::OpaqueTyId<Interner>,
139 fmt: &mut fmt::Formatter<'_>, 57 fmt: &mut fmt::Formatter<'_>,
@@ -141,7 +59,7 @@ impl DebugContext<'_> {
141 fmt.debug_struct("OpaqueTyId").field("index", &opaque_ty_id.0).finish() 59 fmt.debug_struct("OpaqueTyId").field("index", &opaque_ty_id.0).finish()
142 } 60 }
143 61
144 pub fn debug_alias( 62 pub(crate) fn debug_alias(
145 &self, 63 &self,
146 alias_ty: &AliasTy<Interner>, 64 alias_ty: &AliasTy<Interner>,
147 fmt: &mut fmt::Formatter<'_>, 65 fmt: &mut fmt::Formatter<'_>,
@@ -152,7 +70,7 @@ impl DebugContext<'_> {
152 } 70 }
153 } 71 }
154 72
155 pub fn debug_projection_ty( 73 pub(crate) fn debug_projection_ty(
156 &self, 74 &self,
157 projection_ty: &chalk_ir::ProjectionTy<Interner>, 75 projection_ty: &chalk_ir::ProjectionTy<Interner>,
158 fmt: &mut fmt::Formatter<'_>, 76 fmt: &mut fmt::Formatter<'_>,
@@ -177,7 +95,7 @@ impl DebugContext<'_> {
177 write!(fmt, ">::{}", type_alias_data.name) 95 write!(fmt, ">::{}", type_alias_data.name)
178 } 96 }
179 97
180 pub fn debug_opaque_ty( 98 pub(crate) fn debug_opaque_ty(
181 &self, 99 &self,
182 opaque_ty: &chalk_ir::OpaqueTy<Interner>, 100 opaque_ty: &chalk_ir::OpaqueTy<Interner>,
183 fmt: &mut fmt::Formatter<'_>, 101 fmt: &mut fmt::Formatter<'_>,
@@ -185,7 +103,7 @@ impl DebugContext<'_> {
185 write!(fmt, "{:?}", opaque_ty.opaque_ty_id) 103 write!(fmt, "{:?}", opaque_ty.opaque_ty_id)
186 } 104 }
187 105
188 pub fn debug_ty( 106 pub(crate) fn debug_ty(
189 &self, 107 &self,
190 ty: &chalk_ir::Ty<Interner>, 108 ty: &chalk_ir::Ty<Interner>,
191 fmt: &mut fmt::Formatter<'_>, 109 fmt: &mut fmt::Formatter<'_>,
@@ -193,7 +111,7 @@ impl DebugContext<'_> {
193 write!(fmt, "{:?}", ty.data(&Interner)) 111 write!(fmt, "{:?}", ty.data(&Interner))
194 } 112 }
195 113
196 pub fn debug_lifetime( 114 pub(crate) fn debug_lifetime(
197 &self, 115 &self,
198 lifetime: &Lifetime<Interner>, 116 lifetime: &Lifetime<Interner>,
199 fmt: &mut fmt::Formatter<'_>, 117 fmt: &mut fmt::Formatter<'_>,
@@ -201,7 +119,7 @@ impl DebugContext<'_> {
201 write!(fmt, "{:?}", lifetime.data(&Interner)) 119 write!(fmt, "{:?}", lifetime.data(&Interner))
202 } 120 }
203 121
204 pub fn debug_generic_arg( 122 pub(crate) fn debug_generic_arg(
205 &self, 123 &self,
206 parameter: &GenericArg<Interner>, 124 parameter: &GenericArg<Interner>,
207 fmt: &mut fmt::Formatter<'_>, 125 fmt: &mut fmt::Formatter<'_>,
@@ -209,7 +127,7 @@ impl DebugContext<'_> {
209 write!(fmt, "{:?}", parameter.data(&Interner).inner_debug()) 127 write!(fmt, "{:?}", parameter.data(&Interner).inner_debug())
210 } 128 }
211 129
212 pub fn debug_goal( 130 pub(crate) fn debug_goal(
213 &self, 131 &self,
214 goal: &Goal<Interner>, 132 goal: &Goal<Interner>,
215 fmt: &mut fmt::Formatter<'_>, 133 fmt: &mut fmt::Formatter<'_>,
@@ -218,7 +136,7 @@ impl DebugContext<'_> {
218 write!(fmt, "{:?}", goal_data) 136 write!(fmt, "{:?}", goal_data)
219 } 137 }
220 138
221 pub fn debug_goals( 139 pub(crate) fn debug_goals(
222 &self, 140 &self,
223 goals: &Goals<Interner>, 141 goals: &Goals<Interner>,
224 fmt: &mut fmt::Formatter<'_>, 142 fmt: &mut fmt::Formatter<'_>,
@@ -226,7 +144,7 @@ impl DebugContext<'_> {
226 write!(fmt, "{:?}", goals.debug(&Interner)) 144 write!(fmt, "{:?}", goals.debug(&Interner))
227 } 145 }
228 146
229 pub fn debug_program_clause_implication( 147 pub(crate) fn debug_program_clause_implication(
230 &self, 148 &self,
231 pci: &ProgramClauseImplication<Interner>, 149 pci: &ProgramClauseImplication<Interner>,
232 fmt: &mut fmt::Formatter<'_>, 150 fmt: &mut fmt::Formatter<'_>,
@@ -234,15 +152,7 @@ impl DebugContext<'_> {
234 write!(fmt, "{:?}", pci.debug(&Interner)) 152 write!(fmt, "{:?}", pci.debug(&Interner))
235 } 153 }
236 154
237 pub fn debug_application_ty( 155 pub(crate) fn debug_substitution(
238 &self,
239 application_ty: &chalk_ir::ApplicationTy<Interner>,
240 fmt: &mut fmt::Formatter<'_>,
241 ) -> Result<(), fmt::Error> {
242 write!(fmt, "{:?}", application_ty.debug(&Interner))
243 }
244
245 pub fn debug_substitution(
246 &self, 156 &self,
247 substitution: &chalk_ir::Substitution<Interner>, 157 substitution: &chalk_ir::Substitution<Interner>,
248 fmt: &mut fmt::Formatter<'_>, 158 fmt: &mut fmt::Formatter<'_>,
@@ -250,7 +160,7 @@ impl DebugContext<'_> {
250 write!(fmt, "{:?}", substitution.debug(&Interner)) 160 write!(fmt, "{:?}", substitution.debug(&Interner))
251 } 161 }
252 162
253 pub fn debug_separator_trait_ref( 163 pub(crate) fn debug_separator_trait_ref(
254 &self, 164 &self,
255 separator_trait_ref: &chalk_ir::SeparatorTraitRef<Interner>, 165 separator_trait_ref: &chalk_ir::SeparatorTraitRef<Interner>,
256 fmt: &mut fmt::Formatter<'_>, 166 fmt: &mut fmt::Formatter<'_>,
@@ -258,7 +168,7 @@ impl DebugContext<'_> {
258 write!(fmt, "{:?}", separator_trait_ref.debug(&Interner)) 168 write!(fmt, "{:?}", separator_trait_ref.debug(&Interner))
259 } 169 }
260 170
261 pub fn debug_fn_def_id( 171 pub(crate) fn debug_fn_def_id(
262 &self, 172 &self,
263 fn_def_id: chalk_ir::FnDefId<Interner>, 173 fn_def_id: chalk_ir::FnDefId<Interner>,
264 fmt: &mut fmt::Formatter<'_>, 174 fmt: &mut fmt::Formatter<'_>,
@@ -280,7 +190,7 @@ impl DebugContext<'_> {
280 } 190 }
281 } 191 }
282 192
283 pub fn debug_const( 193 pub(crate) fn debug_const(
284 &self, 194 &self,
285 _constant: &chalk_ir::Const<Interner>, 195 _constant: &chalk_ir::Const<Interner>,
286 fmt: &mut fmt::Formatter<'_>, 196 fmt: &mut fmt::Formatter<'_>,
@@ -288,42 +198,42 @@ impl DebugContext<'_> {
288 write!(fmt, "const") 198 write!(fmt, "const")
289 } 199 }
290 200
291 pub fn debug_variable_kinds( 201 pub(crate) fn debug_variable_kinds(
292 &self, 202 &self,
293 variable_kinds: &chalk_ir::VariableKinds<Interner>, 203 variable_kinds: &chalk_ir::VariableKinds<Interner>,
294 fmt: &mut fmt::Formatter<'_>, 204 fmt: &mut fmt::Formatter<'_>,
295 ) -> fmt::Result { 205 ) -> fmt::Result {
296 write!(fmt, "{:?}", variable_kinds.as_slice(&Interner)) 206 write!(fmt, "{:?}", variable_kinds.as_slice(&Interner))
297 } 207 }
298 pub fn debug_variable_kinds_with_angles( 208 pub(crate) fn debug_variable_kinds_with_angles(
299 &self, 209 &self,
300 variable_kinds: &chalk_ir::VariableKinds<Interner>, 210 variable_kinds: &chalk_ir::VariableKinds<Interner>,
301 fmt: &mut fmt::Formatter<'_>, 211 fmt: &mut fmt::Formatter<'_>,
302 ) -> fmt::Result { 212 ) -> fmt::Result {
303 write!(fmt, "{:?}", variable_kinds.inner_debug(&Interner)) 213 write!(fmt, "{:?}", variable_kinds.inner_debug(&Interner))
304 } 214 }
305 pub fn debug_canonical_var_kinds( 215 pub(crate) fn debug_canonical_var_kinds(
306 &self, 216 &self,
307 canonical_var_kinds: &chalk_ir::CanonicalVarKinds<Interner>, 217 canonical_var_kinds: &chalk_ir::CanonicalVarKinds<Interner>,
308 fmt: &mut fmt::Formatter<'_>, 218 fmt: &mut fmt::Formatter<'_>,
309 ) -> fmt::Result { 219 ) -> fmt::Result {
310 write!(fmt, "{:?}", canonical_var_kinds.as_slice(&Interner)) 220 write!(fmt, "{:?}", canonical_var_kinds.as_slice(&Interner))
311 } 221 }
312 pub fn debug_program_clause( 222 pub(crate) fn debug_program_clause(
313 &self, 223 &self,
314 clause: &chalk_ir::ProgramClause<Interner>, 224 clause: &chalk_ir::ProgramClause<Interner>,
315 fmt: &mut fmt::Formatter<'_>, 225 fmt: &mut fmt::Formatter<'_>,
316 ) -> fmt::Result { 226 ) -> fmt::Result {
317 write!(fmt, "{:?}", clause.data(&Interner)) 227 write!(fmt, "{:?}", clause.data(&Interner))
318 } 228 }
319 pub fn debug_program_clauses( 229 pub(crate) fn debug_program_clauses(
320 &self, 230 &self,
321 clauses: &chalk_ir::ProgramClauses<Interner>, 231 clauses: &chalk_ir::ProgramClauses<Interner>,
322 fmt: &mut fmt::Formatter<'_>, 232 fmt: &mut fmt::Formatter<'_>,
323 ) -> fmt::Result { 233 ) -> fmt::Result {
324 write!(fmt, "{:?}", clauses.as_slice(&Interner)) 234 write!(fmt, "{:?}", clauses.as_slice(&Interner))
325 } 235 }
326 pub fn debug_quantified_where_clauses( 236 pub(crate) fn debug_quantified_where_clauses(
327 &self, 237 &self,
328 clauses: &chalk_ir::QuantifiedWhereClauses<Interner>, 238 clauses: &chalk_ir::QuantifiedWhereClauses<Interner>,
329 fmt: &mut fmt::Formatter<'_>, 239 fmt: &mut fmt::Formatter<'_>,
@@ -339,7 +249,7 @@ mod unsafe_tls {
339 249
340 scoped_thread_local!(static PROGRAM: DebugContext); 250 scoped_thread_local!(static PROGRAM: DebugContext);
341 251
342 pub fn with_current_program<R>( 252 pub(crate) fn with_current_program<R>(
343 op: impl for<'a> FnOnce(Option<&'a DebugContext<'a>>) -> R, 253 op: impl for<'a> FnOnce(Option<&'a DebugContext<'a>>) -> R,
344 ) -> R { 254 ) -> R {
345 if PROGRAM.is_set() { 255 if PROGRAM.is_set() {
@@ -349,7 +259,7 @@ mod unsafe_tls {
349 } 259 }
350 } 260 }
351 261
352 pub fn set_current_program<OP, R>(p: &dyn HirDatabase, op: OP) -> R 262 pub(crate) fn set_current_program<OP, R>(p: &dyn HirDatabase, op: OP) -> R
353 where 263 where
354 OP: FnOnce() -> R, 264 OP: FnOnce() -> R,
355 { 265 {