aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/hir/src/lib.rs5
-rw-r--r--crates/hir_def/src/nameres/mod_resolution.rs13
-rw-r--r--crates/hir_expand/src/builtin_macro.rs66
-rw-r--r--crates/hir_expand/src/eager.rs13
-rw-r--r--crates/hir_expand/src/lib.rs23
-rw-r--r--crates/hir_ty/src/display.rs21
-rw-r--r--crates/hir_ty/src/lib.rs17
-rw-r--r--crates/hir_ty/src/lower.rs25
-rw-r--r--crates/hir_ty/src/tests.rs69
-rw-r--r--crates/hir_ty/src/tests/macros.rs23
-rw-r--r--crates/hir_ty/src/tests/traits.rs50
-rw-r--r--crates/hir_ty/src/traits/chalk.rs2
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)]
65pub 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
72impl ExpandedEager {
73 fn new(subtree: tt::Subtree, fragment: FragmentKind) -> Self {
74 ExpandedEager { subtree, fragment, included_file: None }
75 }
76}
77
64pub fn find_builtin_macro( 78pub 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
300fn concat_expand( 314fn 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
331fn relative_file( 345fn 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
404fn include_str_expand( 424fn 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
431fn get_env_inner(db: &dyn AstDatabase, arg_id: EagerMacroId, key: &str) -> Option<String> { 451fn 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
467fn option_env_expand( 487fn 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]
374fn 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]
610fn infer_builtin_macros_include_child_mod() {
611 check_types(
612 r#"
613//- /main.rs
614#[rustc_builtin_macro]
615macro_rules! include {() => {}}
616
617include!("f/foo.rs");
618
619fn main() {
620 bar::bar();
621} //^ u32
622
623//- /f/foo.rs
624pub mod bar;
625
626//- /f/bar.rs
627pub fn bar() -> u32 {0}
628"#,
629 );
630}
631
632#[test]
610fn infer_builtin_macros_include_str() { 633fn 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]
2275fn 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
2280trait Trait {
2281 type Item;
2282 type OtherItem;
2283}
2284
2285fn 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]
2293fn unselected_projection_in_trait_env_no_cycle() {
2294 // this is not a cycle
2295 check_types(
2296 r#"
2297//- /main.rs
2298trait Index {
2299 type Output;
2300}
2301
2302type Key<S: UnificationStoreBase> = <S as UnificationStoreBase>::Key;
2303
2304pub trait UnificationStoreBase: Index<Output = Key<Self>> {
2305 type Key;
2306
2307 fn len(&self) -> usize;
2308}
2309
2310pub trait UnificationStoreMut: UnificationStoreBase {
2311 fn push(&mut self, value: Self::Key);
2312}
2313
2314fn 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]
2275fn inline_assoc_type_bounds_1() { 2325fn 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();