(&mut self)
| 1798 | return Ok((Vec::new(), Vec::new())); |
| 1799 | } |
| 1800 | |
| 1801 | let mut params = Vec::new(); |
| 1802 | let mut bounds = Vec::new(); |
| 1803 | |
| 1804 | // Check for closing bracket |
| 1805 | let should_close = self.check_gt_or_shr(); |
| 1806 | |
| 1807 | if !should_close { |
| 1808 | loop { |
| 1809 | let param = self.expect_ident()?; |
| 1810 | if params.contains(¶m) { |
| 1811 | return Err(self.error(&format!("duplicate generic parameter `{param}`"))); |
| 1812 | } |
| 1813 | if matches!(self.peek(), Some(Token::Colon)) { |
| 1814 | self.advance(); |
| 1815 | let mut seen = std::collections::HashSet::new(); |
| 1816 | loop { |
| 1817 | let mut segments = vec![self.expect_ident()?]; |
| 1818 | while self.match_dot() { |
| 1819 | segments.push(self.expect_ident()?); |
| 1820 | } |
| 1821 | let interface = Path::from_segments(segments); |
| 1822 | if !seen.insert(interface.clone()) { |
| 1823 | return Err( |
| 1824 | self.error(&format!("duplicate bound `{param}: {interface}`")) |
| 1825 | ); |
| 1826 | } |
| 1827 | bounds.push((param.clone(), interface)); |
| 1828 | if !self.match_plus() { |
| 1829 | break; |
| 1830 | } |
| 1831 | } |
| 1832 | } |
| 1833 | params.push(param); |
| 1834 | if self.match_comma() { |
| 1835 | if self.check_gt_or_shr() { |
| 1836 | break; |
| 1837 | } |
| 1838 | continue; |
| 1839 | } |
| 1840 | break; |
| 1841 | } |
| 1842 | } |
| 1843 | |
| 1844 | // Consume the closing bracket |
| 1845 | if self.pending_gt_from_shr { |
| 1846 | // Virtual > available from previous Shr split |
| 1847 | self.pending_gt_from_shr = false; |
| 1848 | } else if self.match_gt() { |
| 1849 | // plain > |
| 1850 | } else if matches!(self.peek(), Some(Token::Shr | Token::Gte)) { |
| 1851 | self.advance(); |
| 1852 | self.pending_gt_from_shr = true; |
| 1853 | } else { |
| 1854 | return Err(self.error("expected `>` to close generic parameters")); |
| 1855 | } |
| 1856 | |
| 1857 | Ok((params, bounds)) |
no test coverage detected