diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/hir/src/lib.rs | 5 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/mod_resolution.rs | 13 | ||||
-rw-r--r-- | crates/hir_expand/src/builtin_macro.rs | 66 | ||||
-rw-r--r-- | crates/hir_expand/src/eager.rs | 13 | ||||
-rw-r--r-- | crates/hir_expand/src/lib.rs | 23 | ||||
-rw-r--r-- | crates/hir_ty/src/display.rs | 21 | ||||
-rw-r--r-- | crates/hir_ty/src/lib.rs | 17 | ||||
-rw-r--r-- | crates/hir_ty/src/lower.rs | 25 | ||||
-rw-r--r-- | crates/hir_ty/src/tests.rs | 69 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/macros.rs | 23 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/traits.rs | 50 | ||||
-rw-r--r-- | crates/hir_ty/src/traits/chalk.rs | 2 |
12 files changed, 281 insertions, 46 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 44eaeffb9..e3ac37e4c 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs | |||
@@ -2068,7 +2068,10 @@ impl Type { | |||
2068 | match pred { | 2068 | match pred { |
2069 | WhereClause::Implemented(trait_ref) => { | 2069 | WhereClause::Implemented(trait_ref) => { |
2070 | cb(type_.clone()); | 2070 | cb(type_.clone()); |
2071 | walk_substs(db, type_, &trait_ref.substitution, cb); | 2071 | // skip the self type. it's likely the type we just got the bounds from |
2072 | for ty in trait_ref.substitution.iter().skip(1) { | ||
2073 | walk_type(db, &type_.derived(ty.clone()), cb); | ||
2074 | } | ||
2072 | } | 2075 | } |
2073 | _ => (), | 2076 | _ => (), |
2074 | } | 2077 | } |
diff --git a/crates/hir_def/src/nameres/mod_resolution.rs b/crates/hir_def/src/nameres/mod_resolution.rs index d5de9899c..d9cec0e27 100644 --- a/crates/hir_def/src/nameres/mod_resolution.rs +++ b/crates/hir_def/src/nameres/mod_resolution.rs | |||
@@ -62,7 +62,7 @@ impl ModDir { | |||
62 | name: &Name, | 62 | name: &Name, |
63 | attr_path: Option<&SmolStr>, | 63 | attr_path: Option<&SmolStr>, |
64 | ) -> Result<(FileId, bool, ModDir), String> { | 64 | ) -> Result<(FileId, bool, ModDir), String> { |
65 | let file_id = file_id.original_file(db.upcast()); | 65 | let orig_file_id = file_id.original_file(db.upcast()); |
66 | 66 | ||
67 | let mut candidate_files = Vec::new(); | 67 | let mut candidate_files = Vec::new(); |
68 | match attr_path { | 68 | match attr_path { |
@@ -70,13 +70,18 @@ impl ModDir { | |||
70 | candidate_files.push(self.dir_path.join_attr(attr_path, self.root_non_dir_owner)) | 70 | candidate_files.push(self.dir_path.join_attr(attr_path, self.root_non_dir_owner)) |
71 | } | 71 | } |
72 | None => { | 72 | None => { |
73 | candidate_files.push(format!("{}{}.rs", self.dir_path.0, name)); | 73 | if file_id.is_include_macro(db.upcast()) { |
74 | candidate_files.push(format!("{}{}/mod.rs", self.dir_path.0, name)); | 74 | candidate_files.push(format!("{}.rs", name)); |
75 | candidate_files.push(format!("{}/mod.rs", name)); | ||
76 | } else { | ||
77 | candidate_files.push(format!("{}{}.rs", self.dir_path.0, name)); | ||
78 | candidate_files.push(format!("{}{}/mod.rs", self.dir_path.0, name)); | ||
79 | } | ||
75 | } | 80 | } |
76 | }; | 81 | }; |
77 | 82 | ||
78 | for candidate in candidate_files.iter() { | 83 | for candidate in candidate_files.iter() { |
79 | let path = AnchoredPath { anchor: file_id, path: candidate.as_str() }; | 84 | let path = AnchoredPath { anchor: orig_file_id, path: candidate.as_str() }; |
80 | if let Some(file_id) = db.resolve_path(path) { | 85 | if let Some(file_id) = db.resolve_path(path) { |
81 | let is_mod_rs = candidate.ends_with("/mod.rs"); | 86 | let is_mod_rs = candidate.ends_with("/mod.rs"); |
82 | 87 | ||
diff --git a/crates/hir_expand/src/builtin_macro.rs b/crates/hir_expand/src/builtin_macro.rs index 8529b43b6..4d52904b9 100644 --- a/crates/hir_expand/src/builtin_macro.rs +++ b/crates/hir_expand/src/builtin_macro.rs | |||
@@ -43,7 +43,7 @@ macro_rules! register_builtin { | |||
43 | db: &dyn AstDatabase, | 43 | db: &dyn AstDatabase, |
44 | arg_id: EagerMacroId, | 44 | arg_id: EagerMacroId, |
45 | tt: &tt::Subtree, | 45 | tt: &tt::Subtree, |
46 | ) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> { | 46 | ) -> ExpandResult<Option<ExpandedEager>> { |
47 | let expander = match *self { | 47 | let expander = match *self { |
48 | $( EagerExpander::$e_kind => $e_expand, )* | 48 | $( EagerExpander::$e_kind => $e_expand, )* |
49 | }; | 49 | }; |
@@ -61,6 +61,20 @@ macro_rules! register_builtin { | |||
61 | }; | 61 | }; |
62 | } | 62 | } |
63 | 63 | ||
64 | #[derive(Debug)] | ||
65 | pub struct ExpandedEager { | ||
66 | pub(crate) subtree: tt::Subtree, | ||
67 | pub(crate) fragment: FragmentKind, | ||
68 | /// The included file ID of the include macro. | ||
69 | pub(crate) included_file: Option<FileId>, | ||
70 | } | ||
71 | |||
72 | impl ExpandedEager { | ||
73 | fn new(subtree: tt::Subtree, fragment: FragmentKind) -> Self { | ||
74 | ExpandedEager { subtree, fragment, included_file: None } | ||
75 | } | ||
76 | } | ||
77 | |||
64 | pub fn find_builtin_macro( | 78 | pub fn find_builtin_macro( |
65 | ident: &name::Name, | 79 | ident: &name::Name, |
66 | krate: CrateId, | 80 | krate: CrateId, |
@@ -280,7 +294,7 @@ fn compile_error_expand( | |||
280 | _db: &dyn AstDatabase, | 294 | _db: &dyn AstDatabase, |
281 | _id: EagerMacroId, | 295 | _id: EagerMacroId, |
282 | tt: &tt::Subtree, | 296 | tt: &tt::Subtree, |
283 | ) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> { | 297 | ) -> ExpandResult<Option<ExpandedEager>> { |
284 | let err = match &*tt.token_trees { | 298 | let err = match &*tt.token_trees { |
285 | [tt::TokenTree::Leaf(tt::Leaf::Literal(it))] => { | 299 | [tt::TokenTree::Leaf(tt::Leaf::Literal(it))] => { |
286 | let text = it.text.as_str(); | 300 | let text = it.text.as_str(); |
@@ -294,14 +308,14 @@ fn compile_error_expand( | |||
294 | _ => mbe::ExpandError::BindingError("`compile_error!` argument must be a string".into()), | 308 | _ => mbe::ExpandError::BindingError("`compile_error!` argument must be a string".into()), |
295 | }; | 309 | }; |
296 | 310 | ||
297 | ExpandResult { value: Some((quote! {}, FragmentKind::Items)), err: Some(err) } | 311 | ExpandResult { value: Some(ExpandedEager::new(quote! {}, FragmentKind::Items)), err: Some(err) } |
298 | } | 312 | } |
299 | 313 | ||
300 | fn concat_expand( | 314 | fn concat_expand( |
301 | _db: &dyn AstDatabase, | 315 | _db: &dyn AstDatabase, |
302 | _arg_id: EagerMacroId, | 316 | _arg_id: EagerMacroId, |
303 | tt: &tt::Subtree, | 317 | tt: &tt::Subtree, |
304 | ) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> { | 318 | ) -> ExpandResult<Option<ExpandedEager>> { |
305 | let mut err = None; | 319 | let mut err = None; |
306 | let mut text = String::new(); | 320 | let mut text = String::new(); |
307 | for (i, t) in tt.token_trees.iter().enumerate() { | 321 | for (i, t) in tt.token_trees.iter().enumerate() { |
@@ -325,7 +339,7 @@ fn concat_expand( | |||
325 | } | 339 | } |
326 | } | 340 | } |
327 | } | 341 | } |
328 | ExpandResult { value: Some((quote!(#text), FragmentKind::Expr)), err } | 342 | ExpandResult { value: Some(ExpandedEager::new(quote!(#text), FragmentKind::Expr)), err } |
329 | } | 343 | } |
330 | 344 | ||
331 | fn relative_file( | 345 | fn relative_file( |
@@ -361,21 +375,27 @@ fn include_expand( | |||
361 | db: &dyn AstDatabase, | 375 | db: &dyn AstDatabase, |
362 | arg_id: EagerMacroId, | 376 | arg_id: EagerMacroId, |
363 | tt: &tt::Subtree, | 377 | tt: &tt::Subtree, |
364 | ) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> { | 378 | ) -> ExpandResult<Option<ExpandedEager>> { |
365 | let res = (|| { | 379 | let res = (|| { |
366 | let path = parse_string(tt)?; | 380 | let path = parse_string(tt)?; |
367 | let file_id = relative_file(db, arg_id.into(), &path, false)?; | 381 | let file_id = relative_file(db, arg_id.into(), &path, false)?; |
368 | 382 | ||
369 | Ok(parse_to_token_tree(&db.file_text(file_id)) | 383 | let subtree = parse_to_token_tree(&db.file_text(file_id)) |
370 | .ok_or_else(|| mbe::ExpandError::ConversionError)? | 384 | .ok_or_else(|| mbe::ExpandError::ConversionError)? |
371 | .0) | 385 | .0; |
386 | Ok((subtree, file_id)) | ||
372 | })(); | 387 | })(); |
373 | 388 | ||
374 | match res { | 389 | match res { |
375 | Ok(res) => { | 390 | Ok((subtree, file_id)) => { |
376 | // FIXME: | 391 | // FIXME: |
377 | // Handle include as expression | 392 | // Handle include as expression |
378 | ExpandResult::ok(Some((res, FragmentKind::Items))) | 393 | |
394 | ExpandResult::ok(Some(ExpandedEager { | ||
395 | subtree, | ||
396 | fragment: FragmentKind::Items, | ||
397 | included_file: Some(file_id), | ||
398 | })) | ||
379 | } | 399 | } |
380 | Err(e) => ExpandResult::only_err(e), | 400 | Err(e) => ExpandResult::only_err(e), |
381 | } | 401 | } |
@@ -385,7 +405,7 @@ fn include_bytes_expand( | |||
385 | _db: &dyn AstDatabase, | 405 | _db: &dyn AstDatabase, |
386 | _arg_id: EagerMacroId, | 406 | _arg_id: EagerMacroId, |
387 | tt: &tt::Subtree, | 407 | tt: &tt::Subtree, |
388 | ) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> { | 408 | ) -> ExpandResult<Option<ExpandedEager>> { |
389 | if let Err(e) = parse_string(tt) { | 409 | if let Err(e) = parse_string(tt) { |
390 | return ExpandResult::only_err(e); | 410 | return ExpandResult::only_err(e); |
391 | } | 411 | } |
@@ -398,14 +418,14 @@ fn include_bytes_expand( | |||
398 | id: tt::TokenId::unspecified(), | 418 | id: tt::TokenId::unspecified(), |
399 | }))], | 419 | }))], |
400 | }; | 420 | }; |
401 | ExpandResult::ok(Some((res, FragmentKind::Expr))) | 421 | ExpandResult::ok(Some(ExpandedEager::new(res, FragmentKind::Expr))) |
402 | } | 422 | } |
403 | 423 | ||
404 | fn include_str_expand( | 424 | fn include_str_expand( |
405 | db: &dyn AstDatabase, | 425 | db: &dyn AstDatabase, |
406 | arg_id: EagerMacroId, | 426 | arg_id: EagerMacroId, |
407 | tt: &tt::Subtree, | 427 | tt: &tt::Subtree, |
408 | ) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> { | 428 | ) -> ExpandResult<Option<ExpandedEager>> { |
409 | let path = match parse_string(tt) { | 429 | let path = match parse_string(tt) { |
410 | Ok(it) => it, | 430 | Ok(it) => it, |
411 | Err(e) => return ExpandResult::only_err(e), | 431 | Err(e) => return ExpandResult::only_err(e), |
@@ -418,14 +438,14 @@ fn include_str_expand( | |||
418 | let file_id = match relative_file(db, arg_id.into(), &path, true) { | 438 | let file_id = match relative_file(db, arg_id.into(), &path, true) { |
419 | Ok(file_id) => file_id, | 439 | Ok(file_id) => file_id, |
420 | Err(_) => { | 440 | Err(_) => { |
421 | return ExpandResult::ok(Some((quote!(""), FragmentKind::Expr))); | 441 | return ExpandResult::ok(Some(ExpandedEager::new(quote!(""), FragmentKind::Expr))); |
422 | } | 442 | } |
423 | }; | 443 | }; |
424 | 444 | ||
425 | let text = db.file_text(file_id); | 445 | let text = db.file_text(file_id); |
426 | let text = &*text; | 446 | let text = &*text; |
427 | 447 | ||
428 | ExpandResult::ok(Some((quote!(#text), FragmentKind::Expr))) | 448 | ExpandResult::ok(Some(ExpandedEager::new(quote!(#text), FragmentKind::Expr))) |
429 | } | 449 | } |
430 | 450 | ||
431 | fn get_env_inner(db: &dyn AstDatabase, arg_id: EagerMacroId, key: &str) -> Option<String> { | 451 | fn get_env_inner(db: &dyn AstDatabase, arg_id: EagerMacroId, key: &str) -> Option<String> { |
@@ -437,7 +457,7 @@ fn env_expand( | |||
437 | db: &dyn AstDatabase, | 457 | db: &dyn AstDatabase, |
438 | arg_id: EagerMacroId, | 458 | arg_id: EagerMacroId, |
439 | tt: &tt::Subtree, | 459 | tt: &tt::Subtree, |
440 | ) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> { | 460 | ) -> ExpandResult<Option<ExpandedEager>> { |
441 | let key = match parse_string(tt) { | 461 | let key = match parse_string(tt) { |
442 | Ok(it) => it, | 462 | Ok(it) => it, |
443 | Err(e) => return ExpandResult::only_err(e), | 463 | Err(e) => return ExpandResult::only_err(e), |
@@ -461,14 +481,14 @@ fn env_expand( | |||
461 | }); | 481 | }); |
462 | let expanded = quote! { #s }; | 482 | let expanded = quote! { #s }; |
463 | 483 | ||
464 | ExpandResult { value: Some((expanded, FragmentKind::Expr)), err } | 484 | ExpandResult { value: Some(ExpandedEager::new(expanded, FragmentKind::Expr)), err } |
465 | } | 485 | } |
466 | 486 | ||
467 | fn option_env_expand( | 487 | fn option_env_expand( |
468 | db: &dyn AstDatabase, | 488 | db: &dyn AstDatabase, |
469 | arg_id: EagerMacroId, | 489 | arg_id: EagerMacroId, |
470 | tt: &tt::Subtree, | 490 | tt: &tt::Subtree, |
471 | ) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> { | 491 | ) -> ExpandResult<Option<ExpandedEager>> { |
472 | let key = match parse_string(tt) { | 492 | let key = match parse_string(tt) { |
473 | Ok(it) => it, | 493 | Ok(it) => it, |
474 | Err(e) => return ExpandResult::only_err(e), | 494 | Err(e) => return ExpandResult::only_err(e), |
@@ -479,7 +499,7 @@ fn option_env_expand( | |||
479 | Some(s) => quote! { std::option::Some(#s) }, | 499 | Some(s) => quote! { std::option::Some(#s) }, |
480 | }; | 500 | }; |
481 | 501 | ||
482 | ExpandResult::ok(Some((expanded, FragmentKind::Expr))) | 502 | ExpandResult::ok(Some(ExpandedEager::new(expanded, FragmentKind::Expr))) |
483 | } | 503 | } |
484 | 504 | ||
485 | #[cfg(test)] | 505 | #[cfg(test)] |
@@ -553,16 +573,18 @@ mod tests { | |||
553 | subtree: Arc::new(parsed_args.clone()), | 573 | subtree: Arc::new(parsed_args.clone()), |
554 | krate, | 574 | krate, |
555 | call: call_id, | 575 | call: call_id, |
576 | included_file: None, | ||
556 | } | 577 | } |
557 | }); | 578 | }); |
558 | 579 | ||
559 | let (subtree, fragment) = expander.expand(&db, arg_id, &parsed_args).value.unwrap(); | 580 | let expanded = expander.expand(&db, arg_id, &parsed_args).value.unwrap(); |
560 | let eager = EagerCallLoc { | 581 | let eager = EagerCallLoc { |
561 | def, | 582 | def, |
562 | fragment, | 583 | fragment: expanded.fragment, |
563 | subtree: Arc::new(subtree), | 584 | subtree: Arc::new(expanded.subtree), |
564 | krate, | 585 | krate, |
565 | call: call_id, | 586 | call: call_id, |
587 | included_file: expanded.included_file, | ||
566 | }; | 588 | }; |
567 | 589 | ||
568 | let id: MacroCallId = db.intern_eager_expansion(eager).into(); | 590 | let id: MacroCallId = db.intern_eager_expansion(eager).into(); |
diff --git a/crates/hir_expand/src/eager.rs b/crates/hir_expand/src/eager.rs index 04f374a29..9eedc8461 100644 --- a/crates/hir_expand/src/eager.rs +++ b/crates/hir_expand/src/eager.rs | |||
@@ -124,6 +124,7 @@ pub fn expand_eager_macro( | |||
124 | subtree: Arc::new(parsed_args.clone()), | 124 | subtree: Arc::new(parsed_args.clone()), |
125 | krate, | 125 | krate, |
126 | call: call_id, | 126 | call: call_id, |
127 | included_file: None, | ||
127 | } | 128 | } |
128 | }); | 129 | }); |
129 | let arg_file_id: MacroCallId = arg_id.into(); | 130 | let arg_file_id: MacroCallId = arg_id.into(); |
@@ -143,9 +144,15 @@ pub fn expand_eager_macro( | |||
143 | if let MacroDefKind::BuiltInEager(eager, _) = def.kind { | 144 | if let MacroDefKind::BuiltInEager(eager, _) = def.kind { |
144 | let res = eager.expand(db, arg_id, &subtree); | 145 | let res = eager.expand(db, arg_id, &subtree); |
145 | 146 | ||
146 | let (subtree, fragment) = diagnostic_sink.expand_result_option(res)?; | 147 | let expanded = diagnostic_sink.expand_result_option(res)?; |
147 | let eager = | 148 | let eager = EagerCallLoc { |
148 | EagerCallLoc { def, fragment, subtree: Arc::new(subtree), krate, call: call_id }; | 149 | def, |
150 | fragment: expanded.fragment, | ||
151 | subtree: Arc::new(expanded.subtree), | ||
152 | krate, | ||
153 | call: call_id, | ||
154 | included_file: expanded.included_file, | ||
155 | }; | ||
149 | 156 | ||
150 | Ok(db.intern_eager_expansion(eager)) | 157 | Ok(db.intern_eager_expansion(eager)) |
151 | } else { | 158 | } else { |
diff --git a/crates/hir_expand/src/lib.rs b/crates/hir_expand/src/lib.rs index f49fd4fda..b8045fda9 100644 --- a/crates/hir_expand/src/lib.rs +++ b/crates/hir_expand/src/lib.rs | |||
@@ -84,7 +84,11 @@ impl HirFileId { | |||
84 | } | 84 | } |
85 | MacroCallId::EagerMacro(id) => { | 85 | MacroCallId::EagerMacro(id) => { |
86 | let loc = db.lookup_intern_eager_expansion(id); | 86 | let loc = db.lookup_intern_eager_expansion(id); |
87 | loc.call.file_id | 87 | if let Some(included_file) = loc.included_file { |
88 | return included_file; | ||
89 | } else { | ||
90 | loc.call.file_id | ||
91 | } | ||
88 | } | 92 | } |
89 | }; | 93 | }; |
90 | file_id.original_file(db) | 94 | file_id.original_file(db) |
@@ -188,6 +192,21 @@ impl HirFileId { | |||
188 | } | 192 | } |
189 | } | 193 | } |
190 | } | 194 | } |
195 | |||
196 | /// Return whether this file is an include macro | ||
197 | pub fn is_include_macro(&self, db: &dyn db::AstDatabase) -> bool { | ||
198 | match self.0 { | ||
199 | HirFileIdRepr::MacroFile(macro_file) => match macro_file.macro_call_id { | ||
200 | MacroCallId::EagerMacro(id) => { | ||
201 | let loc = db.lookup_intern_eager_expansion(id); | ||
202 | return loc.included_file.is_some(); | ||
203 | } | ||
204 | _ => {} | ||
205 | }, | ||
206 | _ => {} | ||
207 | } | ||
208 | false | ||
209 | } | ||
191 | } | 210 | } |
192 | 211 | ||
193 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 212 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
@@ -315,6 +334,8 @@ pub struct EagerCallLoc { | |||
315 | pub(crate) subtree: Arc<tt::Subtree>, | 334 | pub(crate) subtree: Arc<tt::Subtree>, |
316 | pub(crate) krate: CrateId, | 335 | pub(crate) krate: CrateId, |
317 | pub(crate) call: AstId<ast::MacroCall>, | 336 | pub(crate) call: AstId<ast::MacroCall>, |
337 | // The included file ID of the include macro. | ||
338 | pub(crate) included_file: Option<FileId>, | ||
318 | } | 339 | } |
319 | 340 | ||
320 | /// ExpansionInfo mainly describes how to map text range between src and expanded macro | 341 | /// ExpansionInfo mainly describes how to map text range between src and expanded macro |
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs index 3845009ae..9d3b79be3 100644 --- a/crates/hir_ty/src/display.rs +++ b/crates/hir_ty/src/display.rs | |||
@@ -571,13 +571,22 @@ impl HirDisplay for Ty { | |||
571 | write!(f, "{}", param_data.name.clone().unwrap_or_else(Name::missing))? | 571 | write!(f, "{}", param_data.name.clone().unwrap_or_else(Name::missing))? |
572 | } | 572 | } |
573 | TypeParamProvenance::ArgumentImplTrait => { | 573 | TypeParamProvenance::ArgumentImplTrait => { |
574 | let bounds = f.db.generic_predicates_for_param(id); | ||
575 | let substs = Substitution::type_params_for_generics(f.db, &generics); | 574 | let substs = Substitution::type_params_for_generics(f.db, &generics); |
576 | write_bounds_like_dyn_trait_with_prefix( | 575 | let bounds = f |
577 | "impl", | 576 | .db |
578 | &bounds.iter().map(|b| b.clone().subst(&substs)).collect::<Vec<_>>(), | 577 | .generic_predicates(id.parent) |
579 | f, | 578 | .into_iter() |
580 | )?; | 579 | .map(|pred| pred.clone().subst(&substs)) |
580 | .filter(|wc| match &wc { | ||
581 | WhereClause::Implemented(tr) => tr.self_type_parameter() == self, | ||
582 | WhereClause::AliasEq(AliasEq { | ||
583 | alias: AliasTy::Projection(proj), | ||
584 | ty: _, | ||
585 | }) => proj.self_type_parameter() == self, | ||
586 | _ => false, | ||
587 | }) | ||
588 | .collect::<Vec<_>>(); | ||
589 | write_bounds_like_dyn_trait_with_prefix("impl", &bounds, f)?; | ||
581 | } | 590 | } |
582 | } | 591 | } |
583 | } | 592 | } |
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index c46529879..ad908f957 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs | |||
@@ -106,6 +106,10 @@ impl ProjectionTy { | |||
106 | } | 106 | } |
107 | } | 107 | } |
108 | 108 | ||
109 | pub fn self_type_parameter(&self) -> &Ty { | ||
110 | &self.substitution[0] | ||
111 | } | ||
112 | |||
109 | fn trait_(&self, db: &dyn HirDatabase) -> TraitId { | 113 | fn trait_(&self, db: &dyn HirDatabase) -> TraitId { |
110 | match from_assoc_type_id(self.associated_ty_id).lookup(db.upcast()).container { | 114 | match from_assoc_type_id(self.associated_ty_id).lookup(db.upcast()).container { |
111 | AssocContainerId::TraitId(it) => it, | 115 | AssocContainerId::TraitId(it) => it, |
@@ -936,10 +940,19 @@ impl Ty { | |||
936 | let param_data = &generic_params.types[id.local_id]; | 940 | let param_data = &generic_params.types[id.local_id]; |
937 | match param_data.provenance { | 941 | match param_data.provenance { |
938 | hir_def::generics::TypeParamProvenance::ArgumentImplTrait => { | 942 | hir_def::generics::TypeParamProvenance::ArgumentImplTrait => { |
943 | let substs = Substitution::type_params(db, id.parent); | ||
939 | let predicates = db | 944 | let predicates = db |
940 | .generic_predicates_for_param(id) | 945 | .generic_predicates(id.parent) |
941 | .into_iter() | 946 | .into_iter() |
942 | .map(|pred| pred.value.clone()) | 947 | .map(|pred| pred.clone().subst(&substs)) |
948 | .filter(|wc| match &wc { | ||
949 | WhereClause::Implemented(tr) => tr.self_type_parameter() == self, | ||
950 | WhereClause::AliasEq(AliasEq { | ||
951 | alias: AliasTy::Projection(proj), | ||
952 | ty: _, | ||
953 | }) => proj.self_type_parameter() == self, | ||
954 | _ => false, | ||
955 | }) | ||
943 | .collect_vec(); | 956 | .collect_vec(); |
944 | 957 | ||
945 | Some(predicates) | 958 | Some(predicates) |
diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs index c914a3b8e..fd451a823 100644 --- a/crates/hir_ty/src/lower.rs +++ b/crates/hir_ty/src/lower.rs | |||
@@ -189,7 +189,10 @@ impl<'a> TyLoweringContext<'a> { | |||
189 | let self_ty = | 189 | let self_ty = |
190 | TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(&Interner); | 190 | TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(&Interner); |
191 | let predicates = self.with_shifted_in(DebruijnIndex::ONE, |ctx| { | 191 | let predicates = self.with_shifted_in(DebruijnIndex::ONE, |ctx| { |
192 | bounds.iter().flat_map(|b| ctx.lower_type_bound(b, self_ty.clone())).collect() | 192 | bounds |
193 | .iter() | ||
194 | .flat_map(|b| ctx.lower_type_bound(b, self_ty.clone(), false)) | ||
195 | .collect() | ||
193 | }); | 196 | }); |
194 | TyKind::Dyn(predicates).intern(&Interner) | 197 | TyKind::Dyn(predicates).intern(&Interner) |
195 | } | 198 | } |
@@ -666,6 +669,7 @@ impl<'a> TyLoweringContext<'a> { | |||
666 | pub(crate) fn lower_where_predicate( | 669 | pub(crate) fn lower_where_predicate( |
667 | &'a self, | 670 | &'a self, |
668 | where_predicate: &'a WherePredicate, | 671 | where_predicate: &'a WherePredicate, |
672 | ignore_bindings: bool, | ||
669 | ) -> impl Iterator<Item = WhereClause> + 'a { | 673 | ) -> impl Iterator<Item = WhereClause> + 'a { |
670 | match where_predicate { | 674 | match where_predicate { |
671 | WherePredicate::ForLifetime { target, bound, .. } | 675 | WherePredicate::ForLifetime { target, bound, .. } |
@@ -688,7 +692,9 @@ impl<'a> TyLoweringContext<'a> { | |||
688 | .intern(&Interner) | 692 | .intern(&Interner) |
689 | } | 693 | } |
690 | }; | 694 | }; |
691 | self.lower_type_bound(bound, self_ty).collect::<Vec<_>>().into_iter() | 695 | self.lower_type_bound(bound, self_ty, ignore_bindings) |
696 | .collect::<Vec<_>>() | ||
697 | .into_iter() | ||
692 | } | 698 | } |
693 | WherePredicate::Lifetime { .. } => vec![].into_iter(), | 699 | WherePredicate::Lifetime { .. } => vec![].into_iter(), |
694 | } | 700 | } |
@@ -698,6 +704,7 @@ impl<'a> TyLoweringContext<'a> { | |||
698 | &'a self, | 704 | &'a self, |
699 | bound: &'a TypeBound, | 705 | bound: &'a TypeBound, |
700 | self_ty: Ty, | 706 | self_ty: Ty, |
707 | ignore_bindings: bool, | ||
701 | ) -> impl Iterator<Item = WhereClause> + 'a { | 708 | ) -> impl Iterator<Item = WhereClause> + 'a { |
702 | let mut bindings = None; | 709 | let mut bindings = None; |
703 | let trait_ref = match bound { | 710 | let trait_ref = match bound { |
@@ -711,6 +718,7 @@ impl<'a> TyLoweringContext<'a> { | |||
711 | trait_ref.into_iter().chain( | 718 | trait_ref.into_iter().chain( |
712 | bindings | 719 | bindings |
713 | .into_iter() | 720 | .into_iter() |
721 | .filter(move |_| !ignore_bindings) | ||
714 | .flat_map(move |tr| self.assoc_type_bindings_from_type_bound(bound, tr)), | 722 | .flat_map(move |tr| self.assoc_type_bindings_from_type_bound(bound, tr)), |
715 | ) | 723 | ) |
716 | } | 724 | } |
@@ -755,6 +763,7 @@ impl<'a> TyLoweringContext<'a> { | |||
755 | preds.extend(self.lower_type_bound( | 763 | preds.extend(self.lower_type_bound( |
756 | bound, | 764 | bound, |
757 | TyKind::Alias(AliasTy::Projection(projection_ty.clone())).intern(&Interner), | 765 | TyKind::Alias(AliasTy::Projection(projection_ty.clone())).intern(&Interner), |
766 | false, | ||
758 | )); | 767 | )); |
759 | } | 768 | } |
760 | preds | 769 | preds |
@@ -766,7 +775,7 @@ impl<'a> TyLoweringContext<'a> { | |||
766 | let self_ty = | 775 | let self_ty = |
767 | TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(&Interner); | 776 | TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(&Interner); |
768 | let predicates = self.with_shifted_in(DebruijnIndex::ONE, |ctx| { | 777 | let predicates = self.with_shifted_in(DebruijnIndex::ONE, |ctx| { |
769 | bounds.iter().flat_map(|b| ctx.lower_type_bound(b, self_ty.clone())).collect() | 778 | bounds.iter().flat_map(|b| ctx.lower_type_bound(b, self_ty.clone(), false)).collect() |
770 | }); | 779 | }); |
771 | ReturnTypeImplTrait { bounds: Binders::new(1, predicates) } | 780 | ReturnTypeImplTrait { bounds: Binders::new(1, predicates) } |
772 | } | 781 | } |
@@ -896,7 +905,9 @@ pub(crate) fn generic_predicates_for_param_query( | |||
896 | }, | 905 | }, |
897 | WherePredicate::Lifetime { .. } => false, | 906 | WherePredicate::Lifetime { .. } => false, |
898 | }) | 907 | }) |
899 | .flat_map(|pred| ctx.lower_where_predicate(pred).map(|p| Binders::new(generics.len(), p))) | 908 | .flat_map(|pred| { |
909 | ctx.lower_where_predicate(pred, true).map(|p| Binders::new(generics.len(), p)) | ||
910 | }) | ||
900 | .collect() | 911 | .collect() |
901 | } | 912 | } |
902 | 913 | ||
@@ -918,7 +929,7 @@ pub(crate) fn trait_environment_query( | |||
918 | let mut traits_in_scope = Vec::new(); | 929 | let mut traits_in_scope = Vec::new(); |
919 | let mut clauses = Vec::new(); | 930 | let mut clauses = Vec::new(); |
920 | for pred in resolver.where_predicates_in_scope() { | 931 | for pred in resolver.where_predicates_in_scope() { |
921 | for pred in ctx.lower_where_predicate(pred) { | 932 | for pred in ctx.lower_where_predicate(pred, false) { |
922 | if let WhereClause::Implemented(tr) = &pred { | 933 | if let WhereClause::Implemented(tr) = &pred { |
923 | traits_in_scope.push((tr.self_type_parameter().clone(), tr.hir_trait_id())); | 934 | traits_in_scope.push((tr.self_type_parameter().clone(), tr.hir_trait_id())); |
924 | } | 935 | } |
@@ -966,7 +977,9 @@ pub(crate) fn generic_predicates_query( | |||
966 | let generics = generics(db.upcast(), def); | 977 | let generics = generics(db.upcast(), def); |
967 | resolver | 978 | resolver |
968 | .where_predicates_in_scope() | 979 | .where_predicates_in_scope() |
969 | .flat_map(|pred| ctx.lower_where_predicate(pred).map(|p| Binders::new(generics.len(), p))) | 980 | .flat_map(|pred| { |
981 | ctx.lower_where_predicate(pred, false).map(|p| Binders::new(generics.len(), p)) | ||
982 | }) | ||
970 | .collect() | 983 | .collect() |
971 | } | 984 | } |
972 | 985 | ||
diff --git a/crates/hir_ty/src/tests.rs b/crates/hir_ty/src/tests.rs index 0a4141e69..ad283c1e0 100644 --- a/crates/hir_ty/src/tests.rs +++ b/crates/hir_ty/src/tests.rs | |||
@@ -369,3 +369,72 @@ fn check_infer_with_mismatches(ra_fixture: &str, expect: Expect) { | |||
369 | actual.push('\n'); | 369 | actual.push('\n'); |
370 | expect.assert_eq(&actual); | 370 | expect.assert_eq(&actual); |
371 | } | 371 | } |
372 | |||
373 | #[test] | ||
374 | fn salsa_bug() { | ||
375 | let (mut db, pos) = TestDB::with_position( | ||
376 | " | ||
377 | //- /lib.rs | ||
378 | trait Index { | ||
379 | type Output; | ||
380 | } | ||
381 | |||
382 | type Key<S: UnificationStoreBase> = <S as UnificationStoreBase>::Key; | ||
383 | |||
384 | pub trait UnificationStoreBase: Index<Output = Key<Self>> { | ||
385 | type Key; | ||
386 | |||
387 | fn len(&self) -> usize; | ||
388 | } | ||
389 | |||
390 | pub trait UnificationStoreMut: UnificationStoreBase { | ||
391 | fn push(&mut self, value: Self::Key); | ||
392 | } | ||
393 | |||
394 | fn main() { | ||
395 | let x = 1; | ||
396 | x.push(1);$0 | ||
397 | } | ||
398 | ", | ||
399 | ); | ||
400 | |||
401 | let module = db.module_for_file(pos.file_id); | ||
402 | let crate_def_map = module.def_map(&db); | ||
403 | visit_module(&db, &crate_def_map, module.local_id, &mut |def| { | ||
404 | db.infer(def); | ||
405 | }); | ||
406 | |||
407 | let new_text = " | ||
408 | //- /lib.rs | ||
409 | trait Index { | ||
410 | type Output; | ||
411 | } | ||
412 | |||
413 | type Key<S: UnificationStoreBase> = <S as UnificationStoreBase>::Key; | ||
414 | |||
415 | pub trait UnificationStoreBase: Index<Output = Key<Self>> { | ||
416 | type Key; | ||
417 | |||
418 | fn len(&self) -> usize; | ||
419 | } | ||
420 | |||
421 | pub trait UnificationStoreMut: UnificationStoreBase { | ||
422 | fn push(&mut self, value: Self::Key); | ||
423 | } | ||
424 | |||
425 | fn main() { | ||
426 | |||
427 | let x = 1; | ||
428 | x.push(1); | ||
429 | } | ||
430 | " | ||
431 | .to_string(); | ||
432 | |||
433 | db.set_file_text(pos.file_id, Arc::new(new_text)); | ||
434 | |||
435 | let module = db.module_for_file(pos.file_id); | ||
436 | let crate_def_map = module.def_map(&db); | ||
437 | visit_module(&db, &crate_def_map, module.local_id, &mut |def| { | ||
438 | db.infer(def); | ||
439 | }); | ||
440 | } | ||
diff --git a/crates/hir_ty/src/tests/macros.rs b/crates/hir_ty/src/tests/macros.rs index c1e605740..12951fb16 100644 --- a/crates/hir_ty/src/tests/macros.rs +++ b/crates/hir_ty/src/tests/macros.rs | |||
@@ -607,6 +607,29 @@ fn bar() -> u32 {0} | |||
607 | } | 607 | } |
608 | 608 | ||
609 | #[test] | 609 | #[test] |
610 | fn infer_builtin_macros_include_child_mod() { | ||
611 | check_types( | ||
612 | r#" | ||
613 | //- /main.rs | ||
614 | #[rustc_builtin_macro] | ||
615 | macro_rules! include {() => {}} | ||
616 | |||
617 | include!("f/foo.rs"); | ||
618 | |||
619 | fn main() { | ||
620 | bar::bar(); | ||
621 | } //^ u32 | ||
622 | |||
623 | //- /f/foo.rs | ||
624 | pub mod bar; | ||
625 | |||
626 | //- /f/bar.rs | ||
627 | pub fn bar() -> u32 {0} | ||
628 | "#, | ||
629 | ); | ||
630 | } | ||
631 | |||
632 | #[test] | ||
610 | fn infer_builtin_macros_include_str() { | 633 | fn infer_builtin_macros_include_str() { |
611 | check_types( | 634 | check_types( |
612 | r#" | 635 | r#" |
diff --git a/crates/hir_ty/src/tests/traits.rs b/crates/hir_ty/src/tests/traits.rs index 8f2bdffc0..37cd04c6f 100644 --- a/crates/hir_ty/src/tests/traits.rs +++ b/crates/hir_ty/src/tests/traits.rs | |||
@@ -2272,6 +2272,56 @@ fn test<T, U>() where T: Trait<U::Item>, U: Trait<T::Item> { | |||
2272 | } | 2272 | } |
2273 | 2273 | ||
2274 | #[test] | 2274 | #[test] |
2275 | fn unselected_projection_in_trait_env_cycle_3() { | ||
2276 | // this is a cycle for rustc; we currently accept it | ||
2277 | check_types( | ||
2278 | r#" | ||
2279 | //- /main.rs | ||
2280 | trait Trait { | ||
2281 | type Item; | ||
2282 | type OtherItem; | ||
2283 | } | ||
2284 | |||
2285 | fn test<T>() where T: Trait<OtherItem = T::Item> { | ||
2286 | let x: T::Item = no_matter; | ||
2287 | } //^ Trait::Item<T> | ||
2288 | "#, | ||
2289 | ); | ||
2290 | } | ||
2291 | |||
2292 | #[test] | ||
2293 | fn unselected_projection_in_trait_env_no_cycle() { | ||
2294 | // this is not a cycle | ||
2295 | check_types( | ||
2296 | r#" | ||
2297 | //- /main.rs | ||
2298 | trait Index { | ||
2299 | type Output; | ||
2300 | } | ||
2301 | |||
2302 | type Key<S: UnificationStoreBase> = <S as UnificationStoreBase>::Key; | ||
2303 | |||
2304 | pub trait UnificationStoreBase: Index<Output = Key<Self>> { | ||
2305 | type Key; | ||
2306 | |||
2307 | fn len(&self) -> usize; | ||
2308 | } | ||
2309 | |||
2310 | pub trait UnificationStoreMut: UnificationStoreBase { | ||
2311 | fn push(&mut self, value: Self::Key); | ||
2312 | } | ||
2313 | |||
2314 | fn test<T>(t: T) where T: UnificationStoreMut { | ||
2315 | let x; | ||
2316 | t.push(x); | ||
2317 | let y: Key<T>; | ||
2318 | (x, y); | ||
2319 | } //^ (UnificationStoreBase::Key<T>, UnificationStoreBase::Key<T>) | ||
2320 | "#, | ||
2321 | ); | ||
2322 | } | ||
2323 | |||
2324 | #[test] | ||
2275 | fn inline_assoc_type_bounds_1() { | 2325 | fn inline_assoc_type_bounds_1() { |
2276 | check_types( | 2326 | check_types( |
2277 | r#" | 2327 | r#" |
diff --git a/crates/hir_ty/src/traits/chalk.rs b/crates/hir_ty/src/traits/chalk.rs index 734679414..944145603 100644 --- a/crates/hir_ty/src/traits/chalk.rs +++ b/crates/hir_ty/src/traits/chalk.rs | |||
@@ -395,7 +395,7 @@ pub(crate) fn associated_ty_data_query( | |||
395 | let bounds = type_alias_data | 395 | let bounds = type_alias_data |
396 | .bounds | 396 | .bounds |
397 | .iter() | 397 | .iter() |
398 | .flat_map(|bound| ctx.lower_type_bound(bound, self_ty.clone())) | 398 | .flat_map(|bound| ctx.lower_type_bound(bound, self_ty.clone(), false)) |
399 | .filter_map(|pred| generic_predicate_to_inline_bound(db, &pred, &self_ty)) | 399 | .filter_map(|pred| generic_predicate_to_inline_bound(db, &pred, &self_ty)) |
400 | .map(|bound| make_binders(bound.shifted_in(&Interner), 0)) | 400 | .map(|bound| make_binders(bound.shifted_in(&Interner), 0)) |
401 | .collect(); | 401 | .collect(); |