diff options
Diffstat (limited to 'crates/hir_def/src')
| -rw-r--r-- | crates/hir_def/src/item_tree/pretty.rs | 136 | ||||
| -rw-r--r-- | crates/hir_def/src/item_tree/tests.rs | 53 |
2 files changed, 155 insertions, 34 deletions
diff --git a/crates/hir_def/src/item_tree/pretty.rs b/crates/hir_def/src/item_tree/pretty.rs index d00de2f73..4bc87a0e2 100644 --- a/crates/hir_def/src/item_tree/pretty.rs +++ b/crates/hir_def/src/item_tree/pretty.rs | |||
| @@ -3,7 +3,10 @@ | |||
| 3 | use std::fmt::{self, Write}; | 3 | use std::fmt::{self, Write}; |
| 4 | 4 | ||
| 5 | use crate::{ | 5 | use crate::{ |
| 6 | attr::RawAttrs, generics::TypeParamProvenance, path::GenericArg, visibility::RawVisibility, | 6 | attr::RawAttrs, |
| 7 | generics::{WherePredicate, WherePredicateTypeTarget}, | ||
| 8 | path::GenericArg, | ||
| 9 | visibility::RawVisibility, | ||
| 7 | }; | 10 | }; |
| 8 | 11 | ||
| 9 | use super::*; | 12 | use super::*; |
| @@ -72,6 +75,13 @@ impl<'a> Printer<'a> { | |||
| 72 | } | 75 | } |
| 73 | } | 76 | } |
| 74 | 77 | ||
| 78 | fn whitespace(&mut self) { | ||
| 79 | match self.buf.chars().next_back() { | ||
| 80 | None | Some('\n') | Some(' ') => {} | ||
| 81 | _ => self.buf.push(' '), | ||
| 82 | } | ||
| 83 | } | ||
| 84 | |||
| 75 | fn print_attrs(&mut self, attrs: &RawAttrs, inner: bool) { | 85 | fn print_attrs(&mut self, attrs: &RawAttrs, inner: bool) { |
| 76 | let inner = if inner { "!" } else { "" }; | 86 | let inner = if inner { "!" } else { "" }; |
| 77 | for attr in &**attrs { | 87 | for attr in &**attrs { |
| @@ -102,7 +112,8 @@ impl<'a> Printer<'a> { | |||
| 102 | fn print_fields(&mut self, fields: &Fields) { | 112 | fn print_fields(&mut self, fields: &Fields) { |
| 103 | match fields { | 113 | match fields { |
| 104 | Fields::Record(fields) => { | 114 | Fields::Record(fields) => { |
| 105 | w!(self, " {{"); | 115 | self.whitespace(); |
| 116 | w!(self, "{{"); | ||
| 106 | self.indented(|this| { | 117 | self.indented(|this| { |
| 107 | for field in fields.clone() { | 118 | for field in fields.clone() { |
| 108 | let Field { visibility, name, type_ref } = &this.tree[field]; | 119 | let Field { visibility, name, type_ref } = &this.tree[field]; |
| @@ -133,6 +144,25 @@ impl<'a> Printer<'a> { | |||
| 133 | } | 144 | } |
| 134 | } | 145 | } |
| 135 | 146 | ||
| 147 | fn print_fields_and_where_clause(&mut self, fields: &Fields, params: &GenericParams) { | ||
| 148 | match fields { | ||
| 149 | Fields::Record(_) => { | ||
| 150 | if self.print_where_clause(params) { | ||
| 151 | wln!(self); | ||
| 152 | } | ||
| 153 | self.print_fields(fields); | ||
| 154 | } | ||
| 155 | Fields::Unit => { | ||
| 156 | self.print_where_clause(params); | ||
| 157 | self.print_fields(fields); | ||
| 158 | } | ||
| 159 | Fields::Tuple(_) => { | ||
| 160 | self.print_fields(fields); | ||
| 161 | self.print_where_clause(params); | ||
| 162 | } | ||
| 163 | } | ||
| 164 | } | ||
| 165 | |||
| 136 | fn print_mod_item(&mut self, item: ModItem) { | 166 | fn print_mod_item(&mut self, item: ModItem) { |
| 137 | self.print_attrs_of(item); | 167 | self.print_attrs_of(item); |
| 138 | 168 | ||
| @@ -212,6 +242,7 @@ impl<'a> Printer<'a> { | |||
| 212 | } | 242 | } |
| 213 | w!(self, ") -> "); | 243 | w!(self, ") -> "); |
| 214 | self.print_type_ref(ret_type); | 244 | self.print_type_ref(ret_type); |
| 245 | self.print_where_clause(generic_params); | ||
| 215 | wln!(self, ";"); | 246 | wln!(self, ";"); |
| 216 | } | 247 | } |
| 217 | ModItem::Struct(it) => { | 248 | ModItem::Struct(it) => { |
| @@ -219,7 +250,7 @@ impl<'a> Printer<'a> { | |||
| 219 | self.print_visibility(*visibility); | 250 | self.print_visibility(*visibility); |
| 220 | w!(self, "struct {}", name); | 251 | w!(self, "struct {}", name); |
| 221 | self.print_generic_params(generic_params); | 252 | self.print_generic_params(generic_params); |
| 222 | self.print_fields(fields); | 253 | self.print_fields_and_where_clause(fields, generic_params); |
| 223 | if matches!(fields, Fields::Record(_)) { | 254 | if matches!(fields, Fields::Record(_)) { |
| 224 | wln!(self); | 255 | wln!(self); |
| 225 | } else { | 256 | } else { |
| @@ -231,7 +262,7 @@ impl<'a> Printer<'a> { | |||
| 231 | self.print_visibility(*visibility); | 262 | self.print_visibility(*visibility); |
| 232 | w!(self, "union {}", name); | 263 | w!(self, "union {}", name); |
| 233 | self.print_generic_params(generic_params); | 264 | self.print_generic_params(generic_params); |
| 234 | self.print_fields(fields); | 265 | self.print_fields_and_where_clause(fields, generic_params); |
| 235 | if matches!(fields, Fields::Record(_)) { | 266 | if matches!(fields, Fields::Record(_)) { |
| 236 | wln!(self); | 267 | wln!(self); |
| 237 | } else { | 268 | } else { |
| @@ -243,7 +274,7 @@ impl<'a> Printer<'a> { | |||
| 243 | self.print_visibility(*visibility); | 274 | self.print_visibility(*visibility); |
| 244 | w!(self, "enum {}", name); | 275 | w!(self, "enum {}", name); |
| 245 | self.print_generic_params(generic_params); | 276 | self.print_generic_params(generic_params); |
| 246 | w!(self, " {{"); | 277 | self.print_where_clause_and_opening_brace(generic_params); |
| 247 | self.indented(|this| { | 278 | self.indented(|this| { |
| 248 | for variant in variants.clone() { | 279 | for variant in variants.clone() { |
| 249 | let Variant { name, fields } = &this.tree[variant]; | 280 | let Variant { name, fields } = &this.tree[variant]; |
| @@ -301,14 +332,13 @@ impl<'a> Printer<'a> { | |||
| 301 | if *is_auto { | 332 | if *is_auto { |
| 302 | w!(self, "auto "); | 333 | w!(self, "auto "); |
| 303 | } | 334 | } |
| 304 | w!(self, "trait"); | 335 | w!(self, "trait {}", name); |
| 305 | self.print_generic_params(generic_params); | 336 | self.print_generic_params(generic_params); |
| 306 | w!(self, " {}", name); | ||
| 307 | if !bounds.is_empty() { | 337 | if !bounds.is_empty() { |
| 308 | w!(self, ": "); | 338 | w!(self, ": "); |
| 309 | self.print_type_bounds(bounds); | 339 | self.print_type_bounds(bounds); |
| 310 | } | 340 | } |
| 311 | w!(self, " {{"); | 341 | self.print_where_clause_and_opening_brace(generic_params); |
| 312 | self.indented(|this| { | 342 | self.indented(|this| { |
| 313 | for item in &**items { | 343 | for item in &**items { |
| 314 | this.print_mod_item((*item).into()); | 344 | this.print_mod_item((*item).into()); |
| @@ -330,7 +360,7 @@ impl<'a> Printer<'a> { | |||
| 330 | w!(self, " for "); | 360 | w!(self, " for "); |
| 331 | } | 361 | } |
| 332 | self.print_type_ref(self_ty); | 362 | self.print_type_ref(self_ty); |
| 333 | w!(self, " {{"); | 363 | self.print_where_clause_and_opening_brace(generic_params); |
| 334 | self.indented(|this| { | 364 | self.indented(|this| { |
| 335 | for item in &**items { | 365 | for item in &**items { |
| 336 | this.print_mod_item((*item).into()); | 366 | this.print_mod_item((*item).into()); |
| @@ -359,6 +389,7 @@ impl<'a> Printer<'a> { | |||
| 359 | w!(self, " = "); | 389 | w!(self, " = "); |
| 360 | self.print_type_ref(ty); | 390 | self.print_type_ref(ty); |
| 361 | } | 391 | } |
| 392 | self.print_where_clause(generic_params); | ||
| 362 | w!(self, ";"); | 393 | w!(self, ";"); |
| 363 | if *is_extern { | 394 | if *is_extern { |
| 364 | w!(self, " // extern"); | 395 | w!(self, " // extern"); |
| @@ -572,44 +603,93 @@ impl<'a> Printer<'a> { | |||
| 572 | } | 603 | } |
| 573 | 604 | ||
| 574 | fn print_generic_params(&mut self, params: &GenericParams) { | 605 | fn print_generic_params(&mut self, params: &GenericParams) { |
| 606 | if params.types.is_empty() && params.lifetimes.is_empty() && params.consts.is_empty() { | ||
| 607 | return; | ||
| 608 | } | ||
| 609 | |||
| 610 | w!(self, "<"); | ||
| 575 | let mut first = true; | 611 | let mut first = true; |
| 576 | for (_, lt) in params.lifetimes.iter() { | 612 | for (_, lt) in params.lifetimes.iter() { |
| 577 | if first { | 613 | if !first { |
| 578 | w!(self, "<"); | ||
| 579 | } else { | ||
| 580 | w!(self, ", "); | 614 | w!(self, ", "); |
| 581 | } | 615 | } |
| 582 | first = false; | 616 | first = false; |
| 583 | w!(self, "{}", lt.name); | 617 | w!(self, "{}", lt.name); |
| 584 | } | 618 | } |
| 585 | for (_, ty) in params.types.iter() { | 619 | for (idx, ty) in params.types.iter() { |
| 586 | if ty.provenance != TypeParamProvenance::TypeParamList { | 620 | if !first { |
| 587 | continue; | 621 | w!(self, ", "); |
| 588 | } | 622 | } |
| 589 | if let Some(name) = &ty.name { | 623 | first = false; |
| 590 | if first { | 624 | match &ty.name { |
| 591 | w!(self, "<"); | 625 | Some(name) => w!(self, "{}", name), |
| 592 | } else { | 626 | None => w!(self, "_anon_{}", idx.into_raw()), |
| 593 | w!(self, ", "); | ||
| 594 | } | ||
| 595 | first = false; | ||
| 596 | w!(self, "{}", name); | ||
| 597 | } | 627 | } |
| 598 | } | 628 | } |
| 599 | for (_, konst) in params.consts.iter() { | 629 | for (_, konst) in params.consts.iter() { |
| 600 | if first { | 630 | if !first { |
| 601 | w!(self, "<"); | ||
| 602 | } else { | ||
| 603 | w!(self, ", "); | 631 | w!(self, ", "); |
| 604 | } | 632 | } |
| 605 | first = false; | 633 | first = false; |
| 606 | w!(self, "const {}: ", konst.name); | 634 | w!(self, "const {}: ", konst.name); |
| 607 | self.print_type_ref(&konst.ty); | 635 | self.print_type_ref(&konst.ty); |
| 608 | } | 636 | } |
| 609 | if !first { | 637 | w!(self, ">"); |
| 610 | w!(self, ">"); | 638 | } |
| 639 | |||
| 640 | fn print_where_clause_and_opening_brace(&mut self, params: &GenericParams) { | ||
| 641 | if self.print_where_clause(params) { | ||
| 642 | w!(self, "\n{{"); | ||
| 643 | } else { | ||
| 644 | self.whitespace(); | ||
| 645 | w!(self, "{{"); | ||
| 611 | } | 646 | } |
| 612 | } | 647 | } |
| 648 | |||
| 649 | fn print_where_clause(&mut self, params: &GenericParams) -> bool { | ||
| 650 | if params.where_predicates.is_empty() { | ||
| 651 | return false; | ||
| 652 | } | ||
| 653 | |||
| 654 | w!(self, "\nwhere"); | ||
| 655 | self.indented(|this| { | ||
| 656 | for (i, pred) in params.where_predicates.iter().enumerate() { | ||
| 657 | if i != 0 { | ||
| 658 | wln!(this, ","); | ||
| 659 | } | ||
| 660 | |||
| 661 | let (target, bound) = match pred { | ||
| 662 | WherePredicate::TypeBound { target, bound } => (target, bound), | ||
| 663 | WherePredicate::Lifetime { target, bound } => { | ||
| 664 | wln!(this, "{}: {},", target.name, bound.name); | ||
| 665 | continue; | ||
| 666 | } | ||
| 667 | WherePredicate::ForLifetime { lifetimes, target, bound } => { | ||
| 668 | w!(this, "for<"); | ||
| 669 | for (i, lt) in lifetimes.iter().enumerate() { | ||
| 670 | if i != 0 { | ||
| 671 | w!(this, ", "); | ||
| 672 | } | ||
| 673 | w!(this, "{}", lt); | ||
| 674 | } | ||
| 675 | w!(this, "> "); | ||
| 676 | (target, bound) | ||
| 677 | } | ||
| 678 | }; | ||
| 679 | |||
| 680 | match target { | ||
| 681 | WherePredicateTypeTarget::TypeRef(ty) => this.print_type_ref(ty), | ||
| 682 | WherePredicateTypeTarget::TypeParam(id) => match ¶ms.types[*id].name { | ||
| 683 | Some(name) => w!(this, "{}", name), | ||
| 684 | None => w!(this, "_anon_{}", id.into_raw()), | ||
| 685 | }, | ||
| 686 | } | ||
| 687 | w!(this, ": "); | ||
| 688 | this.print_type_bounds(std::slice::from_ref(bound)); | ||
| 689 | } | ||
| 690 | }); | ||
| 691 | true | ||
| 692 | } | ||
| 613 | } | 693 | } |
| 614 | 694 | ||
| 615 | impl<'a> Write for Printer<'a> { | 695 | impl<'a> Write for Printer<'a> { |
diff --git a/crates/hir_def/src/item_tree/tests.rs b/crates/hir_def/src/item_tree/tests.rs index e0847dc75..6407871b5 100644 --- a/crates/hir_def/src/item_tree/tests.rs +++ b/crates/hir_def/src/item_tree/tests.rs | |||
| @@ -183,7 +183,11 @@ trait Tr: SuperTrait + 'lifetime { | |||
| 183 | _: (), | 183 | _: (), |
| 184 | ) -> (); | 184 | ) -> (); |
| 185 | 185 | ||
| 186 | pub(self) trait Tr: SuperTrait + 'lifetime { | 186 | pub(self) trait Tr<Self>: SuperTrait + 'lifetime |
| 187 | where | ||
| 188 | Self: SuperTrait, | ||
| 189 | Self: 'lifetime | ||
| 190 | { | ||
| 187 | pub(self) type Assoc: AssocBound = Default; | 191 | pub(self) type Assoc: AssocBound = Default; |
| 188 | 192 | ||
| 189 | // flags = 0x1 | 193 | // flags = 0x1 |
| @@ -207,6 +211,8 @@ mod inline { | |||
| 207 | 211 | ||
| 208 | fn fn_in_module() {} | 212 | fn fn_in_module() {} |
| 209 | } | 213 | } |
| 214 | |||
| 215 | mod outline; | ||
| 210 | "#, | 216 | "#, |
| 211 | expect![[r##" | 217 | expect![[r##" |
| 212 | #[doc = " outer"] // AttrId { is_doc_comment: true, ast_index: 0 } | 218 | #[doc = " outer"] // AttrId { is_doc_comment: true, ast_index: 0 } |
| @@ -217,6 +223,8 @@ mod inline { | |||
| 217 | // flags = 0x2 | 223 | // flags = 0x2 |
| 218 | pub(self) fn fn_in_module() -> (); | 224 | pub(self) fn fn_in_module() -> (); |
| 219 | } | 225 | } |
| 226 | |||
| 227 | pub(self) mod outline; | ||
| 220 | "##]], | 228 | "##]], |
| 221 | ); | 229 | ); |
| 222 | } | 230 | } |
| @@ -293,7 +301,11 @@ struct S { | |||
| 293 | fn generics() { | 301 | fn generics() { |
| 294 | check( | 302 | check( |
| 295 | r#" | 303 | r#" |
| 296 | struct S<'a, 'b: 'a, T: Copy + 'a + 'b, const K: u8 = 0> {} | 304 | struct S<'a, 'b: 'a, T: Copy + 'a + 'b, const K: u8 = 0> { |
| 305 | field: &'a &'b T, | ||
| 306 | } | ||
| 307 | |||
| 308 | struct Tuple<T: Copy>(T); | ||
| 297 | 309 | ||
| 298 | impl<'a, 'b: 'a, T: Copy + 'a + 'b, const K: u8 = 0> S<'a, 'b, T, K> { | 310 | impl<'a, 'b: 'a, T: Copy + 'a + 'b, const K: u8 = 0> S<'a, 'b, T, K> { |
| 299 | fn f<G: 'a>(arg: impl Copy) -> impl Copy {} | 311 | fn f<G: 'a>(arg: impl Copy) -> impl Copy {} |
| @@ -301,16 +313,38 @@ impl<'a, 'b: 'a, T: Copy + 'a + 'b, const K: u8 = 0> S<'a, 'b, T, K> { | |||
| 301 | 313 | ||
| 302 | enum Enum<'a, T, const U: u8> {} | 314 | enum Enum<'a, T, const U: u8> {} |
| 303 | union Union<'a, T, const U: u8> {} | 315 | union Union<'a, T, const U: u8> {} |
| 316 | |||
| 317 | trait Tr<'a, T: 'a>: Super {} | ||
| 304 | "#, | 318 | "#, |
| 305 | expect![[r#" | 319 | expect![[r#" |
| 306 | pub(self) struct S<'a, 'b, T, const K: u8> { | 320 | pub(self) struct S<'a, 'b, T, const K: u8> |
| 321 | where | ||
| 322 | T: Copy, | ||
| 323 | T: 'a, | ||
| 324 | T: 'b | ||
| 325 | { | ||
| 326 | pub(self) field: &'a &'b T, | ||
| 307 | } | 327 | } |
| 308 | 328 | ||
| 309 | impl<'a, 'b, T, const K: u8> S<'a, 'b, T, K> { | 329 | pub(self) struct Tuple<T>( |
| 330 | pub(self) 0: T, | ||
| 331 | ) | ||
| 332 | where | ||
| 333 | T: Copy; | ||
| 334 | |||
| 335 | impl<'a, 'b, T, const K: u8> S<'a, 'b, T, K> | ||
| 336 | where | ||
| 337 | T: Copy, | ||
| 338 | T: 'a, | ||
| 339 | T: 'b | ||
| 340 | { | ||
| 310 | // flags = 0x2 | 341 | // flags = 0x2 |
| 311 | pub(self) fn f<G>( | 342 | pub(self) fn f<G, _anon_1>( |
| 312 | _: impl Copy, | 343 | _: impl Copy, |
| 313 | ) -> impl Copy; | 344 | ) -> impl Copy |
| 345 | where | ||
| 346 | G: 'a, | ||
| 347 | _anon_1: Copy; | ||
| 314 | } | 348 | } |
| 315 | 349 | ||
| 316 | pub(self) enum Enum<'a, T, const U: u8> { | 350 | pub(self) enum Enum<'a, T, const U: u8> { |
| @@ -318,6 +352,13 @@ union Union<'a, T, const U: u8> {} | |||
| 318 | 352 | ||
| 319 | pub(self) union Union<'a, T, const U: u8> { | 353 | pub(self) union Union<'a, T, const U: u8> { |
| 320 | } | 354 | } |
| 355 | |||
| 356 | pub(self) trait Tr<'a, Self, T>: Super | ||
| 357 | where | ||
| 358 | Self: Super, | ||
| 359 | T: 'a | ||
| 360 | { | ||
| 361 | } | ||
| 321 | "#]], | 362 | "#]], |
| 322 | ) | 363 | ) |
| 323 | } | 364 | } |
