aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock33
-rw-r--r--bench_data/glorious_old_parser8562
-rw-r--r--crates/assists/src/tests.rs4
-rw-r--r--crates/completion/src/completions.rs60
-rw-r--r--crates/completion/src/completions/keyword.rs8
-rw-r--r--crates/completion/src/completions/pattern.rs56
-rw-r--r--crates/completion/src/completions/unqualified_path.rs56
-rw-r--r--crates/completion/src/context.rs16
-rw-r--r--crates/completion/src/render/pattern.rs6
-rw-r--r--crates/hir/src/source_analyzer.rs17
-rw-r--r--crates/hir_def/src/body/scope.rs22
-rw-r--r--crates/hir_def/src/body/tests.rs104
-rw-r--r--crates/hir_def/src/body/tests/block.rs27
-rw-r--r--crates/hir_def/src/find_path.rs101
-rw-r--r--crates/hir_def/src/nameres.rs2
-rw-r--r--crates/hir_def/src/resolver.rs215
-rw-r--r--crates/hir_def/src/test_db.rs99
-rw-r--r--crates/hir_ty/Cargo.toml6
-rw-r--r--crates/hir_ty/src/method_resolution.rs27
-rw-r--r--crates/hir_ty/src/tests/macros.rs23
-rw-r--r--crates/hir_ty/src/tests/method_resolution.rs22
-rw-r--r--crates/hir_ty/src/traits/chalk/interner.rs5
-rw-r--r--crates/ide/src/display/navigation_target.rs12
-rw-r--r--crates/ide/src/fixture.rs16
-rw-r--r--crates/ide/src/goto_definition.rs13
-rw-r--r--crates/ide/src/join_lines.rs41
-rw-r--r--crates/ide/src/parent_module.rs71
-rw-r--r--crates/ide/src/references.rs23
-rw-r--r--crates/ide/src/syntax_highlighting/tests.rs51
-rw-r--r--crates/ide/src/syntax_tree.rs366
-rw-r--r--crates/rust-analyzer/src/cli/analysis_bench.rs14
-rw-r--r--crates/rust-analyzer/src/cli/analysis_stats.rs13
-rw-r--r--crates/rust-analyzer/src/cli/diagnostics.rs18
-rw-r--r--crates/rust-analyzer/src/cli/load_cargo.rs26
-rw-r--r--crates/rust-analyzer/src/cli/ssr.rs19
-rw-r--r--crates/syntax/Cargo.toml2
-rw-r--r--crates/syntax/src/tests.rs28
-rw-r--r--crates/syntax/test_data/accidentally_quadratic3980
-rw-r--r--crates/test_utils/Cargo.toml1
-rw-r--r--crates/test_utils/src/bench_fixture.rs37
-rw-r--r--crates/test_utils/src/lib.rs43
-rw-r--r--docs/dev/architecture.md7
-rw-r--r--docs/user/manual.adoc90
-rw-r--r--editors/code/package.json44
-rw-r--r--xtask/src/release.rs2
45 files changed, 9776 insertions, 4612 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 894fadcb2..25f312faf 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -178,9 +178,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
178 178
179[[package]] 179[[package]]
180name = "chalk-derive" 180name = "chalk-derive"
181version = "0.55.0" 181version = "0.56.0"
182source = "registry+https://github.com/rust-lang/crates.io-index" 182source = "registry+https://github.com/rust-lang/crates.io-index"
183checksum = "3983193cacd81f0f924acb666b7fe5e1a0d81db9f113fa69203eda7ea8ce8b6c" 183checksum = "51f6c7a4b1a119cff6c5a17cf68056069dece7bc525c2a2e26e1117e27f48ca2"
184dependencies = [ 184dependencies = [
185 "proc-macro2", 185 "proc-macro2",
186 "quote", 186 "quote",
@@ -190,9 +190,9 @@ dependencies = [
190 190
191[[package]] 191[[package]]
192name = "chalk-ir" 192name = "chalk-ir"
193version = "0.55.0" 193version = "0.56.0"
194source = "registry+https://github.com/rust-lang/crates.io-index" 194source = "registry+https://github.com/rust-lang/crates.io-index"
195checksum = "a522f53af971e7678f472d687e053120157b3ae26e2ebd5ecbc0f5ab124f2cb6" 195checksum = "7d5f524bc3a5798fe3711c360fde350bffb938b52ef7b302d637550229995e20"
196dependencies = [ 196dependencies = [
197 "bitflags", 197 "bitflags",
198 "chalk-derive", 198 "chalk-derive",
@@ -201,9 +201,9 @@ dependencies = [
201 201
202[[package]] 202[[package]]
203name = "chalk-recursive" 203name = "chalk-recursive"
204version = "0.55.0" 204version = "0.56.0"
205source = "registry+https://github.com/rust-lang/crates.io-index" 205source = "registry+https://github.com/rust-lang/crates.io-index"
206checksum = "8b0a6bc94f16aaba1dd6d1e2350945bbb0239c3633cdabeedbed601c1354d4b4" 206checksum = "f7c0525fb9c43f8f1d7ba4fb42f9ada2a2415901a04b5c655cfe11e559085d4d"
207dependencies = [ 207dependencies = [
208 "chalk-derive", 208 "chalk-derive",
209 "chalk-ir", 209 "chalk-ir",
@@ -214,9 +214,9 @@ dependencies = [
214 214
215[[package]] 215[[package]]
216name = "chalk-solve" 216name = "chalk-solve"
217version = "0.55.0" 217version = "0.56.0"
218source = "registry+https://github.com/rust-lang/crates.io-index" 218source = "registry+https://github.com/rust-lang/crates.io-index"
219checksum = "cdf79fb77a567e456a170f7ec84ea6584163d4ba3f13660cd182013d34ca667c" 219checksum = "3c2e7b54add0f18d5ee7bb043a3108b819e60b1b409d214291bcdc97927cdc32"
220dependencies = [ 220dependencies = [
221 "chalk-derive", 221 "chalk-derive",
222 "chalk-ir", 222 "chalk-ir",
@@ -785,9 +785,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
785 785
786[[package]] 786[[package]]
787name = "libc" 787name = "libc"
788version = "0.2.85" 788version = "0.2.86"
789source = "registry+https://github.com/rust-lang/crates.io-index" 789source = "registry+https://github.com/rust-lang/crates.io-index"
790checksum = "7ccac4b00700875e6a07c6cde370d44d32fa01c5a65cdd2fca6858c479d28bb3" 790checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c"
791 791
792[[package]] 792[[package]]
793name = "libloading" 793name = "libloading"
@@ -888,9 +888,9 @@ checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
888 888
889[[package]] 889[[package]]
890name = "memmap2" 890name = "memmap2"
891version = "0.2.0" 891version = "0.2.1"
892source = "registry+https://github.com/rust-lang/crates.io-index" 892source = "registry+https://github.com/rust-lang/crates.io-index"
893checksum = "e73be3b7d04a0123e933fea1d50d126cc7196bbc0362c0ce426694f777194eee" 893checksum = "04e3e85b970d650e2ae6d70592474087051c11c54da7f7b4949725c5735fbcc6"
894dependencies = [ 894dependencies = [
895 "libc", 895 "libc",
896] 896]
@@ -1377,9 +1377,9 @@ dependencies = [
1377 1377
1378[[package]] 1378[[package]]
1379name = "rustc-ap-rustc_lexer" 1379name = "rustc-ap-rustc_lexer"
1380version = "702.0.0" 1380version = "705.0.0"
1381source = "registry+https://github.com/rust-lang/crates.io-index" 1381source = "registry+https://github.com/rust-lang/crates.io-index"
1382checksum = "47cfdb02425aed8c56f85692975d262cb438ea0388e0c8cd254e73bd22bb6539" 1382checksum = "3a030d00510966cd31e13dca5e6c1bd40d303a932c54eca40e854188bca8c49e"
1383dependencies = [ 1383dependencies = [
1384 "unicode-xid", 1384 "unicode-xid",
1385] 1385]
@@ -1493,9 +1493,9 @@ dependencies = [
1493 1493
1494[[package]] 1494[[package]]
1495name = "serde_json" 1495name = "serde_json"
1496version = "1.0.61" 1496version = "1.0.62"
1497source = "registry+https://github.com/rust-lang/crates.io-index" 1497source = "registry+https://github.com/rust-lang/crates.io-index"
1498checksum = "4fceb2595057b6891a4ee808f70054bd2d12f0e97f1cbb78689b59f676df325a" 1498checksum = "ea1c6153794552ea7cf7cf63b1231a25de00ec90db326ba6264440fa08e31486"
1499dependencies = [ 1499dependencies = [
1500 "indexmap", 1500 "indexmap",
1501 "itoa", 1501 "itoa",
@@ -1640,6 +1640,7 @@ name = "test_utils"
1640version = "0.0.0" 1640version = "0.0.0"
1641dependencies = [ 1641dependencies = [
1642 "dissimilar", 1642 "dissimilar",
1643 "profile",
1643 "rustc-hash", 1644 "rustc-hash",
1644 "serde_json", 1645 "serde_json",
1645 "stdx", 1646 "stdx",
diff --git a/bench_data/glorious_old_parser b/bench_data/glorious_old_parser
new file mode 100644
index 000000000..7e900dfeb
--- /dev/null
+++ b/bench_data/glorious_old_parser
@@ -0,0 +1,8562 @@
1use crate::ast::{AngleBracketedArgs, ParenthesizedArgs, AttrStyle, BareFnTy};
2use crate::ast::{GenericBound, TraitBoundModifier};
3use crate::ast::Unsafety;
4use crate::ast::{Mod, AnonConst, Arg, Arm, Guard, Attribute, BindingMode, TraitItemKind};
5use crate::ast::Block;
6use crate::ast::{BlockCheckMode, CaptureBy, Movability};
7use crate::ast::{Constness, Crate};
8use crate::ast::Defaultness;
9use crate::ast::EnumDef;
10use crate::ast::{Expr, ExprKind, RangeLimits};
11use crate::ast::{Field, FnDecl, FnHeader};
12use crate::ast::{ForeignItem, ForeignItemKind, FunctionRetTy};
13use crate::ast::{GenericParam, GenericParamKind};
14use crate::ast::GenericArg;
15use crate::ast::{Ident, ImplItem, IsAsync, IsAuto, Item, ItemKind};
16use crate::ast::{Label, Lifetime, Lit, LitKind};
17use crate::ast::Local;
18use crate::ast::MacStmtStyle;
19use crate::ast::{Mac, Mac_, MacDelimiter};
20use crate::ast::{MutTy, Mutability};
21use crate::ast::{Pat, PatKind, PathSegment};
22use crate::ast::{PolyTraitRef, QSelf};
23use crate::ast::{Stmt, StmtKind};
24use crate::ast::{VariantData, StructField};
25use crate::ast::StrStyle;
26use crate::ast::SelfKind;
27use crate::ast::{TraitItem, TraitRef, TraitObjectSyntax};
28use crate::ast::{Ty, TyKind, TypeBinding, GenericBounds};
29use crate::ast::{Visibility, VisibilityKind, WhereClause, CrateSugar};
30use crate::ast::{UseTree, UseTreeKind};
31use crate::ast::{BinOpKind, UnOp};
32use crate::ast::{RangeEnd, RangeSyntax};
33use crate::{ast, attr};
34use crate::ext::base::DummyResult;
35use crate::source_map::{self, SourceMap, Spanned, respan};
36use crate::parse::{self, SeqSep, classify, token};
37use crate::parse::lexer::{TokenAndSpan, UnmatchedBrace};
38use crate::parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration};
39use crate::parse::token::DelimToken;
40use crate::parse::{new_sub_parser_from_file, ParseSess, Directory, DirectoryOwnership};
41use crate::util::parser::{AssocOp, Fixity};
42use crate::print::pprust;
43use crate::ptr::P;
44use crate::parse::PResult;
45use crate::ThinVec;
46use crate::tokenstream::{self, DelimSpan, TokenTree, TokenStream, TreeAndJoint};
47use crate::symbol::{Symbol, keywords};
48
49use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
50use rustc_target::spec::abi::{self, Abi};
51use syntax_pos::{Span, MultiSpan, BytePos, FileName};
52use log::{debug, trace};
53
54use std::borrow::Cow;
55use std::cmp;
56use std::mem;
57use std::path::{self, Path, PathBuf};
58use std::slice;
59
60#[derive(Debug)]
61/// Whether the type alias or associated type is a concrete type or an existential type
62pub enum AliasKind {
63 /// Just a new name for the same type
64 Weak(P<Ty>),
65 /// Only trait impls of the type will be usable, not the actual type itself
66 Existential(GenericBounds),
67}
68
69bitflags::bitflags! {
70 struct Restrictions: u8 {
71 const STMT_EXPR = 1 << 0;
72 const NO_STRUCT_LITERAL = 1 << 1;
73 }
74}
75
76type ItemInfo = (Ident, ItemKind, Option<Vec<Attribute>>);
77
78/// Specifies how to parse a path.
79#[derive(Copy, Clone, PartialEq)]
80pub enum PathStyle {
81 /// In some contexts, notably in expressions, paths with generic arguments are ambiguous
82 /// with something else. For example, in expressions `segment < ....` can be interpreted
83 /// as a comparison and `segment ( ....` can be interpreted as a function call.
84 /// In all such contexts the non-path interpretation is preferred by default for practical
85 /// reasons, but the path interpretation can be forced by the disambiguator `::`, e.g.
86 /// `x<y>` - comparisons, `x::<y>` - unambiguously a path.
87 Expr,
88 /// In other contexts, notably in types, no ambiguity exists and paths can be written
89 /// without the disambiguator, e.g., `x<y>` - unambiguously a path.
90 /// Paths with disambiguators are still accepted, `x::<Y>` - unambiguously a path too.
91 Type,
92 /// A path with generic arguments disallowed, e.g., `foo::bar::Baz`, used in imports,
93 /// visibilities or attributes.
94 /// Technically, this variant is unnecessary and e.g., `Expr` can be used instead
95 /// (paths in "mod" contexts have to be checked later for absence of generic arguments
96 /// anyway, due to macros), but it is used to avoid weird suggestions about expected
97 /// tokens when something goes wrong.
98 Mod,
99}
100
101#[derive(Clone, Copy, PartialEq, Debug)]
102enum SemiColonMode {
103 Break,
104 Ignore,
105 Comma,
106}
107
108#[derive(Clone, Copy, PartialEq, Debug)]
109enum BlockMode {
110 Break,
111 Ignore,
112}
113
114/// Possibly accepts an `token::Interpolated` expression (a pre-parsed expression
115/// dropped into the token stream, which happens while parsing the result of
116/// macro expansion). Placement of these is not as complex as I feared it would
117/// be. The important thing is to make sure that lookahead doesn't balk at
118/// `token::Interpolated` tokens.
119macro_rules! maybe_whole_expr {
120 ($p:expr) => {
121 if let token::Interpolated(nt) = $p.token.clone() {
122 match *nt {
123 token::NtExpr(ref e) | token::NtLiteral(ref e) => {
124 $p.bump();
125 return Ok((*e).clone());
126 }
127 token::NtPath(ref path) => {
128 $p.bump();
129 let span = $p.span;
130 let kind = ExprKind::Path(None, (*path).clone());
131 return Ok($p.mk_expr(span, kind, ThinVec::new()));
132 }
133 token::NtBlock(ref block) => {
134 $p.bump();
135 let span = $p.span;
136 let kind = ExprKind::Block((*block).clone(), None);
137 return Ok($p.mk_expr(span, kind, ThinVec::new()));
138 }
139 _ => {},
140 };
141 }
142 }
143}
144
145/// As maybe_whole_expr, but for things other than expressions
146macro_rules! maybe_whole {
147 ($p:expr, $constructor:ident, |$x:ident| $e:expr) => {
148 if let token::Interpolated(nt) = $p.token.clone() {
149 if let token::$constructor($x) = (*nt).clone() {
150 $p.bump();
151 return Ok($e);
152 }
153 }
154 };
155}
156
157fn maybe_append(mut lhs: Vec<Attribute>, mut rhs: Option<Vec<Attribute>>) -> Vec<Attribute> {
158 if let Some(ref mut rhs) = rhs {
159 lhs.append(rhs);
160 }
161 lhs
162}
163
164#[derive(Debug, Clone, Copy, PartialEq)]
165enum PrevTokenKind {
166 DocComment,
167 Comma,
168 Plus,
169 Interpolated,
170 Eof,
171 Ident,
172 Other,
173}
174
175trait RecoverQPath: Sized {
176 const PATH_STYLE: PathStyle = PathStyle::Expr;
177 fn to_ty(&self) -> Option<P<Ty>>;
178 fn to_recovered(&self, qself: Option<QSelf>, path: ast::Path) -> Self;
179 fn to_string(&self) -> String;
180}
181
182impl RecoverQPath for Ty {
183 const PATH_STYLE: PathStyle = PathStyle::Type;
184 fn to_ty(&self) -> Option<P<Ty>> {
185 Some(P(self.clone()))
186 }
187 fn to_recovered(&self, qself: Option<QSelf>, path: ast::Path) -> Self {
188 Self { span: path.span, node: TyKind::Path(qself, path), id: self.id }
189 }
190 fn to_string(&self) -> String {
191 pprust::ty_to_string(self)
192 }
193}
194
195impl RecoverQPath for Pat {
196 fn to_ty(&self) -> Option<P<Ty>> {
197 self.to_ty()
198 }
199 fn to_recovered(&self, qself: Option<QSelf>, path: ast::Path) -> Self {
200 Self { span: path.span, node: PatKind::Path(qself, path), id: self.id }
201 }
202 fn to_string(&self) -> String {
203 pprust::pat_to_string(self)
204 }
205}
206
207impl RecoverQPath for Expr {
208 fn to_ty(&self) -> Option<P<Ty>> {
209 self.to_ty()
210 }
211 fn to_recovered(&self, qself: Option<QSelf>, path: ast::Path) -> Self {
212 Self { span: path.span, node: ExprKind::Path(qself, path),
213 id: self.id, attrs: self.attrs.clone() }
214 }
215 fn to_string(&self) -> String {
216 pprust::expr_to_string(self)
217 }
218}
219
220/* ident is handled by common.rs */
221
222#[derive(Clone)]
223pub struct Parser<'a> {
224 pub sess: &'a ParseSess,
225 /// the current token:
226 pub token: token::Token,
227 /// the span of the current token:
228 pub span: Span,
229 /// the span of the previous token:
230 meta_var_span: Option<Span>,
231 pub prev_span: Span,
232 /// the previous token kind
233 prev_token_kind: PrevTokenKind,
234 restrictions: Restrictions,
235 /// Used to determine the path to externally loaded source files
236 crate directory: Directory<'a>,
237 /// Whether to parse sub-modules in other files.
238 pub recurse_into_file_modules: bool,
239 /// Name of the root module this parser originated from. If `None`, then the
240 /// name is not known. This does not change while the parser is descending
241 /// into modules, and sub-parsers have new values for this name.
242 pub root_module_name: Option<String>,
243 crate expected_tokens: Vec<TokenType>,
244 token_cursor: TokenCursor,
245 desugar_doc_comments: bool,
246 /// Whether we should configure out of line modules as we parse.
247 pub cfg_mods: bool,
248 /// This field is used to keep track of how many left angle brackets we have seen. This is
249 /// required in order to detect extra leading left angle brackets (`<` characters) and error
250 /// appropriately.
251 ///
252 /// See the comments in the `parse_path_segment` function for more details.
253 crate unmatched_angle_bracket_count: u32,
254 crate max_angle_bracket_count: u32,
255 /// List of all unclosed delimiters found by the lexer. If an entry is used for error recovery
256 /// it gets removed from here. Every entry left at the end gets emitted as an independent
257 /// error.
258 crate unclosed_delims: Vec<UnmatchedBrace>,
259}
260
261
262#[derive(Clone)]
263struct TokenCursor {
264 frame: TokenCursorFrame,
265 stack: Vec<TokenCursorFrame>,
266}
267
268#[derive(Clone)]
269struct TokenCursorFrame {
270 delim: token::DelimToken,
271 span: DelimSpan,
272 open_delim: bool,
273 tree_cursor: tokenstream::Cursor,
274 close_delim: bool,
275 last_token: LastToken,
276}
277
278/// This is used in `TokenCursorFrame` above to track tokens that are consumed
279/// by the parser, and then that's transitively used to record the tokens that
280/// each parse AST item is created with.
281///
282/// Right now this has two states, either collecting tokens or not collecting
283/// tokens. If we're collecting tokens we just save everything off into a local
284/// `Vec`. This should eventually though likely save tokens from the original
285/// token stream and just use slicing of token streams to avoid creation of a
286/// whole new vector.
287///
288/// The second state is where we're passively not recording tokens, but the last
289/// token is still tracked for when we want to start recording tokens. This
290/// "last token" means that when we start recording tokens we'll want to ensure
291/// that this, the first token, is included in the output.
292///
293/// You can find some more example usage of this in the `collect_tokens` method
294/// on the parser.
295#[derive(Clone)]
296enum LastToken {
297 Collecting(Vec<TreeAndJoint>),
298 Was(Option<TreeAndJoint>),
299}
300
301impl TokenCursorFrame {
302 fn new(sp: DelimSpan, delim: DelimToken, tts: &TokenStream) -> Self {
303 TokenCursorFrame {
304 delim: delim,
305 span: sp,
306 open_delim: delim == token::NoDelim,
307 tree_cursor: tts.clone().into_trees(),
308 close_delim: delim == token::NoDelim,
309 last_token: LastToken::Was(None),
310 }
311 }
312}
313
314impl TokenCursor {
315 fn next(&mut self) -> TokenAndSpan {
316 loop {
317 let tree = if !self.frame.open_delim {
318 self.frame.open_delim = true;
319 TokenTree::open_tt(self.frame.span.open, self.frame.delim)
320 } else if let Some(tree) = self.frame.tree_cursor.next() {
321 tree
322 } else if !self.frame.close_delim {
323 self.frame.close_delim = true;
324 TokenTree::close_tt(self.frame.span.close, self.frame.delim)
325 } else if let Some(frame) = self.stack.pop() {
326 self.frame = frame;
327 continue
328 } else {
329 return TokenAndSpan { tok: token::Eof, sp: syntax_pos::DUMMY_SP }
330 };
331
332 match self.frame.last_token {
333 LastToken::Collecting(ref mut v) => v.push(tree.clone().into()),
334 LastToken::Was(ref mut t) => *t = Some(tree.clone().into()),
335 }
336
337 match tree {
338 TokenTree::Token(sp, tok) => return TokenAndSpan { tok: tok, sp: sp },
339 TokenTree::Delimited(sp, delim, tts) => {
340 let frame = TokenCursorFrame::new(sp, delim, &tts);
341 self.stack.push(mem::replace(&mut self.frame, frame));
342 }
343 }
344 }
345 }
346
347 fn next_desugared(&mut self) -> TokenAndSpan {
348 let (sp, name) = match self.next() {
349 TokenAndSpan { sp, tok: token::DocComment(name) } => (sp, name),
350 tok => return tok,
351 };
352
353 let stripped = strip_doc_comment_decoration(&name.as_str());
354
355 // Searches for the occurrences of `"#*` and returns the minimum number of `#`s
356 // required to wrap the text.
357 let mut num_of_hashes = 0;
358 let mut count = 0;
359 for ch in stripped.chars() {
360 count = match ch {
361 '"' => 1,
362 '#' if count > 0 => count + 1,
363 _ => 0,
364 };
365 num_of_hashes = cmp::max(num_of_hashes, count);
366 }
367
368 let delim_span = DelimSpan::from_single(sp);
369 let body = TokenTree::Delimited(
370 delim_span,
371 token::Bracket,
372 [TokenTree::Token(sp, token::Ident(ast::Ident::from_str("doc"), false)),
373 TokenTree::Token(sp, token::Eq),
374 TokenTree::Token(sp, token::Literal(
375 token::StrRaw(Symbol::intern(&stripped), num_of_hashes), None))
376 ]
377 .iter().cloned().collect::<TokenStream>().into(),
378 );
379
380 self.stack.push(mem::replace(&mut self.frame, TokenCursorFrame::new(
381 delim_span,
382 token::NoDelim,
383 &if doc_comment_style(&name.as_str()) == AttrStyle::Inner {
384 [TokenTree::Token(sp, token::Pound), TokenTree::Token(sp, token::Not), body]
385 .iter().cloned().collect::<TokenStream>().into()
386 } else {
387 [TokenTree::Token(sp, token::Pound), body]
388 .iter().cloned().collect::<TokenStream>().into()
389 },
390 )));
391
392 self.next()
393 }
394}
395
396#[derive(Clone, PartialEq)]
397crate enum TokenType {
398 Token(token::Token),
399 Keyword(keywords::Keyword),
400 Operator,
401 Lifetime,
402 Ident,
403 Path,
404 Type,
405 Const,
406}
407
408impl TokenType {
409 fn to_string(&self) -> String {
410 match *self {
411 TokenType::Token(ref t) => format!("`{}`", pprust::token_to_string(t)),
412 TokenType::Keyword(kw) => format!("`{}`", kw.name()),
413 TokenType::Operator => "an operator".to_string(),
414 TokenType::Lifetime => "lifetime".to_string(),
415 TokenType::Ident => "identifier".to_string(),
416 TokenType::Path => "path".to_string(),
417 TokenType::Type => "type".to_string(),
418 TokenType::Const => "const".to_string(),
419 }
420 }
421}
422
423/// Returns `true` if `IDENT t` can start a type -- `IDENT::a::b`, `IDENT<u8, u8>`,
424/// `IDENT<<u8 as Trait>::AssocTy>`.
425///
426/// Types can also be of the form `IDENT(u8, u8) -> u8`, however this assumes
427/// that `IDENT` is not the ident of a fn trait.
428fn can_continue_type_after_non_fn_ident(t: &token::Token) -> bool {
429 t == &token::ModSep || t == &token::Lt ||
430 t == &token::BinOp(token::Shl)
431}
432
433/// Information about the path to a module.
434pub struct ModulePath {
435 name: String,
436 path_exists: bool,
437 pub result: Result<ModulePathSuccess, Error>,
438}
439
440pub struct ModulePathSuccess {
441 pub path: PathBuf,
442 pub directory_ownership: DirectoryOwnership,
443 warn: bool,
444}
445
446pub enum Error {
447 FileNotFoundForModule {
448 mod_name: String,
449 default_path: String,
450 secondary_path: String,
451 dir_path: String,
452 },
453 DuplicatePaths {
454 mod_name: String,
455 default_path: String,
456 secondary_path: String,
457 },
458 UselessDocComment,
459 InclusiveRangeWithNoEnd,
460}
461
462impl Error {
463 fn span_err<S: Into<MultiSpan>>(self,
464 sp: S,
465 handler: &errors::Handler) -> DiagnosticBuilder<'_> {
466 match self {
467 Error::FileNotFoundForModule { ref mod_name,
468 ref default_path,
469 ref secondary_path,
470 ref dir_path } => {
471 let mut err = struct_span_err!(handler, sp, E0583,
472 "file not found for module `{}`", mod_name);
473 err.help(&format!("name the file either {} or {} inside the directory \"{}\"",
474 default_path,
475 secondary_path,
476 dir_path));
477 err
478 }
479 Error::DuplicatePaths { ref mod_name, ref default_path, ref secondary_path } => {
480 let mut err = struct_span_err!(handler, sp, E0584,
481 "file for module `{}` found at both {} and {}",
482 mod_name,
483 default_path,
484 secondary_path);
485 err.help("delete or rename one of them to remove the ambiguity");
486 err
487 }
488 Error::UselessDocComment => {
489 let mut err = struct_span_err!(handler, sp, E0585,
490 "found a documentation comment that doesn't document anything");
491 err.help("doc comments must come before what they document, maybe a comment was \
492 intended with `//`?");
493 err
494 }
495 Error::InclusiveRangeWithNoEnd => {
496 let mut err = struct_span_err!(handler, sp, E0586,
497 "inclusive range with no end");
498 err.help("inclusive ranges must be bounded at the end (`..=b` or `a..=b`)");
499 err
500 }
501 }
502 }
503}
504
505#[derive(Debug)]
506enum LhsExpr {
507 NotYetParsed,
508 AttributesParsed(ThinVec<Attribute>),
509 AlreadyParsed(P<Expr>),
510}
511
512impl From<Option<ThinVec<Attribute>>> for LhsExpr {
513 fn from(o: Option<ThinVec<Attribute>>) -> Self {
514 if let Some(attrs) = o {
515 LhsExpr::AttributesParsed(attrs)
516 } else {
517 LhsExpr::NotYetParsed
518 }
519 }
520}
521
522impl From<P<Expr>> for LhsExpr {
523 fn from(expr: P<Expr>) -> Self {
524 LhsExpr::AlreadyParsed(expr)
525 }
526}
527
528/// Creates a placeholder argument.
529fn dummy_arg(span: Span) -> Arg {
530 let ident = Ident::new(keywords::Invalid.name(), span);
531 let pat = P(Pat {
532 id: ast::DUMMY_NODE_ID,
533 node: PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), ident, None),
534 span,
535 });
536 let ty = Ty {
537 node: TyKind::Err,
538 span,
539 id: ast::DUMMY_NODE_ID
540 };
541 Arg { ty: P(ty), pat: pat, id: ast::DUMMY_NODE_ID }
542}
543
544#[derive(Copy, Clone, Debug)]
545enum TokenExpectType {
546 Expect,
547 NoExpect,
548}
549
550impl<'a> Parser<'a> {
551 pub fn new(sess: &'a ParseSess,
552 tokens: TokenStream,
553 directory: Option<Directory<'a>>,
554 recurse_into_file_modules: bool,
555 desugar_doc_comments: bool)
556 -> Self {
557 let mut parser = Parser {
558 sess,
559 token: token::Whitespace,
560 span: syntax_pos::DUMMY_SP,
561 prev_span: syntax_pos::DUMMY_SP,
562 meta_var_span: None,
563 prev_token_kind: PrevTokenKind::Other,
564 restrictions: Restrictions::empty(),
565 recurse_into_file_modules,
566 directory: Directory {
567 path: Cow::from(PathBuf::new()),
568 ownership: DirectoryOwnership::Owned { relative: None }
569 },
570 root_module_name: None,
571 expected_tokens: Vec::new(),
572 token_cursor: TokenCursor {
573 frame: TokenCursorFrame::new(
574 DelimSpan::dummy(),
575 token::NoDelim,
576 &tokens.into(),
577 ),
578 stack: Vec::new(),
579 },
580 desugar_doc_comments,
581 cfg_mods: true,
582 unmatched_angle_bracket_count: 0,
583 max_angle_bracket_count: 0,
584 unclosed_delims: Vec::new(),
585 };
586
587 let tok = parser.next_tok();
588 parser.token = tok.tok;
589 parser.span = tok.sp;
590
591 if let Some(directory) = directory {
592 parser.directory = directory;
593 } else if !parser.span.is_dummy() {
594 if let FileName::Real(mut path) = sess.source_map().span_to_unmapped_path(parser.span) {
595 path.pop();
596 parser.directory.path = Cow::from(path);
597 }
598 }
599
600 parser.process_potential_macro_variable();
601 parser
602 }
603
604 fn next_tok(&mut self) -> TokenAndSpan {
605 let mut next = if self.desugar_doc_comments {
606 self.token_cursor.next_desugared()
607 } else {
608 self.token_cursor.next()
609 };
610 if next.sp.is_dummy() {
611 // Tweak the location for better diagnostics, but keep syntactic context intact.
612 next.sp = self.prev_span.with_ctxt(next.sp.ctxt());
613 }
614 next
615 }
616
617 /// Converts the current token to a string using `self`'s reader.
618 pub fn this_token_to_string(&self) -> String {
619 pprust::token_to_string(&self.token)
620 }
621
622 fn token_descr(&self) -> Option<&'static str> {
623 Some(match &self.token {
624 t if t.is_special_ident() => "reserved identifier",
625 t if t.is_used_keyword() => "keyword",
626 t if t.is_unused_keyword() => "reserved keyword",
627 token::DocComment(..) => "doc comment",
628 _ => return None,
629 })
630 }
631
632 fn this_token_descr(&self) -> String {
633 if let Some(prefix) = self.token_descr() {
634 format!("{} `{}`", prefix, self.this_token_to_string())
635 } else {
636 format!("`{}`", self.this_token_to_string())
637 }
638 }
639
640 fn unexpected_last<T>(&self, t: &token::Token) -> PResult<'a, T> {
641 let token_str = pprust::token_to_string(t);
642 Err(self.span_fatal(self.prev_span, &format!("unexpected token: `{}`", token_str)))
643 }
644
645 crate fn unexpected<T>(&mut self) -> PResult<'a, T> {
646 match self.expect_one_of(&[], &[]) {
647 Err(e) => Err(e),
648 Ok(_) => unreachable!(),
649 }
650 }
651
652 /// Expects and consumes the token `t`. Signals an error if the next token is not `t`.
653 pub fn expect(&mut self, t: &token::Token) -> PResult<'a, bool /* recovered */> {
654 if self.expected_tokens.is_empty() {
655 if self.token == *t {
656 self.bump();
657 Ok(false)
658 } else {
659 let token_str = pprust::token_to_string(t);
660 let this_token_str = self.this_token_descr();
661 let mut err = self.fatal(&format!("expected `{}`, found {}",
662 token_str,
663 this_token_str));
664
665 let sp = if self.token == token::Token::Eof {
666 // EOF, don't want to point at the following char, but rather the last token
667 self.prev_span
668 } else {
669 self.sess.source_map().next_point(self.prev_span)
670 };
671 let label_exp = format!("expected `{}`", token_str);
672 match self.recover_closing_delimiter(&[t.clone()], err) {
673 Err(e) => err = e,
674 Ok(recovered) => {
675 return Ok(recovered);
676 }
677 }
678 let cm = self.sess.source_map();
679 match (cm.lookup_line(self.span.lo()), cm.lookup_line(sp.lo())) {
680 (Ok(ref a), Ok(ref b)) if a.line == b.line => {
681 // When the spans are in the same line, it means that the only content
682 // between them is whitespace, point only at the found token.
683 err.span_label(self.span, label_exp);
684 }
685 _ => {
686 err.span_label(sp, label_exp);
687 err.span_label(self.span, "unexpected token");
688 }
689 }
690 Err(err)
691 }
692 } else {
693 self.expect_one_of(slice::from_ref(t), &[])
694 }
695 }
696
697 fn recover_closing_delimiter(
698 &mut self,
699 tokens: &[token::Token],
700 mut err: DiagnosticBuilder<'a>,
701 ) -> PResult<'a, bool> {
702 let mut pos = None;
703 // we want to use the last closing delim that would apply
704 for (i, unmatched) in self.unclosed_delims.iter().enumerate().rev() {
705 if tokens.contains(&token::CloseDelim(unmatched.expected_delim))
706 && Some(self.span) > unmatched.unclosed_span
707 {
708 pos = Some(i);
709 }
710 }
711 match pos {
712 Some(pos) => {
713 // Recover and assume that the detected unclosed delimiter was meant for
714 // this location. Emit the diagnostic and act as if the delimiter was
715 // present for the parser's sake.
716
717 // Don't attempt to recover from this unclosed delimiter more than once.
718 let unmatched = self.unclosed_delims.remove(pos);
719 let delim = TokenType::Token(token::CloseDelim(unmatched.expected_delim));
720
721 // We want to suggest the inclusion of the closing delimiter where it makes
722 // the most sense, which is immediately after the last token:
723 //
724 // {foo(bar {}}
725 // - ^
726 // | |
727 // | help: `)` may belong here (FIXME: #58270)
728 // |
729 // unclosed delimiter
730 if let Some(sp) = unmatched.unclosed_span {
731 err.span_label(sp, "unclosed delimiter");
732 }
733 err.span_suggestion_short(
734 self.sess.source_map().next_point(self.prev_span),
735 &format!("{} may belong here", delim.to_string()),
736 delim.to_string(),
737 Applicability::MaybeIncorrect,
738 );
739 err.emit();
740 self.expected_tokens.clear(); // reduce errors
741 Ok(true)
742 }
743 _ => Err(err),
744 }
745 }
746
747 /// Expect next token to be edible or inedible token. If edible,
748 /// then consume it; if inedible, then return without consuming
749 /// anything. Signal a fatal error if next token is unexpected.
750 pub fn expect_one_of(
751 &mut self,
752 edible: &[token::Token],
753 inedible: &[token::Token],
754 ) -> PResult<'a, bool /* recovered */> {
755 fn tokens_to_string(tokens: &[TokenType]) -> String {
756 let mut i = tokens.iter();
757 // This might be a sign we need a connect method on Iterator.
758 let b = i.next()
759 .map_or(String::new(), |t| t.to_string());
760 i.enumerate().fold(b, |mut b, (i, a)| {
761 if tokens.len() > 2 && i == tokens.len() - 2 {
762 b.push_str(", or ");
763 } else if tokens.len() == 2 && i == tokens.len() - 2 {
764 b.push_str(" or ");
765 } else {
766 b.push_str(", ");
767 }
768 b.push_str(&a.to_string());
769 b
770 })
771 }
772 if edible.contains(&self.token) {
773 self.bump();
774 Ok(false)
775 } else if inedible.contains(&self.token) {
776 // leave it in the input
777 Ok(false)
778 } else {
779 let mut expected = edible.iter()
780 .map(|x| TokenType::Token(x.clone()))
781 .chain(inedible.iter().map(|x| TokenType::Token(x.clone())))
782 .chain(self.expected_tokens.iter().cloned())
783 .collect::<Vec<_>>();
784 expected.sort_by_cached_key(|x| x.to_string());
785 expected.dedup();
786 let expect = tokens_to_string(&expected[..]);
787 let actual = self.this_token_to_string();
788 let (msg_exp, (label_sp, label_exp)) = if expected.len() > 1 {
789 let short_expect = if expected.len() > 6 {
790 format!("{} possible tokens", expected.len())
791 } else {
792 expect.clone()
793 };
794 (format!("expected one of {}, found `{}`", expect, actual),
795 (self.sess.source_map().next_point(self.prev_span),
796 format!("expected one of {} here", short_expect)))
797 } else if expected.is_empty() {
798 (format!("unexpected token: `{}`", actual),
799 (self.prev_span, "unexpected token after this".to_string()))
800 } else {
801 (format!("expected {}, found `{}`", expect, actual),
802 (self.sess.source_map().next_point(self.prev_span),
803 format!("expected {} here", expect)))
804 };
805 let mut err = self.fatal(&msg_exp);
806 if self.token.is_ident_named("and") {
807 err.span_suggestion_short(
808 self.span,
809 "use `&&` instead of `and` for the boolean operator",
810 "&&".to_string(),
811 Applicability::MaybeIncorrect,
812 );
813 }
814 if self.token.is_ident_named("or") {
815 err.span_suggestion_short(
816 self.span,
817 "use `||` instead of `or` for the boolean operator",
818 "||".to_string(),
819 Applicability::MaybeIncorrect,
820 );
821 }
822 let sp = if self.token == token::Token::Eof {
823 // This is EOF, don't want to point at the following char, but rather the last token
824 self.prev_span
825 } else {
826 label_sp
827 };
828 match self.recover_closing_delimiter(&expected.iter().filter_map(|tt| match tt {
829 TokenType::Token(t) => Some(t.clone()),
830 _ => None,
831 }).collect::<Vec<_>>(), err) {
832 Err(e) => err = e,
833 Ok(recovered) => {
834 return Ok(recovered);
835 }
836 }
837
838 let cm = self.sess.source_map();
839 match (cm.lookup_line(self.span.lo()), cm.lookup_line(sp.lo())) {
840 (Ok(ref a), Ok(ref b)) if a.line == b.line => {
841 // When the spans are in the same line, it means that the only content between
842 // them is whitespace, point at the found token in that case:
843 //
844 // X | () => { syntax error };
845 // | ^^^^^ expected one of 8 possible tokens here
846 //
847 // instead of having:
848 //
849 // X | () => { syntax error };
850 // | -^^^^^ unexpected token
851 // | |
852 // | expected one of 8 possible tokens here
853 err.span_label(self.span, label_exp);
854 }
855 _ if self.prev_span == syntax_pos::DUMMY_SP => {
856 // Account for macro context where the previous span might not be
857 // available to avoid incorrect output (#54841).
858 err.span_label(self.span, "unexpected token");
859 }
860 _ => {
861 err.span_label(sp, label_exp);
862 err.span_label(self.span, "unexpected token");
863 }
864 }
865 Err(err)
866 }
867 }
868
869 /// Returns the span of expr, if it was not interpolated or the span of the interpolated token.
870 fn interpolated_or_expr_span(&self,
871 expr: PResult<'a, P<Expr>>)
872 -> PResult<'a, (Span, P<Expr>)> {
873 expr.map(|e| {
874 if self.prev_token_kind == PrevTokenKind::Interpolated {
875 (self.prev_span, e)
876 } else {
877 (e.span, e)
878 }
879 })
880 }
881
882 fn expected_ident_found(&self) -> DiagnosticBuilder<'a> {
883 let mut err = self.struct_span_err(self.span,
884 &format!("expected identifier, found {}",
885 self.this_token_descr()));
886 if let token::Ident(ident, false) = &self.token {
887 if ident.is_reserved() && !ident.is_path_segment_keyword() &&
888 ident.name != keywords::Underscore.name()
889 {
890 err.span_suggestion(
891 self.span,
892 "you can escape reserved keywords to use them as identifiers",
893 format!("r#{}", ident),
894 Applicability::MaybeIncorrect,
895 );
896 }
897 }
898 if let Some(token_descr) = self.token_descr() {
899 err.span_label(self.span, format!("expected identifier, found {}", token_descr));
900 } else {
901 err.span_label(self.span, "expected identifier");
902 if self.token == token::Comma && self.look_ahead(1, |t| t.is_ident()) {
903 err.span_suggestion(
904 self.span,
905 "remove this comma",
906 String::new(),
907 Applicability::MachineApplicable,
908 );
909 }
910 }
911 err
912 }
913
914 pub fn parse_ident(&mut self) -> PResult<'a, ast::Ident> {
915 self.parse_ident_common(true)
916 }
917
918 fn parse_ident_common(&mut self, recover: bool) -> PResult<'a, ast::Ident> {
919 match self.token {
920 token::Ident(ident, _) => {
921 if self.token.is_reserved_ident() {
922 let mut err = self.expected_ident_found();
923 if recover {
924 err.emit();
925 } else {
926 return Err(err);
927 }
928 }
929 let span = self.span;
930 self.bump();
931 Ok(Ident::new(ident.name, span))
932 }
933 _ => {
934 Err(if self.prev_token_kind == PrevTokenKind::DocComment {
935 self.span_fatal_err(self.prev_span, Error::UselessDocComment)
936 } else {
937 self.expected_ident_found()
938 })
939 }
940 }
941 }
942
943 /// Checks if the next token is `tok`, and returns `true` if so.
944 ///
945 /// This method will automatically add `tok` to `expected_tokens` if `tok` is not
946 /// encountered.
947 crate fn check(&mut self, tok: &token::Token) -> bool {
948 let is_present = self.token == *tok;
949 if !is_present { self.expected_tokens.push(TokenType::Token(tok.clone())); }
950 is_present
951 }
952
953 /// Consumes a token 'tok' if it exists. Returns whether the given token was present.
954 pub fn eat(&mut self, tok: &token::Token) -> bool {
955 let is_present = self.check(tok);
956 if is_present { self.bump() }
957 is_present
958 }
959
960 fn check_keyword(&mut self, kw: keywords::Keyword) -> bool {
961 self.expected_tokens.push(TokenType::Keyword(kw));
962 self.token.is_keyword(kw)
963 }
964
965 /// If the next token is the given keyword, eats it and returns
966 /// `true`. Otherwise, returns `false`.
967 pub fn eat_keyword(&mut self, kw: keywords::Keyword) -> bool {
968 if self.check_keyword(kw) {
969 self.bump();
970 true
971 } else {
972 false
973 }
974 }
975
976 fn eat_keyword_noexpect(&mut self, kw: keywords::Keyword) -> bool {
977 if self.token.is_keyword(kw) {
978 self.bump();
979 true
980 } else {
981 false
982 }
983 }
984
985 /// If the given word is not a keyword, signals an error.
986 /// If the next token is not the given word, signals an error.
987 /// Otherwise, eats it.
988 fn expect_keyword(&mut self, kw: keywords::Keyword) -> PResult<'a, ()> {
989 if !self.eat_keyword(kw) {
990 self.unexpected()
991 } else {
992 Ok(())
993 }
994 }
995
996 fn check_ident(&mut self) -> bool {
997 if self.token.is_ident() {
998 true
999 } else {
1000 self.expected_tokens.push(TokenType::Ident);
1001 false
1002 }
1003 }
1004
1005 fn check_path(&mut self) -> bool {
1006 if self.token.is_path_start() {
1007 true
1008 } else {
1009 self.expected_tokens.push(TokenType::Path);
1010 false
1011 }
1012 }
1013
1014 fn check_type(&mut self) -> bool {
1015 if self.token.can_begin_type() {
1016 true
1017 } else {
1018 self.expected_tokens.push(TokenType::Type);
1019 false
1020 }
1021 }
1022
1023 fn check_const_arg(&mut self) -> bool {
1024 if self.token.can_begin_const_arg() {
1025 true
1026 } else {
1027 self.expected_tokens.push(TokenType::Const);
1028 false
1029 }
1030 }
1031
1032 /// Expects and consumes a `+`. if `+=` is seen, replaces it with a `=`
1033 /// and continues. If a `+` is not seen, returns `false`.
1034 ///
1035 /// This is used when token-splitting `+=` into `+`.
1036 /// See issue #47856 for an example of when this may occur.
1037 fn eat_plus(&mut self) -> bool {
1038 self.expected_tokens.push(TokenType::Token(token::BinOp(token::Plus)));
1039 match self.token {
1040 token::BinOp(token::Plus) => {
1041 self.bump();
1042 true
1043 }
1044 token::BinOpEq(token::Plus) => {
1045 let span = self.span.with_lo(self.span.lo() + BytePos(1));
1046 self.bump_with(token::Eq, span);
1047 true
1048 }
1049 _ => false,
1050 }
1051 }
1052
1053
1054 /// Checks to see if the next token is either `+` or `+=`.
1055 /// Otherwise returns `false`.
1056 fn check_plus(&mut self) -> bool {
1057 if self.token.is_like_plus() {
1058 true
1059 }
1060 else {
1061 self.expected_tokens.push(TokenType::Token(token::BinOp(token::Plus)));
1062 false
1063 }
1064 }
1065
1066 /// Expects and consumes an `&`. If `&&` is seen, replaces it with a single
1067 /// `&` and continues. If an `&` is not seen, signals an error.
1068 fn expect_and(&mut self) -> PResult<'a, ()> {
1069 self.expected_tokens.push(TokenType::Token(token::BinOp(token::And)));
1070 match self.token {
1071 token::BinOp(token::And) => {
1072 self.bump();
1073 Ok(())
1074 }
1075 token::AndAnd => {
1076 let span = self.span.with_lo(self.span.lo() + BytePos(1));
1077 Ok(self.bump_with(token::BinOp(token::And), span))
1078 }
1079 _ => self.unexpected()
1080 }
1081 }
1082
1083 /// Expects and consumes an `|`. If `||` is seen, replaces it with a single
1084 /// `|` and continues. If an `|` is not seen, signals an error.
1085 fn expect_or(&mut self) -> PResult<'a, ()> {
1086 self.expected_tokens.push(TokenType::Token(token::BinOp(token::Or)));
1087 match self.token {
1088 token::BinOp(token::Or) => {
1089 self.bump();
1090 Ok(())
1091 }
1092 token::OrOr => {
1093 let span = self.span.with_lo(self.span.lo() + BytePos(1));
1094 Ok(self.bump_with(token::BinOp(token::Or), span))
1095 }
1096 _ => self.unexpected()
1097 }
1098 }
1099
1100 fn expect_no_suffix(&self, sp: Span, kind: &str, suffix: Option<ast::Name>) {
1101 match suffix {
1102 None => {/* everything ok */}
1103 Some(suf) => {
1104 let text = suf.as_str();
1105 if text.is_empty() {
1106 self.span_bug(sp, "found empty literal suffix in Some")
1107 }
1108 let msg = format!("{} with a suffix is invalid", kind);
1109 self.struct_span_err(sp, &msg)
1110 .span_label(sp, msg)
1111 .emit();
1112 }
1113 }
1114 }
1115
1116 /// Attempts to consume a `<`. If `<<` is seen, replaces it with a single
1117 /// `<` and continue. If `<-` is seen, replaces it with a single `<`
1118 /// and continue. If a `<` is not seen, returns false.
1119 ///
1120 /// This is meant to be used when parsing generics on a path to get the
1121 /// starting token.
1122 fn eat_lt(&mut self) -> bool {
1123 self.expected_tokens.push(TokenType::Token(token::Lt));
1124 let ate = match self.token {
1125 token::Lt => {
1126 self.bump();
1127 true
1128 }
1129 token::BinOp(token::Shl) => {
1130 let span = self.span.with_lo(self.span.lo() + BytePos(1));
1131 self.bump_with(token::Lt, span);
1132 true
1133 }
1134 token::LArrow => {
1135 let span = self.span.with_lo(self.span.lo() + BytePos(1));
1136 self.bump_with(token::BinOp(token::Minus), span);
1137 true
1138 }
1139 _ => false,
1140 };
1141
1142 if ate {
1143 // See doc comment for `unmatched_angle_bracket_count`.
1144 self.unmatched_angle_bracket_count += 1;
1145 self.max_angle_bracket_count += 1;
1146 debug!("eat_lt: (increment) count={:?}", self.unmatched_angle_bracket_count);
1147 }
1148
1149 ate
1150 }
1151
1152 fn expect_lt(&mut self) -> PResult<'a, ()> {
1153 if !self.eat_lt() {
1154 self.unexpected()
1155 } else {
1156 Ok(())
1157 }
1158 }
1159
1160 /// Expects and consumes a single `>` token. if a `>>` is seen, replaces it
1161 /// with a single `>` and continues. If a `>` is not seen, signals an error.
1162 fn expect_gt(&mut self) -> PResult<'a, ()> {
1163 self.expected_tokens.push(TokenType::Token(token::Gt));
1164 let ate = match self.token {
1165 token::Gt => {
1166 self.bump();
1167 Some(())
1168 }
1169 token::BinOp(token::Shr) => {
1170 let span = self.span.with_lo(self.span.lo() + BytePos(1));
1171 Some(self.bump_with(token::Gt, span))
1172 }
1173 token::BinOpEq(token::Shr) => {
1174 let span = self.span.with_lo(self.span.lo() + BytePos(1));
1175 Some(self.bump_with(token::Ge, span))
1176 }
1177 token::Ge => {
1178 let span = self.span.with_lo(self.span.lo() + BytePos(1));
1179 Some(self.bump_with(token::Eq, span))
1180 }
1181 _ => None,
1182 };
1183
1184 match ate {
1185 Some(_) => {
1186 // See doc comment for `unmatched_angle_bracket_count`.
1187 if self.unmatched_angle_bracket_count > 0 {
1188 self.unmatched_angle_bracket_count -= 1;
1189 debug!("expect_gt: (decrement) count={:?}", self.unmatched_angle_bracket_count);
1190 }
1191
1192 Ok(())
1193 },
1194 None => self.unexpected(),
1195 }
1196 }
1197
1198 /// Eats and discards tokens until one of `kets` is encountered. Respects token trees,
1199 /// passes through any errors encountered. Used for error recovery.
1200 fn eat_to_tokens(&mut self, kets: &[&token::Token]) {
1201 let handler = self.diagnostic();
1202
1203 if let Err(ref mut err) = self.parse_seq_to_before_tokens(kets,
1204 SeqSep::none(),
1205 TokenExpectType::Expect,
1206 |p| Ok(p.parse_token_tree())) {
1207 handler.cancel(err);
1208 }
1209 }
1210
1211 /// Parses a sequence, including the closing delimiter. The function
1212 /// `f` must consume tokens until reaching the next separator or
1213 /// closing bracket.
1214 pub fn parse_seq_to_end<T, F>(&mut self,
1215 ket: &token::Token,
1216 sep: SeqSep,
1217 f: F)
1218 -> PResult<'a, Vec<T>> where
1219 F: FnMut(&mut Parser<'a>) -> PResult<'a, T>,
1220 {
1221 let (val, recovered) = self.parse_seq_to_before_end(ket, sep, f)?;
1222 if !recovered {
1223 self.bump();
1224 }
1225 Ok(val)
1226 }
1227
1228 /// Parses a sequence, not including the closing delimiter. The function
1229 /// `f` must consume tokens until reaching the next separator or
1230 /// closing bracket.
1231 pub fn parse_seq_to_before_end<T, F>(
1232 &mut self,
1233 ket: &token::Token,
1234 sep: SeqSep,
1235 f: F,
1236 ) -> PResult<'a, (Vec<T>, bool)>
1237 where F: FnMut(&mut Parser<'a>) -> PResult<'a, T>
1238 {
1239 self.parse_seq_to_before_tokens(&[ket], sep, TokenExpectType::Expect, f)
1240 }
1241
1242 fn parse_seq_to_before_tokens<T, F>(
1243 &mut self,
1244 kets: &[&token::Token],
1245 sep: SeqSep,
1246 expect: TokenExpectType,
1247 mut f: F,
1248 ) -> PResult<'a, (Vec<T>, bool /* recovered */)>
1249 where F: FnMut(&mut Parser<'a>) -> PResult<'a, T>
1250 {
1251 let mut first = true;
1252 let mut recovered = false;
1253 let mut v = vec![];
1254 while !kets.iter().any(|k| {
1255 match expect {
1256 TokenExpectType::Expect => self.check(k),
1257 TokenExpectType::NoExpect => self.token == **k,
1258 }
1259 }) {
1260 match self.token {
1261 token::CloseDelim(..) | token::Eof => break,
1262 _ => {}
1263 };
1264 if let Some(ref t) = sep.sep {
1265 if first {
1266 first = false;
1267 } else {
1268 match self.expect(t) {
1269 Ok(false) => {}
1270 Ok(true) => {
1271 recovered = true;
1272 break;
1273 }
1274 Err(mut e) => {
1275 // Attempt to keep parsing if it was a similar separator
1276 if let Some(ref tokens) = t.similar_tokens() {
1277 if tokens.contains(&self.token) {
1278 self.bump();
1279 }
1280 }
1281 e.emit();
1282 // Attempt to keep parsing if it was an omitted separator
1283 match f(self) {
1284 Ok(t) => {
1285 v.push(t);
1286 continue;
1287 },
1288 Err(mut e) => {
1289 e.cancel();
1290 break;
1291 }
1292 }
1293 }
1294 }
1295 }
1296 }
1297 if sep.trailing_sep_allowed && kets.iter().any(|k| {
1298 match expect {
1299 TokenExpectType::Expect => self.check(k),
1300 TokenExpectType::NoExpect => self.token == **k,
1301 }
1302 }) {
1303 break;
1304 }
1305
1306 let t = f(self)?;
1307 v.push(t);
1308 }
1309
1310 Ok((v, recovered))
1311 }
1312
1313 /// Parses a sequence, including the closing delimiter. The function
1314 /// `f` must consume tokens until reaching the next separator or
1315 /// closing bracket.
1316 fn parse_unspanned_seq<T, F>(
1317 &mut self,
1318 bra: &token::Token,
1319 ket: &token::Token,
1320 sep: SeqSep,
1321 f: F,
1322 ) -> PResult<'a, Vec<T>> where
1323 F: FnMut(&mut Parser<'a>) -> PResult<'a, T>,
1324 {
1325 self.expect(bra)?;
1326 let (result, recovered) = self.parse_seq_to_before_end(ket, sep, f)?;
1327 if !recovered {
1328 self.eat(ket);
1329 }
1330 Ok(result)
1331 }
1332
1333 /// Advance the parser by one token
1334 pub fn bump(&mut self) {
1335 if self.prev_token_kind == PrevTokenKind::Eof {
1336 // Bumping after EOF is a bad sign, usually an infinite loop.
1337 self.bug("attempted to bump the parser past EOF (may be stuck in a loop)");
1338 }
1339
1340 self.prev_span = self.meta_var_span.take().unwrap_or(self.span);
1341
1342 // Record last token kind for possible error recovery.
1343 self.prev_token_kind = match self.token {
1344 token::DocComment(..) => PrevTokenKind::DocComment,
1345 token::Comma => PrevTokenKind::Comma,
1346 token::BinOp(token::Plus) => PrevTokenKind::Plus,
1347 token::Interpolated(..) => PrevTokenKind::Interpolated,
1348 token::Eof => PrevTokenKind::Eof,
1349 token::Ident(..) => PrevTokenKind::Ident,
1350 _ => PrevTokenKind::Other,
1351 };
1352
1353 let next = self.next_tok();
1354 self.span = next.sp;
1355 self.token = next.tok;
1356 self.expected_tokens.clear();
1357 // check after each token
1358 self.process_potential_macro_variable();
1359 }
1360
1361 /// Advance the parser using provided token as a next one. Use this when
1362 /// consuming a part of a token. For example a single `<` from `<<`.
1363 fn bump_with(&mut self, next: token::Token, span: Span) {
1364 self.prev_span = self.span.with_hi(span.lo());
1365 // It would be incorrect to record the kind of the current token, but
1366 // fortunately for tokens currently using `bump_with`, the
1367 // prev_token_kind will be of no use anyway.
1368 self.prev_token_kind = PrevTokenKind::Other;
1369 self.span = span;
1370 self.token = next;
1371 self.expected_tokens.clear();
1372 }
1373
1374 pub fn look_ahead<R, F>(&self, dist: usize, f: F) -> R where
1375 F: FnOnce(&token::Token) -> R,
1376 {
1377 if dist == 0 {
1378 return f(&self.token)
1379 }
1380
1381 f(&match self.token_cursor.frame.tree_cursor.look_ahead(dist - 1) {
1382 Some(tree) => match tree {
1383 TokenTree::Token(_, tok) => tok,
1384 TokenTree::Delimited(_, delim, _) => token::OpenDelim(delim),
1385 },
1386 None => token::CloseDelim(self.token_cursor.frame.delim),
1387 })
1388 }
1389
1390 fn look_ahead_span(&self, dist: usize) -> Span {
1391 if dist == 0 {
1392 return self.span
1393 }
1394
1395 match self.token_cursor.frame.tree_cursor.look_ahead(dist - 1) {
1396 Some(TokenTree::Token(span, _)) => span,
1397 Some(TokenTree::Delimited(span, ..)) => span.entire(),
1398 None => self.look_ahead_span(dist - 1),
1399 }
1400 }
1401 pub fn fatal(&self, m: &str) -> DiagnosticBuilder<'a> {
1402 self.sess.span_diagnostic.struct_span_fatal(self.span, m)
1403 }
1404 pub fn span_fatal<S: Into<MultiSpan>>(&self, sp: S, m: &str) -> DiagnosticBuilder<'a> {
1405 self.sess.span_diagnostic.struct_span_fatal(sp, m)
1406 }
1407 fn span_fatal_err<S: Into<MultiSpan>>(&self, sp: S, err: Error) -> DiagnosticBuilder<'a> {
1408 err.span_err(sp, self.diagnostic())
1409 }
1410 fn bug(&self, m: &str) -> ! {
1411 self.sess.span_diagnostic.span_bug(self.span, m)
1412 }
1413 fn span_err<S: Into<MultiSpan>>(&self, sp: S, m: &str) {
1414 self.sess.span_diagnostic.span_err(sp, m)
1415 }
1416 fn struct_span_err<S: Into<MultiSpan>>(&self, sp: S, m: &str) -> DiagnosticBuilder<'a> {
1417 self.sess.span_diagnostic.struct_span_err(sp, m)
1418 }
1419 crate fn span_bug<S: Into<MultiSpan>>(&self, sp: S, m: &str) -> ! {
1420 self.sess.span_diagnostic.span_bug(sp, m)
1421 }
1422
1423 fn cancel(&self, err: &mut DiagnosticBuilder<'_>) {
1424 self.sess.span_diagnostic.cancel(err)
1425 }
1426
1427 crate fn diagnostic(&self) -> &'a errors::Handler {
1428 &self.sess.span_diagnostic
1429 }
1430
1431 /// Is the current token one of the keywords that signals a bare function type?
1432 fn token_is_bare_fn_keyword(&mut self) -> bool {
1433 self.check_keyword(keywords::Fn) ||
1434 self.check_keyword(keywords::Unsafe) ||
1435 self.check_keyword(keywords::Extern)
1436 }
1437
1438 /// Parses a `TyKind::BareFn` type.
1439 fn parse_ty_bare_fn(&mut self, generic_params: Vec<GenericParam>) -> PResult<'a, TyKind> {
1440 /*
1441
1442 [unsafe] [extern "ABI"] fn (S) -> T
1443 ^~~~^ ^~~~^ ^~^ ^
1444 | | | |
1445 | | | Return type
1446 | | Argument types
1447 | |
1448 | ABI
1449 Function Style
1450 */
1451
1452 let unsafety = self.parse_unsafety();
1453 let abi = if self.eat_keyword(keywords::Extern) {
1454 self.parse_opt_abi()?.unwrap_or(Abi::C)
1455 } else {
1456 Abi::Rust
1457 };
1458
1459 self.expect_keyword(keywords::Fn)?;
1460 let (inputs, variadic) = self.parse_fn_args(false, true)?;
1461 let ret_ty = self.parse_ret_ty(false)?;
1462 let decl = P(FnDecl {
1463 inputs,
1464 output: ret_ty,
1465 variadic,
1466 });
1467 Ok(TyKind::BareFn(P(BareFnTy {
1468 abi,
1469 unsafety,
1470 generic_params,
1471 decl,
1472 })))
1473 }
1474
1475 /// Parses asyncness: `async` or nothing.
1476 fn parse_asyncness(&mut self) -> IsAsync {
1477 if self.eat_keyword(keywords::Async) {
1478 IsAsync::Async {
1479 closure_id: ast::DUMMY_NODE_ID,
1480 return_impl_trait_id: ast::DUMMY_NODE_ID,
1481 }
1482 } else {
1483 IsAsync::NotAsync
1484 }
1485 }
1486
1487 /// Parses unsafety: `unsafe` or nothing.
1488 fn parse_unsafety(&mut self) -> Unsafety {
1489 if self.eat_keyword(keywords::Unsafe) {
1490 Unsafety::Unsafe
1491 } else {
1492 Unsafety::Normal
1493 }
1494 }
1495
1496 /// Parses the items in a trait declaration.
1497 pub fn parse_trait_item(&mut self, at_end: &mut bool) -> PResult<'a, TraitItem> {
1498 maybe_whole!(self, NtTraitItem, |x| x);
1499 let attrs = self.parse_outer_attributes()?;
1500 let (mut item, tokens) = self.collect_tokens(|this| {
1501 this.parse_trait_item_(at_end, attrs)
1502 })?;
1503 // See `parse_item` for why this clause is here.
1504 if !item.attrs.iter().any(|attr| attr.style == AttrStyle::Inner) {
1505 item.tokens = Some(tokens);
1506 }
1507 Ok(item)
1508 }
1509
1510 fn parse_trait_item_(&mut self,
1511 at_end: &mut bool,
1512 mut attrs: Vec<Attribute>) -> PResult<'a, TraitItem> {
1513 let lo = self.span;
1514
1515 let (name, node, generics) = if self.eat_keyword(keywords::Type) {
1516 self.parse_trait_item_assoc_ty()?
1517 } else if self.is_const_item() {
1518 self.expect_keyword(keywords::Const)?;
1519 let ident = self.parse_ident()?;
1520 self.expect(&token::Colon)?;
1521 let ty = self.parse_ty()?;
1522 let default = if self.eat(&token::Eq) {
1523 let expr = self.parse_expr()?;
1524 self.expect(&token::Semi)?;
1525 Some(expr)
1526 } else {
1527 self.expect(&token::Semi)?;
1528 None
1529 };
1530 (ident, TraitItemKind::Const(ty, default), ast::Generics::default())
1531 } else if let Some(mac) = self.parse_assoc_macro_invoc("trait", None, &mut false)? {
1532 // trait item macro.
1533 (keywords::Invalid.ident(), ast::TraitItemKind::Macro(mac), ast::Generics::default())
1534 } else {
1535 let (constness, unsafety, asyncness, abi) = self.parse_fn_front_matter()?;
1536
1537 let ident = self.parse_ident()?;
1538 let mut generics = self.parse_generics()?;
1539
1540 let d = self.parse_fn_decl_with_self(|p: &mut Parser<'a>| {
1541 // This is somewhat dubious; We don't want to allow
1542 // argument names to be left off if there is a
1543 // definition...
1544
1545 // We don't allow argument names to be left off in edition 2018.
1546 p.parse_arg_general(p.span.rust_2018(), true)
1547 })?;
1548 generics.where_clause = self.parse_where_clause()?;
1549
1550 let sig = ast::MethodSig {
1551 header: FnHeader {
1552 unsafety,
1553 constness,
1554 abi,
1555 asyncness,
1556 },
1557 decl: d,
1558 };
1559
1560 let body = match self.token {
1561 token::Semi => {
1562 self.bump();
1563 *at_end = true;
1564 debug!("parse_trait_methods(): parsing required method");
1565 None
1566 }
1567 token::OpenDelim(token::Brace) => {
1568 debug!("parse_trait_methods(): parsing provided method");
1569 *at_end = true;
1570 let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
1571 attrs.extend(inner_attrs.iter().cloned());
1572 Some(body)
1573 }
1574 token::Interpolated(ref nt) => {
1575 match **nt {
1576 token::NtBlock(..) => {
1577 *at_end = true;
1578 let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
1579 attrs.extend(inner_attrs.iter().cloned());
1580 Some(body)
1581 }
1582 _ => {
1583 let token_str = self.this_token_descr();
1584 let mut err = self.fatal(&format!("expected `;` or `{{`, found {}",
1585 token_str));
1586 err.span_label(self.span, "expected `;` or `{`");
1587 return Err(err);
1588 }
1589 }
1590 }
1591 _ => {
1592 let token_str = self.this_token_descr();
1593 let mut err = self.fatal(&format!("expected `;` or `{{`, found {}",
1594 token_str));
1595 err.span_label(self.span, "expected `;` or `{`");
1596 return Err(err);
1597 }
1598 };
1599 (ident, ast::TraitItemKind::Method(sig, body), generics)
1600 };
1601
1602 Ok(TraitItem {
1603 id: ast::DUMMY_NODE_ID,
1604 ident: name,
1605 attrs,
1606 generics,
1607 node,
1608 span: lo.to(self.prev_span),
1609 tokens: None,
1610 })
1611 }
1612
1613 /// Parses an optional return type `[ -> TY ]` in a function declaration.
1614 fn parse_ret_ty(&mut self, allow_plus: bool) -> PResult<'a, FunctionRetTy> {
1615 if self.eat(&token::RArrow) {
1616 Ok(FunctionRetTy::Ty(self.parse_ty_common(allow_plus, true)?))
1617 } else {
1618 Ok(FunctionRetTy::Default(self.span.shrink_to_lo()))
1619 }
1620 }
1621
1622 /// Parses a type.
1623 pub fn parse_ty(&mut self) -> PResult<'a, P<Ty>> {
1624 self.parse_ty_common(true, true)
1625 }
1626
1627 /// Parses a type in restricted contexts where `+` is not permitted.
1628 ///
1629 /// Example 1: `&'a TYPE`
1630 /// `+` is prohibited to maintain operator priority (P(+) < P(&)).
1631 /// Example 2: `value1 as TYPE + value2`
1632 /// `+` is prohibited to avoid interactions with expression grammar.
1633 fn parse_ty_no_plus(&mut self) -> PResult<'a, P<Ty>> {
1634 self.parse_ty_common(false, true)
1635 }
1636
1637 fn parse_ty_common(&mut self, allow_plus: bool, allow_qpath_recovery: bool)
1638 -> PResult<'a, P<Ty>> {
1639 maybe_whole!(self, NtTy, |x| x);
1640
1641 let lo = self.span;
1642 let mut impl_dyn_multi = false;
1643 let node = if self.eat(&token::OpenDelim(token::Paren)) {
1644 // `(TYPE)` is a parenthesized type.
1645 // `(TYPE,)` is a tuple with a single field of type TYPE.
1646 let mut ts = vec![];
1647 let mut last_comma = false;
1648 while self.token != token::CloseDelim(token::Paren) {
1649 ts.push(self.parse_ty()?);
1650 if self.eat(&token::Comma) {
1651 last_comma = true;
1652 } else {
1653 last_comma = false;
1654 break;
1655 }
1656 }
1657 let trailing_plus = self.prev_token_kind == PrevTokenKind::Plus;
1658 self.expect(&token::CloseDelim(token::Paren))?;
1659
1660 if ts.len() == 1 && !last_comma {
1661 let ty = ts.into_iter().nth(0).unwrap().into_inner();
1662 let maybe_bounds = allow_plus && self.token.is_like_plus();
1663 match ty.node {
1664 // `(TY_BOUND_NOPAREN) + BOUND + ...`.
1665 TyKind::Path(None, ref path) if maybe_bounds => {
1666 self.parse_remaining_bounds(Vec::new(), path.clone(), lo, true)?
1667 }
1668 TyKind::TraitObject(ref bounds, TraitObjectSyntax::None)
1669 if maybe_bounds && bounds.len() == 1 && !trailing_plus => {
1670 let path = match bounds[0] {
1671 GenericBound::Trait(ref pt, ..) => pt.trait_ref.path.clone(),
1672 GenericBound::Outlives(..) => self.bug("unexpected lifetime bound"),
1673 };
1674 self.parse_remaining_bounds(Vec::new(), path, lo, true)?
1675 }
1676 // `(TYPE)`
1677 _ => TyKind::Paren(P(ty))
1678 }
1679 } else {
1680 TyKind::Tup(ts)
1681 }
1682 } else if self.eat(&token::Not) {
1683 // Never type `!`
1684 TyKind::Never
1685 } else if self.eat(&token::BinOp(token::Star)) {
1686 // Raw pointer
1687 TyKind::Ptr(self.parse_ptr()?)
1688 } else if self.eat(&token::OpenDelim(token::Bracket)) {
1689 // Array or slice
1690 let t = self.parse_ty()?;
1691 // Parse optional `; EXPR` in `[TYPE; EXPR]`
1692 let t = match self.maybe_parse_fixed_length_of_vec()? {
1693 None => TyKind::Slice(t),
1694 Some(length) => TyKind::Array(t, AnonConst {
1695 id: ast::DUMMY_NODE_ID,
1696 value: length,
1697 }),
1698 };
1699 self.expect(&token::CloseDelim(token::Bracket))?;
1700 t
1701 } else if self.check(&token::BinOp(token::And)) || self.check(&token::AndAnd) {
1702 // Reference
1703 self.expect_and()?;
1704 self.parse_borrowed_pointee()?
1705 } else if self.eat_keyword_noexpect(keywords::Typeof) {
1706 // `typeof(EXPR)`
1707 // In order to not be ambiguous, the type must be surrounded by parens.
1708 self.expect(&token::OpenDelim(token::Paren))?;
1709 let e = AnonConst {
1710 id: ast::DUMMY_NODE_ID,
1711 value: self.parse_expr()?,
1712 };
1713 self.expect(&token::CloseDelim(token::Paren))?;
1714 TyKind::Typeof(e)
1715 } else if self.eat_keyword(keywords::Underscore) {
1716 // A type to be inferred `_`
1717 TyKind::Infer
1718 } else if self.token_is_bare_fn_keyword() {
1719 // Function pointer type
1720 self.parse_ty_bare_fn(Vec::new())?
1721 } else if self.check_keyword(keywords::For) {
1722 // Function pointer type or bound list (trait object type) starting with a poly-trait.
1723 // `for<'lt> [unsafe] [extern "ABI"] fn (&'lt S) -> T`
1724 // `for<'lt> Trait1<'lt> + Trait2 + 'a`
1725 let lo = self.span;
1726 let lifetime_defs = self.parse_late_bound_lifetime_defs()?;
1727 if self.token_is_bare_fn_keyword() {
1728 self.parse_ty_bare_fn(lifetime_defs)?
1729 } else {
1730 let path = self.parse_path(PathStyle::Type)?;
1731 let parse_plus = allow_plus && self.check_plus();
1732 self.parse_remaining_bounds(lifetime_defs, path, lo, parse_plus)?
1733 }
1734 } else if self.eat_keyword(keywords::Impl) {
1735 // Always parse bounds greedily for better error recovery.
1736 let bounds = self.parse_generic_bounds(None)?;
1737 impl_dyn_multi = bounds.len() > 1 || self.prev_token_kind == PrevTokenKind::Plus;
1738 TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds)
1739 } else if self.check_keyword(keywords::Dyn) &&
1740 (self.span.rust_2018() ||
1741 self.look_ahead(1, |t| t.can_begin_bound() &&
1742 !can_continue_type_after_non_fn_ident(t))) {
1743 self.bump(); // `dyn`
1744 // Always parse bounds greedily for better error recovery.
1745 let bounds = self.parse_generic_bounds(None)?;
1746 impl_dyn_multi = bounds.len() > 1 || self.prev_token_kind == PrevTokenKind::Plus;
1747 TyKind::TraitObject(bounds, TraitObjectSyntax::Dyn)
1748 } else if self.check(&token::Question) ||
1749 self.check_lifetime() && self.look_ahead(1, |t| t.is_like_plus()) {
1750 // Bound list (trait object type)
1751 TyKind::TraitObject(self.parse_generic_bounds_common(allow_plus, None)?,
1752 TraitObjectSyntax::None)
1753 } else if self.eat_lt() {
1754 // Qualified path
1755 let (qself, path) = self.parse_qpath(PathStyle::Type)?;
1756 TyKind::Path(Some(qself), path)
1757 } else if self.token.is_path_start() {
1758 // Simple path
1759 let path = self.parse_path(PathStyle::Type)?;
1760 if self.eat(&token::Not) {
1761 // Macro invocation in type position
1762 let (delim, tts) = self.expect_delimited_token_tree()?;
1763 let node = Mac_ { path, tts, delim };
1764 TyKind::Mac(respan(lo.to(self.prev_span), node))
1765 } else {
1766 // Just a type path or bound list (trait object type) starting with a trait.
1767 // `Type`
1768 // `Trait1 + Trait2 + 'a`
1769 if allow_plus && self.check_plus() {
1770 self.parse_remaining_bounds(Vec::new(), path, lo, true)?
1771 } else {
1772 TyKind::Path(None, path)
1773 }
1774 }
1775 } else {
1776 let msg = format!("expected type, found {}", self.this_token_descr());
1777 return Err(self.fatal(&msg));
1778 };
1779
1780 let span = lo.to(self.prev_span);
1781 let ty = Ty { node, span, id: ast::DUMMY_NODE_ID };
1782
1783 // Try to recover from use of `+` with incorrect priority.
1784 self.maybe_report_ambiguous_plus(allow_plus, impl_dyn_multi, &ty);
1785 self.maybe_recover_from_bad_type_plus(allow_plus, &ty)?;
1786 let ty = self.maybe_recover_from_bad_qpath(ty, allow_qpath_recovery)?;
1787
1788 Ok(P(ty))
1789 }
1790
1791 fn parse_remaining_bounds(&mut self, generic_params: Vec<GenericParam>, path: ast::Path,
1792 lo: Span, parse_plus: bool) -> PResult<'a, TyKind> {
1793 let poly_trait_ref = PolyTraitRef::new(generic_params, path, lo.to(self.prev_span));
1794 let mut bounds = vec![GenericBound::Trait(poly_trait_ref, TraitBoundModifier::None)];
1795 if parse_plus {
1796 self.eat_plus(); // `+`, or `+=` gets split and `+` is discarded
1797 bounds.append(&mut self.parse_generic_bounds(None)?);
1798 }
1799 Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::None))
1800 }
1801
1802 fn maybe_report_ambiguous_plus(&mut self, allow_plus: bool, impl_dyn_multi: bool, ty: &Ty) {
1803 if !allow_plus && impl_dyn_multi {
1804 let sum_with_parens = format!("({})", pprust::ty_to_string(&ty));
1805 self.struct_span_err(ty.span, "ambiguous `+` in a type")
1806 .span_suggestion(
1807 ty.span,
1808 "use parentheses to disambiguate",
1809 sum_with_parens,
1810 Applicability::MachineApplicable
1811 ).emit();
1812 }
1813 }
1814
1815 fn maybe_recover_from_bad_type_plus(&mut self, allow_plus: bool, ty: &Ty) -> PResult<'a, ()> {
1816 // Do not add `+` to expected tokens.
1817 if !allow_plus || !self.token.is_like_plus() {
1818 return Ok(())
1819 }
1820
1821 self.bump(); // `+`
1822 let bounds = self.parse_generic_bounds(None)?;
1823 let sum_span = ty.span.to(self.prev_span);
1824
1825 let mut err = struct_span_err!(self.sess.span_diagnostic, sum_span, E0178,
1826 "expected a path on the left-hand side of `+`, not `{}`", pprust::ty_to_string(ty));
1827
1828 match ty.node {
1829 TyKind::Rptr(ref lifetime, ref mut_ty) => {
1830 let sum_with_parens = pprust::to_string(|s| {
1831 use crate::print::pprust::PrintState;
1832
1833 s.s.word("&")?;
1834 s.print_opt_lifetime(lifetime)?;
1835 s.print_mutability(mut_ty.mutbl)?;
1836 s.popen()?;
1837 s.print_type(&mut_ty.ty)?;
1838 s.print_type_bounds(" +", &bounds)?;
1839 s.pclose()
1840 });
1841 err.span_suggestion(
1842 sum_span,
1843 "try adding parentheses",
1844 sum_with_parens,
1845 Applicability::MachineApplicable
1846 );
1847 }
1848 TyKind::Ptr(..) | TyKind::BareFn(..) => {
1849 err.span_label(sum_span, "perhaps you forgot parentheses?");
1850 }
1851 _ => {
1852 err.span_label(sum_span, "expected a path");
1853 },
1854 }
1855 err.emit();
1856 Ok(())
1857 }
1858
1859 // Try to recover from associated item paths like `[T]::AssocItem`/`(T, U)::AssocItem`.
1860 fn maybe_recover_from_bad_qpath<T: RecoverQPath>(&mut self, base: T, allow_recovery: bool)
1861 -> PResult<'a, T> {
1862 // Do not add `::` to expected tokens.
1863 if !allow_recovery || self.token != token::ModSep {
1864 return Ok(base);
1865 }
1866 let ty = match base.to_ty() {
1867 Some(ty) => ty,
1868 None => return Ok(base),
1869 };
1870
1871 self.bump(); // `::`
1872 let mut segments = Vec::new();
1873 self.parse_path_segments(&mut segments, T::PATH_STYLE, true)?;
1874
1875 let span = ty.span.to(self.prev_span);
1876 let path_span = span.to(span); // use an empty path since `position` == 0
1877 let recovered = base.to_recovered(
1878 Some(QSelf { ty, path_span, position: 0 }),
1879 ast::Path { segments, span },
1880 );
1881
1882 self.diagnostic()
1883 .struct_span_err(span, "missing angle brackets in associated item path")
1884 .span_suggestion( // this is a best-effort recovery
1885 span, "try", recovered.to_string(), Applicability::MaybeIncorrect
1886 ).emit();
1887
1888 Ok(recovered)
1889 }
1890
1891 fn parse_borrowed_pointee(&mut self) -> PResult<'a, TyKind> {
1892 let opt_lifetime = if self.check_lifetime() { Some(self.expect_lifetime()) } else { None };
1893 let mutbl = self.parse_mutability();
1894 let ty = self.parse_ty_no_plus()?;
1895 return Ok(TyKind::Rptr(opt_lifetime, MutTy { ty: ty, mutbl: mutbl }));
1896 }
1897
1898 fn parse_ptr(&mut self) -> PResult<'a, MutTy> {
1899 let mutbl = if self.eat_keyword(keywords::Mut) {
1900 Mutability::Mutable
1901 } else if self.eat_keyword(keywords::Const) {
1902 Mutability::Immutable
1903 } else {
1904 let span = self.prev_span;
1905 let msg = "expected mut or const in raw pointer type";
1906 self.struct_span_err(span, msg)
1907 .span_label(span, msg)
1908 .help("use `*mut T` or `*const T` as appropriate")
1909 .emit();
1910 Mutability::Immutable
1911 };
1912 let t = self.parse_ty_no_plus()?;
1913 Ok(MutTy { ty: t, mutbl: mutbl })
1914 }
1915
1916 fn is_named_argument(&mut self) -> bool {
1917 let offset = match self.token {
1918 token::Interpolated(ref nt) => match **nt {
1919 token::NtPat(..) => return self.look_ahead(1, |t| t == &token::Colon),
1920 _ => 0,
1921 }
1922 token::BinOp(token::And) | token::AndAnd => 1,
1923 _ if self.token.is_keyword(keywords::Mut) => 1,
1924 _ => 0,
1925 };
1926
1927 self.look_ahead(offset, |t| t.is_ident()) &&
1928 self.look_ahead(offset + 1, |t| t == &token::Colon)
1929 }
1930
1931 /// Skips unexpected attributes and doc comments in this position and emits an appropriate
1932 /// error.
1933 fn eat_incorrect_doc_comment(&mut self, applied_to: &str) {
1934 if let token::DocComment(_) = self.token {
1935 let mut err = self.diagnostic().struct_span_err(
1936 self.span,
1937 &format!("documentation comments cannot be applied to {}", applied_to),
1938 );
1939 err.span_label(self.span, "doc comments are not allowed here");
1940 err.emit();
1941 self.bump();
1942 } else if self.token == token::Pound && self.look_ahead(1, |t| {
1943 *t == token::OpenDelim(token::Bracket)
1944 }) {
1945 let lo = self.span;
1946 // Skip every token until next possible arg.
1947 while self.token != token::CloseDelim(token::Bracket) {
1948 self.bump();
1949 }
1950 let sp = lo.to(self.span);
1951 self.bump();
1952 let mut err = self.diagnostic().struct_span_err(
1953 sp,
1954 &format!("attributes cannot be applied to {}", applied_to),
1955 );
1956 err.span_label(sp, "attributes are not allowed here");
1957 err.emit();
1958 }
1959 }
1960
1961 /// This version of parse arg doesn't necessarily require identifier names.
1962 fn parse_arg_general(&mut self, require_name: bool, is_trait_item: bool) -> PResult<'a, Arg> {
1963 maybe_whole!(self, NtArg, |x| x);
1964
1965 if let Ok(Some(_)) = self.parse_self_arg() {
1966 let mut err = self.struct_span_err(self.prev_span,
1967 "unexpected `self` argument in function");
1968 err.span_label(self.prev_span,
1969 "`self` is only valid as the first argument of an associated function");
1970 return Err(err);
1971 }
1972
1973 let (pat, ty) = if require_name || self.is_named_argument() {
1974 debug!("parse_arg_general parse_pat (require_name:{})",
1975 require_name);
1976 self.eat_incorrect_doc_comment("method arguments");
1977 let pat = self.parse_pat(Some("argument name"))?;
1978
1979 if let Err(mut err) = self.expect(&token::Colon) {
1980 // If we find a pattern followed by an identifier, it could be an (incorrect)
1981 // C-style parameter declaration.
1982 if self.check_ident() && self.look_ahead(1, |t| {
1983 *t == token::Comma || *t == token::CloseDelim(token::Paren)
1984 }) {
1985 let ident = self.parse_ident().unwrap();
1986 let span = pat.span.with_hi(ident.span.hi());
1987
1988 err.span_suggestion(
1989 span,
1990 "declare the type after the parameter binding",
1991 String::from("<identifier>: <type>"),
1992 Applicability::HasPlaceholders,
1993 );
1994 } else if require_name && is_trait_item {
1995 if let PatKind::Ident(_, ident, _) = pat.node {
1996 err.span_suggestion(
1997 pat.span,
1998 "explicitly ignore parameter",
1999 format!("_: {}", ident),
2000 Applicability::MachineApplicable,
2001 );
2002 }
2003
2004 err.note("anonymous parameters are removed in the 2018 edition (see RFC 1685)");
2005 }
2006
2007 return Err(err);
2008 }
2009
2010 self.eat_incorrect_doc_comment("a method argument's type");
2011 (pat, self.parse_ty()?)
2012 } else {
2013 debug!("parse_arg_general ident_to_pat");
2014 let parser_snapshot_before_ty = self.clone();
2015 self.eat_incorrect_doc_comment("a method argument's type");
2016 let mut ty = self.parse_ty();
2017 if ty.is_ok() && self.token != token::Comma &&
2018 self.token != token::CloseDelim(token::Paren) {
2019 // This wasn't actually a type, but a pattern looking like a type,
2020 // so we are going to rollback and re-parse for recovery.
2021 ty = self.unexpected();
2022 }
2023 match ty {
2024 Ok(ty) => {
2025 let ident = Ident::new(keywords::Invalid.name(), self.prev_span);
2026 let pat = P(Pat {
2027 id: ast::DUMMY_NODE_ID,
2028 node: PatKind::Ident(
2029 BindingMode::ByValue(Mutability::Immutable), ident, None),
2030 span: ty.span,
2031 });
2032 (pat, ty)
2033 }
2034 Err(mut err) => {
2035 // Recover from attempting to parse the argument as a type without pattern.
2036 err.cancel();
2037 mem::replace(self, parser_snapshot_before_ty);
2038 let pat = self.parse_pat(Some("argument name"))?;
2039 self.expect(&token::Colon)?;
2040 let ty = self.parse_ty()?;
2041
2042 let mut err = self.diagnostic().struct_span_err_with_code(
2043 pat.span,
2044 "patterns aren't allowed in methods without bodies",
2045 DiagnosticId::Error("E0642".into()),
2046 );
2047 err.span_suggestion_short(
2048 pat.span,
2049 "give this argument a name or use an underscore to ignore it",
2050 "_".to_owned(),
2051 Applicability::MachineApplicable,
2052 );
2053 err.emit();
2054
2055 // Pretend the pattern is `_`, to avoid duplicate errors from AST validation.
2056 let pat = P(Pat {
2057 node: PatKind::Wild,
2058 span: pat.span,
2059 id: ast::DUMMY_NODE_ID
2060 });
2061 (pat, ty)
2062 }
2063 }
2064 };
2065
2066 Ok(Arg { ty, pat, id: ast::DUMMY_NODE_ID })
2067 }
2068
2069 /// Parses a single function argument.
2070 crate fn parse_arg(&mut self) -> PResult<'a, Arg> {
2071 self.parse_arg_general(true, false)
2072 }
2073
2074 /// Parses an argument in a lambda header (e.g., `|arg, arg|`).
2075 fn parse_fn_block_arg(&mut self) -> PResult<'a, Arg> {
2076 let pat = self.parse_pat(Some("argument name"))?;
2077 let t = if self.eat(&token::Colon) {
2078 self.parse_ty()?
2079 } else {
2080 P(Ty {
2081 id: ast::DUMMY_NODE_ID,
2082 node: TyKind::Infer,
2083 span: self.prev_span,
2084 })
2085 };
2086 Ok(Arg {
2087 ty: t,
2088 pat,
2089 id: ast::DUMMY_NODE_ID
2090 })
2091 }
2092
2093 fn maybe_parse_fixed_length_of_vec(&mut self) -> PResult<'a, Option<P<ast::Expr>>> {
2094 if self.eat(&token::Semi) {
2095 Ok(Some(self.parse_expr()?))
2096 } else {
2097 Ok(None)
2098 }
2099 }
2100
2101 /// Matches `token_lit = LIT_INTEGER | ...`.
2102 fn parse_lit_token(&mut self) -> PResult<'a, LitKind> {
2103 let out = match self.token {
2104 token::Interpolated(ref nt) => match **nt {
2105 token::NtExpr(ref v) | token::NtLiteral(ref v) => match v.node {
2106 ExprKind::Lit(ref lit) => { lit.node.clone() }
2107 _ => { return self.unexpected_last(&self.token); }
2108 },
2109 _ => { return self.unexpected_last(&self.token); }
2110 },
2111 token::Literal(lit, suf) => {
2112 let diag = Some((self.span, &self.sess.span_diagnostic));
2113 let (suffix_illegal, result) = parse::lit_token(lit, suf, diag);
2114
2115 if suffix_illegal {
2116 let sp = self.span;
2117 self.expect_no_suffix(sp, lit.literal_name(), suf)
2118 }
2119
2120 result.unwrap()
2121 }
2122 token::Dot if self.look_ahead(1, |t| match t {
2123 token::Literal(parse::token::Lit::Integer(_) , _) => true,
2124 _ => false,
2125 }) => { // recover from `let x = .4;`
2126 let lo = self.span;
2127 self.bump();
2128 if let token::Literal(
2129 parse::token::Lit::Integer(val),
2130 suffix,
2131 ) = self.token {
2132 let suffix = suffix.and_then(|s| {
2133 let s = s.as_str().get();
2134 if ["f32", "f64"].contains(&s) {
2135 Some(s)
2136 } else {
2137 None
2138 }
2139 }).unwrap_or("");
2140 self.bump();
2141 let sp = lo.to(self.prev_span);
2142 let mut err = self.diagnostic()
2143 .struct_span_err(sp, "float literals must have an integer part");
2144 err.span_suggestion(
2145 sp,
2146 "must have an integer part",
2147 format!("0.{}{}", val, suffix),
2148 Applicability::MachineApplicable,
2149 );
2150 err.emit();
2151 return Ok(match suffix {
2152 "f32" => ast::LitKind::Float(val, ast::FloatTy::F32),
2153 "f64" => ast::LitKind::Float(val, ast::FloatTy::F64),
2154 _ => ast::LitKind::FloatUnsuffixed(val),
2155 });
2156 } else {
2157 unreachable!();
2158 };
2159 }
2160 _ => { return self.unexpected_last(&self.token); }
2161 };
2162
2163 self.bump();
2164 Ok(out)
2165 }
2166
2167 /// Matches `lit = true | false | token_lit`.
2168 crate fn parse_lit(&mut self) -> PResult<'a, Lit> {
2169 let lo = self.span;
2170 let lit = if self.eat_keyword(keywords::True) {
2171 LitKind::Bool(true)
2172 } else if self.eat_keyword(keywords::False) {
2173 LitKind::Bool(false)
2174 } else {
2175 let lit = self.parse_lit_token()?;
2176 lit
2177 };
2178 Ok(source_map::Spanned { node: lit, span: lo.to(self.prev_span) })
2179 }
2180
2181 /// Matches `'-' lit | lit` (cf. `ast_validation::AstValidator::check_expr_within_pat`).
2182 crate fn parse_literal_maybe_minus(&mut self) -> PResult<'a, P<Expr>> {
2183 maybe_whole_expr!(self);
2184
2185 let minus_lo = self.span;
2186 let minus_present = self.eat(&token::BinOp(token::Minus));
2187 let lo = self.span;
2188 let literal = self.parse_lit()?;
2189 let hi = self.prev_span;
2190 let expr = self.mk_expr(lo.to(hi), ExprKind::Lit(literal), ThinVec::new());
2191
2192 if minus_present {
2193 let minus_hi = self.prev_span;
2194 let unary = self.mk_unary(UnOp::Neg, expr);
2195 Ok(self.mk_expr(minus_lo.to(minus_hi), unary, ThinVec::new()))
2196 } else {
2197 Ok(expr)
2198 }
2199 }
2200
2201 fn parse_path_segment_ident(&mut self) -> PResult<'a, ast::Ident> {
2202 match self.token {
2203 token::Ident(ident, _) if self.token.is_path_segment_keyword() => {
2204 let span = self.span;
2205 self.bump();
2206 Ok(Ident::new(ident.name, span))
2207 }
2208 _ => self.parse_ident(),
2209 }
2210 }
2211
2212 fn parse_ident_or_underscore(&mut self) -> PResult<'a, ast::Ident> {
2213 match self.token {
2214 token::Ident(ident, false) if ident.name == keywords::Underscore.name() => {
2215 let span = self.span;
2216 self.bump();
2217 Ok(Ident::new(ident.name, span))
2218 }
2219 _ => self.parse_ident(),
2220 }
2221 }
2222
2223 /// Parses a qualified path.
2224 /// Assumes that the leading `<` has been parsed already.
2225 ///
2226 /// `qualified_path = <type [as trait_ref]>::path`
2227 ///
2228 /// # Examples
2229 /// `<T>::default`
2230 /// `<T as U>::a`
2231 /// `<T as U>::F::a<S>` (without disambiguator)
2232 /// `<T as U>::F::a::<S>` (with disambiguator)
2233 fn parse_qpath(&mut self, style: PathStyle) -> PResult<'a, (QSelf, ast::Path)> {
2234 let lo = self.prev_span;
2235 let ty = self.parse_ty()?;
2236
2237 // `path` will contain the prefix of the path up to the `>`,
2238 // if any (e.g., `U` in the `<T as U>::*` examples
2239 // above). `path_span` has the span of that path, or an empty
2240 // span in the case of something like `<T>::Bar`.
2241 let (mut path, path_span);
2242 if self.eat_keyword(keywords::As) {
2243 let path_lo = self.span;
2244 path = self.parse_path(PathStyle::Type)?;
2245 path_span = path_lo.to(self.prev_span);
2246 } else {
2247 path = ast::Path { segments: Vec::new(), span: syntax_pos::DUMMY_SP };
2248 path_span = self.span.to(self.span);
2249 }
2250
2251 // See doc comment for `unmatched_angle_bracket_count`.
2252 self.expect(&token::Gt)?;
2253 if self.unmatched_angle_bracket_count > 0 {
2254 self.unmatched_angle_bracket_count -= 1;
2255 debug!("parse_qpath: (decrement) count={:?}", self.unmatched_angle_bracket_count);
2256 }
2257
2258 self.expect(&token::ModSep)?;
2259
2260 let qself = QSelf { ty, path_span, position: path.segments.len() };
2261 self.parse_path_segments(&mut path.segments, style, true)?;
2262
2263 Ok((qself, ast::Path { segments: path.segments, span: lo.to(self.prev_span) }))
2264 }
2265
2266 /// Parses simple paths.
2267 ///
2268 /// `path = [::] segment+`
2269 /// `segment = ident | ident[::]<args> | ident[::](args) [-> type]`
2270 ///
2271 /// # Examples
2272 /// `a::b::C<D>` (without disambiguator)
2273 /// `a::b::C::<D>` (with disambiguator)
2274 /// `Fn(Args)` (without disambiguator)
2275 /// `Fn::(Args)` (with disambiguator)
2276 pub fn parse_path(&mut self, style: PathStyle) -> PResult<'a, ast::Path> {
2277 self.parse_path_common(style, true)
2278 }
2279
2280 crate fn parse_path_common(&mut self, style: PathStyle, enable_warning: bool)
2281 -> PResult<'a, ast::Path> {
2282 maybe_whole!(self, NtPath, |path| {
2283 if style == PathStyle::Mod &&
2284 path.segments.iter().any(|segment| segment.args.is_some()) {
2285 self.diagnostic().span_err(path.span, "unexpected generic arguments in path");
2286 }
2287 path
2288 });
2289
2290 let lo = self.meta_var_span.unwrap_or(self.span);
2291 let mut segments = Vec::new();
2292 let mod_sep_ctxt = self.span.ctxt();
2293 if self.eat(&token::ModSep) {
2294 segments.push(PathSegment::path_root(lo.shrink_to_lo().with_ctxt(mod_sep_ctxt)));
2295 }
2296 self.parse_path_segments(&mut segments, style, enable_warning)?;
2297
2298 Ok(ast::Path { segments, span: lo.to(self.prev_span) })
2299 }
2300
2301 /// Like `parse_path`, but also supports parsing `Word` meta items into paths for
2302 /// backwards-compatibility. This is used when parsing derive macro paths in `#[derive]`
2303 /// attributes.
2304 pub fn parse_path_allowing_meta(&mut self, style: PathStyle) -> PResult<'a, ast::Path> {
2305 let meta_ident = match self.token {
2306 token::Interpolated(ref nt) => match **nt {
2307 token::NtMeta(ref meta) => match meta.node {
2308 ast::MetaItemKind::Word => Some(meta.ident.clone()),
2309 _ => None,
2310 },
2311 _ => None,
2312 },
2313 _ => None,
2314 };
2315 if let Some(path) = meta_ident {
2316 self.bump();
2317 return Ok(path);
2318 }
2319 self.parse_path(style)
2320 }
2321
2322 fn parse_path_segments(&mut self,
2323 segments: &mut Vec<PathSegment>,
2324 style: PathStyle,
2325 enable_warning: bool)
2326 -> PResult<'a, ()> {
2327 loop {
2328 let segment = self.parse_path_segment(style, enable_warning)?;
2329 if style == PathStyle::Expr {
2330 // In order to check for trailing angle brackets, we must have finished
2331 // recursing (`parse_path_segment` can indirectly call this function),
2332 // that is, the next token must be the highlighted part of the below example:
2333 //
2334 // `Foo::<Bar as Baz<T>>::Qux`
2335 // ^ here
2336 //
2337 // As opposed to the below highlight (if we had only finished the first
2338 // recursion):
2339 //
2340 // `Foo::<Bar as Baz<T>>::Qux`
2341 // ^ here
2342 //
2343 // `PathStyle::Expr` is only provided at the root invocation and never in
2344 // `parse_path_segment` to recurse and therefore can be checked to maintain
2345 // this invariant.
2346 self.check_trailing_angle_brackets(&segment, token::ModSep);
2347 }
2348 segments.push(segment);
2349
2350 if self.is_import_coupler() || !self.eat(&token::ModSep) {
2351 return Ok(());
2352 }
2353 }
2354 }
2355
2356 fn parse_path_segment(&mut self, style: PathStyle, enable_warning: bool)
2357 -> PResult<'a, PathSegment> {
2358 let ident = self.parse_path_segment_ident()?;
2359
2360 let is_args_start = |token: &token::Token| match *token {
2361 token::Lt | token::BinOp(token::Shl) | token::OpenDelim(token::Paren) => true,
2362 _ => false,
2363 };
2364 let check_args_start = |this: &mut Self| {
2365 this.expected_tokens.extend_from_slice(
2366 &[TokenType::Token(token::Lt), TokenType::Token(token::OpenDelim(token::Paren))]
2367 );
2368 is_args_start(&this.token)
2369 };
2370
2371 Ok(if style == PathStyle::Type && check_args_start(self) ||
2372 style != PathStyle::Mod && self.check(&token::ModSep)
2373 && self.look_ahead(1, |t| is_args_start(t)) {
2374 // Generic arguments are found - `<`, `(`, `::<` or `::(`.
2375 if self.eat(&token::ModSep) && style == PathStyle::Type && enable_warning {
2376 self.diagnostic().struct_span_warn(self.prev_span, "unnecessary path disambiguator")
2377 .span_label(self.prev_span, "try removing `::`").emit();
2378 }
2379 let lo = self.span;
2380
2381 // We use `style == PathStyle::Expr` to check if this is in a recursion or not. If
2382 // it isn't, then we reset the unmatched angle bracket count as we're about to start
2383 // parsing a new path.
2384 if style == PathStyle::Expr {
2385 self.unmatched_angle_bracket_count = 0;
2386 self.max_angle_bracket_count = 0;
2387 }
2388
2389 let args = if self.eat_lt() {
2390 // `<'a, T, A = U>`
2391 let (args, bindings) =
2392 self.parse_generic_args_with_leaning_angle_bracket_recovery(style, lo)?;
2393 self.expect_gt()?;
2394 let span = lo.to(self.prev_span);
2395 AngleBracketedArgs { args, bindings, span }.into()
2396 } else {
2397 // `(T, U) -> R`
2398 self.bump(); // `(`
2399 let (inputs, recovered) = self.parse_seq_to_before_tokens(
2400 &[&token::CloseDelim(token::Paren)],
2401 SeqSep::trailing_allowed(token::Comma),
2402 TokenExpectType::Expect,
2403 |p| p.parse_ty())?;
2404 if !recovered {
2405 self.bump(); // `)`
2406 }
2407 let span = lo.to(self.prev_span);
2408 let output = if self.eat(&token::RArrow) {
2409 Some(self.parse_ty_common(false, false)?)
2410 } else {
2411 None
2412 };
2413 ParenthesizedArgs { inputs, output, span }.into()
2414 };
2415
2416 PathSegment { ident, args, id: ast::DUMMY_NODE_ID }
2417 } else {
2418 // Generic arguments are not found.
2419 PathSegment::from_ident(ident)
2420 })
2421 }
2422
2423 crate fn check_lifetime(&mut self) -> bool {
2424 self.expected_tokens.push(TokenType::Lifetime);
2425 self.token.is_lifetime()
2426 }
2427
2428 /// Parses a single lifetime `'a` or panics.
2429 crate fn expect_lifetime(&mut self) -> Lifetime {
2430 if let Some(ident) = self.token.lifetime() {
2431 let span = self.span;
2432 self.bump();
2433 Lifetime { ident: Ident::new(ident.name, span), id: ast::DUMMY_NODE_ID }
2434 } else {
2435 self.span_bug(self.span, "not a lifetime")
2436 }
2437 }
2438
2439 fn eat_label(&mut self) -> Option<Label> {
2440 if let Some(ident) = self.token.lifetime() {
2441 let span = self.span;
2442 self.bump();
2443 Some(Label { ident: Ident::new(ident.name, span) })
2444 } else {
2445 None
2446 }
2447 }
2448
2449 /// Parses mutability (`mut` or nothing).
2450 fn parse_mutability(&mut self) -> Mutability {
2451 if self.eat_keyword(keywords::Mut) {
2452 Mutability::Mutable
2453 } else {
2454 Mutability::Immutable
2455 }
2456 }
2457
2458 fn parse_field_name(&mut self) -> PResult<'a, Ident> {
2459 if let token::Literal(token::Integer(name), None) = self.token {
2460 self.bump();
2461 Ok(Ident::new(name, self.prev_span))
2462 } else {
2463 self.parse_ident_common(false)
2464 }
2465 }
2466
2467 /// Parse ident (COLON expr)?
2468 fn parse_field(&mut self) -> PResult<'a, Field> {
2469 let attrs = self.parse_outer_attributes()?;
2470 let lo = self.span;
2471
2472 // Check if a colon exists one ahead. This means we're parsing a fieldname.
2473 let (fieldname, expr, is_shorthand) = if self.look_ahead(1, |t| {
2474 t == &token::Colon || t == &token::Eq
2475 }) {
2476 let fieldname = self.parse_field_name()?;
2477
2478 // Check for an equals token. This means the source incorrectly attempts to
2479 // initialize a field with an eq rather than a colon.
2480 if self.token == token::Eq {
2481 self.diagnostic()
2482 .struct_span_err(self.span, "expected `:`, found `=`")
2483 .span_suggestion(
2484 fieldname.span.shrink_to_hi().to(self.span),
2485 "replace equals symbol with a colon",
2486 ":".to_string(),
2487 Applicability::MachineApplicable,
2488 )
2489 .emit();
2490 }
2491 self.bump(); // `:`
2492 (fieldname, self.parse_expr()?, false)
2493 } else {
2494 let fieldname = self.parse_ident_common(false)?;
2495
2496 // Mimic `x: x` for the `x` field shorthand.
2497 let path = ast::Path::from_ident(fieldname);
2498 let expr = self.mk_expr(fieldname.span, ExprKind::Path(None, path), ThinVec::new());
2499 (fieldname, expr, true)
2500 };
2501 Ok(ast::Field {
2502 ident: fieldname,
2503 span: lo.to(expr.span),
2504 expr,
2505 is_shorthand,
2506 attrs: attrs.into(),
2507 })
2508 }
2509
2510 fn mk_expr(&mut self, span: Span, node: ExprKind, attrs: ThinVec<Attribute>) -> P<Expr> {
2511 P(Expr { node, span, attrs, id: ast::DUMMY_NODE_ID })
2512 }
2513
2514 fn mk_unary(&mut self, unop: ast::UnOp, expr: P<Expr>) -> ast::ExprKind {
2515 ExprKind::Unary(unop, expr)
2516 }
2517
2518 fn mk_binary(&mut self, binop: ast::BinOp, lhs: P<Expr>, rhs: P<Expr>) -> ast::ExprKind {
2519 ExprKind::Binary(binop, lhs, rhs)
2520 }
2521
2522 fn mk_call(&mut self, f: P<Expr>, args: Vec<P<Expr>>) -> ast::ExprKind {
2523 ExprKind::Call(f, args)
2524 }
2525
2526 fn mk_index(&mut self, expr: P<Expr>, idx: P<Expr>) -> ast::ExprKind {
2527 ExprKind::Index(expr, idx)
2528 }
2529
2530 fn mk_range(&mut self,
2531 start: Option<P<Expr>>,
2532 end: Option<P<Expr>>,
2533 limits: RangeLimits)
2534 -> PResult<'a, ast::ExprKind> {
2535 if end.is_none() && limits == RangeLimits::Closed {
2536 Err(self.span_fatal_err(self.span, Error::InclusiveRangeWithNoEnd))
2537 } else {
2538 Ok(ExprKind::Range(start, end, limits))
2539 }
2540 }
2541
2542 fn mk_assign_op(&mut self, binop: ast::BinOp,
2543 lhs: P<Expr>, rhs: P<Expr>) -> ast::ExprKind {
2544 ExprKind::AssignOp(binop, lhs, rhs)
2545 }
2546
2547 pub fn mk_mac_expr(&mut self, span: Span, m: Mac_, attrs: ThinVec<Attribute>) -> P<Expr> {
2548 P(Expr {
2549 id: ast::DUMMY_NODE_ID,
2550 node: ExprKind::Mac(source_map::Spanned {node: m, span: span}),
2551 span,
2552 attrs,
2553 })
2554 }
2555
2556 fn expect_delimited_token_tree(&mut self) -> PResult<'a, (MacDelimiter, TokenStream)> {
2557 let delim = match self.token {
2558 token::OpenDelim(delim) => delim,
2559 _ => {
2560 let msg = "expected open delimiter";
2561 let mut err = self.fatal(msg);
2562 err.span_label(self.span, msg);
2563 return Err(err)
2564 }
2565 };
2566 let tts = match self.parse_token_tree() {
2567 TokenTree::Delimited(_, _, tts) => tts,
2568 _ => unreachable!(),
2569 };
2570 let delim = match delim {
2571 token::Paren => MacDelimiter::Parenthesis,
2572 token::Bracket => MacDelimiter::Bracket,
2573 token::Brace => MacDelimiter::Brace,
2574 token::NoDelim => self.bug("unexpected no delimiter"),
2575 };
2576 Ok((delim, tts.into()))
2577 }
2578
2579 /// At the bottom (top?) of the precedence hierarchy,
2580 /// Parses things like parenthesized exprs, macros, `return`, etc.
2581 ///
2582 /// N.B., this does not parse outer attributes, and is private because it only works
2583 /// correctly if called from `parse_dot_or_call_expr()`.
2584 fn parse_bottom_expr(&mut self) -> PResult<'a, P<Expr>> {
2585 maybe_whole_expr!(self);
2586
2587 // Outer attributes are already parsed and will be
2588 // added to the return value after the fact.
2589 //
2590 // Therefore, prevent sub-parser from parsing
2591 // attributes by giving them a empty "already parsed" list.
2592 let mut attrs = ThinVec::new();
2593
2594 let lo = self.span;
2595 let mut hi = self.span;
2596
2597 let ex: ExprKind;
2598
2599 // Note: when adding new syntax here, don't forget to adjust Token::can_begin_expr().
2600 match self.token {
2601 token::OpenDelim(token::Paren) => {
2602 self.bump();
2603
2604 attrs.extend(self.parse_inner_attributes()?);
2605
2606 // (e) is parenthesized e
2607 // (e,) is a tuple with only one field, e
2608 let mut es = vec![];
2609 let mut trailing_comma = false;
2610 let mut recovered = false;
2611 while self.token != token::CloseDelim(token::Paren) {
2612 es.push(self.parse_expr()?);
2613 recovered = self.expect_one_of(
2614 &[],
2615 &[token::Comma, token::CloseDelim(token::Paren)],
2616 )?;
2617 if self.eat(&token::Comma) {
2618 trailing_comma = true;
2619 } else {
2620 trailing_comma = false;
2621 break;
2622 }
2623 }
2624 if !recovered {
2625 self.bump();
2626 }
2627
2628 hi = self.prev_span;
2629 ex = if es.len() == 1 && !trailing_comma {
2630 ExprKind::Paren(es.into_iter().nth(0).unwrap())
2631 } else {
2632 ExprKind::Tup(es)
2633 };
2634 }
2635 token::OpenDelim(token::Brace) => {
2636 return self.parse_block_expr(None, lo, BlockCheckMode::Default, attrs);
2637 }
2638 token::BinOp(token::Or) | token::OrOr => {
2639 return self.parse_lambda_expr(attrs);
2640 }
2641 token::OpenDelim(token::Bracket) => {
2642 self.bump();
2643
2644 attrs.extend(self.parse_inner_attributes()?);
2645
2646 if self.eat(&token::CloseDelim(token::Bracket)) {
2647 // Empty vector.
2648 ex = ExprKind::Array(Vec::new());
2649 } else {
2650 // Nonempty vector.
2651 let first_expr = self.parse_expr()?;
2652 if self.eat(&token::Semi) {
2653 // Repeating array syntax: [ 0; 512 ]
2654 let count = AnonConst {
2655 id: ast::DUMMY_NODE_ID,
2656 value: self.parse_expr()?,
2657 };
2658 self.expect(&token::CloseDelim(token::Bracket))?;
2659 ex = ExprKind::Repeat(first_expr, count);
2660 } else if self.eat(&token::Comma) {
2661 // Vector with two or more elements.
2662 let remaining_exprs = self.parse_seq_to_end(
2663 &token::CloseDelim(token::Bracket),
2664 SeqSep::trailing_allowed(token::Comma),
2665 |p| Ok(p.parse_expr()?)
2666 )?;
2667 let mut exprs = vec![first_expr];
2668 exprs.extend(remaining_exprs);
2669 ex = ExprKind::Array(exprs);
2670 } else {
2671 // Vector with one element.
2672 self.expect(&token::CloseDelim(token::Bracket))?;
2673 ex = ExprKind::Array(vec![first_expr]);
2674 }
2675 }
2676 hi = self.prev_span;
2677 }
2678 _ => {
2679 if self.eat_lt() {
2680 let (qself, path) = self.parse_qpath(PathStyle::Expr)?;
2681 hi = path.span;
2682 return Ok(self.mk_expr(lo.to(hi), ExprKind::Path(Some(qself), path), attrs));
2683 }
2684 if self.span.rust_2018() && self.check_keyword(keywords::Async)
2685 {
2686 if self.is_async_block() { // check for `async {` and `async move {`
2687 return self.parse_async_block(attrs);
2688 } else {
2689 return self.parse_lambda_expr(attrs);
2690 }
2691 }
2692 if self.check_keyword(keywords::Move) || self.check_keyword(keywords::Static) {
2693 return self.parse_lambda_expr(attrs);
2694 }
2695 if self.eat_keyword(keywords::If) {
2696 return self.parse_if_expr(attrs);
2697 }
2698 if self.eat_keyword(keywords::For) {
2699 let lo = self.prev_span;
2700 return self.parse_for_expr(None, lo, attrs);
2701 }
2702 if self.eat_keyword(keywords::While) {
2703 let lo = self.prev_span;
2704 return self.parse_while_expr(None, lo, attrs);
2705 }
2706 if let Some(label) = self.eat_label() {
2707 let lo = label.ident.span;
2708 self.expect(&token::Colon)?;
2709 if self.eat_keyword(keywords::While) {
2710 return self.parse_while_expr(Some(label), lo, attrs)
2711 }
2712 if self.eat_keyword(keywords::For) {
2713 return self.parse_for_expr(Some(label), lo, attrs)
2714 }
2715 if self.eat_keyword(keywords::Loop) {
2716 return self.parse_loop_expr(Some(label), lo, attrs)
2717 }
2718 if self.token == token::OpenDelim(token::Brace) {
2719 return self.parse_block_expr(Some(label),
2720 lo,
2721 BlockCheckMode::Default,
2722 attrs);
2723 }
2724 let msg = "expected `while`, `for`, `loop` or `{` after a label";
2725 let mut err = self.fatal(msg);
2726 err.span_label(self.span, msg);
2727 return Err(err);
2728 }
2729 if self.eat_keyword(keywords::Loop) {
2730 let lo = self.prev_span;
2731 return self.parse_loop_expr(None, lo, attrs);
2732 }
2733 if self.eat_keyword(keywords::Continue) {
2734 let label = self.eat_label();
2735 let ex = ExprKind::Continue(label);
2736 let hi = self.prev_span;
2737 return Ok(self.mk_expr(lo.to(hi), ex, attrs));
2738 }
2739 if self.eat_keyword(keywords::Match) {
2740 let match_sp = self.prev_span;
2741 return self.parse_match_expr(attrs).map_err(|mut err| {
2742 err.span_label(match_sp, "while parsing this match expression");
2743 err
2744 });
2745 }
2746 if self.eat_keyword(keywords::Unsafe) {
2747 return self.parse_block_expr(
2748 None,
2749 lo,
2750 BlockCheckMode::Unsafe(ast::UserProvided),
2751 attrs);
2752 }
2753 if self.is_do_catch_block() {
2754 let mut db = self.fatal("found removed `do catch` syntax");
2755 db.help("Following RFC #2388, the new non-placeholder syntax is `try`");
2756 return Err(db);
2757 }
2758 if self.is_try_block() {
2759 let lo = self.span;
2760 assert!(self.eat_keyword(keywords::Try));
2761 return self.parse_try_block(lo, attrs);
2762 }
2763 if self.eat_keyword(keywords::Return) {
2764 if self.token.can_begin_expr() {
2765 let e = self.parse_expr()?;
2766 hi = e.span;
2767 ex = ExprKind::Ret(Some(e));
2768 } else {
2769 ex = ExprKind::Ret(None);
2770 }
2771 } else if self.eat_keyword(keywords::Break) {
2772 let label = self.eat_label();
2773 let e = if self.token.can_begin_expr()
2774 && !(self.token == token::OpenDelim(token::Brace)
2775 && self.restrictions.contains(
2776 Restrictions::NO_STRUCT_LITERAL)) {
2777 Some(self.parse_expr()?)
2778 } else {
2779 None
2780 };
2781 ex = ExprKind::Break(label, e);
2782 hi = self.prev_span;
2783 } else if self.eat_keyword(keywords::Yield) {
2784 if self.token.can_begin_expr() {
2785 let e = self.parse_expr()?;
2786 hi = e.span;
2787 ex = ExprKind::Yield(Some(e));
2788 } else {
2789 ex = ExprKind::Yield(None);
2790 }
2791 } else if self.token.is_keyword(keywords::Let) {
2792 // Catch this syntax error here, instead of in `parse_ident`, so
2793 // that we can explicitly mention that let is not to be used as an expression
2794 let mut db = self.fatal("expected expression, found statement (`let`)");
2795 db.span_label(self.span, "expected expression");
2796 db.note("variable declaration using `let` is a statement");
2797 return Err(db);
2798 } else if self.token.is_path_start() {
2799 let pth = self.parse_path(PathStyle::Expr)?;
2800
2801 // `!`, as an operator, is prefix, so we know this isn't that
2802 if self.eat(&token::Not) {
2803 // MACRO INVOCATION expression
2804 let (delim, tts) = self.expect_delimited_token_tree()?;
2805 let hi = self.prev_span;
2806 let node = Mac_ { path: pth, tts, delim };
2807 return Ok(self.mk_mac_expr(lo.to(hi), node, attrs))
2808 }
2809 if self.check(&token::OpenDelim(token::Brace)) {
2810 // This is a struct literal, unless we're prohibited
2811 // from parsing struct literals here.
2812 let prohibited = self.restrictions.contains(
2813 Restrictions::NO_STRUCT_LITERAL
2814 );
2815 if !prohibited {
2816 return self.parse_struct_expr(lo, pth, attrs);
2817 }
2818 }
2819
2820 hi = pth.span;
2821 ex = ExprKind::Path(None, pth);
2822 } else {
2823 if !self.unclosed_delims.is_empty() && self.check(&token::Semi) {
2824 // Don't complain about bare semicolons after unclosed braces
2825 // recovery in order to keep the error count down. Fixing the
2826 // delimiters will possibly also fix the bare semicolon found in
2827 // expression context. For example, silence the following error:
2828 // ```
2829 // error: expected expression, found `;`
2830 // --> file.rs:2:13
2831 // |
2832 // 2 | foo(bar(;
2833 // | ^ expected expression
2834 // ```
2835 self.bump();
2836 return Ok(self.mk_expr(self.span, ExprKind::Err, ThinVec::new()));
2837 }
2838 match self.parse_literal_maybe_minus() {
2839 Ok(expr) => {
2840 hi = expr.span;
2841 ex = expr.node.clone();
2842 }
2843 Err(mut err) => {
2844 self.cancel(&mut err);
2845 let msg = format!("expected expression, found {}",
2846 self.this_token_descr());
2847 let mut err = self.fatal(&msg);
2848 err.span_label(self.span, "expected expression");
2849 return Err(err);
2850 }
2851 }
2852 }
2853 }
2854 }
2855
2856 let expr = Expr { node: ex, span: lo.to(hi), id: ast::DUMMY_NODE_ID, attrs };
2857 let expr = self.maybe_recover_from_bad_qpath(expr, true)?;
2858
2859 return Ok(P(expr));
2860 }
2861
2862 fn parse_struct_expr(&mut self, lo: Span, pth: ast::Path, mut attrs: ThinVec<Attribute>)
2863 -> PResult<'a, P<Expr>> {
2864 let struct_sp = lo.to(self.prev_span);
2865 self.bump();
2866 let mut fields = Vec::new();
2867 let mut base = None;
2868
2869 attrs.extend(self.parse_inner_attributes()?);
2870
2871 while self.token != token::CloseDelim(token::Brace) {
2872 if self.eat(&token::DotDot) {
2873 let exp_span = self.prev_span;
2874 match self.parse_expr() {
2875 Ok(e) => {
2876 base = Some(e);
2877 }
2878 Err(mut e) => {
2879 e.emit();
2880 self.recover_stmt();
2881 }
2882 }
2883 if self.token == token::Comma {
2884 let mut err = self.sess.span_diagnostic.mut_span_err(
2885 exp_span.to(self.prev_span),
2886 "cannot use a comma after the base struct",
2887 );
2888 err.span_suggestion_short(
2889 self.span,
2890 "remove this comma",
2891 String::new(),
2892 Applicability::MachineApplicable
2893 );
2894 err.note("the base struct must always be the last field");
2895 err.emit();
2896 self.recover_stmt();
2897 }
2898 break;
2899 }
2900
2901 let mut recovery_field = None;
2902 if let token::Ident(ident, _) = self.token {
2903 if !self.token.is_reserved_ident() && self.look_ahead(1, |t| *t == token::Colon) {
2904 // Use in case of error after field-looking code: `S { foo: () with a }`
2905 let mut ident = ident.clone();
2906 ident.span = self.span;
2907 recovery_field = Some(ast::Field {
2908 ident,
2909 span: self.span,
2910 expr: self.mk_expr(self.span, ExprKind::Err, ThinVec::new()),
2911 is_shorthand: false,
2912 attrs: ThinVec::new(),
2913 });
2914 }
2915 }
2916 let mut parsed_field = None;
2917 match self.parse_field() {
2918 Ok(f) => parsed_field = Some(f),
2919 Err(mut e) => {
2920 e.span_label(struct_sp, "while parsing this struct");
2921 e.emit();
2922
2923 // If the next token is a comma, then try to parse
2924 // what comes next as additional fields, rather than
2925 // bailing out until next `}`.
2926 if self.token != token::Comma {
2927 self.recover_stmt_(SemiColonMode::Comma, BlockMode::Ignore);
2928 if self.token != token::Comma {
2929 break;
2930 }
2931 }
2932 }
2933 }
2934
2935 match self.expect_one_of(&[token::Comma],
2936 &[token::CloseDelim(token::Brace)]) {
2937 Ok(_) => if let Some(f) = parsed_field.or(recovery_field) {
2938 // only include the field if there's no parse error for the field name
2939 fields.push(f);
2940 }
2941 Err(mut e) => {
2942 if let Some(f) = recovery_field {
2943 fields.push(f);
2944 }
2945 e.span_label(struct_sp, "while parsing this struct");
2946 e.emit();
2947 self.recover_stmt_(SemiColonMode::Comma, BlockMode::Ignore);
2948 self.eat(&token::Comma);
2949 }
2950 }
2951 }
2952
2953 let span = lo.to(self.span);
2954 self.expect(&token::CloseDelim(token::Brace))?;
2955 return Ok(self.mk_expr(span, ExprKind::Struct(pth, fields, base), attrs));
2956 }
2957
2958 fn parse_or_use_outer_attributes(&mut self,
2959 already_parsed_attrs: Option<ThinVec<Attribute>>)
2960 -> PResult<'a, ThinVec<Attribute>> {
2961 if let Some(attrs) = already_parsed_attrs {
2962 Ok(attrs)
2963 } else {
2964 self.parse_outer_attributes().map(|a| a.into())
2965 }
2966 }
2967
2968 /// Parses a block or unsafe block.
2969 fn parse_block_expr(&mut self, opt_label: Option<Label>,
2970 lo: Span, blk_mode: BlockCheckMode,
2971 outer_attrs: ThinVec<Attribute>)
2972 -> PResult<'a, P<Expr>> {
2973 self.expect(&token::OpenDelim(token::Brace))?;
2974
2975 let mut attrs = outer_attrs;
2976 attrs.extend(self.parse_inner_attributes()?);
2977
2978 let blk = self.parse_block_tail(lo, blk_mode)?;
2979 return Ok(self.mk_expr(blk.span, ExprKind::Block(blk, opt_label), attrs));
2980 }
2981
2982 /// Parses `a.b` or `a(13)` or `a[4]` or just `a`.
2983 fn parse_dot_or_call_expr(&mut self,
2984 already_parsed_attrs: Option<ThinVec<Attribute>>)
2985 -> PResult<'a, P<Expr>> {
2986 let attrs = self.parse_or_use_outer_attributes(already_parsed_attrs)?;
2987
2988 let b = self.parse_bottom_expr();
2989 let (span, b) = self.interpolated_or_expr_span(b)?;
2990 self.parse_dot_or_call_expr_with(b, span, attrs)
2991 }
2992
2993 fn parse_dot_or_call_expr_with(&mut self,
2994 e0: P<Expr>,
2995 lo: Span,
2996 mut attrs: ThinVec<Attribute>)
2997 -> PResult<'a, P<Expr>> {
2998 // Stitch the list of outer attributes onto the return value.
2999 // A little bit ugly, but the best way given the current code
3000 // structure
3001 self.parse_dot_or_call_expr_with_(e0, lo)
3002 .map(|expr|
3003 expr.map(|mut expr| {
3004 attrs.extend::<Vec<_>>(expr.attrs.into());
3005 expr.attrs = attrs;
3006 match expr.node {
3007 ExprKind::If(..) | ExprKind::IfLet(..) => {
3008 if !expr.attrs.is_empty() {
3009 // Just point to the first attribute in there...
3010 let span = expr.attrs[0].span;
3011
3012 self.span_err(span,
3013 "attributes are not yet allowed on `if` \
3014 expressions");
3015 }
3016 }
3017 _ => {}
3018 }
3019 expr
3020 })
3021 )
3022 }
3023
3024 // Assuming we have just parsed `.`, continue parsing into an expression.
3025 fn parse_dot_suffix(&mut self, self_arg: P<Expr>, lo: Span) -> PResult<'a, P<Expr>> {
3026 let segment = self.parse_path_segment(PathStyle::Expr, true)?;
3027 self.check_trailing_angle_brackets(&segment, token::OpenDelim(token::Paren));
3028
3029 Ok(match self.token {
3030 token::OpenDelim(token::Paren) => {
3031 // Method call `expr.f()`
3032 let mut args = self.parse_unspanned_seq(
3033 &token::OpenDelim(token::Paren),
3034 &token::CloseDelim(token::Paren),
3035 SeqSep::trailing_allowed(token::Comma),
3036 |p| Ok(p.parse_expr()?)
3037 )?;
3038 args.insert(0, self_arg);
3039
3040 let span = lo.to(self.prev_span);
3041 self.mk_expr(span, ExprKind::MethodCall(segment, args), ThinVec::new())
3042 }
3043 _ => {
3044 // Field access `expr.f`
3045 if let Some(args) = segment.args {
3046 self.span_err(args.span(),
3047 "field expressions may not have generic arguments");
3048 }
3049
3050 let span = lo.to(self.prev_span);
3051 self.mk_expr(span, ExprKind::Field(self_arg, segment.ident), ThinVec::new())
3052 }
3053 })
3054 }
3055
3056 /// This function checks if there are trailing angle brackets and produces
3057 /// a diagnostic to suggest removing them.
3058 ///
3059 /// ```ignore (diagnostic)
3060 /// let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>();
3061 /// ^^ help: remove extra angle brackets
3062 /// ```
3063 fn check_trailing_angle_brackets(&mut self, segment: &PathSegment, end: token::Token) {
3064 // This function is intended to be invoked after parsing a path segment where there are two
3065 // cases:
3066 //
3067 // 1. A specific token is expected after the path segment.
3068 // eg. `x.foo(`, `x.foo::<u32>(` (parenthesis - method call),
3069 // `Foo::`, or `Foo::<Bar>::` (mod sep - continued path).
3070 // 2. No specific token is expected after the path segment.
3071 // eg. `x.foo` (field access)
3072 //
3073 // This function is called after parsing `.foo` and before parsing the token `end` (if
3074 // present). This includes any angle bracket arguments, such as `.foo::<u32>` or
3075 // `Foo::<Bar>`.
3076
3077 // We only care about trailing angle brackets if we previously parsed angle bracket
3078 // arguments. This helps stop us incorrectly suggesting that extra angle brackets be
3079 // removed in this case:
3080 //
3081 // `x.foo >> (3)` (where `x.foo` is a `u32` for example)
3082 //
3083 // This case is particularly tricky as we won't notice it just looking at the tokens -
3084 // it will appear the same (in terms of upcoming tokens) as below (since the `::<u32>` will
3085 // have already been parsed):
3086 //
3087 // `x.foo::<u32>>>(3)`
3088 let parsed_angle_bracket_args = segment.args
3089 .as_ref()
3090 .map(|args| args.is_angle_bracketed())
3091 .unwrap_or(false);
3092
3093 debug!(
3094 "check_trailing_angle_brackets: parsed_angle_bracket_args={:?}",
3095 parsed_angle_bracket_args,
3096 );
3097 if !parsed_angle_bracket_args {
3098 return;
3099 }
3100
3101 // Keep the span at the start so we can highlight the sequence of `>` characters to be
3102 // removed.
3103 let lo = self.span;
3104
3105 // We need to look-ahead to see if we have `>` characters without moving the cursor forward
3106 // (since we might have the field access case and the characters we're eating are
3107 // actual operators and not trailing characters - ie `x.foo >> 3`).
3108 let mut position = 0;
3109
3110 // We can encounter `>` or `>>` tokens in any order, so we need to keep track of how
3111 // many of each (so we can correctly pluralize our error messages) and continue to
3112 // advance.
3113 let mut number_of_shr = 0;
3114 let mut number_of_gt = 0;
3115 while self.look_ahead(position, |t| {
3116 trace!("check_trailing_angle_brackets: t={:?}", t);
3117 if *t == token::BinOp(token::BinOpToken::Shr) {
3118 number_of_shr += 1;
3119 true
3120 } else if *t == token::Gt {
3121 number_of_gt += 1;
3122 true
3123 } else {
3124 false
3125 }
3126 }) {
3127 position += 1;
3128 }
3129
3130 // If we didn't find any trailing `>` characters, then we have nothing to error about.
3131 debug!(
3132 "check_trailing_angle_brackets: number_of_gt={:?} number_of_shr={:?}",
3133 number_of_gt, number_of_shr,
3134 );
3135 if number_of_gt < 1 && number_of_shr < 1 {
3136 return;
3137 }
3138
3139 // Finally, double check that we have our end token as otherwise this is the
3140 // second case.
3141 if self.look_ahead(position, |t| {
3142 trace!("check_trailing_angle_brackets: t={:?}", t);
3143 *t == end
3144 }) {
3145 // Eat from where we started until the end token so that parsing can continue
3146 // as if we didn't have those extra angle brackets.
3147 self.eat_to_tokens(&[&end]);
3148 let span = lo.until(self.span);
3149
3150 let plural = number_of_gt > 1 || number_of_shr >= 1;
3151 self.diagnostic()
3152 .struct_span_err(
3153 span,
3154 &format!("unmatched angle bracket{}", if plural { "s" } else { "" }),
3155 )
3156 .span_suggestion(
3157 span,
3158 &format!("remove extra angle bracket{}", if plural { "s" } else { "" }),
3159 String::new(),
3160 Applicability::MachineApplicable,
3161 )
3162 .emit();
3163 }
3164 }
3165
3166 fn parse_dot_or_call_expr_with_(&mut self, e0: P<Expr>, lo: Span) -> PResult<'a, P<Expr>> {
3167 let mut e = e0;
3168 let mut hi;
3169 loop {
3170 // expr?
3171 while self.eat(&token::Question) {
3172 let hi = self.prev_span;
3173 e = self.mk_expr(lo.to(hi), ExprKind::Try(e), ThinVec::new());
3174 }
3175
3176 // expr.f
3177 if self.eat(&token::Dot) {
3178 match self.token {
3179 token::Ident(..) => {
3180 e = self.parse_dot_suffix(e, lo)?;
3181 }
3182 token::Literal(token::Integer(name), _) => {
3183 let span = self.span;
3184 self.bump();
3185 let field = ExprKind::Field(e, Ident::new(name, span));
3186 e = self.mk_expr(lo.to(span), field, ThinVec::new());
3187 }
3188 token::Literal(token::Float(n), _suf) => {
3189 self.bump();
3190 let fstr = n.as_str();
3191 let mut err = self.diagnostic()
3192 .struct_span_err(self.prev_span, &format!("unexpected token: `{}`", n));
3193 err.span_label(self.prev_span, "unexpected token");
3194 if fstr.chars().all(|x| "0123456789.".contains(x)) {
3195 let float = match fstr.parse::<f64>().ok() {
3196 Some(f) => f,
3197 None => continue,
3198 };
3199 let sugg = pprust::to_string(|s| {
3200 use crate::print::pprust::PrintState;
3201 s.popen()?;
3202 s.print_expr(&e)?;
3203 s.s.word( ".")?;
3204 s.print_usize(float.trunc() as usize)?;
3205 s.pclose()?;
3206 s.s.word(".")?;
3207 s.s.word(fstr.splitn(2, ".").last().unwrap().to_string())
3208 });
3209 err.span_suggestion(
3210 lo.to(self.prev_span),
3211 "try parenthesizing the first index",
3212 sugg,
3213 Applicability::MachineApplicable
3214 );
3215 }
3216 return Err(err);
3217
3218 }
3219 _ => {
3220 // FIXME Could factor this out into non_fatal_unexpected or something.
3221 let actual = self.this_token_to_string();
3222 self.span_err(self.span, &format!("unexpected token: `{}`", actual));
3223 }
3224 }
3225 continue;
3226 }
3227 if self.expr_is_complete(&e) { break; }
3228 match self.token {
3229 // expr(...)
3230 token::OpenDelim(token::Paren) => {
3231 let es = self.parse_unspanned_seq(
3232 &token::OpenDelim(token::Paren),
3233 &token::CloseDelim(token::Paren),
3234 SeqSep::trailing_allowed(token::Comma),
3235 |p| Ok(p.parse_expr()?)
3236 )?;
3237 hi = self.prev_span;
3238
3239 let nd = self.mk_call(e, es);
3240 e = self.mk_expr(lo.to(hi), nd, ThinVec::new());
3241 }
3242
3243 // expr[...]
3244 // Could be either an index expression or a slicing expression.
3245 token::OpenDelim(token::Bracket) => {
3246 self.bump();
3247 let ix = self.parse_expr()?;
3248 hi = self.span;
3249 self.expect(&token::CloseDelim(token::Bracket))?;
3250 let index = self.mk_index(e, ix);
3251 e = self.mk_expr(lo.to(hi), index, ThinVec::new())
3252 }
3253 _ => return Ok(e)
3254 }
3255 }
3256 return Ok(e);
3257 }
3258
3259 crate fn process_potential_macro_variable(&mut self) {
3260 let (token, span) = match self.token {
3261 token::Dollar if self.span.ctxt() != syntax_pos::hygiene::SyntaxContext::empty() &&
3262 self.look_ahead(1, |t| t.is_ident()) => {
3263 self.bump();
3264 let name = match self.token {
3265 token::Ident(ident, _) => ident,
3266 _ => unreachable!()
3267 };
3268 let mut err = self.fatal(&format!("unknown macro variable `{}`", name));
3269 err.span_label(self.span, "unknown macro variable");
3270 err.emit();
3271 self.bump();
3272 return
3273 }
3274 token::Interpolated(ref nt) => {
3275 self.meta_var_span = Some(self.span);
3276 // Interpolated identifier and lifetime tokens are replaced with usual identifier
3277 // and lifetime tokens, so the former are never encountered during normal parsing.
3278 match **nt {
3279 token::NtIdent(ident, is_raw) => (token::Ident(ident, is_raw), ident.span),
3280 token::NtLifetime(ident) => (token::Lifetime(ident), ident.span),
3281 _ => return,
3282 }
3283 }
3284 _ => return,
3285 };
3286 self.token = token;
3287 self.span = span;
3288 }
3289
3290 /// Parses a single token tree from the input.
3291 crate fn parse_token_tree(&mut self) -> TokenTree {
3292 match self.token {
3293 token::OpenDelim(..) => {
3294 let frame = mem::replace(&mut self.token_cursor.frame,
3295 self.token_cursor.stack.pop().unwrap());
3296 self.span = frame.span.entire();
3297 self.bump();
3298 TokenTree::Delimited(
3299 frame.span,
3300 frame.delim,
3301 frame.tree_cursor.stream.into(),
3302 )
3303 },
3304 token::CloseDelim(_) | token::Eof => unreachable!(),
3305 _ => {
3306 let (token, span) = (mem::replace(&mut self.token, token::Whitespace), self.span);
3307 self.bump();
3308 TokenTree::Token(span, token)
3309 }
3310 }
3311 }
3312
3313 // parse a stream of tokens into a list of TokenTree's,
3314 // up to EOF.
3315 pub fn parse_all_token_trees(&mut self) -> PResult<'a, Vec<TokenTree>> {
3316 let mut tts = Vec::new();
3317 while self.token != token::Eof {
3318 tts.push(self.parse_token_tree());
3319 }
3320 Ok(tts)
3321 }
3322
3323 pub fn parse_tokens(&mut self) -> TokenStream {
3324 let mut result = Vec::new();
3325 loop {
3326 match self.token {
3327 token::Eof | token::CloseDelim(..) => break,
3328 _ => result.push(self.parse_token_tree().into()),
3329 }
3330 }
3331 TokenStream::new(result)
3332 }
3333
3334 /// Parse a prefix-unary-operator expr
3335 fn parse_prefix_expr(&mut self,
3336 already_parsed_attrs: Option<ThinVec<Attribute>>)
3337 -> PResult<'a, P<Expr>> {
3338 let attrs = self.parse_or_use_outer_attributes(already_parsed_attrs)?;
3339 let lo = self.span;
3340 // Note: when adding new unary operators, don't forget to adjust Token::can_begin_expr()
3341 let (hi, ex) = match self.token {
3342 token::Not => {
3343 self.bump();
3344 let e = self.parse_prefix_expr(None);
3345 let (span, e) = self.interpolated_or_expr_span(e)?;
3346 (lo.to(span), self.mk_unary(UnOp::Not, e))
3347 }
3348 // Suggest `!` for bitwise negation when encountering a `~`
3349 token::Tilde => {
3350 self.bump();
3351 let e = self.parse_prefix_expr(None);
3352 let (span, e) = self.interpolated_or_expr_span(e)?;
3353 let span_of_tilde = lo;
3354 let mut err = self.diagnostic()
3355 .struct_span_err(span_of_tilde, "`~` cannot be used as a unary operator");
3356 err.span_suggestion_short(
3357 span_of_tilde,
3358 "use `!` to perform bitwise negation",
3359 "!".to_owned(),
3360 Applicability::MachineApplicable
3361 );
3362 err.emit();
3363 (lo.to(span), self.mk_unary(UnOp::Not, e))
3364 }
3365 token::BinOp(token::Minus) => {
3366 self.bump();
3367 let e = self.parse_prefix_expr(None);
3368 let (span, e) = self.interpolated_or_expr_span(e)?;
3369 (lo.to(span), self.mk_unary(UnOp::Neg, e))
3370 }
3371 token::BinOp(token::Star) => {
3372 self.bump();
3373 let e = self.parse_prefix_expr(None);
3374 let (span, e) = self.interpolated_or_expr_span(e)?;
3375 (lo.to(span), self.mk_unary(UnOp::Deref, e))
3376 }
3377 token::BinOp(token::And) | token::AndAnd => {
3378 self.expect_and()?;
3379 let m = self.parse_mutability();
3380 let e = self.parse_prefix_expr(None);
3381 let (span, e) = self.interpolated_or_expr_span(e)?;
3382 (lo.to(span), ExprKind::AddrOf(m, e))
3383 }
3384 token::Ident(..) if self.token.is_keyword(keywords::In) => {
3385 self.bump();
3386 let place = self.parse_expr_res(
3387 Restrictions::NO_STRUCT_LITERAL,
3388 None,
3389 )?;
3390 let blk = self.parse_block()?;
3391 let span = blk.span;
3392 let blk_expr = self.mk_expr(span, ExprKind::Block(blk, None), ThinVec::new());
3393 (lo.to(span), ExprKind::ObsoleteInPlace(place, blk_expr))
3394 }
3395 token::Ident(..) if self.token.is_keyword(keywords::Box) => {
3396 self.bump();
3397 let e = self.parse_prefix_expr(None);
3398 let (span, e) = self.interpolated_or_expr_span(e)?;
3399 (lo.to(span), ExprKind::Box(e))
3400 }
3401 token::Ident(..) if self.token.is_ident_named("not") => {
3402 // `not` is just an ordinary identifier in Rust-the-language,
3403 // but as `rustc`-the-compiler, we can issue clever diagnostics
3404 // for confused users who really want to say `!`
3405 let token_cannot_continue_expr = |t: &token::Token| match *t {
3406 // These tokens can start an expression after `!`, but
3407 // can't continue an expression after an ident
3408 token::Ident(ident, is_raw) => token::ident_can_begin_expr(ident, is_raw),
3409 token::Literal(..) | token::Pound => true,
3410 token::Interpolated(ref nt) => match **nt {
3411 token::NtIdent(..) | token::NtExpr(..) |
3412 token::NtBlock(..) | token::NtPath(..) => true,
3413 _ => false,
3414 },
3415 _ => false
3416 };
3417 let cannot_continue_expr = self.look_ahead(1, token_cannot_continue_expr);
3418 if cannot_continue_expr {
3419 self.bump();
3420 // Emit the error ...
3421 let mut err = self.diagnostic()
3422 .struct_span_err(self.span,
3423 &format!("unexpected {} after identifier",
3424 self.this_token_descr()));
3425 // span the `not` plus trailing whitespace to avoid
3426 // trailing whitespace after the `!` in our suggestion
3427 let to_replace = self.sess.source_map()
3428 .span_until_non_whitespace(lo.to(self.span));
3429 err.span_suggestion_short(
3430 to_replace,
3431 "use `!` to perform logical negation",
3432 "!".to_owned(),
3433 Applicability::MachineApplicable
3434 );
3435 err.emit();
3436 // —and recover! (just as if we were in the block
3437 // for the `token::Not` arm)
3438 let e = self.parse_prefix_expr(None);
3439 let (span, e) = self.interpolated_or_expr_span(e)?;
3440 (lo.to(span), self.mk_unary(UnOp::Not, e))
3441 } else {
3442 return self.parse_dot_or_call_expr(Some(attrs));
3443 }
3444 }
3445 _ => { return self.parse_dot_or_call_expr(Some(attrs)); }
3446 };
3447 return Ok(self.mk_expr(lo.to(hi), ex, attrs));
3448 }
3449
3450 /// Parses an associative expression.
3451 ///
3452 /// This parses an expression accounting for associativity and precedence of the operators in
3453 /// the expression.
3454 #[inline]
3455 fn parse_assoc_expr(&mut self,
3456 already_parsed_attrs: Option<ThinVec<Attribute>>)
3457 -> PResult<'a, P<Expr>> {
3458 self.parse_assoc_expr_with(0, already_parsed_attrs.into())
3459 }
3460
3461 /// Parses an associative expression with operators of at least `min_prec` precedence.
3462 fn parse_assoc_expr_with(&mut self,
3463 min_prec: usize,
3464 lhs: LhsExpr)
3465 -> PResult<'a, P<Expr>> {
3466 let mut lhs = if let LhsExpr::AlreadyParsed(expr) = lhs {
3467 expr
3468 } else {
3469 let attrs = match lhs {
3470 LhsExpr::AttributesParsed(attrs) => Some(attrs),
3471 _ => None,
3472 };
3473 if [token::DotDot, token::DotDotDot, token::DotDotEq].contains(&self.token) {
3474 return self.parse_prefix_range_expr(attrs);
3475 } else {
3476 self.parse_prefix_expr(attrs)?
3477 }
3478 };
3479
3480 if self.expr_is_complete(&lhs) {
3481 // Semi-statement forms are odd. See https://github.com/rust-lang/rust/issues/29071
3482 return Ok(lhs);
3483 }
3484 self.expected_tokens.push(TokenType::Operator);
3485 while let Some(op) = AssocOp::from_token(&self.token) {
3486
3487 // Adjust the span for interpolated LHS to point to the `$lhs` token and not to what
3488 // it refers to. Interpolated identifiers are unwrapped early and never show up here
3489 // as `PrevTokenKind::Interpolated` so if LHS is a single identifier we always process
3490 // it as "interpolated", it doesn't change the answer for non-interpolated idents.
3491 let lhs_span = match (self.prev_token_kind, &lhs.node) {
3492 (PrevTokenKind::Interpolated, _) => self.prev_span,
3493 (PrevTokenKind::Ident, &ExprKind::Path(None, ref path))
3494 if path.segments.len() == 1 => self.prev_span,
3495 _ => lhs.span,
3496 };
3497
3498 let cur_op_span = self.span;
3499 let restrictions = if op.is_assign_like() {
3500 self.restrictions & Restrictions::NO_STRUCT_LITERAL
3501 } else {
3502 self.restrictions
3503 };
3504 if op.precedence() < min_prec {
3505 break;
3506 }
3507 // Check for deprecated `...` syntax
3508 if self.token == token::DotDotDot && op == AssocOp::DotDotEq {
3509 self.err_dotdotdot_syntax(self.span);
3510 }
3511
3512 self.bump();
3513 if op.is_comparison() {
3514 self.check_no_chained_comparison(&lhs, &op);
3515 }
3516 // Special cases:
3517 if op == AssocOp::As {
3518 lhs = self.parse_assoc_op_cast(lhs, lhs_span, ExprKind::Cast)?;
3519 continue
3520 } else if op == AssocOp::Colon {
3521 lhs = match self.parse_assoc_op_cast(lhs, lhs_span, ExprKind::Type) {
3522 Ok(lhs) => lhs,
3523 Err(mut err) => {
3524 err.span_label(self.span,
3525 "expecting a type here because of type ascription");
3526 let cm = self.sess.source_map();
3527 let cur_pos = cm.lookup_char_pos(self.span.lo());
3528 let op_pos = cm.lookup_char_pos(cur_op_span.hi());
3529 if cur_pos.line != op_pos.line {
3530 err.span_suggestion(
3531 cur_op_span,
3532 "try using a semicolon",
3533 ";".to_string(),
3534 Applicability::MaybeIncorrect // speculative
3535 );
3536 }
3537 return Err(err);
3538 }
3539 };
3540 continue
3541 } else if op == AssocOp::DotDot || op == AssocOp::DotDotEq {
3542 // If we didn’t have to handle `x..`/`x..=`, it would be pretty easy to
3543 // generalise it to the Fixity::None code.
3544 //
3545 // We have 2 alternatives here: `x..y`/`x..=y` and `x..`/`x..=` The other
3546 // two variants are handled with `parse_prefix_range_expr` call above.
3547 let rhs = if self.is_at_start_of_range_notation_rhs() {
3548 Some(self.parse_assoc_expr_with(op.precedence() + 1,
3549 LhsExpr::NotYetParsed)?)
3550 } else {
3551 None
3552 };
3553 let (lhs_span, rhs_span) = (lhs.span, if let Some(ref x) = rhs {
3554 x.span
3555 } else {
3556 cur_op_span
3557 });
3558 let limits = if op == AssocOp::DotDot {
3559 RangeLimits::HalfOpen
3560 } else {
3561 RangeLimits::Closed
3562 };
3563
3564 let r = self.mk_range(Some(lhs), rhs, limits)?;
3565 lhs = self.mk_expr(lhs_span.to(rhs_span), r, ThinVec::new());
3566 break
3567 }
3568
3569 let rhs = match op.fixity() {
3570 Fixity::Right => self.with_res(
3571 restrictions - Restrictions::STMT_EXPR,
3572 |this| {
3573 this.parse_assoc_expr_with(op.precedence(),
3574 LhsExpr::NotYetParsed)
3575 }),
3576 Fixity::Left => self.with_res(
3577 restrictions - Restrictions::STMT_EXPR,
3578 |this| {
3579 this.parse_assoc_expr_with(op.precedence() + 1,
3580 LhsExpr::NotYetParsed)
3581 }),
3582 // We currently have no non-associative operators that are not handled above by
3583 // the special cases. The code is here only for future convenience.
3584 Fixity::None => self.with_res(
3585 restrictions - Restrictions::STMT_EXPR,
3586 |this| {
3587 this.parse_assoc_expr_with(op.precedence() + 1,
3588 LhsExpr::NotYetParsed)
3589 }),
3590 }?;
3591
3592 // Make sure that the span of the parent node is larger than the span of lhs and rhs,
3593 // including the attributes.
3594 let lhs_span = lhs
3595 .attrs
3596 .iter()
3597 .filter(|a| a.style == AttrStyle::Outer)
3598 .next()
3599 .map_or(lhs_span, |a| a.span);
3600 let span = lhs_span.to(rhs.span);
3601 lhs = match op {
3602 AssocOp::Add | AssocOp::Subtract | AssocOp::Multiply | AssocOp::Divide |
3603 AssocOp::Modulus | AssocOp::LAnd | AssocOp::LOr | AssocOp::BitXor |
3604 AssocOp::BitAnd | AssocOp::BitOr | AssocOp::ShiftLeft | AssocOp::ShiftRight |
3605 AssocOp::Equal | AssocOp::Less | AssocOp::LessEqual | AssocOp::NotEqual |
3606 AssocOp::Greater | AssocOp::GreaterEqual => {
3607 let ast_op = op.to_ast_binop().unwrap();
3608 let binary = self.mk_binary(source_map::respan(cur_op_span, ast_op), lhs, rhs);
3609 self.mk_expr(span, binary, ThinVec::new())
3610 }
3611 AssocOp::Assign =>
3612 self.mk_expr(span, ExprKind::Assign(lhs, rhs), ThinVec::new()),
3613 AssocOp::ObsoleteInPlace =>
3614 self.mk_expr(span, ExprKind::ObsoleteInPlace(lhs, rhs), ThinVec::new()),
3615 AssocOp::AssignOp(k) => {
3616 let aop = match k {
3617 token::Plus => BinOpKind::Add,
3618 token::Minus => BinOpKind::Sub,
3619 token::Star => BinOpKind::Mul,
3620 token::Slash => BinOpKind::Div,
3621 token::Percent => BinOpKind::Rem,
3622 token::Caret => BinOpKind::BitXor,
3623 token::And => BinOpKind::BitAnd,
3624 token::Or => BinOpKind::BitOr,
3625 token::Shl => BinOpKind::Shl,
3626 token::Shr => BinOpKind::Shr,
3627 };
3628 let aopexpr = self.mk_assign_op(source_map::respan(cur_op_span, aop), lhs, rhs);
3629 self.mk_expr(span, aopexpr, ThinVec::new())
3630 }
3631 AssocOp::As | AssocOp::Colon | AssocOp::DotDot | AssocOp::DotDotEq => {
3632 self.bug("AssocOp should have been handled by special case")
3633 }
3634 };
3635
3636 if op.fixity() == Fixity::None { break }
3637 }
3638 Ok(lhs)
3639 }
3640
3641 fn parse_assoc_op_cast(&mut self, lhs: P<Expr>, lhs_span: Span,
3642 expr_kind: fn(P<Expr>, P<Ty>) -> ExprKind)
3643 -> PResult<'a, P<Expr>> {
3644 let mk_expr = |this: &mut Self, rhs: P<Ty>| {
3645 this.mk_expr(lhs_span.to(rhs.span), expr_kind(lhs, rhs), ThinVec::new())
3646 };
3647
3648 // Save the state of the parser before parsing type normally, in case there is a
3649 // LessThan comparison after this cast.
3650 let parser_snapshot_before_type = self.clone();
3651 match self.parse_ty_no_plus() {
3652 Ok(rhs) => {
3653 Ok(mk_expr(self, rhs))
3654 }
3655 Err(mut type_err) => {
3656 // Rewind to before attempting to parse the type with generics, to recover
3657 // from situations like `x as usize < y` in which we first tried to parse
3658 // `usize < y` as a type with generic arguments.
3659 let parser_snapshot_after_type = self.clone();
3660 mem::replace(self, parser_snapshot_before_type);
3661
3662 match self.parse_path(PathStyle::Expr) {
3663 Ok(path) => {
3664 let (op_noun, op_verb) = match self.token {
3665 token::Lt => ("comparison", "comparing"),
3666 token::BinOp(token::Shl) => ("shift", "shifting"),
3667 _ => {
3668 // We can end up here even without `<` being the next token, for
3669 // example because `parse_ty_no_plus` returns `Err` on keywords,
3670 // but `parse_path` returns `Ok` on them due to error recovery.
3671 // Return original error and parser state.
3672 mem::replace(self, parser_snapshot_after_type);
3673 return Err(type_err);
3674 }
3675 };
3676
3677 // Successfully parsed the type path leaving a `<` yet to parse.
3678 type_err.cancel();
3679
3680 // Report non-fatal diagnostics, keep `x as usize` as an expression
3681 // in AST and continue parsing.
3682 let msg = format!("`<` is interpreted as a start of generic \
3683 arguments for `{}`, not a {}", path, op_noun);
3684 let mut err = self.sess.span_diagnostic.struct_span_err(self.span, &msg);
3685 err.span_label(self.look_ahead_span(1).to(parser_snapshot_after_type.span),
3686 "interpreted as generic arguments");
3687 err.span_label(self.span, format!("not interpreted as {}", op_noun));
3688
3689 let expr = mk_expr(self, P(Ty {
3690 span: path.span,
3691 node: TyKind::Path(None, path),
3692 id: ast::DUMMY_NODE_ID
3693 }));
3694
3695 let expr_str = self.sess.source_map().span_to_snippet(expr.span)
3696 .unwrap_or_else(|_| pprust::expr_to_string(&expr));
3697 err.span_suggestion(
3698 expr.span,
3699 &format!("try {} the cast value", op_verb),
3700 format!("({})", expr_str),
3701 Applicability::MachineApplicable
3702 );
3703 err.emit();
3704
3705 Ok(expr)
3706 }
3707 Err(mut path_err) => {
3708 // Couldn't parse as a path, return original error and parser state.
3709 path_err.cancel();
3710 mem::replace(self, parser_snapshot_after_type);
3711 Err(type_err)
3712 }
3713 }
3714 }
3715 }
3716 }
3717
3718 /// Produce an error if comparison operators are chained (RFC #558).
3719 /// We only need to check lhs, not rhs, because all comparison ops
3720 /// have same precedence and are left-associative
3721 fn check_no_chained_comparison(&mut self, lhs: &Expr, outer_op: &AssocOp) {
3722 debug_assert!(outer_op.is_comparison(),
3723 "check_no_chained_comparison: {:?} is not comparison",
3724 outer_op);
3725 match lhs.node {
3726 ExprKind::Binary(op, _, _) if op.node.is_comparison() => {
3727 // respan to include both operators
3728 let op_span = op.span.to(self.span);
3729 let mut err = self.diagnostic().struct_span_err(op_span,
3730 "chained comparison operators require parentheses");
3731 if op.node == BinOpKind::Lt &&
3732 *outer_op == AssocOp::Less || // Include `<` to provide this recommendation
3733 *outer_op == AssocOp::Greater // even in a case like the following:
3734 { // Foo<Bar<Baz<Qux, ()>>>
3735 err.help(
3736 "use `::<...>` instead of `<...>` if you meant to specify type arguments");
3737 err.help("or use `(...)` if you meant to specify fn arguments");
3738 }
3739 err.emit();
3740 }
3741 _ => {}
3742 }
3743 }
3744
3745 /// Parse prefix-forms of range notation: `..expr`, `..`, `..=expr`
3746 fn parse_prefix_range_expr(&mut self,
3747 already_parsed_attrs: Option<ThinVec<Attribute>>)
3748 -> PResult<'a, P<Expr>> {
3749 // Check for deprecated `...` syntax
3750 if self.token == token::DotDotDot {
3751 self.err_dotdotdot_syntax(self.span);
3752 }
3753
3754 debug_assert!([token::DotDot, token::DotDotDot, token::DotDotEq].contains(&self.token),
3755 "parse_prefix_range_expr: token {:?} is not DotDot/DotDotEq",
3756 self.token);
3757 let tok = self.token.clone();
3758 let attrs = self.parse_or_use_outer_attributes(already_parsed_attrs)?;
3759 let lo = self.span;
3760 let mut hi = self.span;
3761 self.bump();
3762 let opt_end = if self.is_at_start_of_range_notation_rhs() {
3763 // RHS must be parsed with more associativity than the dots.
3764 let next_prec = AssocOp::from_token(&tok).unwrap().precedence() + 1;
3765 Some(self.parse_assoc_expr_with(next_prec,
3766 LhsExpr::NotYetParsed)
3767 .map(|x|{
3768 hi = x.span;
3769 x
3770 })?)
3771 } else {
3772 None
3773 };
3774 let limits = if tok == token::DotDot {
3775 RangeLimits::HalfOpen
3776 } else {
3777 RangeLimits::Closed
3778 };
3779
3780 let r = self.mk_range(None, opt_end, limits)?;
3781 Ok(self.mk_expr(lo.to(hi), r, attrs))
3782 }
3783
3784 fn is_at_start_of_range_notation_rhs(&self) -> bool {
3785 if self.token.can_begin_expr() {
3786 // parse `for i in 1.. { }` as infinite loop, not as `for i in (1..{})`.
3787 if self.token == token::OpenDelim(token::Brace) {
3788 return !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL);
3789 }
3790 true
3791 } else {
3792 false
3793 }
3794 }
3795
3796 /// Parses an `if` or `if let` expression (`if` token already eaten).
3797 fn parse_if_expr(&mut self, attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
3798 if self.check_keyword(keywords::Let) {
3799 return self.parse_if_let_expr(attrs);
3800 }
3801 let lo = self.prev_span;
3802 let cond = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?;
3803
3804 // Verify that the parsed `if` condition makes sense as a condition. If it is a block, then
3805 // verify that the last statement is either an implicit return (no `;`) or an explicit
3806 // return. This won't catch blocks with an explicit `return`, but that would be caught by
3807 // the dead code lint.
3808 if self.eat_keyword(keywords::Else) || !cond.returns() {
3809 let sp = self.sess.source_map().next_point(lo);
3810 let mut err = self.diagnostic()
3811 .struct_span_err(sp, "missing condition for `if` statemement");
3812 err.span_label(sp, "expected if condition here");
3813 return Err(err)
3814 }
3815 let not_block = self.token != token::OpenDelim(token::Brace);
3816 let thn = self.parse_block().map_err(|mut err| {
3817 if not_block {
3818 err.span_label(lo, "this `if` statement has a condition, but no block");
3819 }
3820 err
3821 })?;
3822 let mut els: Option<P<Expr>> = None;
3823 let mut hi = thn.span;
3824 if self.eat_keyword(keywords::Else) {
3825 let elexpr = self.parse_else_expr()?;
3826 hi = elexpr.span;
3827 els = Some(elexpr);
3828 }
3829 Ok(self.mk_expr(lo.to(hi), ExprKind::If(cond, thn, els), attrs))
3830 }
3831
3832 /// Parses an `if let` expression (`if` token already eaten).
3833 fn parse_if_let_expr(&mut self, attrs: ThinVec<Attribute>)
3834 -> PResult<'a, P<Expr>> {
3835 let lo = self.prev_span;
3836 self.expect_keyword(keywords::Let)?;
3837 let pats = self.parse_pats()?;
3838 self.expect(&token::Eq)?;
3839 let expr = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?;
3840 let thn = self.parse_block()?;
3841 let (hi, els) = if self.eat_keyword(keywords::Else) {
3842 let expr = self.parse_else_expr()?;
3843 (expr.span, Some(expr))
3844 } else {
3845 (thn.span, None)
3846 };
3847 Ok(self.mk_expr(lo.to(hi), ExprKind::IfLet(pats, expr, thn, els), attrs))
3848 }
3849
3850 /// Parses `move |args| expr`.
3851 fn parse_lambda_expr(&mut self,
3852 attrs: ThinVec<Attribute>)
3853 -> PResult<'a, P<Expr>>
3854 {
3855 let lo = self.span;
3856 let movability = if self.eat_keyword(keywords::Static) {
3857 Movability::Static
3858 } else {
3859 Movability::Movable
3860 };
3861 let asyncness = if self.span.rust_2018() {
3862 self.parse_asyncness()
3863 } else {
3864 IsAsync::NotAsync
3865 };
3866 let capture_clause = if self.eat_keyword(keywords::Move) {
3867 CaptureBy::Value
3868 } else {
3869 CaptureBy::Ref
3870 };
3871 let decl = self.parse_fn_block_decl()?;
3872 let decl_hi = self.prev_span;
3873 let body = match decl.output {
3874 FunctionRetTy::Default(_) => {
3875 let restrictions = self.restrictions - Restrictions::STMT_EXPR;
3876 self.parse_expr_res(restrictions, None)?
3877 },
3878 _ => {
3879 // If an explicit return type is given, require a
3880 // block to appear (RFC 968).
3881 let body_lo = self.span;
3882 self.parse_block_expr(None, body_lo, BlockCheckMode::Default, ThinVec::new())?
3883 }
3884 };
3885
3886 Ok(self.mk_expr(
3887 lo.to(body.span),
3888 ExprKind::Closure(capture_clause, asyncness, movability, decl, body, lo.to(decl_hi)),
3889 attrs))
3890 }
3891
3892 // `else` token already eaten
3893 fn parse_else_expr(&mut self) -> PResult<'a, P<Expr>> {
3894 if self.eat_keyword(keywords::If) {
3895 return self.parse_if_expr(ThinVec::new());
3896 } else {
3897 let blk = self.parse_block()?;
3898 return Ok(self.mk_expr(blk.span, ExprKind::Block(blk, None), ThinVec::new()));
3899 }
3900 }
3901
3902 /// Parse a 'for' .. 'in' expression ('for' token already eaten)
3903 fn parse_for_expr(&mut self, opt_label: Option<Label>,
3904 span_lo: Span,
3905 mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
3906 // Parse: `for <src_pat> in <src_expr> <src_loop_block>`
3907
3908 let pat = self.parse_top_level_pat()?;
3909 if !self.eat_keyword(keywords::In) {
3910 let in_span = self.prev_span.between(self.span);
3911 let mut err = self.sess.span_diagnostic
3912 .struct_span_err(in_span, "missing `in` in `for` loop");
3913 err.span_suggestion_short(
3914 in_span, "try adding `in` here", " in ".into(),
3915 // has been misleading, at least in the past (closed Issue #48492)
3916 Applicability::MaybeIncorrect
3917 );
3918 err.emit();
3919 }
3920 let in_span = self.prev_span;
3921 if self.eat_keyword(keywords::In) {
3922 // a common typo: `for _ in in bar {}`
3923 let mut err = self.sess.span_diagnostic.struct_span_err(
3924 self.prev_span,
3925 "expected iterable, found keyword `in`",
3926 );
3927 err.span_suggestion_short(
3928 in_span.until(self.prev_span),
3929 "remove the duplicated `in`",
3930 String::new(),
3931 Applicability::MachineApplicable,
3932 );
3933 err.note("if you meant to use emplacement syntax, it is obsolete (for now, anyway)");
3934 err.note("for more information on the status of emplacement syntax, see <\
3935 https://github.com/rust-lang/rust/issues/27779#issuecomment-378416911>");
3936 err.emit();
3937 }
3938 let expr = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?;
3939 let (iattrs, loop_block) = self.parse_inner_attrs_and_block()?;
3940 attrs.extend(iattrs);
3941
3942 let hi = self.prev_span;
3943 Ok(self.mk_expr(span_lo.to(hi), ExprKind::ForLoop(pat, expr, loop_block, opt_label), attrs))
3944 }
3945
3946 /// Parses a `while` or `while let` expression (`while` token already eaten).
3947 fn parse_while_expr(&mut self, opt_label: Option<Label>,
3948 span_lo: Span,
3949 mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
3950 if self.token.is_keyword(keywords::Let) {
3951 return self.parse_while_let_expr(opt_label, span_lo, attrs);
3952 }
3953 let cond = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?;
3954 let (iattrs, body) = self.parse_inner_attrs_and_block()?;
3955 attrs.extend(iattrs);
3956 let span = span_lo.to(body.span);
3957 return Ok(self.mk_expr(span, ExprKind::While(cond, body, opt_label), attrs));
3958 }
3959
3960 /// Parses a `while let` expression (`while` token already eaten).
3961 fn parse_while_let_expr(&mut self, opt_label: Option<Label>,
3962 span_lo: Span,
3963 mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
3964 self.expect_keyword(keywords::Let)?;
3965 let pats = self.parse_pats()?;
3966 self.expect(&token::Eq)?;
3967 let expr = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?;
3968 let (iattrs, body) = self.parse_inner_attrs_and_block()?;
3969 attrs.extend(iattrs);
3970 let span = span_lo.to(body.span);
3971 return Ok(self.mk_expr(span, ExprKind::WhileLet(pats, expr, body, opt_label), attrs));
3972 }
3973
3974 // parse `loop {...}`, `loop` token already eaten
3975 fn parse_loop_expr(&mut self, opt_label: Option<Label>,
3976 span_lo: Span,
3977 mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
3978 let (iattrs, body) = self.parse_inner_attrs_and_block()?;
3979 attrs.extend(iattrs);
3980 let span = span_lo.to(body.span);
3981 Ok(self.mk_expr(span, ExprKind::Loop(body, opt_label), attrs))
3982 }
3983
3984 /// Parses an `async move {...}` expression.
3985 pub fn parse_async_block(&mut self, mut attrs: ThinVec<Attribute>)
3986 -> PResult<'a, P<Expr>>
3987 {
3988 let span_lo = self.span;
3989 self.expect_keyword(keywords::Async)?;
3990 let capture_clause = if self.eat_keyword(keywords::Move) {
3991 CaptureBy::Value
3992 } else {
3993 CaptureBy::Ref
3994 };
3995 let (iattrs, body) = self.parse_inner_attrs_and_block()?;
3996 attrs.extend(iattrs);
3997 Ok(self.mk_expr(
3998 span_lo.to(body.span),
3999 ExprKind::Async(capture_clause, ast::DUMMY_NODE_ID, body), attrs))
4000 }
4001
4002 /// Parses a `try {...}` expression (`try` token already eaten).
4003 fn parse_try_block(&mut self, span_lo: Span, mut attrs: ThinVec<Attribute>)
4004 -> PResult<'a, P<Expr>>
4005 {
4006 let (iattrs, body) = self.parse_inner_attrs_and_block()?;
4007 attrs.extend(iattrs);
4008 Ok(self.mk_expr(span_lo.to(body.span), ExprKind::TryBlock(body), attrs))
4009 }
4010
4011 // `match` token already eaten
4012 fn parse_match_expr(&mut self, mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
4013 let match_span = self.prev_span;
4014 let lo = self.prev_span;
4015 let discriminant = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL,
4016 None)?;
4017 if let Err(mut e) = self.expect(&token::OpenDelim(token::Brace)) {
4018 if self.token == token::Token::Semi {
4019 e.span_suggestion_short(
4020 match_span,
4021 "try removing this `match`",
4022 String::new(),
4023 Applicability::MaybeIncorrect // speculative
4024 );
4025 }
4026 return Err(e)
4027 }
4028 attrs.extend(self.parse_inner_attributes()?);
4029
4030 let mut arms: Vec<Arm> = Vec::new();
4031 while self.token != token::CloseDelim(token::Brace) {
4032 match self.parse_arm() {
4033 Ok(arm) => arms.push(arm),
4034 Err(mut e) => {
4035 // Recover by skipping to the end of the block.
4036 e.emit();
4037 self.recover_stmt();
4038 let span = lo.to(self.span);
4039 if self.token == token::CloseDelim(token::Brace) {
4040 self.bump();
4041 }
4042 return Ok(self.mk_expr(span, ExprKind::Match(discriminant, arms), attrs));
4043 }
4044 }
4045 }
4046 let hi = self.span;
4047 self.bump();
4048 return Ok(self.mk_expr(lo.to(hi), ExprKind::Match(discriminant, arms), attrs));
4049 }
4050
4051 crate fn parse_arm(&mut self) -> PResult<'a, Arm> {
4052 maybe_whole!(self, NtArm, |x| x);
4053
4054 let attrs = self.parse_outer_attributes()?;
4055 let pats = self.parse_pats()?;
4056 let guard = if self.eat_keyword(keywords::If) {
4057 Some(Guard::If(self.parse_expr()?))
4058 } else {
4059 None
4060 };
4061 let arrow_span = self.span;
4062 self.expect(&token::FatArrow)?;
4063 let arm_start_span = self.span;
4064
4065 let expr = self.parse_expr_res(Restrictions::STMT_EXPR, None)
4066 .map_err(|mut err| {
4067 err.span_label(arrow_span, "while parsing the `match` arm starting here");
4068 err
4069 })?;
4070
4071 let require_comma = classify::expr_requires_semi_to_be_stmt(&expr)
4072 && self.token != token::CloseDelim(token::Brace);
4073
4074 if require_comma {
4075 let cm = self.sess.source_map();
4076 self.expect_one_of(&[token::Comma], &[token::CloseDelim(token::Brace)])
4077 .map_err(|mut err| {
4078 match (cm.span_to_lines(expr.span), cm.span_to_lines(arm_start_span)) {
4079 (Ok(ref expr_lines), Ok(ref arm_start_lines))
4080 if arm_start_lines.lines[0].end_col == expr_lines.lines[0].end_col
4081 && expr_lines.lines.len() == 2
4082 && self.token == token::FatArrow => {
4083 // We check whether there's any trailing code in the parse span,
4084 // if there isn't, we very likely have the following:
4085 //
4086 // X | &Y => "y"
4087 // | -- - missing comma
4088 // | |
4089 // | arrow_span
4090 // X | &X => "x"
4091 // | - ^^ self.span
4092 // | |
4093 // | parsed until here as `"y" & X`
4094 err.span_suggestion_short(
4095 cm.next_point(arm_start_span),
4096 "missing a comma here to end this `match` arm",
4097 ",".to_owned(),
4098 Applicability::MachineApplicable
4099 );
4100 }
4101 _ => {
4102 err.span_label(arrow_span,
4103 "while parsing the `match` arm starting here");
4104 }
4105 }
4106 err
4107 })?;
4108 } else {
4109 self.eat(&token::Comma);
4110 }
4111
4112 Ok(ast::Arm {
4113 attrs,
4114 pats,
4115 guard,
4116 body: expr,
4117 })
4118 }
4119
4120 /// Parses an expression.
4121 #[inline]
4122 pub fn parse_expr(&mut self) -> PResult<'a, P<Expr>> {
4123 self.parse_expr_res(Restrictions::empty(), None)
4124 }
4125
4126 /// Evaluates the closure with restrictions in place.
4127 ///
4128 /// Afters the closure is evaluated, restrictions are reset.
4129 fn with_res<F, T>(&mut self, r: Restrictions, f: F) -> T
4130 where F: FnOnce(&mut Self) -> T
4131 {
4132 let old = self.restrictions;
4133 self.restrictions = r;
4134 let r = f(self);
4135 self.restrictions = old;
4136 return r;
4137
4138 }
4139
4140 /// Parses an expression, subject to the given restrictions.
4141 #[inline]
4142 fn parse_expr_res(&mut self, r: Restrictions,
4143 already_parsed_attrs: Option<ThinVec<Attribute>>)
4144 -> PResult<'a, P<Expr>> {
4145 self.with_res(r, |this| this.parse_assoc_expr(already_parsed_attrs))
4146 }
4147
4148 /// Parses the RHS of a local variable declaration (e.g., '= 14;').
4149 fn parse_initializer(&mut self, skip_eq: bool) -> PResult<'a, Option<P<Expr>>> {
4150 if self.eat(&token::Eq) {
4151 Ok(Some(self.parse_expr()?))
4152 } else if skip_eq {
4153 Ok(Some(self.parse_expr()?))
4154 } else {
4155 Ok(None)
4156 }
4157 }
4158
4159 /// Parses patterns, separated by '|' s.
4160 fn parse_pats(&mut self) -> PResult<'a, Vec<P<Pat>>> {
4161 // Allow a '|' before the pats (RFC 1925 + RFC 2530)
4162 self.eat(&token::BinOp(token::Or));
4163
4164 let mut pats = Vec::new();
4165 loop {
4166 pats.push(self.parse_top_level_pat()?);
4167
4168 if self.token == token::OrOr {
4169 let mut err = self.struct_span_err(self.span,
4170 "unexpected token `||` after pattern");
4171 err.span_suggestion(
4172 self.span,
4173 "use a single `|` to specify multiple patterns",
4174 "|".to_owned(),
4175 Applicability::MachineApplicable
4176 );
4177 err.emit();
4178 self.bump();
4179 } else if self.eat(&token::BinOp(token::Or)) {
4180 // This is a No-op. Continue the loop to parse the next
4181 // pattern.
4182 } else {
4183 return Ok(pats);
4184 }
4185 };
4186 }
4187
4188 // Parses a parenthesized list of patterns like
4189 // `()`, `(p)`, `(p,)`, `(p, q)`, or `(p, .., q)`. Returns:
4190 // - a vector of the patterns that were parsed
4191 // - an option indicating the index of the `..` element
4192 // - a boolean indicating whether a trailing comma was present.
4193 // Trailing commas are significant because (p) and (p,) are different patterns.
4194 fn parse_parenthesized_pat_list(&mut self) -> PResult<'a, (Vec<P<Pat>>, Option<usize>, bool)> {
4195 self.expect(&token::OpenDelim(token::Paren))?;
4196 let result = self.parse_pat_list()?;
4197 self.expect(&token::CloseDelim(token::Paren))?;
4198 Ok(result)
4199 }
4200
4201 fn parse_pat_list(&mut self) -> PResult<'a, (Vec<P<Pat>>, Option<usize>, bool)> {
4202 let mut fields = Vec::new();
4203 let mut ddpos = None;
4204 let mut trailing_comma = false;
4205 loop {
4206 if self.eat(&token::DotDot) {
4207 if ddpos.is_none() {
4208 ddpos = Some(fields.len());
4209 } else {
4210 // Emit a friendly error, ignore `..` and continue parsing
4211 self.struct_span_err(
4212 self.prev_span,
4213 "`..` can only be used once per tuple or tuple struct pattern",
4214 )
4215 .span_label(self.prev_span, "can only be used once per pattern")
4216 .emit();
4217 }
4218 } else if !self.check(&token::CloseDelim(token::Paren)) {
4219 fields.push(self.parse_pat(None)?);
4220 } else {
4221 break
4222 }
4223
4224 trailing_comma = self.eat(&token::Comma);
4225 if !trailing_comma {
4226 break
4227 }
4228 }
4229
4230 if ddpos == Some(fields.len()) && trailing_comma {
4231 // `..` needs to be followed by `)` or `, pat`, `..,)` is disallowed.
4232 let msg = "trailing comma is not permitted after `..`";
4233 self.struct_span_err(self.prev_span, msg)
4234 .span_label(self.prev_span, msg)
4235 .emit();
4236 }
4237
4238 Ok((fields, ddpos, trailing_comma))
4239 }
4240
4241 fn parse_pat_vec_elements(
4242 &mut self,
4243 ) -> PResult<'a, (Vec<P<Pat>>, Option<P<Pat>>, Vec<P<Pat>>)> {
4244 let mut before = Vec::new();
4245 let mut slice = None;
4246 let mut after = Vec::new();
4247 let mut first = true;
4248 let mut before_slice = true;
4249
4250 while self.token != token::CloseDelim(token::Bracket) {
4251 if first {
4252 first = false;
4253 } else {
4254 self.expect(&token::Comma)?;
4255
4256 if self.token == token::CloseDelim(token::Bracket)
4257 && (before_slice || !after.is_empty()) {
4258 break
4259 }
4260 }
4261
4262 if before_slice {
4263 if self.eat(&token::DotDot) {
4264
4265 if self.check(&token::Comma) ||
4266 self.check(&token::CloseDelim(token::Bracket)) {
4267 slice = Some(P(Pat {
4268 id: ast::DUMMY_NODE_ID,
4269 node: PatKind::Wild,
4270 span: self.prev_span,
4271 }));
4272 before_slice = false;
4273 }
4274 continue
4275 }
4276 }
4277
4278 let subpat = self.parse_pat(None)?;
4279 if before_slice && self.eat(&token::DotDot) {
4280 slice = Some(subpat);
4281 before_slice = false;
4282 } else if before_slice {
4283 before.push(subpat);
4284 } else {
4285 after.push(subpat);
4286 }
4287 }
4288
4289 Ok((before, slice, after))
4290 }
4291
4292 fn parse_pat_field(
4293 &mut self,
4294 lo: Span,
4295 attrs: Vec<Attribute>
4296 ) -> PResult<'a, source_map::Spanned<ast::FieldPat>> {
4297 // Check if a colon exists one ahead. This means we're parsing a fieldname.
4298 let hi;
4299 let (subpat, fieldname, is_shorthand) = if self.look_ahead(1, |t| t == &token::Colon) {
4300 // Parsing a pattern of the form "fieldname: pat"
4301 let fieldname = self.parse_field_name()?;
4302 self.bump();
4303 let pat = self.parse_pat(None)?;
4304 hi = pat.span;
4305 (pat, fieldname, false)
4306 } else {
4307 // Parsing a pattern of the form "(box) (ref) (mut) fieldname"
4308 let is_box = self.eat_keyword(keywords::Box);
4309 let boxed_span = self.span;
4310 let is_ref = self.eat_keyword(keywords::Ref);
4311 let is_mut = self.eat_keyword(keywords::Mut);
4312 let fieldname = self.parse_ident()?;
4313 hi = self.prev_span;
4314
4315 let bind_type = match (is_ref, is_mut) {
4316 (true, true) => BindingMode::ByRef(Mutability::Mutable),
4317 (true, false) => BindingMode::ByRef(Mutability::Immutable),
4318 (false, true) => BindingMode::ByValue(Mutability::Mutable),
4319 (false, false) => BindingMode::ByValue(Mutability::Immutable),
4320 };
4321 let fieldpat = P(Pat {
4322 id: ast::DUMMY_NODE_ID,
4323 node: PatKind::Ident(bind_type, fieldname, None),
4324 span: boxed_span.to(hi),
4325 });
4326
4327 let subpat = if is_box {
4328 P(Pat {
4329 id: ast::DUMMY_NODE_ID,
4330 node: PatKind::Box(fieldpat),
4331 span: lo.to(hi),
4332 })
4333 } else {
4334 fieldpat
4335 };
4336 (subpat, fieldname, true)
4337 };
4338
4339 Ok(source_map::Spanned {
4340 span: lo.to(hi),
4341 node: ast::FieldPat {
4342 ident: fieldname,
4343 pat: subpat,
4344 is_shorthand,
4345 attrs: attrs.into(),
4346 }
4347 })
4348 }
4349
4350 /// Parses the fields of a struct-like pattern.
4351 fn parse_pat_fields(&mut self) -> PResult<'a, (Vec<source_map::Spanned<ast::FieldPat>>, bool)> {
4352 let mut fields = Vec::new();
4353 let mut etc = false;
4354 let mut ate_comma = true;
4355 let mut delayed_err: Option<DiagnosticBuilder<'a>> = None;
4356 let mut etc_span = None;
4357
4358 while self.token != token::CloseDelim(token::Brace) {
4359 let attrs = self.parse_outer_attributes()?;
4360 let lo = self.span;
4361
4362 // check that a comma comes after every field
4363 if !ate_comma {
4364 let err = self.struct_span_err(self.prev_span, "expected `,`");
4365 if let Some(mut delayed) = delayed_err {
4366 delayed.emit();
4367 }
4368 return Err(err);
4369 }
4370 ate_comma = false;
4371
4372 if self.check(&token::DotDot) || self.token == token::DotDotDot {
4373 etc = true;
4374 let mut etc_sp = self.span;
4375
4376 if self.token == token::DotDotDot { // Issue #46718
4377 // Accept `...` as if it were `..` to avoid further errors
4378 let mut err = self.struct_span_err(self.span,
4379 "expected field pattern, found `...`");
4380 err.span_suggestion(
4381 self.span,
4382 "to omit remaining fields, use one fewer `.`",
4383 "..".to_owned(),
4384 Applicability::MachineApplicable
4385 );
4386 err.emit();
4387 }
4388 self.bump(); // `..` || `...`
4389
4390 if self.token == token::CloseDelim(token::Brace) {
4391 etc_span = Some(etc_sp);
4392 break;
4393 }
4394 let token_str = self.this_token_descr();
4395 let mut err = self.fatal(&format!("expected `}}`, found {}", token_str));
4396
4397 err.span_label(self.span, "expected `}`");
4398 let mut comma_sp = None;
4399 if self.token == token::Comma { // Issue #49257
4400 etc_sp = etc_sp.to(self.sess.source_map().span_until_non_whitespace(self.span));
4401 err.span_label(etc_sp,
4402 "`..` must be at the end and cannot have a trailing comma");
4403 comma_sp = Some(self.span);
4404 self.bump();
4405 ate_comma = true;
4406 }
4407
4408 etc_span = Some(etc_sp.until(self.span));
4409 if self.token == token::CloseDelim(token::Brace) {
4410 // If the struct looks otherwise well formed, recover and continue.
4411 if let Some(sp) = comma_sp {
4412 err.span_suggestion_short(
4413 sp,
4414 "remove this comma",
4415 String::new(),
4416 Applicability::MachineApplicable,
4417 );
4418 }
4419 err.emit();
4420 break;
4421 } else if self.token.is_ident() && ate_comma {
4422 // Accept fields coming after `..,`.
4423 // This way we avoid "pattern missing fields" errors afterwards.
4424 // We delay this error until the end in order to have a span for a
4425 // suggested fix.
4426 if let Some(mut delayed_err) = delayed_err {
4427 delayed_err.emit();
4428 return Err(err);
4429 } else {
4430 delayed_err = Some(err);
4431 }
4432 } else {
4433 if let Some(mut err) = delayed_err {
4434 err.emit();
4435 }
4436 return Err(err);
4437 }
4438 }
4439
4440 fields.push(match self.parse_pat_field(lo, attrs) {
4441 Ok(field) => field,
4442 Err(err) => {
4443 if let Some(mut delayed_err) = delayed_err {
4444 delayed_err.emit();
4445 }
4446 return Err(err);
4447 }
4448 });
4449 ate_comma = self.eat(&token::Comma);
4450 }
4451
4452 if let Some(mut err) = delayed_err {
4453 if let Some(etc_span) = etc_span {
4454 err.multipart_suggestion(
4455 "move the `..` to the end of the field list",
4456 vec![
4457 (etc_span, String::new()),
4458 (self.span, format!("{}.. }}", if ate_comma { "" } else { ", " })),
4459 ],
4460 Applicability::MachineApplicable,
4461 );
4462 }
4463 err.emit();
4464 }
4465 return Ok((fields, etc));
4466 }
4467
4468 fn parse_pat_range_end(&mut self) -> PResult<'a, P<Expr>> {
4469 if self.token.is_path_start() {
4470 let lo = self.span;
4471 let (qself, path) = if self.eat_lt() {
4472 // Parse a qualified path
4473 let (qself, path) = self.parse_qpath(PathStyle::Expr)?;
4474 (Some(qself), path)
4475 } else {
4476 // Parse an unqualified path
4477 (None, self.parse_path(PathStyle::Expr)?)
4478 };
4479 let hi = self.prev_span;
4480 Ok(self.mk_expr(lo.to(hi), ExprKind::Path(qself, path), ThinVec::new()))
4481 } else {
4482 self.parse_literal_maybe_minus()
4483 }
4484 }
4485
4486 // helper function to decide whether to parse as ident binding or to try to do
4487 // something more complex like range patterns
4488 fn parse_as_ident(&mut self) -> bool {
4489 self.look_ahead(1, |t| match *t {
4490 token::OpenDelim(token::Paren) | token::OpenDelim(token::Brace) |
4491 token::DotDotDot | token::DotDotEq | token::ModSep | token::Not => Some(false),
4492 // ensure slice patterns [a, b.., c] and [a, b, c..] don't go into the
4493 // range pattern branch
4494 token::DotDot => None,
4495 _ => Some(true),
4496 }).unwrap_or_else(|| self.look_ahead(2, |t| match *t {
4497 token::Comma | token::CloseDelim(token::Bracket) => true,
4498 _ => false,
4499 }))
4500 }
4501
4502 /// A wrapper around `parse_pat` with some special error handling for the
4503 /// "top-level" patterns in a match arm, `for` loop, `let`, &c. (in contrast
4504 /// to subpatterns within such).
4505 fn parse_top_level_pat(&mut self) -> PResult<'a, P<Pat>> {
4506 let pat = self.parse_pat(None)?;
4507 if self.token == token::Comma {
4508 // An unexpected comma after a top-level pattern is a clue that the
4509 // user (perhaps more accustomed to some other language) forgot the
4510 // parentheses in what should have been a tuple pattern; return a
4511 // suggestion-enhanced error here rather than choking on the comma
4512 // later.
4513 let comma_span = self.span;
4514 self.bump();
4515 if let Err(mut err) = self.parse_pat_list() {
4516 // We didn't expect this to work anyway; we just wanted
4517 // to advance to the end of the comma-sequence so we know
4518 // the span to suggest parenthesizing
4519 err.cancel();
4520 }
4521 let seq_span = pat.span.to(self.prev_span);
4522 let mut err = self.struct_span_err(comma_span,
4523 "unexpected `,` in pattern");
4524 if let Ok(seq_snippet) = self.sess.source_map().span_to_snippet(seq_span) {
4525 err.span_suggestion(
4526 seq_span,
4527 "try adding parentheses to match on a tuple..",
4528 format!("({})", seq_snippet),
4529 Applicability::MachineApplicable
4530 ).span_suggestion(
4531 seq_span,
4532 "..or a vertical bar to match on multiple alternatives",
4533 format!("{}", seq_snippet.replace(",", " |")),
4534 Applicability::MachineApplicable
4535 );
4536 }
4537 return Err(err);
4538 }
4539 Ok(pat)
4540 }
4541
4542 /// Parses a pattern.
4543 pub fn parse_pat(&mut self, expected: Option<&'static str>) -> PResult<'a, P<Pat>> {
4544 self.parse_pat_with_range_pat(true, expected)
4545 }
4546
4547 /// Parses a pattern, with a setting whether modern range patterns (e.g., `a..=b`, `a..b` are
4548 /// allowed).
4549 fn parse_pat_with_range_pat(
4550 &mut self,
4551 allow_range_pat: bool,
4552 expected: Option<&'static str>,
4553 ) -> PResult<'a, P<Pat>> {
4554 maybe_whole!(self, NtPat, |x| x);
4555
4556 let lo = self.span;
4557 let pat;
4558 match self.token {
4559 token::BinOp(token::And) | token::AndAnd => {
4560 // Parse &pat / &mut pat
4561 self.expect_and()?;
4562 let mutbl = self.parse_mutability();
4563 if let token::Lifetime(ident) = self.token {
4564 let mut err = self.fatal(&format!("unexpected lifetime `{}` in pattern",
4565 ident));
4566 err.span_label(self.span, "unexpected lifetime");
4567 return Err(err);
4568 }
4569 let subpat = self.parse_pat_with_range_pat(false, expected)?;
4570 pat = PatKind::Ref(subpat, mutbl);
4571 }
4572 token::OpenDelim(token::Paren) => {
4573 // Parse (pat,pat,pat,...) as tuple pattern
4574 let (fields, ddpos, trailing_comma) = self.parse_parenthesized_pat_list()?;
4575 pat = if fields.len() == 1 && ddpos.is_none() && !trailing_comma {
4576 PatKind::Paren(fields.into_iter().nth(0).unwrap())
4577 } else {
4578 PatKind::Tuple(fields, ddpos)
4579 };
4580 }
4581 token::OpenDelim(token::Bracket) => {
4582 // Parse [pat,pat,...] as slice pattern
4583 self.bump();
4584 let (before, slice, after) = self.parse_pat_vec_elements()?;
4585 self.expect(&token::CloseDelim(token::Bracket))?;
4586 pat = PatKind::Slice(before, slice, after);
4587 }
4588 // At this point, token != &, &&, (, [
4589 _ => if self.eat_keyword(keywords::Underscore) {
4590 // Parse _
4591 pat = PatKind::Wild;
4592 } else if self.eat_keyword(keywords::Mut) {
4593 // Parse mut ident @ pat / mut ref ident @ pat
4594 let mutref_span = self.prev_span.to(self.span);
4595 let binding_mode = if self.eat_keyword(keywords::Ref) {
4596 self.diagnostic()
4597 .struct_span_err(mutref_span, "the order of `mut` and `ref` is incorrect")
4598 .span_suggestion(
4599 mutref_span,
4600 "try switching the order",
4601 "ref mut".into(),
4602 Applicability::MachineApplicable
4603 ).emit();
4604 BindingMode::ByRef(Mutability::Mutable)
4605 } else {
4606 BindingMode::ByValue(Mutability::Mutable)
4607 };
4608 pat = self.parse_pat_ident(binding_mode)?;
4609 } else if self.eat_keyword(keywords::Ref) {
4610 // Parse ref ident @ pat / ref mut ident @ pat
4611 let mutbl = self.parse_mutability();
4612 pat = self.parse_pat_ident(BindingMode::ByRef(mutbl))?;
4613 } else if self.eat_keyword(keywords::Box) {
4614 // Parse box pat
4615 let subpat = self.parse_pat_with_range_pat(false, None)?;
4616 pat = PatKind::Box(subpat);
4617 } else if self.token.is_ident() && !self.token.is_reserved_ident() &&
4618 self.parse_as_ident() {
4619 // Parse ident @ pat
4620 // This can give false positives and parse nullary enums,
4621 // they are dealt with later in resolve
4622 let binding_mode = BindingMode::ByValue(Mutability::Immutable);
4623 pat = self.parse_pat_ident(binding_mode)?;
4624 } else if self.token.is_path_start() {
4625 // Parse pattern starting with a path
4626 let (qself, path) = if self.eat_lt() {
4627 // Parse a qualified path
4628 let (qself, path) = self.parse_qpath(PathStyle::Expr)?;
4629 (Some(qself), path)
4630 } else {
4631 // Parse an unqualified path
4632 (None, self.parse_path(PathStyle::Expr)?)
4633 };
4634 match self.token {
4635 token::Not if qself.is_none() => {
4636 // Parse macro invocation
4637 self.bump();
4638 let (delim, tts) = self.expect_delimited_token_tree()?;
4639 let mac = respan(lo.to(self.prev_span), Mac_ { path, tts, delim });
4640 pat = PatKind::Mac(mac);
4641 }
4642 token::DotDotDot | token::DotDotEq | token::DotDot => {
4643 let end_kind = match self.token {
4644 token::DotDot => RangeEnd::Excluded,
4645 token::DotDotDot => RangeEnd::Included(RangeSyntax::DotDotDot),
4646 token::DotDotEq => RangeEnd::Included(RangeSyntax::DotDotEq),
4647 _ => panic!("can only parse `..`/`...`/`..=` for ranges \
4648 (checked above)"),
4649 };
4650 let op_span = self.span;
4651 // Parse range
4652 let span = lo.to(self.prev_span);
4653 let begin = self.mk_expr(span, ExprKind::Path(qself, path), ThinVec::new());
4654 self.bump();
4655 let end = self.parse_pat_range_end()?;
4656 let op = Spanned { span: op_span, node: end_kind };
4657 pat = PatKind::Range(begin, end, op);
4658 }
4659 token::OpenDelim(token::Brace) => {
4660 if qself.is_some() {
4661 let msg = "unexpected `{` after qualified path";
4662 let mut err = self.fatal(msg);
4663 err.span_label(self.span, msg);
4664 return Err(err);
4665 }
4666 // Parse struct pattern
4667 self.bump();
4668 let (fields, etc) = self.parse_pat_fields().unwrap_or_else(|mut e| {
4669 e.emit();
4670 self.recover_stmt();
4671 (vec![], false)
4672 });
4673 self.bump();
4674 pat = PatKind::Struct(path, fields, etc);
4675 }
4676 token::OpenDelim(token::Paren) => {
4677 if qself.is_some() {
4678 let msg = "unexpected `(` after qualified path";
4679 let mut err = self.fatal(msg);
4680 err.span_label(self.span, msg);
4681 return Err(err);
4682 }
4683 // Parse tuple struct or enum pattern
4684 let (fields, ddpos, _) = self.parse_parenthesized_pat_list()?;
4685 pat = PatKind::TupleStruct(path, fields, ddpos)
4686 }
4687 _ => pat = PatKind::Path(qself, path),
4688 }
4689 } else {
4690 // Try to parse everything else as literal with optional minus
4691 match self.parse_literal_maybe_minus() {
4692 Ok(begin) => {
4693 let op_span = self.span;
4694 if self.check(&token::DotDot) || self.check(&token::DotDotEq) ||
4695 self.check(&token::DotDotDot) {
4696 let end_kind = if self.eat(&token::DotDotDot) {
4697 RangeEnd::Included(RangeSyntax::DotDotDot)
4698 } else if self.eat(&token::DotDotEq) {
4699 RangeEnd::Included(RangeSyntax::DotDotEq)
4700 } else if self.eat(&token::DotDot) {
4701 RangeEnd::Excluded
4702 } else {
4703 panic!("impossible case: we already matched \
4704 on a range-operator token")
4705 };
4706 let end = self.parse_pat_range_end()?;
4707 let op = Spanned { span: op_span, node: end_kind };
4708 pat = PatKind::Range(begin, end, op);
4709 } else {
4710 pat = PatKind::Lit(begin);
4711 }
4712 }
4713 Err(mut err) => {
4714 self.cancel(&mut err);
4715 let expected = expected.unwrap_or("pattern");
4716 let msg = format!(
4717 "expected {}, found {}",
4718 expected,
4719 self.this_token_descr(),
4720 );
4721 let mut err = self.fatal(&msg);
4722 err.span_label(self.span, format!("expected {}", expected));
4723 return Err(err);
4724 }
4725 }
4726 }
4727 }
4728
4729 let pat = Pat { node: pat, span: lo.to(self.prev_span), id: ast::DUMMY_NODE_ID };
4730 let pat = self.maybe_recover_from_bad_qpath(pat, true)?;
4731
4732 if !allow_range_pat {
4733 match pat.node {
4734 PatKind::Range(
4735 _, _, Spanned { node: RangeEnd::Included(RangeSyntax::DotDotDot), .. }
4736 ) => {},
4737 PatKind::Range(..) => {
4738 let mut err = self.struct_span_err(
4739 pat.span,
4740 "the range pattern here has ambiguous interpretation",
4741 );
4742 err.span_suggestion(
4743 pat.span,
4744 "add parentheses to clarify the precedence",
4745 format!("({})", pprust::pat_to_string(&pat)),
4746 // "ambiguous interpretation" implies that we have to be guessing
4747 Applicability::MaybeIncorrect
4748 );
4749 return Err(err);
4750 }
4751 _ => {}
4752 }
4753 }
4754
4755 Ok(P(pat))
4756 }
4757
4758 /// Parses `ident` or `ident @ pat`.
4759 /// used by the copy foo and ref foo patterns to give a good
4760 /// error message when parsing mistakes like `ref foo(a, b)`.
4761 fn parse_pat_ident(&mut self,
4762 binding_mode: ast::BindingMode)
4763 -> PResult<'a, PatKind> {
4764 let ident = self.parse_ident()?;
4765 let sub = if self.eat(&token::At) {
4766 Some(self.parse_pat(Some("binding pattern"))?)
4767 } else {
4768 None
4769 };
4770
4771 // just to be friendly, if they write something like
4772 // ref Some(i)
4773 // we end up here with ( as the current token. This shortly
4774 // leads to a parse error. Note that if there is no explicit
4775 // binding mode then we do not end up here, because the lookahead
4776 // will direct us over to parse_enum_variant()
4777 if self.token == token::OpenDelim(token::Paren) {
4778 return Err(self.span_fatal(
4779 self.prev_span,
4780 "expected identifier, found enum pattern"))
4781 }
4782
4783 Ok(PatKind::Ident(binding_mode, ident, sub))
4784 }
4785
4786 /// Parses a local variable declaration.
4787 fn parse_local(&mut self, attrs: ThinVec<Attribute>) -> PResult<'a, P<Local>> {
4788 let lo = self.prev_span;
4789 let pat = self.parse_top_level_pat()?;
4790
4791 let (err, ty) = if self.eat(&token::Colon) {
4792 // Save the state of the parser before parsing type normally, in case there is a `:`
4793 // instead of an `=` typo.
4794 let parser_snapshot_before_type = self.clone();
4795 let colon_sp = self.prev_span;
4796 match self.parse_ty() {
4797 Ok(ty) => (None, Some(ty)),
4798 Err(mut err) => {
4799 // Rewind to before attempting to parse the type and continue parsing
4800 let parser_snapshot_after_type = self.clone();
4801 mem::replace(self, parser_snapshot_before_type);
4802
4803 let snippet = self.sess.source_map().span_to_snippet(pat.span).unwrap();
4804 err.span_label(pat.span, format!("while parsing the type for `{}`", snippet));
4805 (Some((parser_snapshot_after_type, colon_sp, err)), None)
4806 }
4807 }
4808 } else {
4809 (None, None)
4810 };
4811 let init = match (self.parse_initializer(err.is_some()), err) {
4812 (Ok(init), None) => { // init parsed, ty parsed
4813 init
4814 }
4815 (Ok(init), Some((_, colon_sp, mut err))) => { // init parsed, ty error
4816 // Could parse the type as if it were the initializer, it is likely there was a
4817 // typo in the code: `:` instead of `=`. Add suggestion and emit the error.
4818 err.span_suggestion_short(
4819 colon_sp,
4820 "use `=` if you meant to assign",
4821 "=".to_string(),
4822 Applicability::MachineApplicable
4823 );
4824 err.emit();
4825 // As this was parsed successfully, continue as if the code has been fixed for the
4826 // rest of the file. It will still fail due to the emitted error, but we avoid
4827 // extra noise.
4828 init
4829 }
4830 (Err(mut init_err), Some((snapshot, _, ty_err))) => { // init error, ty error
4831 init_err.cancel();
4832 // Couldn't parse the type nor the initializer, only raise the type error and
4833 // return to the parser state before parsing the type as the initializer.
4834 // let x: <parse_error>;
4835 mem::replace(self, snapshot);
4836 return Err(ty_err);
4837 }
4838 (Err(err), None) => { // init error, ty parsed
4839 // Couldn't parse the initializer and we're not attempting to recover a failed
4840 // parse of the type, return the error.
4841 return Err(err);
4842 }
4843 };
4844 let hi = if self.token == token::Semi {
4845 self.span
4846 } else {
4847 self.prev_span
4848 };
4849 Ok(P(ast::Local {
4850 ty,
4851 pat,
4852 init,
4853 id: ast::DUMMY_NODE_ID,
4854 span: lo.to(hi),
4855 attrs,
4856 }))
4857 }
4858
4859 /// Parses a structure field.
4860 fn parse_name_and_ty(&mut self,
4861 lo: Span,
4862 vis: Visibility,
4863 attrs: Vec<Attribute>)
4864 -> PResult<'a, StructField> {
4865 let name = self.parse_ident()?;
4866 self.expect(&token::Colon)?;
4867 let ty = self.parse_ty()?;
4868 Ok(StructField {
4869 span: lo.to(self.prev_span),
4870 ident: Some(name),
4871 vis,
4872 id: ast::DUMMY_NODE_ID,
4873 ty,
4874 attrs,
4875 })
4876 }
4877
4878 /// Emits an expected-item-after-attributes error.
4879 fn expected_item_err(&mut self, attrs: &[Attribute]) -> PResult<'a, ()> {
4880 let message = match attrs.last() {
4881 Some(&Attribute { is_sugared_doc: true, .. }) => "expected item after doc comment",
4882 _ => "expected item after attributes",
4883 };
4884
4885 let mut err = self.diagnostic().struct_span_err(self.prev_span, message);
4886 if attrs.last().unwrap().is_sugared_doc {
4887 err.span_label(self.prev_span, "this doc comment doesn't document anything");
4888 }
4889 Err(err)
4890 }
4891
4892 /// Parse a statement. This stops just before trailing semicolons on everything but items.
4893 /// e.g., a `StmtKind::Semi` parses to a `StmtKind::Expr`, leaving the trailing `;` unconsumed.
4894 pub fn parse_stmt(&mut self) -> PResult<'a, Option<Stmt>> {
4895 Ok(self.parse_stmt_(true))
4896 }
4897
4898 // Eat tokens until we can be relatively sure we reached the end of the
4899 // statement. This is something of a best-effort heuristic.
4900 //
4901 // We terminate when we find an unmatched `}` (without consuming it).
4902 fn recover_stmt(&mut self) {
4903 self.recover_stmt_(SemiColonMode::Ignore, BlockMode::Ignore)
4904 }
4905
4906 // If `break_on_semi` is `Break`, then we will stop consuming tokens after
4907 // finding (and consuming) a `;` outside of `{}` or `[]` (note that this is
4908 // approximate - it can mean we break too early due to macros, but that
4909 // should only lead to sub-optimal recovery, not inaccurate parsing).
4910 //
4911 // If `break_on_block` is `Break`, then we will stop consuming tokens
4912 // after finding (and consuming) a brace-delimited block.
4913 fn recover_stmt_(&mut self, break_on_semi: SemiColonMode, break_on_block: BlockMode) {
4914 let mut brace_depth = 0;
4915 let mut bracket_depth = 0;
4916 let mut in_block = false;
4917 debug!("recover_stmt_ enter loop (semi={:?}, block={:?})",
4918 break_on_semi, break_on_block);
4919 loop {
4920 debug!("recover_stmt_ loop {:?}", self.token);
4921 match self.token {
4922 token::OpenDelim(token::DelimToken::Brace) => {
4923 brace_depth += 1;
4924 self.bump();
4925 if break_on_block == BlockMode::Break &&
4926 brace_depth == 1 &&
4927 bracket_depth == 0 {
4928 in_block = true;
4929 }
4930 }
4931 token::OpenDelim(token::DelimToken::Bracket) => {
4932 bracket_depth += 1;
4933 self.bump();
4934 }
4935 token::CloseDelim(token::DelimToken::Brace) => {
4936 if brace_depth == 0 {
4937 debug!("recover_stmt_ return - close delim {:?}", self.token);
4938 break;
4939 }
4940 brace_depth -= 1;
4941 self.bump();
4942 if in_block && bracket_depth == 0 && brace_depth == 0 {
4943 debug!("recover_stmt_ return - block end {:?}", self.token);
4944 break;
4945 }
4946 }
4947 token::CloseDelim(token::DelimToken::Bracket) => {
4948 bracket_depth -= 1;
4949 if bracket_depth < 0 {
4950 bracket_depth = 0;
4951 }
4952 self.bump();
4953 }
4954 token::Eof => {
4955 debug!("recover_stmt_ return - Eof");
4956 break;
4957 }
4958 token::Semi => {
4959 self.bump();
4960 if break_on_semi == SemiColonMode::Break &&
4961 brace_depth == 0 &&
4962 bracket_depth == 0 {
4963 debug!("recover_stmt_ return - Semi");
4964 break;
4965 }
4966 }
4967 token::Comma => {
4968 if break_on_semi == SemiColonMode::Comma &&
4969 brace_depth == 0 &&
4970 bracket_depth == 0 {
4971 debug!("recover_stmt_ return - Semi");
4972 break;
4973 } else {
4974 self.bump();
4975 }
4976 }
4977 _ => {
4978 self.bump()
4979 }
4980 }
4981 }
4982 }
4983
4984 fn parse_stmt_(&mut self, macro_legacy_warnings: bool) -> Option<Stmt> {
4985 self.parse_stmt_without_recovery(macro_legacy_warnings).unwrap_or_else(|mut e| {
4986 e.emit();
4987 self.recover_stmt_(SemiColonMode::Break, BlockMode::Ignore);
4988 None
4989 })
4990 }
4991
4992 fn is_async_block(&mut self) -> bool {
4993 self.token.is_keyword(keywords::Async) &&
4994 (
4995 ( // `async move {`
4996 self.look_ahead(1, |t| t.is_keyword(keywords::Move)) &&
4997 self.look_ahead(2, |t| *t == token::OpenDelim(token::Brace))
4998 ) || ( // `async {`
4999 self.look_ahead(1, |t| *t == token::OpenDelim(token::Brace))
5000 )
5001 )
5002 }
5003
5004 fn is_do_catch_block(&mut self) -> bool {
5005 self.token.is_keyword(keywords::Do) &&
5006 self.look_ahead(1, |t| t.is_keyword(keywords::Catch)) &&
5007 self.look_ahead(2, |t| *t == token::OpenDelim(token::Brace)) &&
5008 !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL)
5009 }
5010
5011 fn is_try_block(&mut self) -> bool {
5012 self.token.is_keyword(keywords::Try) &&
5013 self.look_ahead(1, |t| *t == token::OpenDelim(token::Brace)) &&
5014 self.span.rust_2018() &&
5015 // prevent `while try {} {}`, `if try {} {} else {}`, etc.
5016 !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL)
5017 }
5018
5019 fn is_union_item(&self) -> bool {
5020 self.token.is_keyword(keywords::Union) &&
5021 self.look_ahead(1, |t| t.is_ident() && !t.is_reserved_ident())
5022 }
5023
5024 fn is_crate_vis(&self) -> bool {
5025 self.token.is_keyword(keywords::Crate) && self.look_ahead(1, |t| t != &token::ModSep)
5026 }
5027
5028 fn is_existential_type_decl(&self) -> bool {
5029 self.token.is_keyword(keywords::Existential) &&
5030 self.look_ahead(1, |t| t.is_keyword(keywords::Type))
5031 }
5032
5033 fn is_auto_trait_item(&mut self) -> bool {
5034 // auto trait
5035 (self.token.is_keyword(keywords::Auto)
5036 && self.look_ahead(1, |t| t.is_keyword(keywords::Trait)))
5037 || // unsafe auto trait
5038 (self.token.is_keyword(keywords::Unsafe) &&
5039 self.look_ahead(1, |t| t.is_keyword(keywords::Auto)) &&
5040 self.look_ahead(2, |t| t.is_keyword(keywords::Trait)))
5041 }
5042
5043 fn eat_macro_def(&mut self, attrs: &[Attribute], vis: &Visibility, lo: Span)
5044 -> PResult<'a, Option<P<Item>>> {
5045 let token_lo = self.span;
5046 let (ident, def) = match self.token {
5047 token::Ident(ident, false) if ident.name == keywords::Macro.name() => {
5048 self.bump();
5049 let ident = self.parse_ident()?;
5050 let tokens = if self.check(&token::OpenDelim(token::Brace)) {
5051 match self.parse_token_tree() {
5052 TokenTree::Delimited(_, _, tts) => tts,
5053 _ => unreachable!(),
5054 }
5055 } else if self.check(&token::OpenDelim(token::Paren)) {
5056 let args = self.parse_token_tree();
5057 let body = if self.check(&token::OpenDelim(token::Brace)) {
5058 self.parse_token_tree()
5059 } else {
5060 self.unexpected()?;
5061 unreachable!()
5062 };
5063 TokenStream::new(vec![
5064 args.into(),
5065 TokenTree::Token(token_lo.to(self.prev_span), token::FatArrow).into(),
5066 body.into(),
5067 ])
5068 } else {
5069 self.unexpected()?;
5070 unreachable!()
5071 };
5072
5073 (ident, ast::MacroDef { tokens: tokens.into(), legacy: false })
5074 }
5075 token::Ident(ident, _) if ident.name == "macro_rules" &&
5076 self.look_ahead(1, |t| *t == token::Not) => {
5077 let prev_span = self.prev_span;
5078 self.complain_if_pub_macro(&vis.node, prev_span);
5079 self.bump();
5080 self.bump();
5081
5082 let ident = self.parse_ident()?;
5083 let (delim, tokens) = self.expect_delimited_token_tree()?;
5084 if delim != MacDelimiter::Brace {
5085 if !self.eat(&token::Semi) {
5086 let msg = "macros that expand to items must either \
5087 be surrounded with braces or followed by a semicolon";
5088 self.span_err(self.prev_span, msg);
5089 }
5090 }
5091
5092 (ident, ast::MacroDef { tokens: tokens, legacy: true })
5093 }
5094 _ => return Ok(None),
5095 };
5096
5097 let span = lo.to(self.prev_span);
5098 Ok(Some(self.mk_item(span, ident, ItemKind::MacroDef(def), vis.clone(), attrs.to_vec())))
5099 }
5100
5101 fn parse_stmt_without_recovery(&mut self,
5102 macro_legacy_warnings: bool)
5103 -> PResult<'a, Option<Stmt>> {
5104 maybe_whole!(self, NtStmt, |x| Some(x));
5105
5106 let attrs = self.parse_outer_attributes()?;
5107 let lo = self.span;
5108
5109 Ok(Some(if self.eat_keyword(keywords::Let) {
5110 Stmt {
5111 id: ast::DUMMY_NODE_ID,
5112 node: StmtKind::Local(self.parse_local(attrs.into())?),
5113 span: lo.to(self.prev_span),
5114 }
5115 } else if let Some(macro_def) = self.eat_macro_def(
5116 &attrs,
5117 &source_map::respan(lo, VisibilityKind::Inherited),
5118 lo,
5119 )? {
5120 Stmt {
5121 id: ast::DUMMY_NODE_ID,
5122 node: StmtKind::Item(macro_def),
5123 span: lo.to(self.prev_span),
5124 }
5125 // Starts like a simple path, being careful to avoid contextual keywords
5126 // such as a union items, item with `crate` visibility or auto trait items.
5127 // Our goal here is to parse an arbitrary path `a::b::c` but not something that starts
5128 // like a path (1 token), but it fact not a path.
5129 // `union::b::c` - path, `union U { ... }` - not a path.
5130 // `crate::b::c` - path, `crate struct S;` - not a path.
5131 } else if self.token.is_path_start() &&
5132 !self.token.is_qpath_start() &&
5133 !self.is_union_item() &&
5134 !self.is_crate_vis() &&
5135 !self.is_existential_type_decl() &&
5136 !self.is_auto_trait_item() {
5137 let pth = self.parse_path(PathStyle::Expr)?;
5138
5139 if !self.eat(&token::Not) {
5140 let expr = if self.check(&token::OpenDelim(token::Brace)) {
5141 self.parse_struct_expr(lo, pth, ThinVec::new())?
5142 } else {
5143 let hi = self.prev_span;
5144 self.mk_expr(lo.to(hi), ExprKind::Path(None, pth), ThinVec::new())
5145 };
5146
5147 let expr = self.with_res(Restrictions::STMT_EXPR, |this| {
5148 let expr = this.parse_dot_or_call_expr_with(expr, lo, attrs.into())?;
5149 this.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(expr))
5150 })?;
5151
5152 return Ok(Some(Stmt {
5153 id: ast::DUMMY_NODE_ID,
5154 node: StmtKind::Expr(expr),
5155 span: lo.to(self.prev_span),
5156 }));
5157 }
5158
5159 // it's a macro invocation
5160 let id = match self.token {
5161 token::OpenDelim(_) => keywords::Invalid.ident(), // no special identifier
5162 _ => self.parse_ident()?,
5163 };
5164
5165 // check that we're pointing at delimiters (need to check
5166 // again after the `if`, because of `parse_ident`
5167 // consuming more tokens).
5168 match self.token {
5169 token::OpenDelim(_) => {}
5170 _ => {
5171 // we only expect an ident if we didn't parse one
5172 // above.
5173 let ident_str = if id.name == keywords::Invalid.name() {
5174 "identifier, "
5175 } else {
5176 ""
5177 };
5178 let tok_str = self.this_token_descr();
5179 let mut err = self.fatal(&format!("expected {}`(` or `{{`, found {}",
5180 ident_str,
5181 tok_str));
5182 err.span_label(self.span, format!("expected {}`(` or `{{`", ident_str));
5183 return Err(err)
5184 },
5185 }
5186
5187 let (delim, tts) = self.expect_delimited_token_tree()?;
5188 let hi = self.prev_span;
5189
5190 let style = if delim == MacDelimiter::Brace {
5191 MacStmtStyle::Braces
5192 } else {
5193 MacStmtStyle::NoBraces
5194 };
5195
5196 if id.name == keywords::Invalid.name() {
5197 let mac = respan(lo.to(hi), Mac_ { path: pth, tts, delim });
5198 let node = if delim == MacDelimiter::Brace ||
5199 self.token == token::Semi || self.token == token::Eof {
5200 StmtKind::Mac(P((mac, style, attrs.into())))
5201 }
5202 // We used to incorrectly stop parsing macro-expanded statements here.
5203 // If the next token will be an error anyway but could have parsed with the
5204 // earlier behavior, stop parsing here and emit a warning to avoid breakage.
5205 else if macro_legacy_warnings && self.token.can_begin_expr() && match self.token {
5206 // These can continue an expression, so we can't stop parsing and warn.
5207 token::OpenDelim(token::Paren) | token::OpenDelim(token::Bracket) |
5208 token::BinOp(token::Minus) | token::BinOp(token::Star) |
5209 token::BinOp(token::And) | token::BinOp(token::Or) |
5210 token::AndAnd | token::OrOr |
5211 token::DotDot | token::DotDotDot | token::DotDotEq => false,
5212 _ => true,
5213 } {
5214 self.warn_missing_semicolon();
5215 StmtKind::Mac(P((mac, style, attrs.into())))
5216 } else {
5217 let e = self.mk_mac_expr(lo.to(hi), mac.node, ThinVec::new());
5218 let e = self.parse_dot_or_call_expr_with(e, lo, attrs.into())?;
5219 let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e))?;
5220 StmtKind::Expr(e)
5221 };
5222 Stmt {
5223 id: ast::DUMMY_NODE_ID,
5224 span: lo.to(hi),
5225 node,
5226 }
5227 } else {
5228 // if it has a special ident, it's definitely an item
5229 //
5230 // Require a semicolon or braces.
5231 if style != MacStmtStyle::Braces {
5232 if !self.eat(&token::Semi) {
5233 self.span_err(self.prev_span,
5234 "macros that expand to items must \
5235 either be surrounded with braces or \
5236 followed by a semicolon");
5237 }
5238 }
5239 let span = lo.to(hi);
5240 Stmt {
5241 id: ast::DUMMY_NODE_ID,
5242 span,
5243 node: StmtKind::Item({
5244 self.mk_item(
5245 span, id /*id is good here*/,
5246 ItemKind::Mac(respan(span, Mac_ { path: pth, tts, delim })),
5247 respan(lo, VisibilityKind::Inherited),
5248 attrs)
5249 }),
5250 }
5251 }
5252 } else {
5253 // FIXME: Bad copy of attrs
5254 let old_directory_ownership =
5255 mem::replace(&mut self.directory.ownership, DirectoryOwnership::UnownedViaBlock);
5256 let item = self.parse_item_(attrs.clone(), false, true)?;
5257 self.directory.ownership = old_directory_ownership;
5258
5259 match item {
5260 Some(i) => Stmt {
5261 id: ast::DUMMY_NODE_ID,
5262 span: lo.to(i.span),
5263 node: StmtKind::Item(i),
5264 },
5265 None => {
5266 let unused_attrs = |attrs: &[Attribute], s: &mut Self| {
5267 if !attrs.is_empty() {
5268 if s.prev_token_kind == PrevTokenKind::DocComment {
5269 s.span_fatal_err(s.prev_span, Error::UselessDocComment).emit();
5270 } else if attrs.iter().any(|a| a.style == AttrStyle::Outer) {
5271 s.span_err(s.span, "expected statement after outer attribute");
5272 }
5273 }
5274 };
5275
5276 // Do not attempt to parse an expression if we're done here.
5277 if self.token == token::Semi {
5278 unused_attrs(&attrs, self);
5279 self.bump();
5280 return Ok(None);
5281 }
5282
5283 if self.token == token::CloseDelim(token::Brace) {
5284 unused_attrs(&attrs, self);
5285 return Ok(None);
5286 }
5287
5288 // Remainder are line-expr stmts.
5289 let e = self.parse_expr_res(
5290 Restrictions::STMT_EXPR, Some(attrs.into()))?;
5291 Stmt {
5292 id: ast::DUMMY_NODE_ID,
5293 span: lo.to(e.span),
5294 node: StmtKind::Expr(e),
5295 }
5296 }
5297 }
5298 }))
5299 }
5300
5301 /// Checks if this expression is a successfully parsed statement.
5302 fn expr_is_complete(&mut self, e: &Expr) -> bool {
5303 self.restrictions.contains(Restrictions::STMT_EXPR) &&
5304 !classify::expr_requires_semi_to_be_stmt(e)
5305 }
5306
5307 /// Parses a block. No inner attributes are allowed.
5308 pub fn parse_block(&mut self) -> PResult<'a, P<Block>> {
5309 maybe_whole!(self, NtBlock, |x| x);
5310
5311 let lo = self.span;
5312
5313 if !self.eat(&token::OpenDelim(token::Brace)) {
5314 let sp = self.span;
5315 let tok = self.this_token_descr();
5316 let mut e = self.span_fatal(sp, &format!("expected `{{`, found {}", tok));
5317 let do_not_suggest_help =
5318 self.token.is_keyword(keywords::In) || self.token == token::Colon;
5319
5320 if self.token.is_ident_named("and") {
5321 e.span_suggestion_short(
5322 self.span,
5323 "use `&&` instead of `and` for the boolean operator",
5324 "&&".to_string(),
5325 Applicability::MaybeIncorrect,
5326 );
5327 }
5328 if self.token.is_ident_named("or") {
5329 e.span_suggestion_short(
5330 self.span,
5331 "use `||` instead of `or` for the boolean operator",
5332 "||".to_string(),
5333 Applicability::MaybeIncorrect,
5334 );
5335 }
5336
5337 // Check to see if the user has written something like
5338 //
5339 // if (cond)
5340 // bar;
5341 //
5342 // Which is valid in other languages, but not Rust.
5343 match self.parse_stmt_without_recovery(false) {
5344 Ok(Some(stmt)) => {
5345 if self.look_ahead(1, |t| t == &token::OpenDelim(token::Brace))
5346 || do_not_suggest_help {
5347 // if the next token is an open brace (e.g., `if a b {`), the place-
5348 // inside-a-block suggestion would be more likely wrong than right
5349 e.span_label(sp, "expected `{`");
5350 return Err(e);
5351 }
5352 let mut stmt_span = stmt.span;
5353 // expand the span to include the semicolon, if it exists
5354 if self.eat(&token::Semi) {
5355 stmt_span = stmt_span.with_hi(self.prev_span.hi());
5356 }
5357 let sugg = pprust::to_string(|s| {
5358 use crate::print::pprust::{PrintState, INDENT_UNIT};
5359 s.ibox(INDENT_UNIT)?;
5360 s.bopen()?;
5361 s.print_stmt(&stmt)?;
5362 s.bclose_maybe_open(stmt.span, INDENT_UNIT, false)
5363 });
5364 e.span_suggestion(
5365 stmt_span,
5366 "try placing this code inside a block",
5367 sugg,
5368 // speculative, has been misleading in the past (closed Issue #46836)
5369 Applicability::MaybeIncorrect
5370 );
5371 }
5372 Err(mut e) => {
5373 self.recover_stmt_(SemiColonMode::Break, BlockMode::Ignore);
5374 self.cancel(&mut e);
5375 }
5376 _ => ()
5377 }
5378 e.span_label(sp, "expected `{`");
5379 return Err(e);
5380 }
5381
5382 self.parse_block_tail(lo, BlockCheckMode::Default)
5383 }
5384
5385 /// Parses a block. Inner attributes are allowed.
5386 fn parse_inner_attrs_and_block(&mut self) -> PResult<'a, (Vec<Attribute>, P<Block>)> {
5387 maybe_whole!(self, NtBlock, |x| (Vec::new(), x));
5388
5389 let lo = self.span;
5390 self.expect(&token::OpenDelim(token::Brace))?;
5391 Ok((self.parse_inner_attributes()?,
5392 self.parse_block_tail(lo, BlockCheckMode::Default)?))
5393 }
5394
5395 /// Parses the rest of a block expression or function body.
5396 /// Precondition: already parsed the '{'.
5397 fn parse_block_tail(&mut self, lo: Span, s: BlockCheckMode) -> PResult<'a, P<Block>> {
5398 let mut stmts = vec![];
5399 while !self.eat(&token::CloseDelim(token::Brace)) {
5400 let stmt = match self.parse_full_stmt(false) {
5401 Err(mut err) => {
5402 err.emit();
5403 self.recover_stmt_(SemiColonMode::Ignore, BlockMode::Ignore);
5404 Some(Stmt {
5405 id: ast::DUMMY_NODE_ID,
5406 node: StmtKind::Expr(DummyResult::raw_expr(self.span, true)),
5407 span: self.span,
5408 })
5409 }
5410 Ok(stmt) => stmt,
5411 };
5412 if let Some(stmt) = stmt {
5413 stmts.push(stmt);
5414 } else if self.token == token::Eof {
5415 break;
5416 } else {
5417 // Found only `;` or `}`.
5418 continue;
5419 };
5420 }
5421 Ok(P(ast::Block {
5422 stmts,
5423 id: ast::DUMMY_NODE_ID,
5424 rules: s,
5425 span: lo.to(self.prev_span),
5426 }))
5427 }
5428
5429 /// Parses a statement, including the trailing semicolon.
5430 crate fn parse_full_stmt(&mut self, macro_legacy_warnings: bool) -> PResult<'a, Option<Stmt>> {
5431 // skip looking for a trailing semicolon when we have an interpolated statement
5432 maybe_whole!(self, NtStmt, |x| Some(x));
5433
5434 let mut stmt = match self.parse_stmt_without_recovery(macro_legacy_warnings)? {
5435 Some(stmt) => stmt,
5436 None => return Ok(None),
5437 };
5438
5439 match stmt.node {
5440 StmtKind::Expr(ref expr) if self.token != token::Eof => {
5441 // expression without semicolon
5442 if classify::expr_requires_semi_to_be_stmt(expr) {
5443 // Just check for errors and recover; do not eat semicolon yet.
5444 if let Err(mut e) =
5445 self.expect_one_of(&[], &[token::Semi, token::CloseDelim(token::Brace)])
5446 {
5447 e.emit();
5448 self.recover_stmt();
5449 }
5450 }
5451 }
5452 StmtKind::Local(..) => {
5453 // We used to incorrectly allow a macro-expanded let statement to lack a semicolon.
5454 if macro_legacy_warnings && self.token != token::Semi {
5455 self.warn_missing_semicolon();
5456 } else {
5457 self.expect_one_of(&[], &[token::Semi])?;
5458 }
5459 }
5460 _ => {}
5461 }
5462
5463 if self.eat(&token::Semi) {
5464 stmt = stmt.add_trailing_semicolon();
5465 }
5466
5467 stmt.span = stmt.span.with_hi(self.prev_span.hi());
5468 Ok(Some(stmt))
5469 }
5470
5471 fn warn_missing_semicolon(&self) {
5472 self.diagnostic().struct_span_warn(self.span, {
5473 &format!("expected `;`, found {}", self.this_token_descr())
5474 }).note({
5475 "This was erroneously allowed and will become a hard error in a future release"
5476 }).emit();
5477 }
5478
5479 fn err_dotdotdot_syntax(&self, span: Span) {
5480 self.diagnostic().struct_span_err(span, {
5481 "unexpected token: `...`"
5482 }).span_suggestion(
5483 span, "use `..` for an exclusive range", "..".to_owned(),
5484 Applicability::MaybeIncorrect
5485 ).span_suggestion(
5486 span, "or `..=` for an inclusive range", "..=".to_owned(),
5487 Applicability::MaybeIncorrect
5488 ).emit();
5489 }
5490
5491 /// Parses bounds of a type parameter `BOUND + BOUND + ...`, possibly with trailing `+`.
5492 ///
5493 /// ```
5494 /// BOUND = TY_BOUND | LT_BOUND
5495 /// LT_BOUND = LIFETIME (e.g., `'a`)
5496 /// TY_BOUND = TY_BOUND_NOPAREN | (TY_BOUND_NOPAREN)
5497 /// TY_BOUND_NOPAREN = [?] [for<LT_PARAM_DEFS>] SIMPLE_PATH (e.g., `?for<'a: 'b> m::Trait<'a>`)
5498 /// ```
5499 fn parse_generic_bounds_common(&mut self,
5500 allow_plus: bool,
5501 colon_span: Option<Span>) -> PResult<'a, GenericBounds> {
5502 let mut bounds = Vec::new();
5503 let mut negative_bounds = Vec::new();
5504 let mut last_plus_span = None;
5505 loop {
5506 // This needs to be synchronized with `Token::can_begin_bound`.
5507 let is_bound_start = self.check_path() || self.check_lifetime() ||
5508 self.check(&token::Not) || // used for error reporting only
5509 self.check(&token::Question) ||
5510 self.check_keyword(keywords::For) ||
5511 self.check(&token::OpenDelim(token::Paren));
5512 if is_bound_start {
5513 let lo = self.span;
5514 let has_parens = self.eat(&token::OpenDelim(token::Paren));
5515 let inner_lo = self.span;
5516 let is_negative = self.eat(&token::Not);
5517 let question = if self.eat(&token::Question) { Some(self.prev_span) } else { None };
5518 if self.token.is_lifetime() {
5519 if let Some(question_span) = question {
5520 self.span_err(question_span,
5521 "`?` may only modify trait bounds, not lifetime bounds");
5522 }
5523 bounds.push(GenericBound::Outlives(self.expect_lifetime()));
5524 if has_parens {
5525 let inner_span = inner_lo.to(self.prev_span);
5526 self.expect(&token::CloseDelim(token::Paren))?;
5527 let mut err = self.struct_span_err(
5528 lo.to(self.prev_span),
5529 "parenthesized lifetime bounds are not supported"
5530 );
5531 if let Ok(snippet) = self.sess.source_map().span_to_snippet(inner_span) {
5532 err.span_suggestion_short(
5533 lo.to(self.prev_span),
5534 "remove the parentheses",
5535 snippet.to_owned(),
5536 Applicability::MachineApplicable
5537 );
5538 }
5539 err.emit();
5540 }
5541 } else {
5542 let lifetime_defs = self.parse_late_bound_lifetime_defs()?;
5543 let path = self.parse_path(PathStyle::Type)?;
5544 if has_parens {
5545 self.expect(&token::CloseDelim(token::Paren))?;
5546 }
5547 let poly_span = lo.to(self.prev_span);
5548 if is_negative {
5549 negative_bounds.push(
5550 last_plus_span.or(colon_span).unwrap()
5551 .to(poly_span));
5552 } else {
5553 let poly_trait = PolyTraitRef::new(lifetime_defs, path, poly_span);
5554 let modifier = if question.is_some() {
5555 TraitBoundModifier::Maybe
5556 } else {
5557 TraitBoundModifier::None
5558 };
5559 bounds.push(GenericBound::Trait(poly_trait, modifier));
5560 }
5561 }
5562 } else {
5563 break
5564 }
5565
5566 if !allow_plus || !self.eat_plus() {
5567 break
5568 } else {
5569 last_plus_span = Some(self.prev_span);
5570 }
5571 }
5572
5573 if !negative_bounds.is_empty() {
5574 let plural = negative_bounds.len() > 1;
5575 let mut err = self.struct_span_err(negative_bounds,
5576 "negative trait bounds are not supported");
5577 let bound_list = colon_span.unwrap().to(self.prev_span);
5578 let mut new_bound_list = String::new();
5579 if !bounds.is_empty() {
5580 let mut snippets = bounds.iter().map(|bound| bound.span())
5581 .map(|span| self.sess.source_map().span_to_snippet(span));
5582 while let Some(Ok(snippet)) = snippets.next() {
5583 new_bound_list.push_str(" + ");
5584 new_bound_list.push_str(&snippet);
5585 }
5586 new_bound_list = new_bound_list.replacen(" +", ":", 1);
5587 }
5588 err.span_suggestion_short(bound_list,
5589 &format!("remove the trait bound{}",
5590 if plural { "s" } else { "" }),
5591 new_bound_list,
5592 Applicability::MachineApplicable);
5593 err.emit();
5594 }
5595
5596 return Ok(bounds);
5597 }
5598
5599 fn parse_generic_bounds(&mut self, colon_span: Option<Span>) -> PResult<'a, GenericBounds> {
5600 self.parse_generic_bounds_common(true, colon_span)
5601 }
5602
5603 /// Parses bounds of a lifetime parameter `BOUND + BOUND + BOUND`, possibly with trailing `+`.
5604 ///
5605 /// ```
5606 /// BOUND = LT_BOUND (e.g., `'a`)
5607 /// ```
5608 fn parse_lt_param_bounds(&mut self) -> GenericBounds {
5609 let mut lifetimes = Vec::new();
5610 while self.check_lifetime() {
5611 lifetimes.push(ast::GenericBound::Outlives(self.expect_lifetime()));
5612
5613 if !self.eat_plus() {
5614 break
5615 }
5616 }
5617 lifetimes
5618 }
5619
5620 /// Matches `typaram = IDENT (`?` unbound)? optbounds ( EQ ty )?`.
5621 fn parse_ty_param(&mut self,
5622 preceding_attrs: Vec<Attribute>)
5623 -> PResult<'a, GenericParam> {
5624 let ident = self.parse_ident()?;
5625
5626 // Parse optional colon and param bounds.
5627 let bounds = if self.eat(&token::Colon) {
5628 self.parse_generic_bounds(None)?
5629 } else {
5630 Vec::new()
5631 };
5632
5633 let default = if self.eat(&token::Eq) {
5634 Some(self.parse_ty()?)
5635 } else {
5636 None
5637 };
5638
5639 Ok(GenericParam {
5640 ident,
5641 id: ast::DUMMY_NODE_ID,
5642 attrs: preceding_attrs.into(),
5643 bounds,
5644 kind: GenericParamKind::Type {
5645 default,
5646 }
5647 })
5648 }
5649
5650 /// Parses the following grammar:
5651 ///
5652 /// TraitItemAssocTy = Ident ["<"...">"] [":" [GenericBounds]] ["where" ...] ["=" Ty]
5653 fn parse_trait_item_assoc_ty(&mut self)
5654 -> PResult<'a, (Ident, TraitItemKind, ast::Generics)> {
5655 let ident = self.parse_ident()?;
5656 let mut generics = self.parse_generics()?;
5657
5658 // Parse optional colon and param bounds.
5659 let bounds = if self.eat(&token::Colon) {
5660 self.parse_generic_bounds(None)?
5661 } else {
5662 Vec::new()
5663 };
5664 generics.where_clause = self.parse_where_clause()?;
5665
5666 let default = if self.eat(&token::Eq) {
5667 Some(self.parse_ty()?)
5668 } else {
5669 None
5670 };
5671 self.expect(&token::Semi)?;
5672
5673 Ok((ident, TraitItemKind::Type(bounds, default), generics))
5674 }
5675
5676 fn parse_const_param(&mut self, preceding_attrs: Vec<Attribute>) -> PResult<'a, GenericParam> {
5677 self.expect_keyword(keywords::Const)?;
5678 let ident = self.parse_ident()?;
5679 self.expect(&token::Colon)?;
5680 let ty = self.parse_ty()?;
5681
5682 Ok(GenericParam {
5683 ident,
5684 id: ast::DUMMY_NODE_ID,
5685 attrs: preceding_attrs.into(),
5686 bounds: Vec::new(),
5687 kind: GenericParamKind::Const {
5688 ty,
5689 }
5690 })
5691 }
5692
5693 /// Parses a (possibly empty) list of lifetime and type parameters, possibly including
5694 /// a trailing comma and erroneous trailing attributes.
5695 crate fn parse_generic_params(&mut self) -> PResult<'a, Vec<ast::GenericParam>> {
5696 let mut params = Vec::new();
5697 loop {
5698 let attrs = self.parse_outer_attributes()?;
5699 if self.check_lifetime() {
5700 let lifetime = self.expect_lifetime();
5701 // Parse lifetime parameter.
5702 let bounds = if self.eat(&token::Colon) {
5703 self.parse_lt_param_bounds()
5704 } else {
5705 Vec::new()
5706 };
5707 params.push(ast::GenericParam {
5708 ident: lifetime.ident,
5709 id: lifetime.id,
5710 attrs: attrs.into(),
5711 bounds,
5712 kind: ast::GenericParamKind::Lifetime,
5713 });
5714 } else if self.check_keyword(keywords::Const) {
5715 // Parse const parameter.
5716 params.push(self.parse_const_param(attrs)?);
5717 } else if self.check_ident() {
5718 // Parse type parameter.
5719 params.push(self.parse_ty_param(attrs)?);
5720 } else {
5721 // Check for trailing attributes and stop parsing.
5722 if !attrs.is_empty() {
5723 if !params.is_empty() {
5724 self.struct_span_err(
5725 attrs[0].span,
5726 &format!("trailing attribute after generic parameter"),
5727 )
5728 .span_label(attrs[0].span, "attributes must go before parameters")
5729 .emit();
5730 } else {
5731 self.struct_span_err(
5732 attrs[0].span,
5733 &format!("attribute without generic parameters"),
5734 )
5735 .span_label(
5736 attrs[0].span,
5737 "attributes are only permitted when preceding parameters",
5738 )
5739 .emit();
5740 }
5741 }
5742 break
5743 }
5744
5745 if !self.eat(&token::Comma) {
5746 break
5747 }
5748 }
5749 Ok(params)
5750 }
5751
5752 /// Parses a set of optional generic type parameter declarations. Where
5753 /// clauses are not parsed here, and must be added later via
5754 /// `parse_where_clause()`.
5755 ///
5756 /// matches generics = ( ) | ( < > ) | ( < typaramseq ( , )? > ) | ( < lifetimes ( , )? > )
5757 /// | ( < lifetimes , typaramseq ( , )? > )
5758 /// where typaramseq = ( typaram ) | ( typaram , typaramseq )
5759 fn parse_generics(&mut self) -> PResult<'a, ast::Generics> {
5760 maybe_whole!(self, NtGenerics, |x| x);
5761
5762 let span_lo = self.span;
5763 if self.eat_lt() {
5764 let params = self.parse_generic_params()?;
5765 self.expect_gt()?;
5766 Ok(ast::Generics {
5767 params,
5768 where_clause: WhereClause {
5769 id: ast::DUMMY_NODE_ID,
5770 predicates: Vec::new(),
5771 span: syntax_pos::DUMMY_SP,
5772 },
5773 span: span_lo.to(self.prev_span),
5774 })
5775 } else {
5776 Ok(ast::Generics::default())
5777 }
5778 }
5779
5780 /// Parses generic args (within a path segment) with recovery for extra leading angle brackets.
5781 /// For the purposes of understanding the parsing logic of generic arguments, this function
5782 /// can be thought of being the same as just calling `self.parse_generic_args()` if the source
5783 /// had the correct amount of leading angle brackets.
5784 ///
5785 /// ```ignore (diagnostics)
5786 /// bar::<<<<T as Foo>::Output>();
5787 /// ^^ help: remove extra angle brackets
5788 /// ```
5789 fn parse_generic_args_with_leaning_angle_bracket_recovery(
5790 &mut self,
5791 style: PathStyle,
5792 lo: Span,
5793 ) -> PResult<'a, (Vec<GenericArg>, Vec<TypeBinding>)> {
5794 // We need to detect whether there are extra leading left angle brackets and produce an
5795 // appropriate error and suggestion. This cannot be implemented by looking ahead at
5796 // upcoming tokens for a matching `>` character - if there are unmatched `<` tokens
5797 // then there won't be matching `>` tokens to find.
5798 //
5799 // To explain how this detection works, consider the following example:
5800 //
5801 // ```ignore (diagnostics)
5802 // bar::<<<<T as Foo>::Output>();
5803 // ^^ help: remove extra angle brackets
5804 // ```
5805 //
5806 // Parsing of the left angle brackets starts in this function. We start by parsing the
5807 // `<` token (incrementing the counter of unmatched angle brackets on `Parser` via
5808 // `eat_lt`):
5809 //
5810 // *Upcoming tokens:* `<<<<T as Foo>::Output>;`
5811 // *Unmatched count:* 1
5812 // *`parse_path_segment` calls deep:* 0
5813 //
5814 // This has the effect of recursing as this function is called if a `<` character
5815 // is found within the expected generic arguments:
5816 //
5817 // *Upcoming tokens:* `<<<T as Foo>::Output>;`
5818 // *Unmatched count:* 2
5819 // *`parse_path_segment` calls deep:* 1
5820 //
5821 // Eventually we will have recursed until having consumed all of the `<` tokens and
5822 // this will be reflected in the count:
5823 //
5824 // *Upcoming tokens:* `T as Foo>::Output>;`
5825 // *Unmatched count:* 4
5826 // `parse_path_segment` calls deep:* 3
5827 //
5828 // The parser will continue until reaching the first `>` - this will decrement the
5829 // unmatched angle bracket count and return to the parent invocation of this function
5830 // having succeeded in parsing:
5831 //
5832 // *Upcoming tokens:* `::Output>;`
5833 // *Unmatched count:* 3
5834 // *`parse_path_segment` calls deep:* 2
5835 //
5836 // This will continue until the next `>` character which will also return successfully
5837 // to the parent invocation of this function and decrement the count:
5838 //
5839 // *Upcoming tokens:* `;`
5840 // *Unmatched count:* 2
5841 // *`parse_path_segment` calls deep:* 1
5842 //
5843 // At this point, this function will expect to find another matching `>` character but
5844 // won't be able to and will return an error. This will continue all the way up the
5845 // call stack until the first invocation:
5846 //
5847 // *Upcoming tokens:* `;`
5848 // *Unmatched count:* 2
5849 // *`parse_path_segment` calls deep:* 0
5850 //
5851 // In doing this, we have managed to work out how many unmatched leading left angle
5852 // brackets there are, but we cannot recover as the unmatched angle brackets have
5853 // already been consumed. To remedy this, we keep a snapshot of the parser state
5854 // before we do the above. We can then inspect whether we ended up with a parsing error
5855 // and unmatched left angle brackets and if so, restore the parser state before we
5856 // consumed any `<` characters to emit an error and consume the erroneous tokens to
5857 // recover by attempting to parse again.
5858 //
5859 // In practice, the recursion of this function is indirect and there will be other
5860 // locations that consume some `<` characters - as long as we update the count when
5861 // this happens, it isn't an issue.
5862
5863 let is_first_invocation = style == PathStyle::Expr;
5864 // Take a snapshot before attempting to parse - we can restore this later.
5865 let snapshot = if is_first_invocation {
5866 Some(self.clone())
5867 } else {
5868 None
5869 };
5870
5871 debug!("parse_generic_args_with_leading_angle_bracket_recovery: (snapshotting)");
5872 match self.parse_generic_args() {
5873 Ok(value) => Ok(value),
5874 Err(ref mut e) if is_first_invocation && self.unmatched_angle_bracket_count > 0 => {
5875 // Cancel error from being unable to find `>`. We know the error
5876 // must have been this due to a non-zero unmatched angle bracket
5877 // count.
5878 e.cancel();
5879
5880 // Swap `self` with our backup of the parser state before attempting to parse
5881 // generic arguments.
5882 let snapshot = mem::replace(self, snapshot.unwrap());
5883
5884 debug!(
5885 "parse_generic_args_with_leading_angle_bracket_recovery: (snapshot failure) \
5886 snapshot.count={:?}",
5887 snapshot.unmatched_angle_bracket_count,
5888 );
5889
5890 // Eat the unmatched angle brackets.
5891 for _ in 0..snapshot.unmatched_angle_bracket_count {
5892 self.eat_lt();
5893 }
5894
5895 // Make a span over ${unmatched angle bracket count} characters.
5896 let span = lo.with_hi(
5897 lo.lo() + BytePos(snapshot.unmatched_angle_bracket_count)
5898 );
5899 let plural = snapshot.unmatched_angle_bracket_count > 1;
5900 self.diagnostic()
5901 .struct_span_err(
5902 span,
5903 &format!(
5904 "unmatched angle bracket{}",
5905 if plural { "s" } else { "" }
5906 ),
5907 )
5908 .span_suggestion(
5909 span,
5910 &format!(
5911 "remove extra angle bracket{}",
5912 if plural { "s" } else { "" }
5913 ),
5914 String::new(),
5915 Applicability::MachineApplicable,
5916 )
5917 .emit();
5918
5919 // Try again without unmatched angle bracket characters.
5920 self.parse_generic_args()
5921 },
5922 Err(e) => Err(e),
5923 }
5924 }
5925
5926 /// Parses (possibly empty) list of lifetime and type arguments and associated type bindings,
5927 /// possibly including trailing comma.
5928 fn parse_generic_args(&mut self) -> PResult<'a, (Vec<GenericArg>, Vec<TypeBinding>)> {
5929 let mut args = Vec::new();
5930 let mut bindings = Vec::new();
5931 let mut misplaced_assoc_ty_bindings: Vec<Span> = Vec::new();
5932 let mut assoc_ty_bindings: Vec<Span> = Vec::new();
5933
5934 let args_lo = self.span;
5935
5936 loop {
5937 if self.check_lifetime() && self.look_ahead(1, |t| !t.is_like_plus()) {
5938 // Parse lifetime argument.
5939 args.push(GenericArg::Lifetime(self.expect_lifetime()));
5940 misplaced_assoc_ty_bindings.append(&mut assoc_ty_bindings);
5941 } else if self.check_ident() && self.look_ahead(1, |t| t == &token::Eq) {
5942 // Parse associated type binding.
5943 let lo = self.span;
5944 let ident = self.parse_ident()?;
5945 self.bump();
5946 let ty = self.parse_ty()?;
5947 let span = lo.to(self.prev_span);
5948 bindings.push(TypeBinding {
5949 id: ast::DUMMY_NODE_ID,
5950 ident,
5951 ty,
5952 span,
5953 });
5954 assoc_ty_bindings.push(span);
5955 } else if self.check_const_arg() {
5956 // FIXME(const_generics): to distinguish between idents for types and consts,
5957 // we should introduce a GenericArg::Ident in the AST and distinguish when
5958 // lowering to the HIR. For now, idents for const args are not permitted.
5959
5960 // Parse const argument.
5961 let expr = if let token::OpenDelim(token::Brace) = self.token {
5962 self.parse_block_expr(None, self.span, BlockCheckMode::Default, ThinVec::new())?
5963 } else if self.token.is_ident() {
5964 // FIXME(const_generics): to distinguish between idents for types and consts,
5965 // we should introduce a GenericArg::Ident in the AST and distinguish when
5966 // lowering to the HIR. For now, idents for const args are not permitted.
5967 return Err(
5968 self.fatal("identifiers may currently not be used for const generics")
5969 );
5970 } else {
5971 // FIXME(const_generics): this currently conflicts with emplacement syntax
5972 // with negative integer literals.
5973 self.parse_literal_maybe_minus()?
5974 };
5975 let value = AnonConst {
5976 id: ast::DUMMY_NODE_ID,
5977 value: expr,
5978 };
5979 args.push(GenericArg::Const(value));
5980 misplaced_assoc_ty_bindings.append(&mut assoc_ty_bindings);
5981 } else if self.check_type() {
5982 // Parse type argument.
5983 args.push(GenericArg::Type(self.parse_ty()?));
5984 misplaced_assoc_ty_bindings.append(&mut assoc_ty_bindings);
5985 } else {
5986 break
5987 }
5988
5989 if !self.eat(&token::Comma) {
5990 break
5991 }
5992 }
5993
5994 // FIXME: we would like to report this in ast_validation instead, but we currently do not
5995 // preserve ordering of generic parameters with respect to associated type binding, so we
5996 // lose that information after parsing.
5997 if misplaced_assoc_ty_bindings.len() > 0 {
5998 let mut err = self.struct_span_err(
5999 args_lo.to(self.prev_span),
6000 "associated type bindings must be declared after generic parameters",
6001 );
6002 for span in misplaced_assoc_ty_bindings {
6003 err.span_label(
6004 span,
6005 "this associated type binding should be moved after the generic parameters",
6006 );
6007 }
6008 err.emit();
6009 }
6010
6011 Ok((args, bindings))
6012 }
6013
6014 /// Parses an optional where-clause and places it in `generics`.
6015 ///
6016 /// ```ignore (only-for-syntax-highlight)
6017 /// where T : Trait<U, V> + 'b, 'a : 'b
6018 /// ```
6019 fn parse_where_clause(&mut self) -> PResult<'a, WhereClause> {
6020 maybe_whole!(self, NtWhereClause, |x| x);
6021
6022 let mut where_clause = WhereClause {
6023 id: ast::DUMMY_NODE_ID,
6024 predicates: Vec::new(),
6025 span: syntax_pos::DUMMY_SP,
6026 };
6027
6028 if !self.eat_keyword(keywords::Where) {
6029 return Ok(where_clause);
6030 }
6031 let lo = self.prev_span;
6032
6033 // We are considering adding generics to the `where` keyword as an alternative higher-rank
6034 // parameter syntax (as in `where<'a>` or `where<T>`. To avoid that being a breaking
6035 // change we parse those generics now, but report an error.
6036 if self.choose_generics_over_qpath() {
6037 let generics = self.parse_generics()?;
6038 self.struct_span_err(
6039 generics.span,
6040 "generic parameters on `where` clauses are reserved for future use",
6041 )
6042 .span_label(generics.span, "currently unsupported")
6043 .emit();
6044 }
6045
6046 loop {
6047 let lo = self.span;
6048 if self.check_lifetime() && self.look_ahead(1, |t| !t.is_like_plus()) {
6049 let lifetime = self.expect_lifetime();
6050 // Bounds starting with a colon are mandatory, but possibly empty.
6051 self.expect(&token::Colon)?;
6052 let bounds = self.parse_lt_param_bounds();
6053 where_clause.predicates.push(ast::WherePredicate::RegionPredicate(
6054 ast::WhereRegionPredicate {
6055 span: lo.to(self.prev_span),
6056 lifetime,
6057 bounds,
6058 }
6059 ));
6060 } else if self.check_type() {
6061 // Parse optional `for<'a, 'b>`.
6062 // This `for` is parsed greedily and applies to the whole predicate,
6063 // the bounded type can have its own `for` applying only to it.
6064 // Example 1: for<'a> Trait1<'a>: Trait2<'a /*ok*/>
6065 // Example 2: (for<'a> Trait1<'a>): Trait2<'a /*not ok*/>
6066 // Example 3: for<'a> for<'b> Trait1<'a, 'b>: Trait2<'a /*ok*/, 'b /*not ok*/>
6067 let lifetime_defs = self.parse_late_bound_lifetime_defs()?;
6068
6069 // Parse type with mandatory colon and (possibly empty) bounds,
6070 // or with mandatory equality sign and the second type.
6071 let ty = self.parse_ty()?;
6072 if self.eat(&token::Colon) {
6073 let bounds = self.parse_generic_bounds(None)?;
6074 where_clause.predicates.push(ast::WherePredicate::BoundPredicate(
6075 ast::WhereBoundPredicate {
6076 span: lo.to(self.prev_span),
6077 bound_generic_params: lifetime_defs,
6078 bounded_ty: ty,
6079 bounds,
6080 }
6081 ));
6082 // FIXME: Decide what should be used here, `=` or `==`.
6083 // FIXME: We are just dropping the binders in lifetime_defs on the floor here.
6084 } else if self.eat(&token::Eq) || self.eat(&token::EqEq) {
6085 let rhs_ty = self.parse_ty()?;
6086 where_clause.predicates.push(ast::WherePredicate::EqPredicate(
6087 ast::WhereEqPredicate {
6088 span: lo.to(self.prev_span),
6089 lhs_ty: ty,
6090 rhs_ty,
6091 id: ast::DUMMY_NODE_ID,
6092 }
6093 ));
6094 } else {
6095 return self.unexpected();
6096 }
6097 } else {
6098 break
6099 }
6100
6101 if !self.eat(&token::Comma) {
6102 break
6103 }
6104 }
6105
6106 where_clause.span = lo.to(self.prev_span);
6107 Ok(where_clause)
6108 }
6109
6110 fn parse_fn_args(&mut self, named_args: bool, allow_variadic: bool)
6111 -> PResult<'a, (Vec<Arg> , bool)> {
6112 self.expect(&token::OpenDelim(token::Paren))?;
6113
6114 let sp = self.span;
6115 let mut variadic = false;
6116 let (args, recovered): (Vec<Option<Arg>>, bool) =
6117 self.parse_seq_to_before_end(
6118 &token::CloseDelim(token::Paren),
6119 SeqSep::trailing_allowed(token::Comma),
6120 |p| {
6121 if p.token == token::DotDotDot {
6122 p.bump();
6123 variadic = true;
6124 if allow_variadic {
6125 if p.token != token::CloseDelim(token::Paren) {
6126 let span = p.span;
6127 p.span_err(span,
6128 "`...` must be last in argument list for variadic function");
6129 }
6130 Ok(None)
6131 } else {
6132 let span = p.prev_span;
6133 if p.token == token::CloseDelim(token::Paren) {
6134 // continue parsing to present any further errors
6135 p.struct_span_err(
6136 span,
6137 "only foreign functions are allowed to be variadic"
6138 ).emit();
6139 Ok(Some(dummy_arg(span)))
6140 } else {
6141 // this function definition looks beyond recovery, stop parsing
6142 p.span_err(span,
6143 "only foreign functions are allowed to be variadic");
6144 Ok(None)
6145 }
6146 }
6147 } else {
6148 match p.parse_arg_general(named_args, false) {
6149 Ok(arg) => Ok(Some(arg)),
6150 Err(mut e) => {
6151 e.emit();
6152 let lo = p.prev_span;
6153 // Skip every token until next possible arg or end.
6154 p.eat_to_tokens(&[&token::Comma, &token::CloseDelim(token::Paren)]);
6155 // Create a placeholder argument for proper arg count (#34264).
6156 let span = lo.to(p.prev_span);
6157 Ok(Some(dummy_arg(span)))
6158 }
6159 }
6160 }
6161 }
6162 )?;
6163
6164 if !recovered {
6165 self.eat(&token::CloseDelim(token::Paren));
6166 }
6167
6168 let args: Vec<_> = args.into_iter().filter_map(|x| x).collect();
6169
6170 if variadic && args.is_empty() {
6171 self.span_err(sp,
6172 "variadic function must be declared with at least one named argument");
6173 }
6174
6175 Ok((args, variadic))
6176 }
6177
6178 /// Parses the argument list and result type of a function declaration.
6179 fn parse_fn_decl(&mut self, allow_variadic: bool) -> PResult<'a, P<FnDecl>> {
6180
6181 let (args, variadic) = self.parse_fn_args(true, allow_variadic)?;
6182 let ret_ty = self.parse_ret_ty(true)?;
6183
6184 Ok(P(FnDecl {
6185 inputs: args,
6186 output: ret_ty,
6187 variadic,
6188 }))
6189 }
6190
6191 /// Returns the parsed optional self argument and whether a self shortcut was used.
6192 fn parse_self_arg(&mut self) -> PResult<'a, Option<Arg>> {
6193 let expect_ident = |this: &mut Self| match this.token {
6194 // Preserve hygienic context.
6195 token::Ident(ident, _) =>
6196 { let span = this.span; this.bump(); Ident::new(ident.name, span) }
6197 _ => unreachable!()
6198 };
6199 let isolated_self = |this: &mut Self, n| {
6200 this.look_ahead(n, |t| t.is_keyword(keywords::SelfLower)) &&
6201 this.look_ahead(n + 1, |t| t != &token::ModSep)
6202 };
6203
6204 // Parse optional self parameter of a method.
6205 // Only a limited set of initial token sequences is considered self parameters, anything
6206 // else is parsed as a normal function parameter list, so some lookahead is required.
6207 let eself_lo = self.span;
6208 let (eself, eself_ident, eself_hi) = match self.token {
6209 token::BinOp(token::And) => {
6210 // &self
6211 // &mut self
6212 // &'lt self
6213 // &'lt mut self
6214 // &not_self
6215 (if isolated_self(self, 1) {
6216 self.bump();
6217 SelfKind::Region(None, Mutability::Immutable)
6218 } else if self.look_ahead(1, |t| t.is_keyword(keywords::Mut)) &&
6219 isolated_self(self, 2) {
6220 self.bump();
6221 self.bump();
6222 SelfKind::Region(None, Mutability::Mutable)
6223 } else if self.look_ahead(1, |t| t.is_lifetime()) &&
6224 isolated_self(self, 2) {
6225 self.bump();
6226 let lt = self.expect_lifetime();
6227 SelfKind::Region(Some(lt), Mutability::Immutable)
6228 } else if self.look_ahead(1, |t| t.is_lifetime()) &&
6229 self.look_ahead(2, |t| t.is_keyword(keywords::Mut)) &&
6230 isolated_self(self, 3) {
6231 self.bump();
6232 let lt = self.expect_lifetime();
6233 self.bump();
6234 SelfKind::Region(Some(lt), Mutability::Mutable)
6235 } else {
6236 return Ok(None);
6237 }, expect_ident(self), self.prev_span)
6238 }
6239 token::BinOp(token::Star) => {
6240 // *self
6241 // *const self
6242 // *mut self
6243 // *not_self
6244 // Emit special error for `self` cases.
6245 let msg = "cannot pass `self` by raw pointer";
6246 (if isolated_self(self, 1) {
6247 self.bump();
6248 self.struct_span_err(self.span, msg)
6249 .span_label(self.span, msg)
6250 .emit();
6251 SelfKind::Value(Mutability::Immutable)
6252 } else if self.look_ahead(1, |t| t.is_mutability()) &&
6253 isolated_self(self, 2) {
6254 self.bump();
6255 self.bump();
6256 self.struct_span_err(self.span, msg)
6257 .span_label(self.span, msg)
6258 .emit();
6259 SelfKind::Value(Mutability::Immutable)
6260 } else {
6261 return Ok(None);
6262 }, expect_ident(self), self.prev_span)
6263 }
6264 token::Ident(..) => {
6265 if isolated_self(self, 0) {
6266 // self
6267 // self: TYPE
6268 let eself_ident = expect_ident(self);
6269 let eself_hi = self.prev_span;
6270 (if self.eat(&token::Colon) {
6271 let ty = self.parse_ty()?;
6272 SelfKind::Explicit(ty, Mutability::Immutable)
6273 } else {
6274 SelfKind::Value(Mutability::Immutable)
6275 }, eself_ident, eself_hi)
6276 } else if self.token.is_keyword(keywords::Mut) &&
6277 isolated_self(self, 1) {
6278 // mut self
6279 // mut self: TYPE
6280 self.bump();
6281 let eself_ident = expect_ident(self);
6282 let eself_hi = self.prev_span;
6283 (if self.eat(&token::Colon) {
6284 let ty = self.parse_ty()?;
6285 SelfKind::Explicit(ty, Mutability::Mutable)
6286 } else {
6287 SelfKind::Value(Mutability::Mutable)
6288 }, eself_ident, eself_hi)
6289 } else {
6290 return Ok(None);
6291 }
6292 }
6293 _ => return Ok(None),
6294 };
6295
6296 let eself = source_map::respan(eself_lo.to(eself_hi), eself);
6297 Ok(Some(Arg::from_self(eself, eself_ident)))
6298 }
6299
6300 /// Parses the parameter list and result type of a function that may have a `self` parameter.
6301 fn parse_fn_decl_with_self<F>(&mut self, parse_arg_fn: F) -> PResult<'a, P<FnDecl>>
6302 where F: FnMut(&mut Parser<'a>) -> PResult<'a, Arg>,
6303 {
6304 self.expect(&token::OpenDelim(token::Paren))?;
6305
6306 // Parse optional self argument
6307 let self_arg = self.parse_self_arg()?;
6308
6309 // Parse the rest of the function parameter list.
6310 let sep = SeqSep::trailing_allowed(token::Comma);
6311 let (fn_inputs, recovered) = if let Some(self_arg) = self_arg {
6312 if self.check(&token::CloseDelim(token::Paren)) {
6313 (vec![self_arg], false)
6314 } else if self.eat(&token::Comma) {
6315 let mut fn_inputs = vec![self_arg];
6316 let (mut input, recovered) = self.parse_seq_to_before_end(
6317 &token::CloseDelim(token::Paren), sep, parse_arg_fn)?;
6318 fn_inputs.append(&mut input);
6319 (fn_inputs, recovered)
6320 } else {
6321 return self.unexpected();
6322 }
6323 } else {
6324 self.parse_seq_to_before_end(&token::CloseDelim(token::Paren), sep, parse_arg_fn)?
6325 };
6326
6327 if !recovered {
6328 // Parse closing paren and return type.
6329 self.expect(&token::CloseDelim(token::Paren))?;
6330 }
6331 Ok(P(FnDecl {
6332 inputs: fn_inputs,
6333 output: self.parse_ret_ty(true)?,
6334 variadic: false
6335 }))
6336 }
6337
6338 /// Parses the `|arg, arg|` header of a closure.
6339 fn parse_fn_block_decl(&mut self) -> PResult<'a, P<FnDecl>> {
6340 let inputs_captures = {
6341 if self.eat(&token::OrOr) {
6342 Vec::new()
6343 } else {
6344 self.expect(&token::BinOp(token::Or))?;
6345 let args = self.parse_seq_to_before_tokens(
6346 &[&token::BinOp(token::Or), &token::OrOr],
6347 SeqSep::trailing_allowed(token::Comma),
6348 TokenExpectType::NoExpect,
6349 |p| p.parse_fn_block_arg()
6350 )?.0;
6351 self.expect_or()?;
6352 args
6353 }
6354 };
6355 let output = self.parse_ret_ty(true)?;
6356
6357 Ok(P(FnDecl {
6358 inputs: inputs_captures,
6359 output,
6360 variadic: false
6361 }))
6362 }
6363
6364 /// Parses the name and optional generic types of a function header.
6365 fn parse_fn_header(&mut self) -> PResult<'a, (Ident, ast::Generics)> {
6366 let id = self.parse_ident()?;
6367 let generics = self.parse_generics()?;
6368 Ok((id, generics))
6369 }
6370
6371 fn mk_item(&mut self, span: Span, ident: Ident, node: ItemKind, vis: Visibility,
6372 attrs: Vec<Attribute>) -> P<Item> {
6373 P(Item {
6374 ident,
6375 attrs,
6376 id: ast::DUMMY_NODE_ID,
6377 node,
6378 vis,
6379 span,
6380 tokens: None,
6381 })
6382 }
6383
6384 /// Parses an item-position function declaration.
6385 fn parse_item_fn(&mut self,
6386 unsafety: Unsafety,
6387 asyncness: IsAsync,
6388 constness: Spanned<Constness>,
6389 abi: Abi)
6390 -> PResult<'a, ItemInfo> {
6391 let (ident, mut generics) = self.parse_fn_header()?;
6392 let decl = self.parse_fn_decl(false)?;
6393 generics.where_clause = self.parse_where_clause()?;
6394 let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
6395 let header = FnHeader { unsafety, asyncness, constness, abi };
6396 Ok((ident, ItemKind::Fn(decl, header, generics, body), Some(inner_attrs)))
6397 }
6398
6399 /// Returns `true` if we are looking at `const ID`
6400 /// (returns `false` for things like `const fn`, etc.).
6401 fn is_const_item(&mut self) -> bool {
6402 self.token.is_keyword(keywords::Const) &&
6403 !self.look_ahead(1, |t| t.is_keyword(keywords::Fn)) &&
6404 !self.look_ahead(1, |t| t.is_keyword(keywords::Unsafe))
6405 }
6406
6407 /// Parses all the "front matter" for a `fn` declaration, up to
6408 /// and including the `fn` keyword:
6409 ///
6410 /// - `const fn`
6411 /// - `unsafe fn`
6412 /// - `const unsafe fn`
6413 /// - `extern fn`
6414 /// - etc.
6415 fn parse_fn_front_matter(&mut self)
6416 -> PResult<'a, (
6417 Spanned<Constness>,
6418 Unsafety,
6419 IsAsync,
6420 Abi
6421 )>
6422 {
6423 let is_const_fn = self.eat_keyword(keywords::Const);
6424 let const_span = self.prev_span;
6425 let unsafety = self.parse_unsafety();
6426 let asyncness = self.parse_asyncness();
6427 let (constness, unsafety, abi) = if is_const_fn {
6428 (respan(const_span, Constness::Const), unsafety, Abi::Rust)
6429 } else {
6430 let abi = if self.eat_keyword(keywords::Extern) {
6431 self.parse_opt_abi()?.unwrap_or(Abi::C)
6432 } else {
6433 Abi::Rust
6434 };
6435 (respan(self.prev_span, Constness::NotConst), unsafety, abi)
6436 };
6437 self.expect_keyword(keywords::Fn)?;
6438 Ok((constness, unsafety, asyncness, abi))
6439 }
6440
6441 /// Parses an impl item.
6442 pub fn parse_impl_item(&mut self, at_end: &mut bool) -> PResult<'a, ImplItem> {
6443 maybe_whole!(self, NtImplItem, |x| x);
6444 let attrs = self.parse_outer_attributes()?;
6445 let (mut item, tokens) = self.collect_tokens(|this| {
6446 this.parse_impl_item_(at_end, attrs)
6447 })?;
6448
6449 // See `parse_item` for why this clause is here.
6450 if !item.attrs.iter().any(|attr| attr.style == AttrStyle::Inner) {
6451 item.tokens = Some(tokens);
6452 }
6453 Ok(item)
6454 }
6455
6456 fn parse_impl_item_(&mut self,
6457 at_end: &mut bool,
6458 mut attrs: Vec<Attribute>) -> PResult<'a, ImplItem> {
6459 let lo = self.span;
6460 let vis = self.parse_visibility(false)?;
6461 let defaultness = self.parse_defaultness();
6462 let (name, node, generics) = if let Some(type_) = self.eat_type() {
6463 let (name, alias, generics) = type_?;
6464 let kind = match alias {
6465 AliasKind::Weak(typ) => ast::ImplItemKind::Type(typ),
6466 AliasKind::Existential(bounds) => ast::ImplItemKind::Existential(bounds),
6467 };
6468 (name, kind, generics)
6469 } else if self.is_const_item() {
6470 // This parses the grammar:
6471 // ImplItemConst = "const" Ident ":" Ty "=" Expr ";"
6472 self.expect_keyword(keywords::Const)?;
6473 let name = self.parse_ident()?;
6474 self.expect(&token::Colon)?;
6475 let typ = self.parse_ty()?;
6476 self.expect(&token::Eq)?;
6477 let expr = self.parse_expr()?;
6478 self.expect(&token::Semi)?;
6479 (name, ast::ImplItemKind::Const(typ, expr), ast::Generics::default())
6480 } else {
6481 let (name, inner_attrs, generics, node) = self.parse_impl_method(&vis, at_end)?;
6482 attrs.extend(inner_attrs);
6483 (name, node, generics)
6484 };
6485
6486 Ok(ImplItem {
6487 id: ast::DUMMY_NODE_ID,
6488 span: lo.to(self.prev_span),
6489 ident: name,
6490 vis,
6491 defaultness,
6492 attrs,
6493 generics,
6494 node,
6495 tokens: None,
6496 })
6497 }
6498
6499 fn complain_if_pub_macro(&mut self, vis: &VisibilityKind, sp: Span) {
6500 match *vis {
6501 VisibilityKind::Inherited => {}
6502 _ => {
6503 let is_macro_rules: bool = match self.token {
6504 token::Ident(sid, _) => sid.name == Symbol::intern("macro_rules"),
6505 _ => false,
6506 };
6507 let mut err = if is_macro_rules {
6508 let mut err = self.diagnostic()
6509 .struct_span_err(sp, "can't qualify macro_rules invocation with `pub`");
6510 err.span_suggestion(
6511 sp,
6512 "try exporting the macro",
6513 "#[macro_export]".to_owned(),
6514 Applicability::MaybeIncorrect // speculative
6515 );
6516 err
6517 } else {
6518 let mut err = self.diagnostic()
6519 .struct_span_err(sp, "can't qualify macro invocation with `pub`");
6520 err.help("try adjusting the macro to put `pub` inside the invocation");
6521 err
6522 };
6523 err.emit();
6524 }
6525 }
6526 }
6527
6528 fn missing_assoc_item_kind_err(&mut self, item_type: &str, prev_span: Span)
6529 -> DiagnosticBuilder<'a>
6530 {
6531 let expected_kinds = if item_type == "extern" {
6532 "missing `fn`, `type`, or `static`"
6533 } else {
6534 "missing `fn`, `type`, or `const`"
6535 };
6536
6537 // Given this code `path(`, it seems like this is not
6538 // setting the visibility of a macro invocation, but rather
6539 // a mistyped method declaration.
6540 // Create a diagnostic pointing out that `fn` is missing.
6541 //
6542 // x | pub path(&self) {
6543 // | ^ missing `fn`, `type`, or `const`
6544 // pub path(
6545 // ^^ `sp` below will point to this
6546 let sp = prev_span.between(self.prev_span);
6547 let mut err = self.diagnostic().struct_span_err(
6548 sp,
6549 &format!("{} for {}-item declaration",
6550 expected_kinds, item_type));
6551 err.span_label(sp, expected_kinds);
6552 err
6553 }
6554
6555 /// Parse a method or a macro invocation in a trait impl.
6556 fn parse_impl_method(&mut self, vis: &Visibility, at_end: &mut bool)
6557 -> PResult<'a, (Ident, Vec<Attribute>, ast::Generics,
6558 ast::ImplItemKind)> {
6559 // code copied from parse_macro_use_or_failure... abstraction!
6560 if let Some(mac) = self.parse_assoc_macro_invoc("impl", Some(vis), at_end)? {
6561 // method macro
6562 Ok((keywords::Invalid.ident(), vec![], ast::Generics::default(),
6563 ast::ImplItemKind::Macro(mac)))
6564 } else {
6565 let (constness, unsafety, asyncness, abi) = self.parse_fn_front_matter()?;
6566 let ident = self.parse_ident()?;
6567 let mut generics = self.parse_generics()?;
6568 let decl = self.parse_fn_decl_with_self(|p| p.parse_arg())?;
6569 generics.where_clause = self.parse_where_clause()?;
6570 *at_end = true;
6571 let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
6572 let header = ast::FnHeader { abi, unsafety, constness, asyncness };
6573 Ok((ident, inner_attrs, generics, ast::ImplItemKind::Method(
6574 ast::MethodSig { header, decl },
6575 body
6576 )))
6577 }
6578 }
6579
6580 /// Parses `trait Foo { ... }` or `trait Foo = Bar;`.
6581 fn parse_item_trait(&mut self, is_auto: IsAuto, unsafety: Unsafety) -> PResult<'a, ItemInfo> {
6582 let ident = self.parse_ident()?;
6583 let mut tps = self.parse_generics()?;
6584
6585 // Parse optional colon and supertrait bounds.
6586 let bounds = if self.eat(&token::Colon) {
6587 self.parse_generic_bounds(Some(self.prev_span))?
6588 } else {
6589 Vec::new()
6590 };
6591
6592 if self.eat(&token::Eq) {
6593 // it's a trait alias
6594 let bounds = self.parse_generic_bounds(None)?;
6595 tps.where_clause = self.parse_where_clause()?;
6596 self.expect(&token::Semi)?;
6597 if is_auto == IsAuto::Yes {
6598 let msg = "trait aliases cannot be `auto`";
6599 self.struct_span_err(self.prev_span, msg)
6600 .span_label(self.prev_span, msg)
6601 .emit();
6602 }
6603 if unsafety != Unsafety::Normal {
6604 let msg = "trait aliases cannot be `unsafe`";
6605 self.struct_span_err(self.prev_span, msg)
6606 .span_label(self.prev_span, msg)
6607 .emit();
6608 }
6609 Ok((ident, ItemKind::TraitAlias(tps, bounds), None))
6610 } else {
6611 // it's a normal trait
6612 tps.where_clause = self.parse_where_clause()?;
6613 self.expect(&token::OpenDelim(token::Brace))?;
6614 let mut trait_items = vec![];
6615 while !self.eat(&token::CloseDelim(token::Brace)) {
6616 let mut at_end = false;
6617 match self.parse_trait_item(&mut at_end) {
6618 Ok(item) => trait_items.push(item),
6619 Err(mut e) => {
6620 e.emit();
6621 if !at_end {
6622 self.recover_stmt_(SemiColonMode::Break, BlockMode::Break);
6623 }
6624 }
6625 }
6626 }
6627 Ok((ident, ItemKind::Trait(is_auto, unsafety, tps, bounds, trait_items), None))
6628 }
6629 }
6630
6631 fn choose_generics_over_qpath(&self) -> bool {
6632 // There's an ambiguity between generic parameters and qualified paths in impls.
6633 // If we see `<` it may start both, so we have to inspect some following tokens.
6634 // The following combinations can only start generics,
6635 // but not qualified paths (with one exception):
6636 // `<` `>` - empty generic parameters
6637 // `<` `#` - generic parameters with attributes
6638 // `<` (LIFETIME|IDENT) `>` - single generic parameter
6639 // `<` (LIFETIME|IDENT) `,` - first generic parameter in a list
6640 // `<` (LIFETIME|IDENT) `:` - generic parameter with bounds
6641 // `<` (LIFETIME|IDENT) `=` - generic parameter with a default
6642 // `<` const - generic const parameter
6643 // The only truly ambiguous case is
6644 // `<` IDENT `>` `::` IDENT ...
6645 // we disambiguate it in favor of generics (`impl<T> ::absolute::Path<T> { ... }`)
6646 // because this is what almost always expected in practice, qualified paths in impls
6647 // (`impl <Type>::AssocTy { ... }`) aren't even allowed by type checker at the moment.
6648 self.token == token::Lt &&
6649 (self.look_ahead(1, |t| t == &token::Pound || t == &token::Gt) ||
6650 self.look_ahead(1, |t| t.is_lifetime() || t.is_ident()) &&
6651 self.look_ahead(2, |t| t == &token::Gt || t == &token::Comma ||
6652 t == &token::Colon || t == &token::Eq) ||
6653 self.look_ahead(1, |t| t.is_keyword(keywords::Const)))
6654 }
6655
6656 fn parse_impl_body(&mut self) -> PResult<'a, (Vec<ImplItem>, Vec<Attribute>)> {
6657 self.expect(&token::OpenDelim(token::Brace))?;
6658 let attrs = self.parse_inner_attributes()?;
6659
6660 let mut impl_items = Vec::new();
6661 while !self.eat(&token::CloseDelim(token::Brace)) {
6662 let mut at_end = false;
6663 match self.parse_impl_item(&mut at_end) {
6664 Ok(impl_item) => impl_items.push(impl_item),
6665 Err(mut err) => {
6666 err.emit();
6667 if !at_end {
6668 self.recover_stmt_(SemiColonMode::Break, BlockMode::Break);
6669 }
6670 }
6671 }
6672 }
6673 Ok((impl_items, attrs))
6674 }
6675
6676 /// Parses an implementation item, `impl` keyword is already parsed.
6677 ///
6678 /// impl<'a, T> TYPE { /* impl items */ }
6679 /// impl<'a, T> TRAIT for TYPE { /* impl items */ }
6680 /// impl<'a, T> !TRAIT for TYPE { /* impl items */ }
6681 ///
6682 /// We actually parse slightly more relaxed grammar for better error reporting and recovery.
6683 /// `impl` GENERICS `!`? TYPE `for`? (TYPE | `..`) (`where` PREDICATES)? `{` BODY `}`
6684 /// `impl` GENERICS `!`? TYPE (`where` PREDICATES)? `{` BODY `}`
6685 fn parse_item_impl(&mut self, unsafety: Unsafety, defaultness: Defaultness)
6686 -> PResult<'a, ItemInfo> {
6687 // First, parse generic parameters if necessary.
6688 let mut generics = if self.choose_generics_over_qpath() {
6689 self.parse_generics()?
6690 } else {
6691 ast::Generics::default()
6692 };
6693
6694 // Disambiguate `impl !Trait for Type { ... }` and `impl ! { ... }` for the never type.
6695 let polarity = if self.check(&token::Not) && self.look_ahead(1, |t| t.can_begin_type()) {
6696 self.bump(); // `!`
6697 ast::ImplPolarity::Negative
6698 } else {
6699 ast::ImplPolarity::Positive
6700 };
6701
6702 // Parse both types and traits as a type, then reinterpret if necessary.
6703 let ty_first = self.parse_ty()?;
6704
6705 // If `for` is missing we try to recover.
6706 let has_for = self.eat_keyword(keywords::For);
6707 let missing_for_span = self.prev_span.between(self.span);
6708
6709 let ty_second = if self.token == token::DotDot {
6710 // We need to report this error after `cfg` expansion for compatibility reasons
6711 self.bump(); // `..`, do not add it to expected tokens
6712 Some(P(Ty { node: TyKind::Err, span: self.prev_span, id: ast::DUMMY_NODE_ID }))
6713 } else if has_for || self.token.can_begin_type() {
6714 Some(self.parse_ty()?)
6715 } else {
6716 None
6717 };
6718
6719 generics.where_clause = self.parse_where_clause()?;
6720
6721 let (impl_items, attrs) = self.parse_impl_body()?;
6722
6723 let item_kind = match ty_second {
6724 Some(ty_second) => {
6725 // impl Trait for Type
6726 if !has_for {
6727 self.struct_span_err(missing_for_span, "missing `for` in a trait impl")
6728 .span_suggestion_short(
6729 missing_for_span,
6730 "add `for` here",
6731 " for ".to_string(),
6732 Applicability::MachineApplicable,
6733 ).emit();
6734 }
6735
6736 let ty_first = ty_first.into_inner();
6737 let path = match ty_first.node {
6738 // This notably includes paths passed through `ty` macro fragments (#46438).
6739 TyKind::Path(None, path) => path,
6740 _ => {
6741 self.span_err(ty_first.span, "expected a trait, found type");
6742 ast::Path::from_ident(Ident::new(keywords::Invalid.name(), ty_first.span))
6743 }
6744 };
6745 let trait_ref = TraitRef { path, ref_id: ty_first.id };
6746
6747 ItemKind::Impl(unsafety, polarity, defaultness,
6748 generics, Some(trait_ref), ty_second, impl_items)
6749 }
6750 None => {
6751 // impl Type
6752 ItemKind::Impl(unsafety, polarity, defaultness,
6753 generics, None, ty_first, impl_items)
6754 }
6755 };
6756
6757 Ok((keywords::Invalid.ident(), item_kind, Some(attrs)))
6758 }
6759
6760 fn parse_late_bound_lifetime_defs(&mut self) -> PResult<'a, Vec<GenericParam>> {
6761 if self.eat_keyword(keywords::For) {
6762 self.expect_lt()?;
6763 let params = self.parse_generic_params()?;
6764 self.expect_gt()?;
6765 // We rely on AST validation to rule out invalid cases: There must not be type
6766 // parameters, and the lifetime parameters must not have bounds.
6767 Ok(params)
6768 } else {
6769 Ok(Vec::new())
6770 }
6771 }
6772
6773 /// Parses `struct Foo { ... }`.
6774 fn parse_item_struct(&mut self) -> PResult<'a, ItemInfo> {
6775 let class_name = self.parse_ident()?;
6776
6777 let mut generics = self.parse_generics()?;
6778
6779 // There is a special case worth noting here, as reported in issue #17904.
6780 // If we are parsing a tuple struct it is the case that the where clause
6781 // should follow the field list. Like so:
6782 //
6783 // struct Foo<T>(T) where T: Copy;
6784 //
6785 // If we are parsing a normal record-style struct it is the case
6786 // that the where clause comes before the body, and after the generics.
6787 // So if we look ahead and see a brace or a where-clause we begin
6788 // parsing a record style struct.
6789 //
6790 // Otherwise if we look ahead and see a paren we parse a tuple-style
6791 // struct.
6792
6793 let vdata = if self.token.is_keyword(keywords::Where) {
6794 generics.where_clause = self.parse_where_clause()?;
6795 if self.eat(&token::Semi) {
6796 // If we see a: `struct Foo<T> where T: Copy;` style decl.
6797 VariantData::Unit(ast::DUMMY_NODE_ID)
6798 } else {
6799 // If we see: `struct Foo<T> where T: Copy { ... }`
6800 VariantData::Struct(self.parse_record_struct_body()?, ast::DUMMY_NODE_ID)
6801 }
6802 // No `where` so: `struct Foo<T>;`
6803 } else if self.eat(&token::Semi) {
6804 VariantData::Unit(ast::DUMMY_NODE_ID)
6805 // Record-style struct definition
6806 } else if self.token == token::OpenDelim(token::Brace) {
6807 VariantData::Struct(self.parse_record_struct_body()?, ast::DUMMY_NODE_ID)
6808 // Tuple-style struct definition with optional where-clause.
6809 } else if self.token == token::OpenDelim(token::Paren) {
6810 let body = VariantData::Tuple(self.parse_tuple_struct_body()?, ast::DUMMY_NODE_ID);
6811 generics.where_clause = self.parse_where_clause()?;
6812 self.expect(&token::Semi)?;
6813 body
6814 } else {
6815 let token_str = self.this_token_descr();
6816 let mut err = self.fatal(&format!(
6817 "expected `where`, `{{`, `(`, or `;` after struct name, found {}",
6818 token_str
6819 ));
6820 err.span_label(self.span, "expected `where`, `{`, `(`, or `;` after struct name");
6821 return Err(err);
6822 };
6823
6824 Ok((class_name, ItemKind::Struct(vdata, generics), None))
6825 }
6826
6827 /// Parses `union Foo { ... }`.
6828 fn parse_item_union(&mut self) -> PResult<'a, ItemInfo> {
6829 let class_name = self.parse_ident()?;
6830
6831 let mut generics = self.parse_generics()?;
6832
6833 let vdata = if self.token.is_keyword(keywords::Where) {
6834 generics.where_clause = self.parse_where_clause()?;
6835 VariantData::Struct(self.parse_record_struct_body()?, ast::DUMMY_NODE_ID)
6836 } else if self.token == token::OpenDelim(token::Brace) {
6837 VariantData::Struct(self.parse_record_struct_body()?, ast::DUMMY_NODE_ID)
6838 } else {
6839 let token_str = self.this_token_descr();
6840 let mut err = self.fatal(&format!(
6841 "expected `where` or `{{` after union name, found {}", token_str));
6842 err.span_label(self.span, "expected `where` or `{` after union name");
6843 return Err(err);
6844 };
6845
6846 Ok((class_name, ItemKind::Union(vdata, generics), None))
6847 }
6848
6849 fn consume_block(&mut self, delim: token::DelimToken) {
6850 let mut brace_depth = 0;
6851 loop {
6852 if self.eat(&token::OpenDelim(delim)) {
6853 brace_depth += 1;
6854 } else if self.eat(&token::CloseDelim(delim)) {
6855 if brace_depth == 0 {
6856 return;
6857 } else {
6858 brace_depth -= 1;
6859 continue;
6860 }
6861 } else if self.token == token::Eof || self.eat(&token::CloseDelim(token::NoDelim)) {
6862 return;
6863 } else {
6864 self.bump();
6865 }
6866 }
6867 }
6868
6869 fn parse_record_struct_body(&mut self) -> PResult<'a, Vec<StructField>> {
6870 let mut fields = Vec::new();
6871 if self.eat(&token::OpenDelim(token::Brace)) {
6872 while self.token != token::CloseDelim(token::Brace) {
6873 let field = self.parse_struct_decl_field().map_err(|e| {
6874 self.recover_stmt();
6875 e
6876 });
6877 match field {
6878 Ok(field) => fields.push(field),
6879 Err(mut err) => {
6880 err.emit();
6881 }
6882 }
6883 }
6884 self.eat(&token::CloseDelim(token::Brace));
6885 } else {
6886 let token_str = self.this_token_descr();
6887 let mut err = self.fatal(&format!(
6888 "expected `where`, or `{{` after struct name, found {}", token_str));
6889 err.span_label(self.span, "expected `where`, or `{` after struct name");
6890 return Err(err);
6891 }
6892
6893 Ok(fields)
6894 }
6895
6896 fn parse_tuple_struct_body(&mut self) -> PResult<'a, Vec<StructField>> {
6897 // This is the case where we find `struct Foo<T>(T) where T: Copy;`
6898 // Unit like structs are handled in parse_item_struct function
6899 let fields = self.parse_unspanned_seq(
6900 &token::OpenDelim(token::Paren),
6901 &token::CloseDelim(token::Paren),
6902 SeqSep::trailing_allowed(token::Comma),
6903 |p| {
6904 let attrs = p.parse_outer_attributes()?;
6905 let lo = p.span;
6906 let vis = p.parse_visibility(true)?;
6907 let ty = p.parse_ty()?;
6908 Ok(StructField {
6909 span: lo.to(ty.span),
6910 vis,
6911 ident: None,
6912 id: ast::DUMMY_NODE_ID,
6913 ty,
6914 attrs,
6915 })
6916 })?;
6917
6918 Ok(fields)
6919 }
6920
6921 /// Parses a structure field declaration.
6922 fn parse_single_struct_field(&mut self,
6923 lo: Span,
6924 vis: Visibility,
6925 attrs: Vec<Attribute> )
6926 -> PResult<'a, StructField> {
6927 let mut seen_comma: bool = false;
6928 let a_var = self.parse_name_and_ty(lo, vis, attrs)?;
6929 if self.token == token::Comma {
6930 seen_comma = true;
6931 }
6932 match self.token {
6933 token::Comma => {
6934 self.bump();
6935 }
6936 token::CloseDelim(token::Brace) => {}
6937 token::DocComment(_) => {
6938 let previous_span = self.prev_span;
6939 let mut err = self.span_fatal_err(self.span, Error::UselessDocComment);
6940 self.bump(); // consume the doc comment
6941 let comma_after_doc_seen = self.eat(&token::Comma);
6942 // `seen_comma` is always false, because we are inside doc block
6943 // condition is here to make code more readable
6944 if seen_comma == false && comma_after_doc_seen == true {
6945 seen_comma = true;
6946 }
6947 if comma_after_doc_seen || self.token == token::CloseDelim(token::Brace) {
6948 err.emit();
6949 } else {
6950 if seen_comma == false {
6951 let sp = self.sess.source_map().next_point(previous_span);
6952 err.span_suggestion(
6953 sp,
6954 "missing comma here",
6955 ",".into(),
6956 Applicability::MachineApplicable
6957 );
6958 }
6959 return Err(err);
6960 }
6961 }
6962 _ => {
6963 let sp = self.sess.source_map().next_point(self.prev_span);
6964 let mut err = self.struct_span_err(sp, &format!("expected `,`, or `}}`, found {}",
6965 self.this_token_descr()));
6966 if self.token.is_ident() {
6967 // This is likely another field; emit the diagnostic and keep going
6968 err.span_suggestion(
6969 sp,
6970 "try adding a comma",
6971 ",".into(),
6972 Applicability::MachineApplicable,
6973 );
6974 err.emit();
6975 } else {
6976 return Err(err)
6977 }
6978 }
6979 }
6980 Ok(a_var)
6981 }
6982
6983 /// Parses an element of a struct declaration.
6984 fn parse_struct_decl_field(&mut self) -> PResult<'a, StructField> {
6985 let attrs = self.parse_outer_attributes()?;
6986 let lo = self.span;
6987 let vis = self.parse_visibility(false)?;
6988 self.parse_single_struct_field(lo, vis, attrs)
6989 }
6990
6991 /// Parses `pub`, `pub(crate)` and `pub(in path)` plus shortcuts `crate` for `pub(crate)`,
6992 /// `pub(self)` for `pub(in self)` and `pub(super)` for `pub(in super)`.
6993 /// If the following element can't be a tuple (i.e., it's a function definition), then
6994 /// it's not a tuple struct field), and the contents within the parentheses isn't valid,
6995 /// so emit a proper diagnostic.
6996 pub fn parse_visibility(&mut self, can_take_tuple: bool) -> PResult<'a, Visibility> {
6997 maybe_whole!(self, NtVis, |x| x);
6998
6999 self.expected_tokens.push(TokenType::Keyword(keywords::Crate));
7000 if self.is_crate_vis() {
7001 self.bump(); // `crate`
7002 return Ok(respan(self.prev_span, VisibilityKind::Crate(CrateSugar::JustCrate)));
7003 }
7004
7005 if !self.eat_keyword(keywords::Pub) {
7006 // We need a span for our `Spanned<VisibilityKind>`, but there's inherently no
7007 // keyword to grab a span from for inherited visibility; an empty span at the
7008 // beginning of the current token would seem to be the "Schelling span".
7009 return Ok(respan(self.span.shrink_to_lo(), VisibilityKind::Inherited))
7010 }
7011 let lo = self.prev_span;
7012
7013 if self.check(&token::OpenDelim(token::Paren)) {
7014 // We don't `self.bump()` the `(` yet because this might be a struct definition where
7015 // `()` or a tuple might be allowed. For example, `struct Struct(pub (), pub (usize));`.
7016 // Because of this, we only `bump` the `(` if we're assured it is appropriate to do so
7017 // by the following tokens.
7018 if self.look_ahead(1, |t| t.is_keyword(keywords::Crate)) {
7019 // `pub(crate)`
7020 self.bump(); // `(`
7021 self.bump(); // `crate`
7022 self.expect(&token::CloseDelim(token::Paren))?; // `)`
7023 let vis = respan(
7024 lo.to(self.prev_span),
7025 VisibilityKind::Crate(CrateSugar::PubCrate),
7026 );
7027 return Ok(vis)
7028 } else if self.look_ahead(1, |t| t.is_keyword(keywords::In)) {
7029 // `pub(in path)`
7030 self.bump(); // `(`
7031 self.bump(); // `in`
7032 let path = self.parse_path(PathStyle::Mod)?; // `path`
7033 self.expect(&token::CloseDelim(token::Paren))?; // `)`
7034 let vis = respan(lo.to(self.prev_span), VisibilityKind::Restricted {
7035 path: P(path),
7036 id: ast::DUMMY_NODE_ID,
7037 });
7038 return Ok(vis)
7039 } else if self.look_ahead(2, |t| t == &token::CloseDelim(token::Paren)) &&
7040 self.look_ahead(1, |t| t.is_keyword(keywords::Super) ||
7041 t.is_keyword(keywords::SelfLower))
7042 {
7043 // `pub(self)` or `pub(super)`
7044 self.bump(); // `(`
7045 let path = self.parse_path(PathStyle::Mod)?; // `super`/`self`
7046 self.expect(&token::CloseDelim(token::Paren))?; // `)`
7047 let vis = respan(lo.to(self.prev_span), VisibilityKind::Restricted {
7048 path: P(path),
7049 id: ast::DUMMY_NODE_ID,
7050 });
7051 return Ok(vis)
7052 } else if !can_take_tuple { // Provide this diagnostic if this is not a tuple struct
7053 // `pub(something) fn ...` or `struct X { pub(something) y: Z }`
7054 self.bump(); // `(`
7055 let msg = "incorrect visibility restriction";
7056 let suggestion = r##"some possible visibility restrictions are:
7057`pub(crate)`: visible only on the current crate
7058`pub(super)`: visible only in the current module's parent
7059`pub(in path::to::module)`: visible only on the specified path"##;
7060 let path = self.parse_path(PathStyle::Mod)?;
7061 let sp = self.prev_span;
7062 let help_msg = format!("make this visible only to module `{}` with `in`", path);
7063 self.expect(&token::CloseDelim(token::Paren))?; // `)`
7064 let mut err = struct_span_err!(self.sess.span_diagnostic, sp, E0704, "{}", msg);
7065 err.help(suggestion);
7066 err.span_suggestion(
7067 sp, &help_msg, format!("in {}", path), Applicability::MachineApplicable
7068 );
7069 err.emit(); // emit diagnostic, but continue with public visibility
7070 }
7071 }
7072
7073 Ok(respan(lo, VisibilityKind::Public))
7074 }
7075
7076 /// Parses defaultness (i.e., `default` or nothing).
7077 fn parse_defaultness(&mut self) -> Defaultness {
7078 // `pub` is included for better error messages
7079 if self.check_keyword(keywords::Default) &&
7080 self.look_ahead(1, |t| t.is_keyword(keywords::Impl) ||
7081 t.is_keyword(keywords::Const) ||
7082 t.is_keyword(keywords::Fn) ||
7083 t.is_keyword(keywords::Unsafe) ||
7084 t.is_keyword(keywords::Extern) ||
7085 t.is_keyword(keywords::Type) ||
7086 t.is_keyword(keywords::Pub)) {
7087 self.bump(); // `default`
7088 Defaultness::Default
7089 } else {
7090 Defaultness::Final
7091 }
7092 }
7093
7094 fn maybe_consume_incorrect_semicolon(&mut self, items: &[P<Item>]) -> bool {
7095 if self.eat(&token::Semi) {
7096 let mut err = self.struct_span_err(self.prev_span, "expected item, found `;`");
7097 err.span_suggestion_short(
7098 self.prev_span,
7099 "remove this semicolon",
7100 String::new(),
7101 Applicability::MachineApplicable,
7102 );
7103 if !items.is_empty() {
7104 let previous_item = &items[items.len()-1];
7105 let previous_item_kind_name = match previous_item.node {
7106 // say "braced struct" because tuple-structs and
7107 // braceless-empty-struct declarations do take a semicolon
7108 ItemKind::Struct(..) => Some("braced struct"),
7109 ItemKind::Enum(..) => Some("enum"),
7110 ItemKind::Trait(..) => Some("trait"),
7111 ItemKind::Union(..) => Some("union"),
7112 _ => None,
7113 };
7114 if let Some(name) = previous_item_kind_name {
7115 err.help(&format!("{} declarations are not followed by a semicolon", name));
7116 }
7117 }
7118 err.emit();
7119 true
7120 } else {
7121 false
7122 }
7123 }
7124
7125 /// Given a termination token, parses all of the items in a module.
7126 fn parse_mod_items(&mut self, term: &token::Token, inner_lo: Span) -> PResult<'a, Mod> {
7127 let mut items = vec![];
7128 while let Some(item) = self.parse_item()? {
7129 items.push(item);
7130 self.maybe_consume_incorrect_semicolon(&items);
7131 }
7132
7133 if !self.eat(term) {
7134 let token_str = self.this_token_descr();
7135 if !self.maybe_consume_incorrect_semicolon(&items) {
7136 let mut err = self.fatal(&format!("expected item, found {}", token_str));
7137 err.span_label(self.span, "expected item");
7138 return Err(err);
7139 }
7140 }
7141
7142 let hi = if self.span.is_dummy() {
7143 inner_lo
7144 } else {
7145 self.prev_span
7146 };
7147
7148 Ok(ast::Mod {
7149 inner: inner_lo.to(hi),
7150 items,
7151 inline: true
7152 })
7153 }
7154
7155 fn parse_item_const(&mut self, m: Option<Mutability>) -> PResult<'a, ItemInfo> {
7156 let id = if m.is_none() { self.parse_ident_or_underscore() } else { self.parse_ident() }?;
7157 self.expect(&token::Colon)?;
7158 let ty = self.parse_ty()?;
7159 self.expect(&token::Eq)?;
7160 let e = self.parse_expr()?;
7161 self.expect(&token::Semi)?;
7162 let item = match m {
7163 Some(m) => ItemKind::Static(ty, m, e),
7164 None => ItemKind::Const(ty, e),
7165 };
7166 Ok((id, item, None))
7167 }
7168
7169 /// Parse a `mod <foo> { ... }` or `mod <foo>;` item
7170 fn parse_item_mod(&mut self, outer_attrs: &[Attribute]) -> PResult<'a, ItemInfo> {
7171 let (in_cfg, outer_attrs) = {
7172 let mut strip_unconfigured = crate::config::StripUnconfigured {
7173 sess: self.sess,
7174 features: None, // don't perform gated feature checking
7175 };
7176 let mut outer_attrs = outer_attrs.to_owned();
7177 strip_unconfigured.process_cfg_attrs(&mut outer_attrs);
7178 (!self.cfg_mods || strip_unconfigured.in_cfg(&outer_attrs), outer_attrs)
7179 };
7180
7181 let id_span = self.span;
7182 let id = self.parse_ident()?;
7183 if self.eat(&token::Semi) {
7184 if in_cfg && self.recurse_into_file_modules {
7185 // This mod is in an external file. Let's go get it!
7186 let ModulePathSuccess { path, directory_ownership, warn } =
7187 self.submod_path(id, &outer_attrs, id_span)?;
7188 let (module, mut attrs) =
7189 self.eval_src_mod(path, directory_ownership, id.to_string(), id_span)?;
7190 // Record that we fetched the mod from an external file
7191 if warn {
7192 let attr = Attribute {
7193 id: attr::mk_attr_id(),
7194 style: ast::AttrStyle::Outer,
7195 path: ast::Path::from_ident(Ident::from_str("warn_directory_ownership")),
7196 tokens: TokenStream::empty(),
7197 is_sugared_doc: false,
7198 span: syntax_pos::DUMMY_SP,
7199 };
7200 attr::mark_known(&attr);
7201 attrs.push(attr);
7202 }
7203 Ok((id, ItemKind::Mod(module), Some(attrs)))
7204 } else {
7205 let placeholder = ast::Mod {
7206 inner: syntax_pos::DUMMY_SP,
7207 items: Vec::new(),
7208 inline: false
7209 };
7210 Ok((id, ItemKind::Mod(placeholder), None))
7211 }
7212 } else {
7213 let old_directory = self.directory.clone();
7214 self.push_directory(id, &outer_attrs);
7215
7216 self.expect(&token::OpenDelim(token::Brace))?;
7217 let mod_inner_lo = self.span;
7218 let attrs = self.parse_inner_attributes()?;
7219 let module = self.parse_mod_items(&token::CloseDelim(token::Brace), mod_inner_lo)?;
7220
7221 self.directory = old_directory;
7222 Ok((id, ItemKind::Mod(module), Some(attrs)))
7223 }
7224 }
7225
7226 fn push_directory(&mut self, id: Ident, attrs: &[Attribute]) {
7227 if let Some(path) = attr::first_attr_value_str_by_name(attrs, "path") {
7228 self.directory.path.to_mut().push(&path.as_str());
7229 self.directory.ownership = DirectoryOwnership::Owned { relative: None };
7230 } else {
7231 // We have to push on the current module name in the case of relative
7232 // paths in order to ensure that any additional module paths from inline
7233 // `mod x { ... }` come after the relative extension.
7234 //
7235 // For example, a `mod z { ... }` inside `x/y.rs` should set the current
7236 // directory path to `/x/y/z`, not `/x/z` with a relative offset of `y`.
7237 if let DirectoryOwnership::Owned { relative } = &mut self.directory.ownership {
7238 if let Some(ident) = relative.take() { // remove the relative offset
7239 self.directory.path.to_mut().push(ident.as_str());
7240 }
7241 }
7242 self.directory.path.to_mut().push(&id.as_str());
7243 }
7244 }
7245
7246 pub fn submod_path_from_attr(attrs: &[Attribute], dir_path: &Path) -> Option<PathBuf> {
7247 if let Some(s) = attr::first_attr_value_str_by_name(attrs, "path") {
7248 let s = s.as_str();
7249
7250 // On windows, the base path might have the form
7251 // `\\?\foo\bar` in which case it does not tolerate
7252 // mixed `/` and `\` separators, so canonicalize
7253 // `/` to `\`.
7254 #[cfg(windows)]
7255 let s = s.replace("/", "\\");
7256 Some(dir_path.join(s))
7257 } else {
7258 None
7259 }
7260 }
7261
7262 /// Returns a path to a module.
7263 pub fn default_submod_path(
7264 id: ast::Ident,
7265 relative: Option<ast::Ident>,
7266 dir_path: &Path,
7267 source_map: &SourceMap) -> ModulePath
7268 {
7269 // If we're in a foo.rs file instead of a mod.rs file,
7270 // we need to look for submodules in
7271 // `./foo/<id>.rs` and `./foo/<id>/mod.rs` rather than
7272 // `./<id>.rs` and `./<id>/mod.rs`.
7273 let relative_prefix_string;
7274 let relative_prefix = if let Some(ident) = relative {
7275 relative_prefix_string = format!("{}{}", ident.as_str(), path::MAIN_SEPARATOR);
7276 &relative_prefix_string
7277 } else {
7278 ""
7279 };
7280
7281 let mod_name = id.to_string();
7282 let default_path_str = format!("{}{}.rs", relative_prefix, mod_name);
7283 let secondary_path_str = format!("{}{}{}mod.rs",
7284 relative_prefix, mod_name, path::MAIN_SEPARATOR);
7285 let default_path = dir_path.join(&default_path_str);
7286 let secondary_path = dir_path.join(&secondary_path_str);
7287 let default_exists = source_map.file_exists(&default_path);
7288 let secondary_exists = source_map.file_exists(&secondary_path);
7289
7290 let result = match (default_exists, secondary_exists) {
7291 (true, false) => Ok(ModulePathSuccess {
7292 path: default_path,
7293 directory_ownership: DirectoryOwnership::Owned {
7294 relative: Some(id),
7295 },
7296 warn: false,
7297 }),
7298 (false, true) => Ok(ModulePathSuccess {
7299 path: secondary_path,
7300 directory_ownership: DirectoryOwnership::Owned {
7301 relative: None,
7302 },
7303 warn: false,
7304 }),
7305 (false, false) => Err(Error::FileNotFoundForModule {
7306 mod_name: mod_name.clone(),
7307 default_path: default_path_str,
7308 secondary_path: secondary_path_str,
7309 dir_path: dir_path.display().to_string(),
7310 }),
7311 (true, true) => Err(Error::DuplicatePaths {
7312 mod_name: mod_name.clone(),
7313 default_path: default_path_str,
7314 secondary_path: secondary_path_str,
7315 }),
7316 };
7317
7318 ModulePath {
7319 name: mod_name,
7320 path_exists: default_exists || secondary_exists,
7321 result,
7322 }
7323 }
7324
7325 fn submod_path(&mut self,
7326 id: ast::Ident,
7327 outer_attrs: &[Attribute],
7328 id_sp: Span)
7329 -> PResult<'a, ModulePathSuccess> {
7330 if let Some(path) = Parser::submod_path_from_attr(outer_attrs, &self.directory.path) {
7331 return Ok(ModulePathSuccess {
7332 directory_ownership: match path.file_name().and_then(|s| s.to_str()) {
7333 // All `#[path]` files are treated as though they are a `mod.rs` file.
7334 // This means that `mod foo;` declarations inside `#[path]`-included
7335 // files are siblings,
7336 //
7337 // Note that this will produce weirdness when a file named `foo.rs` is
7338 // `#[path]` included and contains a `mod foo;` declaration.
7339 // If you encounter this, it's your own darn fault :P
7340 Some(_) => DirectoryOwnership::Owned { relative: None },
7341 _ => DirectoryOwnership::UnownedViaMod(true),
7342 },
7343 path,
7344 warn: false,
7345 });
7346 }
7347
7348 let relative = match self.directory.ownership {
7349 DirectoryOwnership::Owned { relative } => relative,
7350 DirectoryOwnership::UnownedViaBlock |
7351 DirectoryOwnership::UnownedViaMod(_) => None,
7352 };
7353 let paths = Parser::default_submod_path(
7354 id, relative, &self.directory.path, self.sess.source_map());
7355
7356 match self.directory.ownership {
7357 DirectoryOwnership::Owned { .. } => {
7358 paths.result.map_err(|err| self.span_fatal_err(id_sp, err))
7359 },
7360 DirectoryOwnership::UnownedViaBlock => {
7361 let msg =
7362 "Cannot declare a non-inline module inside a block \
7363 unless it has a path attribute";
7364 let mut err = self.diagnostic().struct_span_err(id_sp, msg);
7365 if paths.path_exists {
7366 let msg = format!("Maybe `use` the module `{}` instead of redeclaring it",
7367 paths.name);
7368 err.span_note(id_sp, &msg);
7369 }
7370 Err(err)
7371 }
7372 DirectoryOwnership::UnownedViaMod(warn) => {
7373 if warn {
7374 if let Ok(result) = paths.result {
7375 return Ok(ModulePathSuccess { warn: true, ..result });
7376 }
7377 }
7378 let mut err = self.diagnostic().struct_span_err(id_sp,
7379 "cannot declare a new module at this location");
7380 if !id_sp.is_dummy() {
7381 let src_path = self.sess.source_map().span_to_filename(id_sp);
7382 if let FileName::Real(src_path) = src_path {
7383 if let Some(stem) = src_path.file_stem() {
7384 let mut dest_path = src_path.clone();
7385 dest_path.set_file_name(stem);
7386 dest_path.push("mod.rs");
7387 err.span_note(id_sp,
7388 &format!("maybe move this module `{}` to its own \
7389 directory via `{}`", src_path.display(),
7390 dest_path.display()));
7391 }
7392 }
7393 }
7394 if paths.path_exists {
7395 err.span_note(id_sp,
7396 &format!("... or maybe `use` the module `{}` instead \
7397 of possibly redeclaring it",
7398 paths.name));
7399 }
7400 Err(err)
7401 }
7402 }
7403 }
7404
7405 /// Reads a module from a source file.
7406 fn eval_src_mod(&mut self,
7407 path: PathBuf,
7408 directory_ownership: DirectoryOwnership,
7409 name: String,
7410 id_sp: Span)
7411 -> PResult<'a, (ast::Mod, Vec<Attribute> )> {
7412 let mut included_mod_stack = self.sess.included_mod_stack.borrow_mut();
7413 if let Some(i) = included_mod_stack.iter().position(|p| *p == path) {
7414 let mut err = String::from("circular modules: ");
7415 let len = included_mod_stack.len();
7416 for p in &included_mod_stack[i.. len] {
7417 err.push_str(&p.to_string_lossy());
7418 err.push_str(" -> ");
7419 }
7420 err.push_str(&path.to_string_lossy());
7421 return Err(self.span_fatal(id_sp, &err[..]));
7422 }
7423 included_mod_stack.push(path.clone());
7424 drop(included_mod_stack);
7425
7426 let mut p0 =
7427 new_sub_parser_from_file(self.sess, &path, directory_ownership, Some(name), id_sp);
7428 p0.cfg_mods = self.cfg_mods;
7429 let mod_inner_lo = p0.span;
7430 let mod_attrs = p0.parse_inner_attributes()?;
7431 let mut m0 = p0.parse_mod_items(&token::Eof, mod_inner_lo)?;
7432 m0.inline = false;
7433 self.sess.included_mod_stack.borrow_mut().pop();
7434 Ok((m0, mod_attrs))
7435 }
7436
7437 /// Parses a function declaration from a foreign module.
7438 fn parse_item_foreign_fn(&mut self, vis: ast::Visibility, lo: Span, attrs: Vec<Attribute>)
7439 -> PResult<'a, ForeignItem> {
7440 self.expect_keyword(keywords::Fn)?;
7441
7442 let (ident, mut generics) = self.parse_fn_header()?;
7443 let decl = self.parse_fn_decl(true)?;
7444 generics.where_clause = self.parse_where_clause()?;
7445 let hi = self.span;
7446 self.expect(&token::Semi)?;
7447 Ok(ast::ForeignItem {
7448 ident,
7449 attrs,
7450 node: ForeignItemKind::Fn(decl, generics),
7451 id: ast::DUMMY_NODE_ID,
7452 span: lo.to(hi),
7453 vis,
7454 })
7455 }
7456
7457 /// Parses a static item from a foreign module.
7458 /// Assumes that the `static` keyword is already parsed.
7459 fn parse_item_foreign_static(&mut self, vis: ast::Visibility, lo: Span, attrs: Vec<Attribute>)
7460 -> PResult<'a, ForeignItem> {
7461 let mutbl = self.eat_keyword(keywords::Mut);
7462 let ident = self.parse_ident()?;
7463 self.expect(&token::Colon)?;
7464 let ty = self.parse_ty()?;
7465 let hi = self.span;
7466 self.expect(&token::Semi)?;
7467 Ok(ForeignItem {
7468 ident,
7469 attrs,
7470 node: ForeignItemKind::Static(ty, mutbl),
7471 id: ast::DUMMY_NODE_ID,
7472 span: lo.to(hi),
7473 vis,
7474 })
7475 }
7476
7477 /// Parses a type from a foreign module.
7478 fn parse_item_foreign_type(&mut self, vis: ast::Visibility, lo: Span, attrs: Vec<Attribute>)
7479 -> PResult<'a, ForeignItem> {
7480 self.expect_keyword(keywords::Type)?;
7481
7482 let ident = self.parse_ident()?;
7483 let hi = self.span;
7484 self.expect(&token::Semi)?;
7485 Ok(ast::ForeignItem {
7486 ident: ident,
7487 attrs: attrs,
7488 node: ForeignItemKind::Ty,
7489 id: ast::DUMMY_NODE_ID,
7490 span: lo.to(hi),
7491 vis: vis
7492 })
7493 }
7494
7495 fn parse_crate_name_with_dashes(&mut self) -> PResult<'a, ast::Ident> {
7496 let error_msg = "crate name using dashes are not valid in `extern crate` statements";
7497 let suggestion_msg = "if the original crate name uses dashes you need to use underscores \
7498 in the code";
7499 let mut ident = if self.token.is_keyword(keywords::SelfLower) {
7500 self.parse_path_segment_ident()
7501 } else {
7502 self.parse_ident()
7503 }?;
7504 let mut idents = vec![];
7505 let mut replacement = vec![];
7506 let mut fixed_crate_name = false;
7507 // Accept `extern crate name-like-this` for better diagnostics
7508 let dash = token::Token::BinOp(token::BinOpToken::Minus);
7509 if self.token == dash { // Do not include `-` as part of the expected tokens list
7510 while self.eat(&dash) {
7511 fixed_crate_name = true;
7512 replacement.push((self.prev_span, "_".to_string()));
7513 idents.push(self.parse_ident()?);
7514 }
7515 }
7516 if fixed_crate_name {
7517 let fixed_name_sp = ident.span.to(idents.last().unwrap().span);
7518 let mut fixed_name = format!("{}", ident.name);
7519 for part in idents {
7520 fixed_name.push_str(&format!("_{}", part.name));
7521 }
7522 ident = Ident::from_str(&fixed_name).with_span_pos(fixed_name_sp);
7523
7524 let mut err = self.struct_span_err(fixed_name_sp, error_msg);
7525 err.span_label(fixed_name_sp, "dash-separated idents are not valid");
7526 err.multipart_suggestion(
7527 suggestion_msg,
7528 replacement,
7529 Applicability::MachineApplicable,
7530 );
7531 err.emit();
7532 }
7533 Ok(ident)
7534 }
7535
7536 /// Parses `extern crate` links.
7537 ///
7538 /// # Examples
7539 ///
7540 /// ```
7541 /// extern crate foo;
7542 /// extern crate bar as foo;
7543 /// ```
7544 fn parse_item_extern_crate(&mut self,
7545 lo: Span,
7546 visibility: Visibility,
7547 attrs: Vec<Attribute>)
7548 -> PResult<'a, P<Item>> {
7549 // Accept `extern crate name-like-this` for better diagnostics
7550 let orig_name = self.parse_crate_name_with_dashes()?;
7551 let (item_name, orig_name) = if let Some(rename) = self.parse_rename()? {
7552 (rename, Some(orig_name.name))
7553 } else {
7554 (orig_name, None)
7555 };
7556 self.expect(&token::Semi)?;
7557
7558 let span = lo.to(self.prev_span);
7559 Ok(self.mk_item(span, item_name, ItemKind::ExternCrate(orig_name), visibility, attrs))
7560 }
7561
7562 /// Parses `extern` for foreign ABIs modules.
7563 ///
7564 /// `extern` is expected to have been
7565 /// consumed before calling this method.
7566 ///
7567 /// # Examples
7568 ///
7569 /// ```ignore (only-for-syntax-highlight)
7570 /// extern "C" {}
7571 /// extern {}
7572 /// ```
7573 fn parse_item_foreign_mod(&mut self,
7574 lo: Span,
7575 opt_abi: Option<Abi>,
7576 visibility: Visibility,
7577 mut attrs: Vec<Attribute>)
7578 -> PResult<'a, P<Item>> {
7579 self.expect(&token::OpenDelim(token::Brace))?;
7580
7581 let abi = opt_abi.unwrap_or(Abi::C);
7582
7583 attrs.extend(self.parse_inner_attributes()?);
7584
7585 let mut foreign_items = vec![];
7586 while !self.eat(&token::CloseDelim(token::Brace)) {
7587 foreign_items.push(self.parse_foreign_item()?);
7588 }
7589
7590 let prev_span = self.prev_span;
7591 let m = ast::ForeignMod {
7592 abi,
7593 items: foreign_items
7594 };
7595 let invalid = keywords::Invalid.ident();
7596 Ok(self.mk_item(lo.to(prev_span), invalid, ItemKind::ForeignMod(m), visibility, attrs))
7597 }
7598
7599 /// Parses `type Foo = Bar;`
7600 /// or
7601 /// `existential type Foo: Bar;`
7602 /// or
7603 /// `return `None``
7604 /// without modifying the parser state.
7605 fn eat_type(&mut self) -> Option<PResult<'a, (Ident, AliasKind, ast::Generics)>> {
7606 // This parses the grammar:
7607 // Ident ["<"...">"] ["where" ...] ("=" | ":") Ty ";"
7608 if self.check_keyword(keywords::Type) ||
7609 self.check_keyword(keywords::Existential) &&
7610 self.look_ahead(1, |t| t.is_keyword(keywords::Type)) {
7611 let existential = self.eat_keyword(keywords::Existential);
7612 assert!(self.eat_keyword(keywords::Type));
7613 Some(self.parse_existential_or_alias(existential))
7614 } else {
7615 None
7616 }
7617 }
7618
7619 /// Parses a type alias or existential type.
7620 fn parse_existential_or_alias(
7621 &mut self,
7622 existential: bool,
7623 ) -> PResult<'a, (Ident, AliasKind, ast::Generics)> {
7624 let ident = self.parse_ident()?;
7625 let mut tps = self.parse_generics()?;
7626 tps.where_clause = self.parse_where_clause()?;
7627 let alias = if existential {
7628 self.expect(&token::Colon)?;
7629 let bounds = self.parse_generic_bounds(None)?;
7630 AliasKind::Existential(bounds)
7631 } else {
7632 self.expect(&token::Eq)?;
7633 let ty = self.parse_ty()?;
7634 AliasKind::Weak(ty)
7635 };
7636 self.expect(&token::Semi)?;
7637 Ok((ident, alias, tps))
7638 }
7639
7640 /// Parses the part of an enum declaration following the `{`.
7641 fn parse_enum_def(&mut self, _generics: &ast::Generics) -> PResult<'a, EnumDef> {
7642 let mut variants = Vec::new();
7643 let mut all_nullary = true;
7644 let mut any_disr = vec![];
7645 while self.token != token::CloseDelim(token::Brace) {
7646 let variant_attrs = self.parse_outer_attributes()?;
7647 let vlo = self.span;
7648
7649 let struct_def;
7650 let mut disr_expr = None;
7651 let ident = self.parse_ident()?;
7652 if self.check(&token::OpenDelim(token::Brace)) {
7653 // Parse a struct variant.
7654 all_nullary = false;
7655 struct_def = VariantData::Struct(self.parse_record_struct_body()?,
7656 ast::DUMMY_NODE_ID);
7657 } else if self.check(&token::OpenDelim(token::Paren)) {
7658 all_nullary = false;
7659 struct_def = VariantData::Tuple(self.parse_tuple_struct_body()?,
7660 ast::DUMMY_NODE_ID);
7661 } else if self.eat(&token::Eq) {
7662 disr_expr = Some(AnonConst {
7663 id: ast::DUMMY_NODE_ID,
7664 value: self.parse_expr()?,
7665 });
7666 if let Some(sp) = disr_expr.as_ref().map(|c| c.value.span) {
7667 any_disr.push(sp);
7668 }
7669 struct_def = VariantData::Unit(ast::DUMMY_NODE_ID);
7670 } else {
7671 struct_def = VariantData::Unit(ast::DUMMY_NODE_ID);
7672 }
7673
7674 let vr = ast::Variant_ {
7675 ident,
7676 attrs: variant_attrs,
7677 data: struct_def,
7678 disr_expr,
7679 };
7680 variants.push(respan(vlo.to(self.prev_span), vr));
7681
7682 if !self.eat(&token::Comma) { break; }
7683 }
7684 self.expect(&token::CloseDelim(token::Brace))?;
7685 if !any_disr.is_empty() && !all_nullary {
7686 let mut err =self.struct_span_err(
7687 any_disr.clone(),
7688 "discriminator values can only be used with a field-less enum",
7689 );
7690 for sp in any_disr {
7691 err.span_label(sp, "only valid in field-less enums");
7692 }
7693 err.emit();
7694 }
7695
7696 Ok(ast::EnumDef { variants })
7697 }
7698
7699 /// Parses an enum declaration.
7700 fn parse_item_enum(&mut self) -> PResult<'a, ItemInfo> {
7701 let id = self.parse_ident()?;
7702 let mut generics = self.parse_generics()?;
7703 generics.where_clause = self.parse_where_clause()?;
7704 self.expect(&token::OpenDelim(token::Brace))?;
7705
7706 let enum_definition = self.parse_enum_def(&generics).map_err(|e| {
7707 self.recover_stmt();
7708 self.eat(&token::CloseDelim(token::Brace));
7709 e
7710 })?;
7711 Ok((id, ItemKind::Enum(enum_definition, generics), None))
7712 }
7713
7714 /// Parses a string as an ABI spec on an extern type or module. Consumes
7715 /// the `extern` keyword, if one is found.
7716 fn parse_opt_abi(&mut self) -> PResult<'a, Option<Abi>> {
7717 match self.token {
7718 token::Literal(token::Str_(s), suf) | token::Literal(token::StrRaw(s, _), suf) => {
7719 let sp = self.span;
7720 self.expect_no_suffix(sp, "ABI spec", suf);
7721 self.bump();
7722 match abi::lookup(&s.as_str()) {
7723 Some(abi) => Ok(Some(abi)),
7724 None => {
7725 let prev_span = self.prev_span;
7726 let mut err = struct_span_err!(
7727 self.sess.span_diagnostic,
7728 prev_span,
7729 E0703,
7730 "invalid ABI: found `{}`",
7731 s);
7732 err.span_label(prev_span, "invalid ABI");
7733 err.help(&format!("valid ABIs: {}", abi::all_names().join(", ")));
7734 err.emit();
7735 Ok(None)
7736 }
7737 }
7738 }
7739
7740 _ => Ok(None),
7741 }
7742 }
7743
7744 fn is_static_global(&mut self) -> bool {
7745 if self.check_keyword(keywords::Static) {
7746 // Check if this could be a closure
7747 !self.look_ahead(1, |token| {
7748 if token.is_keyword(keywords::Move) {
7749 return true;
7750 }
7751 match *token {
7752 token::BinOp(token::Or) | token::OrOr => true,
7753 _ => false,
7754 }
7755 })
7756 } else {
7757 false
7758 }
7759 }
7760
7761 fn parse_item_(
7762 &mut self,
7763 attrs: Vec<Attribute>,
7764 macros_allowed: bool,
7765 attributes_allowed: bool,
7766 ) -> PResult<'a, Option<P<Item>>> {
7767 let (ret, tokens) = self.collect_tokens(|this| {
7768 this.parse_item_implementation(attrs, macros_allowed, attributes_allowed)
7769 })?;
7770
7771 // Once we've parsed an item and recorded the tokens we got while
7772 // parsing we may want to store `tokens` into the item we're about to
7773 // return. Note, though, that we specifically didn't capture tokens
7774 // related to outer attributes. The `tokens` field here may later be
7775 // used with procedural macros to convert this item back into a token
7776 // stream, but during expansion we may be removing attributes as we go
7777 // along.
7778 //
7779 // If we've got inner attributes then the `tokens` we've got above holds
7780 // these inner attributes. If an inner attribute is expanded we won't
7781 // actually remove it from the token stream, so we'll just keep yielding
7782 // it (bad!). To work around this case for now we just avoid recording
7783 // `tokens` if we detect any inner attributes. This should help keep
7784 // expansion correct, but we should fix this bug one day!
7785 Ok(ret.map(|item| {
7786 item.map(|mut i| {
7787 if !i.attrs.iter().any(|attr| attr.style == AttrStyle::Inner) {
7788 i.tokens = Some(tokens);
7789 }
7790 i
7791 })
7792 }))
7793 }
7794
7795 /// Parses one of the items allowed by the flags.
7796 fn parse_item_implementation(
7797 &mut self,
7798 attrs: Vec<Attribute>,
7799 macros_allowed: bool,
7800 attributes_allowed: bool,
7801 ) -> PResult<'a, Option<P<Item>>> {
7802 maybe_whole!(self, NtItem, |item| {
7803 let mut item = item.into_inner();
7804 let mut attrs = attrs;
7805 mem::swap(&mut item.attrs, &mut attrs);
7806 item.attrs.extend(attrs);
7807 Some(P(item))
7808 });
7809
7810 let lo = self.span;
7811
7812 let visibility = self.parse_visibility(false)?;
7813
7814 if self.eat_keyword(keywords::Use) {
7815 // USE ITEM
7816 let item_ = ItemKind::Use(P(self.parse_use_tree()?));
7817 self.expect(&token::Semi)?;
7818
7819 let span = lo.to(self.prev_span);
7820 let item = self.mk_item(span, keywords::Invalid.ident(), item_, visibility, attrs);
7821 return Ok(Some(item));
7822 }
7823
7824 if self.eat_keyword(keywords::Extern) {
7825 if self.eat_keyword(keywords::Crate) {
7826 return Ok(Some(self.parse_item_extern_crate(lo, visibility, attrs)?));
7827 }
7828
7829 let opt_abi = self.parse_opt_abi()?;
7830
7831 if self.eat_keyword(keywords::Fn) {
7832 // EXTERN FUNCTION ITEM
7833 let fn_span = self.prev_span;
7834 let abi = opt_abi.unwrap_or(Abi::C);
7835 let (ident, item_, extra_attrs) =
7836 self.parse_item_fn(Unsafety::Normal,
7837 IsAsync::NotAsync,
7838 respan(fn_span, Constness::NotConst),
7839 abi)?;
7840 let prev_span = self.prev_span;
7841 let item = self.mk_item(lo.to(prev_span),
7842 ident,
7843 item_,
7844 visibility,
7845 maybe_append(attrs, extra_attrs));
7846 return Ok(Some(item));
7847 } else if self.check(&token::OpenDelim(token::Brace)) {
7848 return Ok(Some(self.parse_item_foreign_mod(lo, opt_abi, visibility, attrs)?));
7849 }
7850
7851 self.unexpected()?;
7852 }
7853
7854 if self.is_static_global() {
7855 self.bump();
7856 // STATIC ITEM
7857 let m = if self.eat_keyword(keywords::Mut) {
7858 Mutability::Mutable
7859 } else {
7860 Mutability::Immutable
7861 };
7862 let (ident, item_, extra_attrs) = self.parse_item_const(Some(m))?;
7863 let prev_span = self.prev_span;
7864 let item = self.mk_item(lo.to(prev_span),
7865 ident,
7866 item_,
7867 visibility,
7868 maybe_append(attrs, extra_attrs));
7869 return Ok(Some(item));
7870 }
7871 if self.eat_keyword(keywords::Const) {
7872 let const_span = self.prev_span;
7873 if self.check_keyword(keywords::Fn)
7874 || (self.check_keyword(keywords::Unsafe)
7875 && self.look_ahead(1, |t| t.is_keyword(keywords::Fn))) {
7876 // CONST FUNCTION ITEM
7877 let unsafety = self.parse_unsafety();
7878 self.bump();
7879 let (ident, item_, extra_attrs) =
7880 self.parse_item_fn(unsafety,
7881 IsAsync::NotAsync,
7882 respan(const_span, Constness::Const),
7883 Abi::Rust)?;
7884 let prev_span = self.prev_span;
7885 let item = self.mk_item(lo.to(prev_span),
7886 ident,
7887 item_,
7888 visibility,
7889 maybe_append(attrs, extra_attrs));
7890 return Ok(Some(item));
7891 }
7892
7893 // CONST ITEM
7894 if self.eat_keyword(keywords::Mut) {
7895 let prev_span = self.prev_span;
7896 let mut err = self.diagnostic()
7897 .struct_span_err(prev_span, "const globals cannot be mutable");
7898 err.span_label(prev_span, "cannot be mutable");
7899 err.span_suggestion(
7900 const_span,
7901 "you might want to declare a static instead",
7902 "static".to_owned(),
7903 Applicability::MaybeIncorrect,
7904 );
7905 err.emit();
7906 }
7907 let (ident, item_, extra_attrs) = self.parse_item_const(None)?;
7908 let prev_span = self.prev_span;
7909 let item = self.mk_item(lo.to(prev_span),
7910 ident,
7911 item_,
7912 visibility,
7913 maybe_append(attrs, extra_attrs));
7914 return Ok(Some(item));
7915 }
7916
7917 // `unsafe async fn` or `async fn`
7918 if (
7919 self.check_keyword(keywords::Unsafe) &&
7920 self.look_ahead(1, |t| t.is_keyword(keywords::Async))
7921 ) || (
7922 self.check_keyword(keywords::Async) &&
7923 self.look_ahead(1, |t| t.is_keyword(keywords::Fn))
7924 )
7925 {
7926 // ASYNC FUNCTION ITEM
7927 let unsafety = self.parse_unsafety();
7928 self.expect_keyword(keywords::Async)?;
7929 self.expect_keyword(keywords::Fn)?;
7930 let fn_span = self.prev_span;
7931 let (ident, item_, extra_attrs) =
7932 self.parse_item_fn(unsafety,
7933 IsAsync::Async {
7934 closure_id: ast::DUMMY_NODE_ID,
7935 return_impl_trait_id: ast::DUMMY_NODE_ID,
7936 },
7937 respan(fn_span, Constness::NotConst),
7938 Abi::Rust)?;
7939 let prev_span = self.prev_span;
7940 let item = self.mk_item(lo.to(prev_span),
7941 ident,
7942 item_,
7943 visibility,
7944 maybe_append(attrs, extra_attrs));
7945 return Ok(Some(item));
7946 }
7947 if self.check_keyword(keywords::Unsafe) &&
7948 (self.look_ahead(1, |t| t.is_keyword(keywords::Trait)) ||
7949 self.look_ahead(1, |t| t.is_keyword(keywords::Auto)))
7950 {
7951 // UNSAFE TRAIT ITEM
7952 self.bump(); // `unsafe`
7953 let is_auto = if self.eat_keyword(keywords::Trait) {
7954 IsAuto::No
7955 } else {
7956 self.expect_keyword(keywords::Auto)?;
7957 self.expect_keyword(keywords::Trait)?;
7958 IsAuto::Yes
7959 };
7960 let (ident, item_, extra_attrs) =
7961 self.parse_item_trait(is_auto, Unsafety::Unsafe)?;
7962 let prev_span = self.prev_span;
7963 let item = self.mk_item(lo.to(prev_span),
7964 ident,
7965 item_,
7966 visibility,
7967 maybe_append(attrs, extra_attrs));
7968 return Ok(Some(item));
7969 }
7970 if self.check_keyword(keywords::Impl) ||
7971 self.check_keyword(keywords::Unsafe) &&
7972 self.look_ahead(1, |t| t.is_keyword(keywords::Impl)) ||
7973 self.check_keyword(keywords::Default) &&
7974 self.look_ahead(1, |t| t.is_keyword(keywords::Impl)) ||
7975 self.check_keyword(keywords::Default) &&
7976 self.look_ahead(1, |t| t.is_keyword(keywords::Unsafe)) {
7977 // IMPL ITEM
7978 let defaultness = self.parse_defaultness();
7979 let unsafety = self.parse_unsafety();
7980 self.expect_keyword(keywords::Impl)?;
7981 let (ident, item, extra_attrs) = self.parse_item_impl(unsafety, defaultness)?;
7982 let span = lo.to(self.prev_span);
7983 return Ok(Some(self.mk_item(span, ident, item, visibility,
7984 maybe_append(attrs, extra_attrs))));
7985 }
7986 if self.check_keyword(keywords::Fn) {
7987 // FUNCTION ITEM
7988 self.bump();
7989 let fn_span = self.prev_span;
7990 let (ident, item_, extra_attrs) =
7991 self.parse_item_fn(Unsafety::Normal,
7992 IsAsync::NotAsync,
7993 respan(fn_span, Constness::NotConst),
7994 Abi::Rust)?;
7995 let prev_span = self.prev_span;
7996 let item = self.mk_item(lo.to(prev_span),
7997 ident,
7998 item_,
7999 visibility,
8000 maybe_append(attrs, extra_attrs));
8001 return Ok(Some(item));
8002 }
8003 if self.check_keyword(keywords::Unsafe)
8004 && self.look_ahead(1, |t| *t != token::OpenDelim(token::Brace)) {
8005 // UNSAFE FUNCTION ITEM
8006 self.bump(); // `unsafe`
8007 // `{` is also expected after `unsafe`, in case of error, include it in the diagnostic
8008 self.check(&token::OpenDelim(token::Brace));
8009 let abi = if self.eat_keyword(keywords::Extern) {
8010 self.parse_opt_abi()?.unwrap_or(Abi::C)
8011 } else {
8012 Abi::Rust
8013 };
8014 self.expect_keyword(keywords::Fn)?;
8015 let fn_span = self.prev_span;
8016 let (ident, item_, extra_attrs) =
8017 self.parse_item_fn(Unsafety::Unsafe,
8018 IsAsync::NotAsync,
8019 respan(fn_span, Constness::NotConst),
8020 abi)?;
8021 let prev_span = self.prev_span;
8022 let item = self.mk_item(lo.to(prev_span),
8023 ident,
8024 item_,
8025 visibility,
8026 maybe_append(attrs, extra_attrs));
8027 return Ok(Some(item));
8028 }
8029 if self.eat_keyword(keywords::Mod) {
8030 // MODULE ITEM
8031 let (ident, item_, extra_attrs) =
8032 self.parse_item_mod(&attrs[..])?;
8033 let prev_span = self.prev_span;
8034 let item = self.mk_item(lo.to(prev_span),
8035 ident,
8036 item_,
8037 visibility,
8038 maybe_append(attrs, extra_attrs));
8039 return Ok(Some(item));
8040 }
8041 if let Some(type_) = self.eat_type() {
8042 let (ident, alias, generics) = type_?;
8043 // TYPE ITEM
8044 let item_ = match alias {
8045 AliasKind::Weak(ty) => ItemKind::Ty(ty, generics),
8046 AliasKind::Existential(bounds) => ItemKind::Existential(bounds, generics),
8047 };
8048 let prev_span = self.prev_span;
8049 let item = self.mk_item(lo.to(prev_span),
8050 ident,
8051 item_,
8052 visibility,
8053 attrs);
8054 return Ok(Some(item));
8055 }
8056 if self.eat_keyword(keywords::Enum) {
8057 // ENUM ITEM
8058 let (ident, item_, extra_attrs) = self.parse_item_enum()?;
8059 let prev_span = self.prev_span;
8060 let item = self.mk_item(lo.to(prev_span),
8061 ident,
8062 item_,
8063 visibility,
8064 maybe_append(attrs, extra_attrs));
8065 return Ok(Some(item));
8066 }
8067 if self.check_keyword(keywords::Trait)
8068 || (self.check_keyword(keywords::Auto)
8069 && self.look_ahead(1, |t| t.is_keyword(keywords::Trait)))
8070 {
8071 let is_auto = if self.eat_keyword(keywords::Trait) {
8072 IsAuto::No
8073 } else {
8074 self.expect_keyword(keywords::Auto)?;
8075 self.expect_keyword(keywords::Trait)?;
8076 IsAuto::Yes
8077 };
8078 // TRAIT ITEM
8079 let (ident, item_, extra_attrs) =
8080 self.parse_item_trait(is_auto, Unsafety::Normal)?;
8081 let prev_span = self.prev_span;
8082 let item = self.mk_item(lo.to(prev_span),
8083 ident,
8084 item_,
8085 visibility,
8086 maybe_append(attrs, extra_attrs));
8087 return Ok(Some(item));
8088 }
8089 if self.eat_keyword(keywords::Struct) {
8090 // STRUCT ITEM
8091 let (ident, item_, extra_attrs) = self.parse_item_struct()?;
8092 let prev_span = self.prev_span;
8093 let item = self.mk_item(lo.to(prev_span),
8094 ident,
8095 item_,
8096 visibility,
8097 maybe_append(attrs, extra_attrs));
8098 return Ok(Some(item));
8099 }
8100 if self.is_union_item() {
8101 // UNION ITEM
8102 self.bump();
8103 let (ident, item_, extra_attrs) = self.parse_item_union()?;
8104 let prev_span = self.prev_span;
8105 let item = self.mk_item(lo.to(prev_span),
8106 ident,
8107 item_,
8108 visibility,
8109 maybe_append(attrs, extra_attrs));
8110 return Ok(Some(item));
8111 }
8112 if let Some(macro_def) = self.eat_macro_def(&attrs, &visibility, lo)? {
8113 return Ok(Some(macro_def));
8114 }
8115
8116 // Verify whether we have encountered a struct or method definition where the user forgot to
8117 // add the `struct` or `fn` keyword after writing `pub`: `pub S {}`
8118 if visibility.node.is_pub() &&
8119 self.check_ident() &&
8120 self.look_ahead(1, |t| *t != token::Not)
8121 {
8122 // Space between `pub` keyword and the identifier
8123 //
8124 // pub S {}
8125 // ^^^ `sp` points here
8126 let sp = self.prev_span.between(self.span);
8127 let full_sp = self.prev_span.to(self.span);
8128 let ident_sp = self.span;
8129 if self.look_ahead(1, |t| *t == token::OpenDelim(token::Brace)) {
8130 // possible public struct definition where `struct` was forgotten
8131 let ident = self.parse_ident().unwrap();
8132 let msg = format!("add `struct` here to parse `{}` as a public struct",
8133 ident);
8134 let mut err = self.diagnostic()
8135 .struct_span_err(sp, "missing `struct` for struct definition");
8136 err.span_suggestion_short(
8137 sp, &msg, " struct ".into(), Applicability::MaybeIncorrect // speculative
8138 );
8139 return Err(err);
8140 } else if self.look_ahead(1, |t| *t == token::OpenDelim(token::Paren)) {
8141 let ident = self.parse_ident().unwrap();
8142 self.bump(); // `(`
8143 let kw_name = if let Ok(Some(_)) = self.parse_self_arg() {
8144 "method"
8145 } else {
8146 "function"
8147 };
8148 self.consume_block(token::Paren);
8149 let (kw, kw_name, ambiguous) = if self.check(&token::RArrow) {
8150 self.eat_to_tokens(&[&token::OpenDelim(token::Brace)]);
8151 self.bump(); // `{`
8152 ("fn", kw_name, false)
8153 } else if self.check(&token::OpenDelim(token::Brace)) {
8154 self.bump(); // `{`
8155 ("fn", kw_name, false)
8156 } else if self.check(&token::Colon) {
8157 let kw = "struct";
8158 (kw, kw, false)
8159 } else {
8160 ("fn` or `struct", "function or struct", true)
8161 };
8162 self.consume_block(token::Brace);
8163
8164 let msg = format!("missing `{}` for {} definition", kw, kw_name);
8165 let mut err = self.diagnostic().struct_span_err(sp, &msg);
8166 if !ambiguous {
8167 let suggestion = format!("add `{}` here to parse `{}` as a public {}",
8168 kw,
8169 ident,
8170 kw_name);
8171 err.span_suggestion_short(
8172 sp, &suggestion, format!(" {} ", kw), Applicability::MachineApplicable
8173 );
8174 } else {
8175 if let Ok(snippet) = self.sess.source_map().span_to_snippet(ident_sp) {
8176 err.span_suggestion(
8177 full_sp,
8178 "if you meant to call a macro, try",
8179 format!("{}!", snippet),
8180 // this is the `ambiguous` conditional branch
8181 Applicability::MaybeIncorrect
8182 );
8183 } else {
8184 err.help("if you meant to call a macro, remove the `pub` \
8185 and add a trailing `!` after the identifier");
8186 }
8187 }
8188 return Err(err);
8189 } else if self.look_ahead(1, |t| *t == token::Lt) {
8190 let ident = self.parse_ident().unwrap();
8191 self.eat_to_tokens(&[&token::Gt]);
8192 self.bump(); // `>`
8193 let (kw, kw_name, ambiguous) = if self.eat(&token::OpenDelim(token::Paren)) {
8194 if let Ok(Some(_)) = self.parse_self_arg() {
8195 ("fn", "method", false)
8196 } else {
8197 ("fn", "function", false)
8198 }
8199 } else if self.check(&token::OpenDelim(token::Brace)) {
8200 ("struct", "struct", false)
8201 } else {
8202 ("fn` or `struct", "function or struct", true)
8203 };
8204 let msg = format!("missing `{}` for {} definition", kw, kw_name);
8205 let mut err = self.diagnostic().struct_span_err(sp, &msg);
8206 if !ambiguous {
8207 err.span_suggestion_short(
8208 sp,
8209 &format!("add `{}` here to parse `{}` as a public {}", kw, ident, kw_name),
8210 format!(" {} ", kw),
8211 Applicability::MachineApplicable,
8212 );
8213 }
8214 return Err(err);
8215 }
8216 }
8217 self.parse_macro_use_or_failure(attrs, macros_allowed, attributes_allowed, lo, visibility)
8218 }
8219
8220 /// Parses a foreign item.
8221 crate fn parse_foreign_item(&mut self) -> PResult<'a, ForeignItem> {
8222 maybe_whole!(self, NtForeignItem, |ni| ni);
8223
8224 let attrs = self.parse_outer_attributes()?;
8225 let lo = self.span;
8226 let visibility = self.parse_visibility(false)?;
8227
8228 // FOREIGN STATIC ITEM
8229 // Treat `const` as `static` for error recovery, but don't add it to expected tokens.
8230 if self.check_keyword(keywords::Static) || self.token.is_keyword(keywords::Const) {
8231 if self.token.is_keyword(keywords::Const) {
8232 self.diagnostic()
8233 .struct_span_err(self.span, "extern items cannot be `const`")
8234 .span_suggestion(
8235 self.span,
8236 "try using a static value",
8237 "static".to_owned(),
8238 Applicability::MachineApplicable
8239 ).emit();
8240 }
8241 self.bump(); // `static` or `const`
8242 return Ok(self.parse_item_foreign_static(visibility, lo, attrs)?);
8243 }
8244 // FOREIGN FUNCTION ITEM
8245 if self.check_keyword(keywords::Fn) {
8246 return Ok(self.parse_item_foreign_fn(visibility, lo, attrs)?);
8247 }
8248 // FOREIGN TYPE ITEM
8249 if self.check_keyword(keywords::Type) {
8250 return Ok(self.parse_item_foreign_type(visibility, lo, attrs)?);
8251 }
8252
8253 match self.parse_assoc_macro_invoc("extern", Some(&visibility), &mut false)? {
8254 Some(mac) => {
8255 Ok(
8256 ForeignItem {
8257 ident: keywords::Invalid.ident(),
8258 span: lo.to(self.prev_span),
8259 id: ast::DUMMY_NODE_ID,
8260 attrs,
8261 vis: visibility,
8262 node: ForeignItemKind::Macro(mac),
8263 }
8264 )
8265 }
8266 None => {
8267 if !attrs.is_empty() {
8268 self.expected_item_err(&attrs)?;
8269 }
8270
8271 self.unexpected()
8272 }
8273 }
8274 }
8275
8276 /// This is the fall-through for parsing items.
8277 fn parse_macro_use_or_failure(
8278 &mut self,
8279 attrs: Vec<Attribute> ,
8280 macros_allowed: bool,
8281 attributes_allowed: bool,
8282 lo: Span,
8283 visibility: Visibility
8284 ) -> PResult<'a, Option<P<Item>>> {
8285 if macros_allowed && self.token.is_path_start() {
8286 // MACRO INVOCATION ITEM
8287
8288 let prev_span = self.prev_span;
8289 self.complain_if_pub_macro(&visibility.node, prev_span);
8290
8291 let mac_lo = self.span;
8292
8293 // item macro.
8294 let pth = self.parse_path(PathStyle::Mod)?;
8295 self.expect(&token::Not)?;
8296
8297 // a 'special' identifier (like what `macro_rules!` uses)
8298 // is optional. We should eventually unify invoc syntax
8299 // and remove this.
8300 let id = if self.token.is_ident() {
8301 self.parse_ident()?
8302 } else {
8303 keywords::Invalid.ident() // no special identifier
8304 };
8305 // eat a matched-delimiter token tree:
8306 let (delim, tts) = self.expect_delimited_token_tree()?;
8307 if delim != MacDelimiter::Brace {
8308 if !self.eat(&token::Semi) {
8309 self.span_err(self.prev_span,
8310 "macros that expand to items must either \
8311 be surrounded with braces or followed by \
8312 a semicolon");
8313 }
8314 }
8315
8316 let hi = self.prev_span;
8317 let mac = respan(mac_lo.to(hi), Mac_ { path: pth, tts, delim });
8318 let item = self.mk_item(lo.to(hi), id, ItemKind::Mac(mac), visibility, attrs);
8319 return Ok(Some(item));
8320 }
8321
8322 // FAILURE TO PARSE ITEM
8323 match visibility.node {
8324 VisibilityKind::Inherited => {}
8325 _ => {
8326 return Err(self.span_fatal(self.prev_span, "unmatched visibility `pub`"));
8327 }
8328 }
8329
8330 if !attributes_allowed && !attrs.is_empty() {
8331 self.expected_item_err(&attrs)?;
8332 }
8333 Ok(None)
8334 }
8335
8336 /// Parses a macro invocation inside a `trait`, `impl` or `extern` block.
8337 fn parse_assoc_macro_invoc(&mut self, item_kind: &str, vis: Option<&Visibility>,
8338 at_end: &mut bool) -> PResult<'a, Option<Mac>>
8339 {
8340 if self.token.is_path_start() {
8341 let prev_span = self.prev_span;
8342 let lo = self.span;
8343 let pth = self.parse_path(PathStyle::Mod)?;
8344
8345 if pth.segments.len() == 1 {
8346 if !self.eat(&token::Not) {
8347 return Err(self.missing_assoc_item_kind_err(item_kind, prev_span));
8348 }
8349 } else {
8350 self.expect(&token::Not)?;
8351 }
8352
8353 if let Some(vis) = vis {
8354 self.complain_if_pub_macro(&vis.node, prev_span);
8355 }
8356
8357 *at_end = true;
8358
8359 // eat a matched-delimiter token tree:
8360 let (delim, tts) = self.expect_delimited_token_tree()?;
8361 if delim != MacDelimiter::Brace {
8362 self.expect(&token::Semi)?;
8363 }
8364
8365 Ok(Some(respan(lo.to(self.prev_span), Mac_ { path: pth, tts, delim })))
8366 } else {
8367 Ok(None)
8368 }
8369 }
8370
8371 fn collect_tokens<F, R>(&mut self, f: F) -> PResult<'a, (R, TokenStream)>
8372 where F: FnOnce(&mut Self) -> PResult<'a, R>
8373 {
8374 // Record all tokens we parse when parsing this item.
8375 let mut tokens = Vec::new();
8376 let prev_collecting = match self.token_cursor.frame.last_token {
8377 LastToken::Collecting(ref mut list) => {
8378 Some(mem::replace(list, Vec::new()))
8379 }
8380 LastToken::Was(ref mut last) => {
8381 tokens.extend(last.take());
8382 None
8383 }
8384 };
8385 self.token_cursor.frame.last_token = LastToken::Collecting(tokens);
8386 let prev = self.token_cursor.stack.len();
8387 let ret = f(self);
8388 let last_token = if self.token_cursor.stack.len() == prev {
8389 &mut self.token_cursor.frame.last_token
8390 } else {
8391 &mut self.token_cursor.stack[prev].last_token
8392 };
8393
8394 // Pull out the tokens that we've collected from the call to `f` above.
8395 let mut collected_tokens = match *last_token {
8396 LastToken::Collecting(ref mut v) => mem::replace(v, Vec::new()),
8397 LastToken::Was(_) => panic!("our vector went away?"),
8398 };
8399
8400 // If we're not at EOF our current token wasn't actually consumed by
8401 // `f`, but it'll still be in our list that we pulled out. In that case
8402 // put it back.
8403 let extra_token = if self.token != token::Eof {
8404 collected_tokens.pop()
8405 } else {
8406 None
8407 };
8408
8409 // If we were previously collecting tokens, then this was a recursive
8410 // call. In that case we need to record all the tokens we collected in
8411 // our parent list as well. To do that we push a clone of our stream
8412 // onto the previous list.
8413 match prev_collecting {
8414 Some(mut list) => {
8415 list.extend(collected_tokens.iter().cloned());
8416 list.extend(extra_token);
8417 *last_token = LastToken::Collecting(list);
8418 }
8419 None => {
8420 *last_token = LastToken::Was(extra_token);
8421 }
8422 }
8423
8424 Ok((ret?, TokenStream::new(collected_tokens)))
8425 }
8426
8427 pub fn parse_item(&mut self) -> PResult<'a, Option<P<Item>>> {
8428 let attrs = self.parse_outer_attributes()?;
8429 self.parse_item_(attrs, true, false)
8430 }
8431
8432 /// `::{` or `::*`
8433 fn is_import_coupler(&mut self) -> bool {
8434 self.check(&token::ModSep) &&
8435 self.look_ahead(1, |t| *t == token::OpenDelim(token::Brace) ||
8436 *t == token::BinOp(token::Star))
8437 }
8438
8439 /// Parses a `UseTree`.
8440 ///
8441 /// ```
8442 /// USE_TREE = [`::`] `*` |
8443 /// [`::`] `{` USE_TREE_LIST `}` |
8444 /// PATH `::` `*` |
8445 /// PATH `::` `{` USE_TREE_LIST `}` |
8446 /// PATH [`as` IDENT]
8447 /// ```
8448 fn parse_use_tree(&mut self) -> PResult<'a, UseTree> {
8449 let lo = self.span;
8450
8451 let mut prefix = ast::Path { segments: Vec::new(), span: lo.shrink_to_lo() };
8452 let kind = if self.check(&token::OpenDelim(token::Brace)) ||
8453 self.check(&token::BinOp(token::Star)) ||
8454 self.is_import_coupler() {
8455 // `use *;` or `use ::*;` or `use {...};` or `use ::{...};`
8456 let mod_sep_ctxt = self.span.ctxt();
8457 if self.eat(&token::ModSep) {
8458 prefix.segments.push(
8459 PathSegment::path_root(lo.shrink_to_lo().with_ctxt(mod_sep_ctxt))
8460 );
8461 }
8462
8463 if self.eat(&token::BinOp(token::Star)) {
8464 UseTreeKind::Glob
8465 } else {
8466 UseTreeKind::Nested(self.parse_use_tree_list()?)
8467 }
8468 } else {
8469 // `use path::*;` or `use path::{...};` or `use path;` or `use path as bar;`
8470 prefix = self.parse_path(PathStyle::Mod)?;
8471
8472 if self.eat(&token::ModSep) {
8473 if self.eat(&token::BinOp(token::Star)) {
8474 UseTreeKind::Glob
8475 } else {
8476 UseTreeKind::Nested(self.parse_use_tree_list()?)
8477 }
8478 } else {
8479 UseTreeKind::Simple(self.parse_rename()?, ast::DUMMY_NODE_ID, ast::DUMMY_NODE_ID)
8480 }
8481 };
8482
8483 Ok(UseTree { prefix, kind, span: lo.to(self.prev_span) })
8484 }
8485
8486 /// Parses a `UseTreeKind::Nested(list)`.
8487 ///
8488 /// ```
8489 /// USE_TREE_LIST = Ø | (USE_TREE `,`)* USE_TREE [`,`]
8490 /// ```
8491 fn parse_use_tree_list(&mut self) -> PResult<'a, Vec<(UseTree, ast::NodeId)>> {
8492 self.parse_unspanned_seq(&token::OpenDelim(token::Brace),
8493 &token::CloseDelim(token::Brace),
8494 SeqSep::trailing_allowed(token::Comma), |this| {
8495 Ok((this.parse_use_tree()?, ast::DUMMY_NODE_ID))
8496 })
8497 }
8498
8499 fn parse_rename(&mut self) -> PResult<'a, Option<Ident>> {
8500 if self.eat_keyword(keywords::As) {
8501 self.parse_ident_or_underscore().map(Some)
8502 } else {
8503 Ok(None)
8504 }
8505 }
8506
8507 /// Parses a source module as a crate. This is the main entry point for the parser.
8508 pub fn parse_crate_mod(&mut self) -> PResult<'a, Crate> {
8509 let lo = self.span;
8510 let krate = Ok(ast::Crate {
8511 attrs: self.parse_inner_attributes()?,
8512 module: self.parse_mod_items(&token::Eof, lo)?,
8513 span: lo.to(self.span),
8514 });
8515 emit_unclosed_delims(&self.unclosed_delims, self.diagnostic());
8516 self.unclosed_delims.clear();
8517 krate
8518 }
8519
8520 pub fn parse_optional_str(&mut self) -> Option<(Symbol, ast::StrStyle, Option<ast::Name>)> {
8521 let ret = match self.token {
8522 token::Literal(token::Str_(s), suf) => (s, ast::StrStyle::Cooked, suf),
8523 token::Literal(token::StrRaw(s, n), suf) => (s, ast::StrStyle::Raw(n), suf),
8524 _ => return None
8525 };
8526 self.bump();
8527 Some(ret)
8528 }
8529
8530 pub fn parse_str(&mut self) -> PResult<'a, (Symbol, StrStyle)> {
8531 match self.parse_optional_str() {
8532 Some((s, style, suf)) => {
8533 let sp = self.prev_span;
8534 self.expect_no_suffix(sp, "string literal", suf);
8535 Ok((s, style))
8536 }
8537 _ => {
8538 let msg = "expected string literal";
8539 let mut err = self.fatal(msg);
8540 err.span_label(self.span, msg);
8541 Err(err)
8542 }
8543 }
8544 }
8545}
8546
8547pub fn emit_unclosed_delims(unclosed_delims: &[UnmatchedBrace], handler: &errors::Handler) {
8548 for unmatched in unclosed_delims {
8549 let mut err = handler.struct_span_err(unmatched.found_span, &format!(
8550 "incorrect close delimiter: `{}`",
8551 pprust::token_to_string(&token::Token::CloseDelim(unmatched.found_delim)),
8552 ));
8553 err.span_label(unmatched.found_span, "incorrect close delimiter");
8554 if let Some(sp) = unmatched.candidate_span {
8555 err.span_label(sp, "close delimiter possibly meant for this");
8556 }
8557 if let Some(sp) = unmatched.unclosed_span {
8558 err.span_label(sp, "un-closed delimiter");
8559 }
8560 err.emit();
8561 }
8562}
diff --git a/crates/assists/src/tests.rs b/crates/assists/src/tests.rs
index 32bd8698b..b27f6bf75 100644
--- a/crates/assists/src/tests.rs
+++ b/crates/assists/src/tests.rs
@@ -49,14 +49,17 @@ pub(crate) fn check_assist_by_label(
49// FIXME: instead of having a separate function here, maybe use 49// FIXME: instead of having a separate function here, maybe use
50// `extract_ranges` and mark the target as `<target> </target>` in the 50// `extract_ranges` and mark the target as `<target> </target>` in the
51// fixture? 51// fixture?
52#[track_caller]
52pub(crate) fn check_assist_target(assist: Handler, ra_fixture: &str, target: &str) { 53pub(crate) fn check_assist_target(assist: Handler, ra_fixture: &str, target: &str) {
53 check(assist, ra_fixture, ExpectedResult::Target(target), None); 54 check(assist, ra_fixture, ExpectedResult::Target(target), None);
54} 55}
55 56
57#[track_caller]
56pub(crate) fn check_assist_not_applicable(assist: Handler, ra_fixture: &str) { 58pub(crate) fn check_assist_not_applicable(assist: Handler, ra_fixture: &str) {
57 check(assist, ra_fixture, ExpectedResult::NotApplicable, None); 59 check(assist, ra_fixture, ExpectedResult::NotApplicable, None);
58} 60}
59 61
62#[track_caller]
60fn check_doc_test(assist_id: &str, before: &str, after: &str) { 63fn check_doc_test(assist_id: &str, before: &str, after: &str) {
61 let after = trim_indent(after); 64 let after = trim_indent(after);
62 let (db, file_id, selection) = RootDatabase::with_range_or_offset(&before); 65 let (db, file_id, selection) = RootDatabase::with_range_or_offset(&before);
@@ -95,6 +98,7 @@ enum ExpectedResult<'a> {
95 Target(&'a str), 98 Target(&'a str),
96} 99}
97 100
101#[track_caller]
98fn check(handler: Handler, before: &str, expected: ExpectedResult, assist_label: Option<&str>) { 102fn check(handler: Handler, before: &str, expected: ExpectedResult, assist_label: Option<&str>) {
99 let (db, file_with_caret_id, range_or_offset) = RootDatabase::with_range_or_offset(before); 103 let (db, file_with_caret_id, range_or_offset) = RootDatabase::with_range_or_offset(before);
100 let text_without_caret = db.file_text(file_with_caret_id).to_string(); 104 let text_without_caret = db.file_text(file_with_caret_id).to_string();
diff --git a/crates/completion/src/completions.rs b/crates/completion/src/completions.rs
index c3ce6e51d..3b582ed07 100644
--- a/crates/completion/src/completions.rs
+++ b/crates/completion/src/completions.rs
@@ -15,7 +15,9 @@ pub(crate) mod trait_impl;
15pub(crate) mod mod_; 15pub(crate) mod mod_;
16pub(crate) mod flyimport; 16pub(crate) mod flyimport;
17 17
18use hir::{ModPath, ScopeDef, Type}; 18use std::iter;
19
20use hir::{known, ModPath, ScopeDef, Type};
19 21
20use crate::{ 22use crate::{
21 item::Builder, 23 item::Builder,
@@ -118,7 +120,18 @@ impl Completions {
118 variant: hir::Variant, 120 variant: hir::Variant,
119 local_name: Option<hir::Name>, 121 local_name: Option<hir::Name>,
120 ) { 122 ) {
121 if let Some(item) = render_variant_pat(RenderContext::new(ctx), variant, local_name) { 123 if let Some(item) = render_variant_pat(RenderContext::new(ctx), variant, local_name, None) {
124 self.add(item);
125 }
126 }
127
128 pub(crate) fn add_qualified_variant_pat(
129 &mut self,
130 ctx: &CompletionContext,
131 variant: hir::Variant,
132 path: ModPath,
133 ) {
134 if let Some(item) = render_variant_pat(RenderContext::new(ctx), variant, None, Some(path)) {
122 self.add(item); 135 self.add(item);
123 } 136 }
124 } 137 }
@@ -166,3 +179,46 @@ impl Completions {
166 self.add(item); 179 self.add(item);
167 } 180 }
168} 181}
182
183fn complete_enum_variants(
184 acc: &mut Completions,
185 ctx: &CompletionContext,
186 ty: &hir::Type,
187 cb: impl Fn(&mut Completions, &CompletionContext, hir::Variant, hir::ModPath),
188) {
189 if let Some(hir::Adt::Enum(enum_data)) =
190 iter::successors(Some(ty.clone()), |ty| ty.remove_ref()).last().and_then(|ty| ty.as_adt())
191 {
192 let variants = enum_data.variants(ctx.db);
193
194 let module = if let Some(module) = ctx.scope.module() {
195 // Compute path from the completion site if available.
196 module
197 } else {
198 // Otherwise fall back to the enum's definition site.
199 enum_data.module(ctx.db)
200 };
201
202 if let Some(impl_) = ctx.impl_def.as_ref().and_then(|impl_| ctx.sema.to_def(impl_)) {
203 if impl_.target_ty(ctx.db) == *ty {
204 for &variant in &variants {
205 let self_path = hir::ModPath::from_segments(
206 hir::PathKind::Plain,
207 iter::once(known::SELF_TYPE).chain(iter::once(variant.name(ctx.db))),
208 );
209 cb(acc, ctx, variant, self_path);
210 }
211 }
212 }
213
214 for variant in variants {
215 if let Some(path) = module.find_use_path(ctx.db, hir::ModuleDef::from(variant)) {
216 // Variants with trivial paths are already added by the existing completion logic,
217 // so we should avoid adding these twice
218 if path.segments().len() > 1 {
219 cb(acc, ctx, variant, path);
220 }
221 }
222 }
223 }
224}
diff --git a/crates/completion/src/completions/keyword.rs b/crates/completion/src/completions/keyword.rs
index 47e146128..eb81f9765 100644
--- a/crates/completion/src/completions/keyword.rs
+++ b/crates/completion/src/completions/keyword.rs
@@ -88,6 +88,7 @@ pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
88 add_keyword(ctx, acc, "loop", "loop {$0}"); 88 add_keyword(ctx, acc, "loop", "loop {$0}");
89 add_keyword(ctx, acc, "if", "if $0 {}"); 89 add_keyword(ctx, acc, "if", "if $0 {}");
90 add_keyword(ctx, acc, "if let", "if let $1 = $0 {}"); 90 add_keyword(ctx, acc, "if let", "if let $1 = $0 {}");
91 add_keyword(ctx, acc, "for", "for $1 in $0 {}");
91 } 92 }
92 93
93 if ctx.if_is_prev || ctx.block_expr_parent { 94 if ctx.if_is_prev || ctx.block_expr_parent {
@@ -258,6 +259,7 @@ mod tests {
258 kw loop 259 kw loop
259 kw if 260 kw if
260 kw if let 261 kw if let
262 kw for
261 kw let 263 kw let
262 kw mod 264 kw mod
263 kw const 265 kw const
@@ -284,6 +286,7 @@ mod tests {
284 kw loop 286 kw loop
285 kw if 287 kw if
286 kw if let 288 kw if let
289 kw for
287 kw let 290 kw let
288 kw mod 291 kw mod
289 kw const 292 kw const
@@ -310,6 +313,7 @@ mod tests {
310 kw loop 313 kw loop
311 kw if 314 kw if
312 kw if let 315 kw if let
316 kw for
313 kw let 317 kw let
314 kw else 318 kw else
315 kw else if 319 kw else if
@@ -343,6 +347,7 @@ fn quux() -> i32 {
343 kw loop 347 kw loop
344 kw if 348 kw if
345 kw if let 349 kw if let
350 kw for
346 kw unsafe 351 kw unsafe
347 kw return 352 kw return
348 "#]], 353 "#]],
@@ -391,6 +396,7 @@ fn quux() -> i32 {
391 kw loop 396 kw loop
392 kw if 397 kw if
393 kw if let 398 kw if let
399 kw for
394 kw let 400 kw let
395 kw mod 401 kw mod
396 kw const 402 kw const
@@ -549,6 +555,7 @@ pub mod future {
549 kw loop 555 kw loop
550 kw if 556 kw if
551 kw if let 557 kw if let
558 kw for
552 kw return 559 kw return
553 "#]], 560 "#]],
554 ) 561 )
@@ -607,6 +614,7 @@ fn foo() {
607 kw loop 614 kw loop
608 kw if 615 kw if
609 kw if let 616 kw if let
617 kw for
610 kw return 618 kw return
611 "#]], 619 "#]],
612 ); 620 );
diff --git a/crates/completion/src/completions/pattern.rs b/crates/completion/src/completions/pattern.rs
index 595160ff5..9282c3827 100644
--- a/crates/completion/src/completions/pattern.rs
+++ b/crates/completion/src/completions/pattern.rs
@@ -11,6 +11,12 @@ pub(crate) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) {
11 return; 11 return;
12 } 12 }
13 13
14 if let Some(ty) = &ctx.expected_type {
15 super::complete_enum_variants(acc, ctx, ty, |acc, ctx, variant, path| {
16 acc.add_qualified_variant_pat(ctx, variant, path)
17 });
18 }
19
14 // FIXME: ideally, we should look at the type we are matching against and 20 // FIXME: ideally, we should look at the type we are matching against and
15 // suggest variants + auto-imports 21 // suggest variants + auto-imports
16 ctx.scope.process_all_names(&mut |name, res| { 22 ctx.scope.process_all_names(&mut |name, res| {
@@ -31,6 +37,14 @@ pub(crate) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) {
31 _ => false, 37 _ => false,
32 }, 38 },
33 hir::ScopeDef::MacroDef(_) => true, 39 hir::ScopeDef::MacroDef(_) => true,
40 hir::ScopeDef::ImplSelfType(impl_) => match impl_.target_ty(ctx.db).as_adt() {
41 Some(hir::Adt::Struct(strukt)) => {
42 acc.add_struct_pat(ctx, strukt, Some(name.clone()));
43 true
44 }
45 Some(hir::Adt::Enum(_)) => !ctx.is_irrefutable_pat_binding,
46 _ => true,
47 },
34 _ => false, 48 _ => false,
35 }; 49 };
36 if add_resolution { 50 if add_resolution {
@@ -258,4 +272,46 @@ fn main() {
258"#, 272"#,
259 ); 273 );
260 } 274 }
275
276 #[test]
277 fn completes_self_pats() {
278 check_snippet(
279 r#"
280struct Foo(i32);
281impl Foo {
282 fn foo() {
283 match () {
284 $0
285 }
286 }
287}
288 "#,
289 expect![[r#"
290 bn Self Self($1)$0
291 bn Foo Foo($1)$0
292 "#]],
293 )
294 }
295
296 #[test]
297 fn completes_qualified_variant() {
298 check_snippet(
299 r#"
300enum Foo {
301 Bar { baz: i32 }
302}
303impl Foo {
304 fn foo() {
305 match {Foo::Bar { baz: 0 }} {
306 B$0
307 }
308 }
309}
310 "#,
311 expect![[r#"
312 bn Self::Bar Self::Bar { baz$1 }$0
313 bn Foo::Bar Foo::Bar { baz$1 }$0
314 "#]],
315 )
316 }
261} 317}
diff --git a/crates/completion/src/completions/unqualified_path.rs b/crates/completion/src/completions/unqualified_path.rs
index e2482f959..e9d0ff665 100644
--- a/crates/completion/src/completions/unqualified_path.rs
+++ b/crates/completion/src/completions/unqualified_path.rs
@@ -1,8 +1,6 @@
1//! Completion of names from the current scope, e.g. locals and imported items. 1//! Completion of names from the current scope, e.g. locals and imported items.
2 2
3use std::iter; 3use hir::ScopeDef;
4
5use hir::{Adt, ModuleDef, ScopeDef, Type};
6use syntax::AstNode; 4use syntax::AstNode;
7use test_utils::mark; 5use test_utils::mark;
8 6
@@ -21,7 +19,9 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
21 } 19 }
22 20
23 if let Some(ty) = &ctx.expected_type { 21 if let Some(ty) = &ctx.expected_type {
24 complete_enum_variants(acc, ctx, ty); 22 super::complete_enum_variants(acc, ctx, ty, |acc, ctx, variant, path| {
23 acc.add_qualified_enum_variant(ctx, variant, path)
24 });
25 } 25 }
26 26
27 if ctx.is_pat_binding_or_const { 27 if ctx.is_pat_binding_or_const {
@@ -45,32 +45,6 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
45 }); 45 });
46} 46}
47 47
48fn complete_enum_variants(acc: &mut Completions, ctx: &CompletionContext, ty: &Type) {
49 if let Some(Adt::Enum(enum_data)) =
50 iter::successors(Some(ty.clone()), |ty| ty.remove_ref()).last().and_then(|ty| ty.as_adt())
51 {
52 let variants = enum_data.variants(ctx.db);
53
54 let module = if let Some(module) = ctx.scope.module() {
55 // Compute path from the completion site if available.
56 module
57 } else {
58 // Otherwise fall back to the enum's definition site.
59 enum_data.module(ctx.db)
60 };
61
62 for variant in variants {
63 if let Some(path) = module.find_use_path(ctx.db, ModuleDef::from(variant)) {
64 // Variants with trivial paths are already added by the existing completion logic,
65 // so we should avoid adding these twice
66 if path.segments().len() > 1 {
67 acc.add_qualified_enum_variant(ctx, variant, path);
68 }
69 }
70 }
71 }
72}
73
74#[cfg(test)] 48#[cfg(test)]
75mod tests { 49mod tests {
76 use expect_test::{expect, Expect}; 50 use expect_test::{expect, Expect};
@@ -729,6 +703,28 @@ fn f() -> m::E { V$0 }
729 } 703 }
730 704
731 #[test] 705 #[test]
706 fn completes_enum_variant_impl() {
707 check(
708 r#"
709enum Foo { Bar, Baz, Quux }
710impl Foo {
711 fn foo() { match Foo::Bar { Q$0 } }
712}
713"#,
714 expect![[r#"
715 ev Self::Bar ()
716 ev Self::Baz ()
717 ev Self::Quux ()
718 ev Foo::Bar ()
719 ev Foo::Baz ()
720 ev Foo::Quux ()
721 sp Self
722 en Foo
723 "#]],
724 )
725 }
726
727 #[test]
732 fn dont_complete_attr() { 728 fn dont_complete_attr() {
733 check( 729 check(
734 r#" 730 r#"
diff --git a/crates/completion/src/context.rs b/crates/completion/src/context.rs
index b1e8eba85..3db357855 100644
--- a/crates/completion/src/context.rs
+++ b/crates/completion/src/context.rs
@@ -276,6 +276,14 @@ impl<'a> CompletionContext<'a> {
276 }); 276 });
277 } 277 }
278 278
279 fn fill_impl_def(&mut self) {
280 self.impl_def = self
281 .sema
282 .ancestors_with_macros(self.token.parent())
283 .take_while(|it| it.kind() != SOURCE_FILE && it.kind() != MODULE)
284 .find_map(ast::Impl::cast);
285 }
286
279 fn fill( 287 fn fill(
280 &mut self, 288 &mut self,
281 original_file: &SyntaxNode, 289 original_file: &SyntaxNode,
@@ -345,6 +353,8 @@ impl<'a> CompletionContext<'a> {
345 self.is_irrefutable_pat_binding = true; 353 self.is_irrefutable_pat_binding = true;
346 } 354 }
347 } 355 }
356
357 self.fill_impl_def();
348 } 358 }
349 if is_node::<ast::Param>(name.syntax()) { 359 if is_node::<ast::Param>(name.syntax()) {
350 self.is_param = true; 360 self.is_param = true;
@@ -372,11 +382,7 @@ impl<'a> CompletionContext<'a> {
372 self.sema.find_node_at_offset_with_macros(&original_file, offset); 382 self.sema.find_node_at_offset_with_macros(&original_file, offset);
373 } 383 }
374 384
375 self.impl_def = self 385 self.fill_impl_def();
376 .sema
377 .ancestors_with_macros(self.token.parent())
378 .take_while(|it| it.kind() != SOURCE_FILE && it.kind() != MODULE)
379 .find_map(ast::Impl::cast);
380 386
381 let top_node = name_ref 387 let top_node = name_ref
382 .syntax() 388 .syntax()
diff --git a/crates/completion/src/render/pattern.rs b/crates/completion/src/render/pattern.rs
index 61d8a17e5..465dfe00c 100644
--- a/crates/completion/src/render/pattern.rs
+++ b/crates/completion/src/render/pattern.rs
@@ -49,13 +49,17 @@ pub(crate) fn render_variant_pat(
49 ctx: RenderContext<'_>, 49 ctx: RenderContext<'_>,
50 variant: hir::Variant, 50 variant: hir::Variant,
51 local_name: Option<Name>, 51 local_name: Option<Name>,
52 path: Option<hir::ModPath>,
52) -> Option<CompletionItem> { 53) -> Option<CompletionItem> {
53 let _p = profile::span("render_variant_pat"); 54 let _p = profile::span("render_variant_pat");
54 55
55 let fields = variant.fields(ctx.db()); 56 let fields = variant.fields(ctx.db());
56 let (visible_fields, fields_omitted) = visible_fields(&ctx, &fields, variant)?; 57 let (visible_fields, fields_omitted) = visible_fields(&ctx, &fields, variant)?;
57 58
58 let name = local_name.unwrap_or_else(|| variant.name(ctx.db())).to_string(); 59 let name = match &path {
60 Some(path) => path.to_string(),
61 None => local_name.unwrap_or_else(|| variant.name(ctx.db())).to_string(),
62 };
59 let pat = render_pat(&ctx, &name, variant.kind(ctx.db()), &visible_fields, fields_omitted)?; 63 let pat = render_pat(&ctx, &name, variant.kind(ctx.db()), &visible_fields, fields_omitted)?;
60 64
61 Some(build_completion(ctx, name, pat, variant)) 65 Some(build_completion(ctx, name, pat, variant))
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs
index 626c3078a..bed3fa50f 100644
--- a/crates/hir/src/source_analyzer.rs
+++ b/crates/hir/src/source_analyzer.rs
@@ -222,8 +222,9 @@ impl SourceAnalyzer {
222 db: &dyn HirDatabase, 222 db: &dyn HirDatabase,
223 path: &ast::Path, 223 path: &ast::Path,
224 ) -> Option<PathResolution> { 224 ) -> Option<PathResolution> {
225 let parent = || path.syntax().parent();
225 let mut prefer_value_ns = false; 226 let mut prefer_value_ns = false;
226 if let Some(path_expr) = path.syntax().parent().and_then(ast::PathExpr::cast) { 227 if let Some(path_expr) = parent().and_then(ast::PathExpr::cast) {
227 let expr_id = self.expr_id(db, &path_expr.into())?; 228 let expr_id = self.expr_id(db, &path_expr.into())?;
228 let infer = self.infer.as_ref()?; 229 let infer = self.infer.as_ref()?;
229 if let Some(assoc) = infer.assoc_resolutions_for_expr(expr_id) { 230 if let Some(assoc) = infer.assoc_resolutions_for_expr(expr_id) {
@@ -237,7 +238,7 @@ impl SourceAnalyzer {
237 prefer_value_ns = true; 238 prefer_value_ns = true;
238 } 239 }
239 240
240 if let Some(path_pat) = path.syntax().parent().and_then(ast::PathPat::cast) { 241 if let Some(path_pat) = parent().and_then(ast::PathPat::cast) {
241 let pat_id = self.pat_id(&path_pat.into())?; 242 let pat_id = self.pat_id(&path_pat.into())?;
242 if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_pat(pat_id) { 243 if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_pat(pat_id) {
243 return Some(PathResolution::AssocItem(assoc.into())); 244 return Some(PathResolution::AssocItem(assoc.into()));
@@ -249,7 +250,7 @@ impl SourceAnalyzer {
249 } 250 }
250 } 251 }
251 252
252 if let Some(rec_lit) = path.syntax().parent().and_then(ast::RecordExpr::cast) { 253 if let Some(rec_lit) = parent().and_then(ast::RecordExpr::cast) {
253 let expr_id = self.expr_id(db, &rec_lit.into())?; 254 let expr_id = self.expr_id(db, &rec_lit.into())?;
254 if let Some(VariantId::EnumVariantId(variant)) = 255 if let Some(VariantId::EnumVariantId(variant)) =
255 self.infer.as_ref()?.variant_resolution_for_expr(expr_id) 256 self.infer.as_ref()?.variant_resolution_for_expr(expr_id)
@@ -258,8 +259,12 @@ impl SourceAnalyzer {
258 } 259 }
259 } 260 }
260 261
261 if let Some(rec_pat) = path.syntax().parent().and_then(ast::RecordPat::cast) { 262 if let Some(pat) = parent()
262 let pat_id = self.pat_id(&rec_pat.into())?; 263 .and_then(ast::RecordPat::cast)
264 .map(ast::Pat::from)
265 .or_else(|| parent().and_then(ast::TupleStructPat::cast).map(ast::Pat::from))
266 {
267 let pat_id = self.pat_id(&pat)?;
263 if let Some(VariantId::EnumVariantId(variant)) = 268 if let Some(VariantId::EnumVariantId(variant)) =
264 self.infer.as_ref()?.variant_resolution_for_pat(pat_id) 269 self.infer.as_ref()?.variant_resolution_for_pat(pat_id)
265 { 270 {
@@ -272,7 +277,7 @@ impl SourceAnalyzer {
272 277
273 // Case where path is a qualifier of another path, e.g. foo::bar::Baz where we 278 // Case where path is a qualifier of another path, e.g. foo::bar::Baz where we
274 // trying to resolve foo::bar. 279 // trying to resolve foo::bar.
275 if let Some(outer_path) = path.syntax().parent().and_then(ast::Path::cast) { 280 if let Some(outer_path) = parent().and_then(ast::Path::cast) {
276 if let Some(qualifier) = outer_path.qualifier() { 281 if let Some(qualifier) = outer_path.qualifier() {
277 if path == &qualifier { 282 if path == &qualifier {
278 return resolve_hir_path_qualifier(db, &self.resolver, &hir_path); 283 return resolve_hir_path_qualifier(db, &self.resolver, &hir_path);
diff --git a/crates/hir_def/src/body/scope.rs b/crates/hir_def/src/body/scope.rs
index 49f1427b4..210b4a617 100644
--- a/crates/hir_def/src/body/scope.rs
+++ b/crates/hir_def/src/body/scope.rs
@@ -9,7 +9,7 @@ use crate::{
9 body::Body, 9 body::Body,
10 db::DefDatabase, 10 db::DefDatabase,
11 expr::{Expr, ExprId, Pat, PatId, Statement}, 11 expr::{Expr, ExprId, Pat, PatId, Statement},
12 DefWithBodyId, 12 BlockId, DefWithBodyId,
13}; 13};
14 14
15pub type ScopeId = Idx<ScopeData>; 15pub type ScopeId = Idx<ScopeData>;
@@ -39,6 +39,7 @@ impl ScopeEntry {
39#[derive(Debug, PartialEq, Eq)] 39#[derive(Debug, PartialEq, Eq)]
40pub struct ScopeData { 40pub struct ScopeData {
41 parent: Option<ScopeId>, 41 parent: Option<ScopeId>,
42 block: Option<BlockId>,
42 entries: Vec<ScopeEntry>, 43 entries: Vec<ScopeEntry>,
43} 44}
44 45
@@ -61,6 +62,11 @@ impl ExprScopes {
61 &self.scopes[scope].entries 62 &self.scopes[scope].entries
62 } 63 }
63 64
65 /// If `scope` refers to a block expression scope, returns the corresponding `BlockId`.
66 pub fn block(&self, scope: ScopeId) -> Option<BlockId> {
67 self.scopes[scope].block
68 }
69
64 pub fn scope_chain(&self, scope: Option<ScopeId>) -> impl Iterator<Item = ScopeId> + '_ { 70 pub fn scope_chain(&self, scope: Option<ScopeId>) -> impl Iterator<Item = ScopeId> + '_ {
65 std::iter::successors(scope, move |&scope| self.scopes[scope].parent) 71 std::iter::successors(scope, move |&scope| self.scopes[scope].parent)
66 } 72 }
@@ -79,11 +85,15 @@ impl ExprScopes {
79 } 85 }
80 86
81 fn root_scope(&mut self) -> ScopeId { 87 fn root_scope(&mut self) -> ScopeId {
82 self.scopes.alloc(ScopeData { parent: None, entries: vec![] }) 88 self.scopes.alloc(ScopeData { parent: None, block: None, entries: vec![] })
83 } 89 }
84 90
85 fn new_scope(&mut self, parent: ScopeId) -> ScopeId { 91 fn new_scope(&mut self, parent: ScopeId) -> ScopeId {
86 self.scopes.alloc(ScopeData { parent: Some(parent), entries: vec![] }) 92 self.scopes.alloc(ScopeData { parent: Some(parent), block: None, entries: vec![] })
93 }
94
95 fn new_block_scope(&mut self, parent: ScopeId, block: BlockId) -> ScopeId {
96 self.scopes.alloc(ScopeData { parent: Some(parent), block: Some(block), entries: vec![] })
87 } 97 }
88 98
89 fn add_bindings(&mut self, body: &Body, scope: ScopeId, pat: PatId) { 99 fn add_bindings(&mut self, body: &Body, scope: ScopeId, pat: PatId) {
@@ -136,7 +146,11 @@ fn compute_block_scopes(
136fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope: ScopeId) { 146fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope: ScopeId) {
137 scopes.set_scope(expr, scope); 147 scopes.set_scope(expr, scope);
138 match &body[expr] { 148 match &body[expr] {
139 Expr::Block { statements, tail, .. } => { 149 Expr::Block { statements, tail, id, .. } => {
150 let scope = scopes.new_block_scope(scope, *id);
151 // Overwrite the old scope for the block expr, so that every block scope can be found
152 // via the block itself (important for blocks that only contain items, no expressions).
153 scopes.set_scope(expr, scope);
140 compute_block_scopes(&statements, *tail, body, scopes, scope); 154 compute_block_scopes(&statements, *tail, body, scopes, scope);
141 } 155 }
142 Expr::For { iterable, pat, body: body_expr, .. } => { 156 Expr::For { iterable, pat, body: body_expr, .. } => {
diff --git a/crates/hir_def/src/body/tests.rs b/crates/hir_def/src/body/tests.rs
index a92134ba7..bb43569d7 100644
--- a/crates/hir_def/src/body/tests.rs
+++ b/crates/hir_def/src/body/tests.rs
@@ -1,10 +1,10 @@
1mod block; 1mod block;
2 2
3use base_db::{fixture::WithFixture, FilePosition, SourceDatabase}; 3use base_db::{fixture::WithFixture, SourceDatabase};
4use expect_test::Expect; 4use expect_test::Expect;
5use test_utils::mark; 5use test_utils::mark;
6 6
7use crate::{test_db::TestDB, BlockId, ModuleDefId}; 7use crate::{test_db::TestDB, ModuleDefId};
8 8
9use super::*; 9use super::*;
10 10
@@ -37,104 +37,8 @@ fn check_diagnostics(ra_fixture: &str) {
37fn block_def_map_at(ra_fixture: &str) -> String { 37fn block_def_map_at(ra_fixture: &str) -> String {
38 let (db, position) = crate::test_db::TestDB::with_position(ra_fixture); 38 let (db, position) = crate::test_db::TestDB::with_position(ra_fixture);
39 39
40 let krate = db.crate_graph().iter().next().unwrap(); 40 let module = db.module_at_position(position);
41 let def_map = db.crate_def_map(krate); 41 module.def_map(&db).dump(&db)
42
43 let mut block =
44 block_at_pos(&db, &def_map, position).expect("couldn't find enclosing function or block");
45 loop {
46 let def_map = db.block_def_map(block).unwrap_or_else(|| def_map.clone());
47 let new_block = block_at_pos(&db, &def_map, position);
48 match new_block {
49 Some(new_block) => {
50 assert_ne!(block, new_block);
51 block = new_block;
52 }
53 None => {
54 return def_map.dump(&db);
55 }
56 }
57 }
58}
59
60fn block_at_pos(db: &dyn DefDatabase, def_map: &DefMap, position: FilePosition) -> Option<BlockId> {
61 // Find the smallest (innermost) function containing the cursor.
62 let mut size = None;
63 let mut fn_def = None;
64 for (_, module) in def_map.modules() {
65 let file_id = module.definition_source(db).file_id;
66 if file_id != position.file_id.into() {
67 continue;
68 }
69 let root = db.parse_or_expand(file_id).unwrap();
70 let ast_map = db.ast_id_map(file_id);
71 let item_tree = db.item_tree(file_id);
72 for decl in module.scope.declarations() {
73 if let ModuleDefId::FunctionId(it) = decl {
74 let ast = ast_map.get(item_tree[it.lookup(db).id.value].ast_id).to_node(&root);
75 let range = ast.syntax().text_range();
76
77 if !range.contains(position.offset) {
78 continue;
79 }
80
81 let new_size = match size {
82 None => range.len(),
83 Some(size) => {
84 if range.len() < size {
85 range.len()
86 } else {
87 size
88 }
89 }
90 };
91 if size != Some(new_size) {
92 size = Some(new_size);
93 fn_def = Some(it);
94 }
95 }
96 }
97 }
98
99 let (body, source_map) = db.body_with_source_map(fn_def?.into());
100
101 // Now find the smallest encompassing block expression in the function body.
102 let mut size = None;
103 let mut block_id = None;
104 for (expr_id, expr) in body.exprs.iter() {
105 if let Expr::Block { id, .. } = expr {
106 if let Ok(ast) = source_map.expr_syntax(expr_id) {
107 if ast.file_id != position.file_id.into() {
108 continue;
109 }
110
111 let root = db.parse_or_expand(ast.file_id).unwrap();
112 let ast = ast.value.to_node(&root);
113 let range = ast.syntax().text_range();
114
115 if !range.contains(position.offset) {
116 continue;
117 }
118
119 let new_size = match size {
120 None => range.len(),
121 Some(size) => {
122 if range.len() < size {
123 range.len()
124 } else {
125 size
126 }
127 }
128 };
129 if size != Some(new_size) {
130 size = Some(new_size);
131 block_id = Some(*id);
132 }
133 }
134 }
135 }
136
137 Some(block_id.expect("can't find block containing cursor"))
138} 42}
139 43
140fn check_at(ra_fixture: &str, expect: Expect) { 44fn check_at(ra_fixture: &str, expect: Expect) {
diff --git a/crates/hir_def/src/body/tests/block.rs b/crates/hir_def/src/body/tests/block.rs
index b599c6269..a5ec0883f 100644
--- a/crates/hir_def/src/body/tests/block.rs
+++ b/crates/hir_def/src/body/tests/block.rs
@@ -232,3 +232,30 @@ fn f() {
232 "#]], 232 "#]],
233 ) 233 )
234} 234}
235
236#[test]
237fn super_does_not_resolve_to_block_module() {
238 check_at(
239 r#"
240fn main() {
241 struct Struct {}
242 mod module {
243 use super::Struct;
244
245 $0
246 }
247}
248 "#,
249 expect![[r#"
250 block scope
251 Struct: t
252 module: t
253
254 block scope::module
255 Struct: _
256
257 crate
258 main: v
259 "#]],
260 );
261}
diff --git a/crates/hir_def/src/find_path.rs b/crates/hir_def/src/find_path.rs
index aa2c6e04e..5e2a711b8 100644
--- a/crates/hir_def/src/find_path.rs
+++ b/crates/hir_def/src/find_path.rs
@@ -13,8 +13,6 @@ use crate::{
13 ModuleDefId, ModuleId, 13 ModuleDefId, ModuleId,
14}; 14};
15 15
16// FIXME: handle local items
17
18/// Find a path that can be used to refer to a certain item. This can depend on 16/// Find a path that can be used to refer to a certain item. This can depend on
19/// *from where* you're referring to the item, hence the `from` parameter. 17/// *from where* you're referring to the item, hence the `from` parameter.
20pub fn find_path(db: &dyn DefDatabase, item: ItemInNs, from: ModuleId) -> Option<ModPath> { 18pub fn find_path(db: &dyn DefDatabase, item: ItemInNs, from: ModuleId) -> Option<ModPath> {
@@ -107,9 +105,9 @@ fn find_path_inner(
107 105
108 // - if the item is already in scope, return the name under which it is 106 // - if the item is already in scope, return the name under which it is
109 let def_map = from.def_map(db); 107 let def_map = from.def_map(db);
110 let from_scope: &crate::item_scope::ItemScope = &def_map[from.local_id].scope; 108 let scope_name = def_map.with_ancestor_maps(db, from.local_id, &mut |def_map, local_id| {
111 let scope_name = 109 def_map[local_id].scope.name_of(item).map(|(name, _)| name.clone())
112 if let Some((name, _)) = from_scope.name_of(item) { Some(name.clone()) } else { None }; 110 });
113 if prefixed.is_none() && scope_name.is_some() { 111 if prefixed.is_none() && scope_name.is_some() {
114 return scope_name 112 return scope_name
115 .map(|scope_name| ModPath::from_segments(PathKind::Plain, vec![scope_name])); 113 .map(|scope_name| ModPath::from_segments(PathKind::Plain, vec![scope_name]));
@@ -117,7 +115,7 @@ fn find_path_inner(
117 115
118 // - if the item is the crate root, return `crate` 116 // - if the item is the crate root, return `crate`
119 let root = def_map.module_id(def_map.root()); 117 let root = def_map.module_id(def_map.root());
120 if item == ItemInNs::Types(ModuleDefId::ModuleId(root)) { 118 if item == ItemInNs::Types(ModuleDefId::ModuleId(root)) && def_map.block_id().is_none() {
121 return Some(ModPath::from_segments(PathKind::Crate, Vec::new())); 119 return Some(ModPath::from_segments(PathKind::Crate, Vec::new()));
122 } 120 }
123 121
@@ -230,7 +228,12 @@ fn find_path_inner(
230 } 228 }
231 } 229 }
232 230
233 if let Some(prefix) = prefixed.map(PrefixKind::prefix) { 231 if let Some(mut prefix) = prefixed.map(PrefixKind::prefix) {
232 if matches!(prefix, PathKind::Crate | PathKind::Super(0)) && def_map.block_id().is_some() {
233 // Inner items cannot be referred to via `crate::` or `self::` paths.
234 prefix = PathKind::Plain;
235 }
236
234 best_path.or_else(|| { 237 best_path.or_else(|| {
235 scope_name.map(|scope_name| ModPath::from_segments(prefix, vec![scope_name])) 238 scope_name.map(|scope_name| ModPath::from_segments(prefix, vec![scope_name]))
236 }) 239 })
@@ -358,14 +361,14 @@ mod tests {
358 /// module the cursor is in. 361 /// module the cursor is in.
359 fn check_found_path_(ra_fixture: &str, path: &str, prefix_kind: Option<PrefixKind>) { 362 fn check_found_path_(ra_fixture: &str, path: &str, prefix_kind: Option<PrefixKind>) {
360 let (db, pos) = TestDB::with_position(ra_fixture); 363 let (db, pos) = TestDB::with_position(ra_fixture);
361 let module = db.module_for_file(pos.file_id); 364 let module = db.module_at_position(pos);
362 let parsed_path_file = syntax::SourceFile::parse(&format!("use {};", path)); 365 let parsed_path_file = syntax::SourceFile::parse(&format!("use {};", path));
363 let ast_path = 366 let ast_path =
364 parsed_path_file.syntax_node().descendants().find_map(syntax::ast::Path::cast).unwrap(); 367 parsed_path_file.syntax_node().descendants().find_map(syntax::ast::Path::cast).unwrap();
365 let mod_path = ModPath::from_src(ast_path, &Hygiene::new_unhygienic()).unwrap(); 368 let mod_path = ModPath::from_src(ast_path, &Hygiene::new_unhygienic()).unwrap();
366 369
367 let crate_def_map = module.def_map(&db); 370 let def_map = module.def_map(&db);
368 let resolved = crate_def_map 371 let resolved = def_map
369 .resolve_path( 372 .resolve_path(
370 &db, 373 &db,
371 module.local_id, 374 module.local_id,
@@ -788,4 +791,82 @@ mod tests {
788 check_found_path(code, "u8", "u8", "u8", "u8"); 791 check_found_path(code, "u8", "u8", "u8", "u8");
789 check_found_path(code, "u16", "u16", "u16", "u16"); 792 check_found_path(code, "u16", "u16", "u16", "u16");
790 } 793 }
794
795 #[test]
796 fn inner_items() {
797 check_found_path(
798 r#"
799 fn main() {
800 struct Inner {}
801 $0
802 }
803 "#,
804 "Inner",
805 "Inner",
806 "Inner",
807 "Inner",
808 );
809 }
810
811 #[test]
812 fn inner_items_from_outer_scope() {
813 check_found_path(
814 r#"
815 fn main() {
816 struct Struct {}
817 {
818 $0
819 }
820 }
821 "#,
822 "Struct",
823 "Struct",
824 "Struct",
825 "Struct",
826 );
827 }
828
829 #[test]
830 fn inner_items_from_inner_module() {
831 check_found_path(
832 r#"
833 fn main() {
834 mod module {
835 struct Struct {}
836 }
837 {
838 $0
839 }
840 }
841 "#,
842 "module::Struct",
843 "module::Struct",
844 "module::Struct",
845 "module::Struct",
846 );
847 }
848
849 #[test]
850 #[ignore]
851 fn inner_items_from_parent_module() {
852 // FIXME: ItemTree currently associates all inner items with `main`. Luckily, this sort of
853 // code is very rare, so this isn't terrible.
854 // To fix it, we should probably build dedicated `ItemTree`s for inner items, and not store
855 // them in the file's main ItemTree. This would also allow us to stop parsing function
856 // bodies when we only want to compute the crate's main DefMap.
857 check_found_path(
858 r#"
859 fn main() {
860 struct Struct {}
861 mod module {
862 $0
863 }
864 }
865 "#,
866 "super::Struct",
867 "super::Struct",
868 "super::Struct",
869 "super::Struct",
870 );
871 }
791} 872}
diff --git a/crates/hir_def/src/nameres.rs b/crates/hir_def/src/nameres.rs
index ad2e9bcac..34ff07f3c 100644
--- a/crates/hir_def/src/nameres.rs
+++ b/crates/hir_def/src/nameres.rs
@@ -316,7 +316,7 @@ impl DefMap {
316 /// 316 ///
317 /// If `f` returns `Some(val)`, iteration is stopped and `Some(val)` is returned. If `f` returns 317 /// If `f` returns `Some(val)`, iteration is stopped and `Some(val)` is returned. If `f` returns
318 /// `None`, iteration continues. 318 /// `None`, iteration continues.
319 fn with_ancestor_maps<T>( 319 pub fn with_ancestor_maps<T>(
320 &self, 320 &self,
321 db: &dyn DefDatabase, 321 db: &dyn DefDatabase,
322 local_mod: LocalModuleId, 322 local_mod: LocalModuleId,
diff --git a/crates/hir_def/src/resolver.rs b/crates/hir_def/src/resolver.rs
index f9ad50301..a8467c88e 100644
--- a/crates/hir_def/src/resolver.rs
+++ b/crates/hir_def/src/resolver.rs
@@ -10,7 +10,6 @@ use rustc_hash::FxHashSet;
10 10
11use crate::{ 11use crate::{
12 body::scope::{ExprScopes, ScopeId}, 12 body::scope::{ExprScopes, ScopeId},
13 body::Body,
14 builtin_type::BuiltinType, 13 builtin_type::BuiltinType,
15 db::DefDatabase, 14 db::DefDatabase,
16 expr::{ExprId, PatId}, 15 expr::{ExprId, PatId},
@@ -58,8 +57,6 @@ enum Scope {
58 AdtScope(AdtId), 57 AdtScope(AdtId),
59 /// Local bindings 58 /// Local bindings
60 ExprScope(ExprScope), 59 ExprScope(ExprScope),
61 /// Temporary hack to support local items.
62 LocalItemsScope(Arc<Body>),
63} 60}
64 61
65#[derive(Debug, Clone, PartialEq, Eq, Hash)] 62#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -169,13 +166,7 @@ impl Resolver {
169 for scope in self.scopes.iter().rev() { 166 for scope in self.scopes.iter().rev() {
170 match scope { 167 match scope {
171 Scope::ExprScope(_) => continue, 168 Scope::ExprScope(_) => continue,
172 Scope::GenericParams { .. } 169 Scope::GenericParams { .. } | Scope::ImplDefScope(_) if skip_to_mod => continue,
173 | Scope::ImplDefScope(_)
174 | Scope::LocalItemsScope(_)
175 if skip_to_mod =>
176 {
177 continue
178 }
179 170
180 Scope::GenericParams { params, def } => { 171 Scope::GenericParams { params, def } => {
181 if let Some(local_id) = params.find_type_by_name(first_name) { 172 if let Some(local_id) = params.find_type_by_name(first_name) {
@@ -199,41 +190,13 @@ impl Resolver {
199 } 190 }
200 } 191 }
201 Scope::ModuleScope(m) => { 192 Scope::ModuleScope(m) => {
202 let (module_def, idx) = m.crate_def_map.resolve_path( 193 if let Some(res) = m.resolve_path_in_type_ns(db, path) {
203 db, 194 return Some(res);
204 m.module_id,
205 &path,
206 BuiltinShadowMode::Other,
207 );
208 let res = to_type_ns(module_def)?;
209 return Some((res, idx));
210 }
211 Scope::LocalItemsScope(body) => {
212 let def = body.item_scope.get(first_name);
213 if let Some(res) = to_type_ns(def) {
214 return Some((res, None));
215 } 195 }
216 } 196 }
217 } 197 }
218 } 198 }
219 return None; 199 None
220 fn to_type_ns(per_ns: PerNs) -> Option<TypeNs> {
221 let res = match per_ns.take_types()? {
222 ModuleDefId::AdtId(it) => TypeNs::AdtId(it),
223 ModuleDefId::EnumVariantId(it) => TypeNs::EnumVariantId(it),
224
225 ModuleDefId::TypeAliasId(it) => TypeNs::TypeAliasId(it),
226 ModuleDefId::BuiltinType(it) => TypeNs::BuiltinType(it),
227
228 ModuleDefId::TraitId(it) => TypeNs::TraitId(it),
229
230 ModuleDefId::FunctionId(_)
231 | ModuleDefId::ConstId(_)
232 | ModuleDefId::StaticId(_)
233 | ModuleDefId::ModuleId(_) => return None,
234 };
235 Some(res)
236 }
237 } 200 }
238 201
239 pub fn resolve_path_in_type_ns_fully( 202 pub fn resolve_path_in_type_ns_fully(
@@ -280,7 +243,6 @@ impl Resolver {
280 | Scope::ExprScope(_) 243 | Scope::ExprScope(_)
281 | Scope::GenericParams { .. } 244 | Scope::GenericParams { .. }
282 | Scope::ImplDefScope(_) 245 | Scope::ImplDefScope(_)
283 | Scope::LocalItemsScope(_)
284 if skip_to_mod => 246 if skip_to_mod =>
285 { 247 {
286 continue 248 continue
@@ -335,63 +297,14 @@ impl Resolver {
335 } 297 }
336 298
337 Scope::ModuleScope(m) => { 299 Scope::ModuleScope(m) => {
338 let (module_def, idx) = m.crate_def_map.resolve_path( 300 if let Some(def) = m.resolve_path_in_value_ns(db, path) {
339 db, 301 return Some(def);
340 m.module_id,
341 &path,
342 BuiltinShadowMode::Other,
343 );
344 return match idx {
345 None => {
346 let value = to_value_ns(module_def)?;
347 Some(ResolveValueResult::ValueNs(value))
348 }
349 Some(idx) => {
350 let ty = match module_def.take_types()? {
351 ModuleDefId::AdtId(it) => TypeNs::AdtId(it),
352 ModuleDefId::TraitId(it) => TypeNs::TraitId(it),
353 ModuleDefId::TypeAliasId(it) => TypeNs::TypeAliasId(it),
354 ModuleDefId::BuiltinType(it) => TypeNs::BuiltinType(it),
355
356 ModuleDefId::ModuleId(_)
357 | ModuleDefId::FunctionId(_)
358 | ModuleDefId::EnumVariantId(_)
359 | ModuleDefId::ConstId(_)
360 | ModuleDefId::StaticId(_) => return None,
361 };
362 Some(ResolveValueResult::Partial(ty, idx))
363 }
364 };
365 }
366 Scope::LocalItemsScope(body) => {
367 // we don't bother looking in the builtin scope here because there are no builtin values
368 let def = to_value_ns(body.item_scope.get(first_name));
369
370 if let Some(res) = def {
371 return Some(ResolveValueResult::ValueNs(res));
372 } 302 }
373 } 303 }
374 } 304 }
375 } 305 }
376 return None; 306
377 307 None
378 fn to_value_ns(per_ns: PerNs) -> Option<ValueNs> {
379 let res = match per_ns.take_values()? {
380 ModuleDefId::FunctionId(it) => ValueNs::FunctionId(it),
381 ModuleDefId::AdtId(AdtId::StructId(it)) => ValueNs::StructId(it),
382 ModuleDefId::EnumVariantId(it) => ValueNs::EnumVariantId(it),
383 ModuleDefId::ConstId(it) => ValueNs::ConstId(it),
384 ModuleDefId::StaticId(it) => ValueNs::StaticId(it),
385
386 ModuleDefId::AdtId(AdtId::EnumId(_))
387 | ModuleDefId::AdtId(AdtId::UnionId(_))
388 | ModuleDefId::TraitId(_)
389 | ModuleDefId::TypeAliasId(_)
390 | ModuleDefId::BuiltinType(_)
391 | ModuleDefId::ModuleId(_) => return None,
392 };
393 Some(res)
394 }
395 } 308 }
396 309
397 pub fn resolve_path_in_value_ns_fully( 310 pub fn resolve_path_in_value_ns_fully(
@@ -410,11 +323,6 @@ impl Resolver {
410 db: &dyn DefDatabase, 323 db: &dyn DefDatabase,
411 path: &ModPath, 324 path: &ModPath,
412 ) -> Option<MacroDefId> { 325 ) -> Option<MacroDefId> {
413 // Search item scope legacy macro first
414 if let Some(def) = self.resolve_local_macro_def(path) {
415 return Some(def);
416 }
417
418 let (item_map, module) = self.module_scope()?; 326 let (item_map, module) = self.module_scope()?;
419 item_map.resolve_path(db, module, &path, BuiltinShadowMode::Other).0.take_macros() 327 item_map.resolve_path(db, module, &path, BuiltinShadowMode::Other).0.take_macros()
420 } 328 }
@@ -447,16 +355,6 @@ impl Resolver {
447 }) 355 })
448 } 356 }
449 357
450 fn resolve_local_macro_def(&self, path: &ModPath) -> Option<MacroDefId> {
451 let name = path.as_ident()?;
452 self.scopes.iter().rev().find_map(|scope| {
453 if let Scope::LocalItemsScope(body) = scope {
454 return body.item_scope.get_legacy_macro(name);
455 }
456 None
457 })
458 }
459
460 pub fn module(&self) -> Option<ModuleId> { 358 pub fn module(&self) -> Option<ModuleId> {
461 let (def_map, local_id) = self.module_scope()?; 359 let (def_map, local_id) = self.module_scope()?;
462 Some(def_map.module_id(local_id)) 360 Some(def_map.module_id(local_id))
@@ -538,9 +436,6 @@ impl Scope {
538 }); 436 });
539 } 437 }
540 } 438 }
541 Scope::LocalItemsScope(body) => body.item_scope.entries().for_each(|(name, def)| {
542 f(name.clone(), ScopeDef::PerNs(def));
543 }),
544 &Scope::GenericParams { ref params, def: parent } => { 439 &Scope::GenericParams { ref params, def: parent } => {
545 for (local_id, param) in params.types.iter() { 440 for (local_id, param) in params.types.iter() {
546 if let Some(ref name) = param.name { 441 if let Some(ref name) = param.name {
@@ -584,10 +479,19 @@ pub fn resolver_for_scope(
584 scope_id: Option<ScopeId>, 479 scope_id: Option<ScopeId>,
585) -> Resolver { 480) -> Resolver {
586 let mut r = owner.resolver(db); 481 let mut r = owner.resolver(db);
587 r = r.push_local_items_scope(db.body(owner));
588 let scopes = db.expr_scopes(owner); 482 let scopes = db.expr_scopes(owner);
589 let scope_chain = scopes.scope_chain(scope_id).collect::<Vec<_>>(); 483 let scope_chain = scopes.scope_chain(scope_id).collect::<Vec<_>>();
590 for scope in scope_chain.into_iter().rev() { 484 for scope in scope_chain.into_iter().rev() {
485 if let Some(block) = scopes.block(scope) {
486 if let Some(def_map) = db.block_def_map(block) {
487 let root = def_map.root();
488 r = r.push_module_scope(def_map, root);
489 // FIXME: This adds as many module scopes as there are blocks, but resolving in each
490 // already traverses all parents, so this is O(n²). I think we could only store the
491 // innermost module scope instead?
492 }
493 }
494
591 r = r.push_expr_scope(owner, Arc::clone(&scopes), scope); 495 r = r.push_expr_scope(owner, Arc::clone(&scopes), scope);
592 } 496 }
593 r 497 r
@@ -612,10 +516,6 @@ impl Resolver {
612 self.push_scope(Scope::ModuleScope(ModuleItemMap { crate_def_map, module_id })) 516 self.push_scope(Scope::ModuleScope(ModuleItemMap { crate_def_map, module_id }))
613 } 517 }
614 518
615 fn push_local_items_scope(self, body: Arc<Body>) -> Resolver {
616 self.push_scope(Scope::LocalItemsScope(body))
617 }
618
619 fn push_expr_scope( 519 fn push_expr_scope(
620 self, 520 self,
621 owner: DefWithBodyId, 521 owner: DefWithBodyId,
@@ -626,6 +526,85 @@ impl Resolver {
626 } 526 }
627} 527}
628 528
529impl ModuleItemMap {
530 fn resolve_path_in_value_ns(
531 &self,
532 db: &dyn DefDatabase,
533 path: &ModPath,
534 ) -> Option<ResolveValueResult> {
535 let (module_def, idx) =
536 self.crate_def_map.resolve_path(db, self.module_id, &path, BuiltinShadowMode::Other);
537 match idx {
538 None => {
539 let value = to_value_ns(module_def)?;
540 Some(ResolveValueResult::ValueNs(value))
541 }
542 Some(idx) => {
543 let ty = match module_def.take_types()? {
544 ModuleDefId::AdtId(it) => TypeNs::AdtId(it),
545 ModuleDefId::TraitId(it) => TypeNs::TraitId(it),
546 ModuleDefId::TypeAliasId(it) => TypeNs::TypeAliasId(it),
547 ModuleDefId::BuiltinType(it) => TypeNs::BuiltinType(it),
548
549 ModuleDefId::ModuleId(_)
550 | ModuleDefId::FunctionId(_)
551 | ModuleDefId::EnumVariantId(_)
552 | ModuleDefId::ConstId(_)
553 | ModuleDefId::StaticId(_) => return None,
554 };
555 Some(ResolveValueResult::Partial(ty, idx))
556 }
557 }
558 }
559
560 fn resolve_path_in_type_ns(
561 &self,
562 db: &dyn DefDatabase,
563 path: &ModPath,
564 ) -> Option<(TypeNs, Option<usize>)> {
565 let (module_def, idx) =
566 self.crate_def_map.resolve_path(db, self.module_id, &path, BuiltinShadowMode::Other);
567 let res = to_type_ns(module_def)?;
568 Some((res, idx))
569 }
570}
571
572fn to_value_ns(per_ns: PerNs) -> Option<ValueNs> {
573 let res = match per_ns.take_values()? {
574 ModuleDefId::FunctionId(it) => ValueNs::FunctionId(it),
575 ModuleDefId::AdtId(AdtId::StructId(it)) => ValueNs::StructId(it),
576 ModuleDefId::EnumVariantId(it) => ValueNs::EnumVariantId(it),
577 ModuleDefId::ConstId(it) => ValueNs::ConstId(it),
578 ModuleDefId::StaticId(it) => ValueNs::StaticId(it),
579
580 ModuleDefId::AdtId(AdtId::EnumId(_))
581 | ModuleDefId::AdtId(AdtId::UnionId(_))
582 | ModuleDefId::TraitId(_)
583 | ModuleDefId::TypeAliasId(_)
584 | ModuleDefId::BuiltinType(_)
585 | ModuleDefId::ModuleId(_) => return None,
586 };
587 Some(res)
588}
589
590fn to_type_ns(per_ns: PerNs) -> Option<TypeNs> {
591 let res = match per_ns.take_types()? {
592 ModuleDefId::AdtId(it) => TypeNs::AdtId(it),
593 ModuleDefId::EnumVariantId(it) => TypeNs::EnumVariantId(it),
594
595 ModuleDefId::TypeAliasId(it) => TypeNs::TypeAliasId(it),
596 ModuleDefId::BuiltinType(it) => TypeNs::BuiltinType(it),
597
598 ModuleDefId::TraitId(it) => TypeNs::TraitId(it),
599
600 ModuleDefId::FunctionId(_)
601 | ModuleDefId::ConstId(_)
602 | ModuleDefId::StaticId(_)
603 | ModuleDefId::ModuleId(_) => return None,
604 };
605 Some(res)
606}
607
629pub trait HasResolver: Copy { 608pub trait HasResolver: Copy {
630 /// Builds a resolver for type references inside this def. 609 /// Builds a resolver for type references inside this def.
631 fn resolver(self, db: &dyn DefDatabase) -> Resolver; 610 fn resolver(self, db: &dyn DefDatabase) -> Resolver;
diff --git a/crates/hir_def/src/test_db.rs b/crates/hir_def/src/test_db.rs
index 6665d902d..eda982c85 100644
--- a/crates/hir_def/src/test_db.rs
+++ b/crates/hir_def/src/test_db.rs
@@ -5,17 +5,17 @@ use std::{
5 sync::{Arc, Mutex}, 5 sync::{Arc, Mutex},
6}; 6};
7 7
8use base_db::{salsa, CrateId, FileId, FileLoader, FileLoaderDelegate, Upcast}; 8use base_db::{salsa, CrateId, FileId, FileLoader, FileLoaderDelegate, FilePosition, Upcast};
9use base_db::{AnchoredPath, SourceDatabase}; 9use base_db::{AnchoredPath, SourceDatabase};
10use hir_expand::db::AstDatabase;
11use hir_expand::diagnostics::Diagnostic; 10use hir_expand::diagnostics::Diagnostic;
12use hir_expand::diagnostics::DiagnosticSinkBuilder; 11use hir_expand::diagnostics::DiagnosticSinkBuilder;
12use hir_expand::{db::AstDatabase, InFile};
13use rustc_hash::FxHashMap; 13use rustc_hash::FxHashMap;
14use rustc_hash::FxHashSet; 14use rustc_hash::FxHashSet;
15use syntax::{TextRange, TextSize}; 15use syntax::{algo, ast, AstNode, TextRange, TextSize};
16use test_utils::extract_annotations; 16use test_utils::extract_annotations;
17 17
18use crate::{db::DefDatabase, ModuleDefId, ModuleId}; 18use crate::{db::DefDatabase, nameres::DefMap, Lookup, ModuleDefId, ModuleId};
19 19
20#[salsa::database( 20#[salsa::database(
21 base_db::SourceDatabaseExtStorage, 21 base_db::SourceDatabaseExtStorage,
@@ -84,6 +84,97 @@ impl TestDB {
84 panic!("Can't find module for file") 84 panic!("Can't find module for file")
85 } 85 }
86 86
87 pub(crate) fn module_at_position(&self, position: FilePosition) -> ModuleId {
88 let file_module = self.module_for_file(position.file_id);
89 let mut def_map = file_module.def_map(self);
90
91 def_map = match self.block_at_position(&def_map, position) {
92 Some(it) => it,
93 None => return file_module,
94 };
95 loop {
96 let new_map = self.block_at_position(&def_map, position);
97 match new_map {
98 Some(new_block) if !Arc::ptr_eq(&new_block, &def_map) => {
99 def_map = new_block;
100 }
101 _ => {
102 // FIXME: handle `mod` inside block expression
103 return def_map.module_id(def_map.root());
104 }
105 }
106 }
107 }
108
109 fn block_at_position(&self, def_map: &DefMap, position: FilePosition) -> Option<Arc<DefMap>> {
110 // Find the smallest (innermost) function in `def_map` containing the cursor.
111 let mut size = None;
112 let mut fn_def = None;
113 for (_, module) in def_map.modules() {
114 let file_id = module.definition_source(self).file_id;
115 if file_id != position.file_id.into() {
116 continue;
117 }
118 let root = self.parse_or_expand(file_id).unwrap();
119 let ast_map = self.ast_id_map(file_id);
120 let item_tree = self.item_tree(file_id);
121 for decl in module.scope.declarations() {
122 if let ModuleDefId::FunctionId(it) = decl {
123 let ast =
124 ast_map.get(item_tree[it.lookup(self).id.value].ast_id).to_node(&root);
125 let range = ast.syntax().text_range();
126
127 if !range.contains(position.offset) {
128 continue;
129 }
130
131 let new_size = match size {
132 None => range.len(),
133 Some(size) => {
134 if range.len() < size {
135 range.len()
136 } else {
137 size
138 }
139 }
140 };
141 if size != Some(new_size) {
142 size = Some(new_size);
143 fn_def = Some(it);
144 }
145 }
146 }
147 }
148
149 // Find the innermost block expression that has a `DefMap`.
150 let def_with_body = fn_def?.into();
151 let (_, source_map) = self.body_with_source_map(def_with_body);
152 let scopes = self.expr_scopes(def_with_body);
153 let root = self.parse(position.file_id);
154
155 let scope_iter = algo::ancestors_at_offset(&root.syntax_node(), position.offset)
156 .filter_map(|node| {
157 let block = ast::BlockExpr::cast(node)?;
158 let expr = ast::Expr::from(block);
159 let expr_id = source_map.node_expr(InFile::new(position.file_id.into(), &expr))?;
160 let scope = scopes.scope_for(expr_id).unwrap();
161 Some(scope)
162 });
163
164 for scope in scope_iter {
165 let containing_blocks =
166 scopes.scope_chain(Some(scope)).filter_map(|scope| scopes.block(scope));
167
168 for block in containing_blocks {
169 if let Some(def_map) = self.block_def_map(block) {
170 return Some(def_map);
171 }
172 }
173 }
174
175 None
176 }
177
87 pub(crate) fn log(&self, f: impl FnOnce()) -> Vec<salsa::Event> { 178 pub(crate) fn log(&self, f: impl FnOnce()) -> Vec<salsa::Event> {
88 *self.events.lock().unwrap() = Some(Vec::new()); 179 *self.events.lock().unwrap() = Some(Vec::new());
89 f(); 180 f();
diff --git a/crates/hir_ty/Cargo.toml b/crates/hir_ty/Cargo.toml
index f6bf49546..418ac8cbb 100644
--- a/crates/hir_ty/Cargo.toml
+++ b/crates/hir_ty/Cargo.toml
@@ -17,9 +17,9 @@ ena = "0.14.0"
17log = "0.4.8" 17log = "0.4.8"
18rustc-hash = "1.1.0" 18rustc-hash = "1.1.0"
19scoped-tls = "1" 19scoped-tls = "1"
20chalk-solve = { version = "0.55", default-features = false } 20chalk-solve = { version = "0.56", default-features = false }
21chalk-ir = "0.55" 21chalk-ir = "0.56"
22chalk-recursive = "0.55" 22chalk-recursive = "0.56"
23la-arena = { version = "0.2.0", path = "../../lib/arena" } 23la-arena = { version = "0.2.0", path = "../../lib/arena" }
24 24
25stdx = { path = "../stdx", version = "0.0.0" } 25stdx = { path = "../stdx", version = "0.0.0" }
diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs
index a302456b0..b3d1fe9a4 100644
--- a/crates/hir_ty/src/method_resolution.rs
+++ b/crates/hir_ty/src/method_resolution.rs
@@ -10,25 +10,26 @@ use hir_def::{
10 builtin_type::{IntBitness, Signedness}, 10 builtin_type::{IntBitness, Signedness},
11 lang_item::LangItemTarget, 11 lang_item::LangItemTarget,
12 type_ref::Mutability, 12 type_ref::Mutability,
13 AssocContainerId, AssocItemId, FunctionId, HasModule, ImplId, Lookup, TraitId, 13 AssocContainerId, AssocItemId, FunctionId, GenericDefId, HasModule, ImplId, Lookup, ModuleId,
14 TraitId,
14}; 15};
15use hir_expand::name::Name; 16use hir_expand::name::Name;
16use rustc_hash::{FxHashMap, FxHashSet}; 17use rustc_hash::{FxHashMap, FxHashSet};
17 18
18use super::Substs;
19use crate::{ 19use crate::{
20 autoderef, 20 autoderef,
21 db::HirDatabase, 21 db::HirDatabase,
22 primitive::{FloatBitness, FloatTy, IntTy}, 22 primitive::{FloatBitness, FloatTy, IntTy},
23 utils::all_super_traits, 23 utils::all_super_traits,
24 ApplicationTy, Canonical, DebruijnIndex, InEnvironment, TraitEnvironment, TraitRef, Ty, TyKind, 24 ApplicationTy, Canonical, DebruijnIndex, InEnvironment, Substs, TraitEnvironment, TraitRef, Ty,
25 TypeCtor, TypeWalk, 25 TyKind, TypeCtor, TypeWalk,
26}; 26};
27 27
28/// This is used as a key for indexing impls. 28/// This is used as a key for indexing impls.
29#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] 29#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
30pub enum TyFingerprint { 30pub enum TyFingerprint {
31 Apply(TypeCtor), 31 Apply(TypeCtor),
32 Dyn(TraitId),
32} 33}
33 34
34impl TyFingerprint { 35impl TyFingerprint {
@@ -38,6 +39,7 @@ impl TyFingerprint {
38 pub(crate) fn for_impl(ty: &Ty) -> Option<TyFingerprint> { 39 pub(crate) fn for_impl(ty: &Ty) -> Option<TyFingerprint> {
39 match ty { 40 match ty {
40 Ty::Apply(a_ty) => Some(TyFingerprint::Apply(a_ty.ctor)), 41 Ty::Apply(a_ty) => Some(TyFingerprint::Apply(a_ty.ctor)),
42 Ty::Dyn(_) => ty.dyn_trait().map(|trait_| TyFingerprint::Dyn(trait_)),
41 _ => None, 43 _ => None,
42 } 44 }
43 } 45 }
@@ -245,18 +247,15 @@ impl Ty {
245 }}; 247 }};
246 } 248 }
247 249
250 let mod_to_crate_ids = |module: ModuleId| Some(std::iter::once(module.krate()).collect());
251
248 let lang_item_targets = match self { 252 let lang_item_targets = match self {
249 Ty::Apply(a_ty) => match a_ty.ctor { 253 Ty::Apply(a_ty) => match a_ty.ctor {
250 TypeCtor::Adt(def_id) => { 254 TypeCtor::Adt(def_id) => {
251 return Some(std::iter::once(def_id.module(db.upcast()).krate()).collect()) 255 return mod_to_crate_ids(def_id.module(db.upcast()));
252 } 256 }
253 TypeCtor::ForeignType(type_alias_id) => { 257 TypeCtor::ForeignType(type_alias_id) => {
254 return Some( 258 return mod_to_crate_ids(type_alias_id.lookup(db.upcast()).module(db.upcast()));
255 std::iter::once(
256 type_alias_id.lookup(db.upcast()).module(db.upcast()).krate(),
257 )
258 .collect(),
259 )
260 } 259 }
261 TypeCtor::Bool => lang_item_crate!("bool"), 260 TypeCtor::Bool => lang_item_crate!("bool"),
262 TypeCtor::Char => lang_item_crate!("char"), 261 TypeCtor::Char => lang_item_crate!("char"),
@@ -272,6 +271,11 @@ impl Ty {
272 TypeCtor::RawPtr(Mutability::Mut) => lang_item_crate!("mut_ptr"), 271 TypeCtor::RawPtr(Mutability::Mut) => lang_item_crate!("mut_ptr"),
273 _ => return None, 272 _ => return None,
274 }, 273 },
274 Ty::Dyn(_) => {
275 return self.dyn_trait().and_then(|trait_| {
276 mod_to_crate_ids(GenericDefId::TraitId(trait_).module(db.upcast()))
277 });
278 }
275 _ => return None, 279 _ => return None,
276 }; 280 };
277 let res = lang_item_targets 281 let res = lang_item_targets
@@ -285,6 +289,7 @@ impl Ty {
285 Some(res) 289 Some(res)
286 } 290 }
287} 291}
292
288/// Look up the method with the given name, returning the actual autoderefed 293/// Look up the method with the given name, returning the actual autoderefed
289/// receiver type (but without autoref applied yet). 294/// receiver type (but without autoref applied yet).
290pub(crate) fn lookup_method( 295pub(crate) fn lookup_method(
diff --git a/crates/hir_ty/src/tests/macros.rs b/crates/hir_ty/src/tests/macros.rs
index c64f0b5b5..fb3afaedc 100644
--- a/crates/hir_ty/src/tests/macros.rs
+++ b/crates/hir_ty/src/tests/macros.rs
@@ -1,7 +1,5 @@
1use std::fs;
2
3use expect_test::expect; 1use expect_test::expect;
4use test_utils::project_dir; 2use test_utils::{bench, bench_fixture, skip_slow_tests};
5 3
6use super::{check_infer, check_types}; 4use super::{check_infer, check_types};
7 5
@@ -617,12 +615,11 @@ hello
617} 615}
618 616
619#[test] 617#[test]
620#[ignore] 618fn benchmark_include_macro() {
621fn include_accidentally_quadratic() { 619 if skip_slow_tests() {
622 let file = project_dir().join("crates/syntax/test_data/accidentally_quadratic"); 620 return;
623 let big_file = fs::read_to_string(file).unwrap(); 621 }
624 let big_file = vec![big_file; 10].join("\n"); 622 let data = bench_fixture::big_struct();
625
626 let fixture = r#" 623 let fixture = r#"
627//- /main.rs 624//- /main.rs
628#[rustc_builtin_macro] 625#[rustc_builtin_macro]
@@ -635,8 +632,12 @@ fn main() {
635 //^ RegisterBlock 632 //^ RegisterBlock
636} 633}
637 "#; 634 "#;
638 let fixture = format!("{}\n//- /foo.rs\n{}", fixture, big_file); 635 let fixture = format!("{}\n//- /foo.rs\n{}", fixture, data);
639 check_types(&fixture); 636
637 {
638 let _b = bench("include macro");
639 check_types(&fixture);
640 }
640} 641}
641 642
642#[test] 643#[test]
diff --git a/crates/hir_ty/src/tests/method_resolution.rs b/crates/hir_ty/src/tests/method_resolution.rs
index a6a54e542..80e795fbf 100644
--- a/crates/hir_ty/src/tests/method_resolution.rs
+++ b/crates/hir_ty/src/tests/method_resolution.rs
@@ -1106,3 +1106,25 @@ fn main() {
1106"#, 1106"#,
1107 ); 1107 );
1108} 1108}
1109
1110#[test]
1111fn method_on_dyn_impl() {
1112 check_types(
1113 r#"
1114trait Foo {}
1115
1116impl Foo for u32 {}
1117impl dyn Foo {
1118 pub fn dyn_foo(&self) -> u32 {
1119 0
1120 }
1121}
1122
1123fn main() {
1124 let f = &42u32 as &dyn Foo<u32>;
1125 f.dyn_foo();
1126 // ^u32
1127}
1128"#,
1129 );
1130}
diff --git a/crates/hir_ty/src/traits/chalk/interner.rs b/crates/hir_ty/src/traits/chalk/interner.rs
index 6a4aa8333..54bd1c724 100644
--- a/crates/hir_ty/src/traits/chalk/interner.rs
+++ b/crates/hir_ty/src/traits/chalk/interner.rs
@@ -193,8 +193,9 @@ impl chalk_ir::interner::Interner for Interner {
193 tls::with_current_program(|prog| Some(prog?.debug_quantified_where_clauses(clauses, fmt))) 193 tls::with_current_program(|prog| Some(prog?.debug_quantified_where_clauses(clauses, fmt)))
194 } 194 }
195 195
196 fn intern_ty(&self, ty: chalk_ir::TyData<Self>) -> Arc<chalk_ir::TyData<Self>> { 196 fn intern_ty(&self, kind: chalk_ir::TyKind<Self>) -> Arc<chalk_ir::TyData<Self>> {
197 Arc::new(ty) 197 let flags = kind.compute_flags(self);
198 Arc::new(chalk_ir::TyData { kind, flags })
198 } 199 }
199 200
200 fn ty_data<'a>(&self, ty: &'a Arc<chalk_ir::TyData<Self>>) -> &'a chalk_ir::TyData<Self> { 201 fn ty_data<'a>(&self, ty: &'a Arc<chalk_ir::TyData<Self>>) -> &'a chalk_ir::TyData<Self> {
diff --git a/crates/ide/src/display/navigation_target.rs b/crates/ide/src/display/navigation_target.rs
index 23d885218..198243466 100644
--- a/crates/ide/src/display/navigation_target.rs
+++ b/crates/ide/src/display/navigation_target.rs
@@ -85,12 +85,16 @@ impl NavigationTarget {
85 let name = module.name(db).map(|it| it.to_string().into()).unwrap_or_default(); 85 let name = module.name(db).map(|it| it.to_string().into()).unwrap_or_default();
86 if let Some(src) = module.declaration_source(db) { 86 if let Some(src) = module.declaration_source(db) {
87 let node = src.as_ref().map(|it| it.syntax()); 87 let node = src.as_ref().map(|it| it.syntax());
88 let frange = node.original_file_range(db); 88 let full_range = node.original_file_range(db);
89 let focus_range = src
90 .value
91 .name()
92 .map(|name| src.with_value(name.syntax()).original_file_range(db).range);
89 let mut res = NavigationTarget::from_syntax( 93 let mut res = NavigationTarget::from_syntax(
90 frange.file_id, 94 full_range.file_id,
91 name, 95 name,
92 None, 96 focus_range,
93 frange.range, 97 full_range.range,
94 SymbolKind::Module, 98 SymbolKind::Module,
95 ); 99 );
96 res.docs = module.attrs(db).docs(); 100 res.docs = module.attrs(db).docs();
diff --git a/crates/ide/src/fixture.rs b/crates/ide/src/fixture.rs
index cc8218885..cc6641ba1 100644
--- a/crates/ide/src/fixture.rs
+++ b/crates/ide/src/fixture.rs
@@ -1,5 +1,6 @@
1//! Utilities for creating `Analysis` instances for tests. 1//! Utilities for creating `Analysis` instances for tests.
2use ide_db::base_db::fixture::ChangeFixture; 2use ide_db::base_db::fixture::ChangeFixture;
3use syntax::{TextRange, TextSize};
3use test_utils::{extract_annotations, RangeOrOffset}; 4use test_utils::{extract_annotations, RangeOrOffset};
4 5
5use crate::{Analysis, AnalysisHost, FileId, FilePosition, FileRange}; 6use crate::{Analysis, AnalysisHost, FileId, FilePosition, FileRange};
@@ -68,3 +69,18 @@ pub(crate) fn annotations(ra_fixture: &str) -> (Analysis, FilePosition, Vec<(Fil
68 .collect(); 69 .collect();
69 (host.analysis(), FilePosition { file_id, offset }, annotations) 70 (host.analysis(), FilePosition { file_id, offset }, annotations)
70} 71}
72
73pub(crate) fn nav_target_annotation(ra_fixture: &str) -> (Analysis, FilePosition, FileRange) {
74 let (analysis, position, mut annotations) = annotations(ra_fixture);
75 let (mut expected, data) = annotations.pop().unwrap();
76 assert!(annotations.is_empty());
77 match data.as_str() {
78 "" => (),
79 "file" => {
80 expected.range =
81 TextRange::up_to(TextSize::of(&*analysis.file_text(expected.file_id).unwrap()))
82 }
83 data => panic!("bad data: {}", data),
84 }
85 (analysis, position, expected)
86}
diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs
index 1a997fa40..e86ae2a18 100644
--- a/crates/ide/src/goto_definition.rs
+++ b/crates/ide/src/goto_definition.rs
@@ -131,22 +131,11 @@ pub(crate) fn reference_definition(
131#[cfg(test)] 131#[cfg(test)]
132mod tests { 132mod tests {
133 use ide_db::base_db::FileRange; 133 use ide_db::base_db::FileRange;
134 use syntax::{TextRange, TextSize};
135 134
136 use crate::fixture; 135 use crate::fixture;
137 136
138 fn check(ra_fixture: &str) { 137 fn check(ra_fixture: &str) {
139 let (analysis, position, mut annotations) = fixture::annotations(ra_fixture); 138 let (analysis, position, expected) = fixture::nav_target_annotation(ra_fixture);
140 let (mut expected, data) = annotations.pop().unwrap();
141 match data.as_str() {
142 "" => (),
143 "file" => {
144 expected.range =
145 TextRange::up_to(TextSize::of(&*analysis.file_text(expected.file_id).unwrap()))
146 }
147 data => panic!("bad data: {}", data),
148 }
149
150 let mut navs = 139 let mut navs =
151 analysis.goto_definition(position).unwrap().expect("no definition found").info; 140 analysis.goto_definition(position).unwrap().expect("no definition found").info;
152 if navs.len() == 0 { 141 if navs.len() == 0 {
diff --git a/crates/ide/src/join_lines.rs b/crates/ide/src/join_lines.rs
index 631bde0f1..e3f3985d1 100644
--- a/crates/ide/src/join_lines.rs
+++ b/crates/ide/src/join_lines.rs
@@ -270,27 +270,28 @@ fn foo() {
270 270
271 #[test] 271 #[test]
272 fn test_join_lines_diverging_block() { 272 fn test_join_lines_diverging_block() {
273 let before = r" 273 check_join_lines(
274 fn foo() { 274 r"
275 loop { 275fn foo() {
276 match x { 276 loop {
277 92 => $0{ 277 match x {
278 continue; 278 92 => $0{
279 } 279 continue;
280 }
281 }
282 }
283 ";
284 let after = r"
285 fn foo() {
286 loop {
287 match x {
288 92 => $0continue,
289 }
290 }
291 } 280 }
292 "; 281 }
293 check_join_lines(before, after); 282 }
283}
284 ",
285 r"
286fn foo() {
287 loop {
288 match x {
289 92 => $0continue,
290 }
291 }
292}
293 ",
294 );
294 } 295 }
295 296
296 #[test] 297 #[test]
diff --git a/crates/ide/src/parent_module.rs b/crates/ide/src/parent_module.rs
index d343638fb..ddbaf22b7 100644
--- a/crates/ide/src/parent_module.rs
+++ b/crates/ide/src/parent_module.rs
@@ -63,57 +63,62 @@ pub(crate) fn crate_for(db: &RootDatabase, file_id: FileId) -> Vec<CrateId> {
63 63
64#[cfg(test)] 64#[cfg(test)]
65mod tests { 65mod tests {
66 use ide_db::base_db::FileRange;
66 use test_utils::mark; 67 use test_utils::mark;
67 68
68 use crate::fixture::{self}; 69 use crate::fixture;
70
71 fn check(ra_fixture: &str) {
72 let (analysis, position, expected) = fixture::nav_target_annotation(ra_fixture);
73 let mut navs = analysis.parent_module(position).unwrap();
74 assert_eq!(navs.len(), 1);
75 let nav = navs.pop().unwrap();
76 assert_eq!(expected, FileRange { file_id: nav.file_id, range: nav.focus_or_full_range() });
77 }
69 78
70 #[test] 79 #[test]
71 fn test_resolve_parent_module() { 80 fn test_resolve_parent_module() {
72 let (analysis, pos) = fixture::position( 81 check(
73 " 82 r#"
74 //- /lib.rs 83//- /lib.rs
75 mod foo; 84mod foo;
76 //- /foo.rs 85 //^^^
77 $0// empty 86
78 ", 87//- /foo.rs
88$0// empty
89"#,
79 ); 90 );
80 let nav = analysis.parent_module(pos).unwrap().pop().unwrap();
81 nav.assert_match("foo Module FileId(0) 0..8");
82 } 91 }
83 92
84 #[test] 93 #[test]
85 fn test_resolve_parent_module_on_module_decl() { 94 fn test_resolve_parent_module_on_module_decl() {
86 mark::check!(test_resolve_parent_module_on_module_decl); 95 mark::check!(test_resolve_parent_module_on_module_decl);
87 let (analysis, pos) = fixture::position( 96 check(
88 " 97 r#"
89 //- /lib.rs 98//- /lib.rs
90 mod foo; 99mod foo;
91 100 //^^^
92 //- /foo.rs 101//- /foo.rs
93 mod $0bar; 102mod $0bar;
94 103
95 //- /foo/bar.rs 104//- /foo/bar.rs
96 // empty 105// empty
97 ", 106"#,
98 ); 107 );
99 let nav = analysis.parent_module(pos).unwrap().pop().unwrap();
100 nav.assert_match("foo Module FileId(0) 0..8");
101 } 108 }
102 109
103 #[test] 110 #[test]
104 fn test_resolve_parent_module_for_inline() { 111 fn test_resolve_parent_module_for_inline() {
105 let (analysis, pos) = fixture::position( 112 check(
106 " 113 r#"
107 //- /lib.rs 114//- /lib.rs
108 mod foo { 115mod foo {
109 mod bar { 116 mod bar {
110 mod baz { $0 } 117 mod baz { $0 }
111 } 118 } //^^^
112 } 119}
113 ", 120"#,
114 ); 121 );
115 let nav = analysis.parent_module(pos).unwrap().pop().unwrap();
116 nav.assert_match("baz Module FileId(0) 32..44");
117 } 122 }
118 123
119 #[test] 124 #[test]
diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs
index 40d9487eb..6999dacee 100644
--- a/crates/ide/src/references.rs
+++ b/crates/ide/src/references.rs
@@ -1114,4 +1114,27 @@ trait Foo {
1114 "#]], 1114 "#]],
1115 ); 1115 );
1116 } 1116 }
1117
1118 #[test]
1119 fn test_self_variant_with_payload() {
1120 check(
1121 r#"
1122enum Foo { Bar() }
1123
1124impl Foo {
1125 fn foo(self) {
1126 match self {
1127 Self::Bar$0() => (),
1128 }
1129 }
1130}
1131
1132"#,
1133 expect![[r#"
1134 Bar Variant FileId(0) 11..16 11..14 Other
1135
1136 FileId(0) 89..92 Other
1137 "#]],
1138 );
1139 }
1117} 1140}
diff --git a/crates/ide/src/syntax_highlighting/tests.rs b/crates/ide/src/syntax_highlighting/tests.rs
index 1854da914..9d0cd1af5 100644
--- a/crates/ide/src/syntax_highlighting/tests.rs
+++ b/crates/ide/src/syntax_highlighting/tests.rs
@@ -1,9 +1,8 @@
1use std::fs;
2
3use expect_test::{expect_file, ExpectFile}; 1use expect_test::{expect_file, ExpectFile};
4use test_utils::project_dir; 2use ide_db::SymbolKind;
3use test_utils::{bench, bench_fixture, skip_slow_tests};
5 4
6use crate::{fixture, FileRange, TextRange}; 5use crate::{fixture, FileRange, HlTag, TextRange};
7 6
8#[test] 7#[test]
9fn test_highlighting() { 8fn test_highlighting() {
@@ -228,15 +227,45 @@ fn bar() {
228} 227}
229 228
230#[test] 229#[test]
231fn accidentally_quadratic() { 230fn benchmark_syntax_highlighting_long_struct() {
232 let file = project_dir().join("crates/syntax/test_data/accidentally_quadratic"); 231 if skip_slow_tests() {
233 let src = fs::read_to_string(file).unwrap(); 232 return;
233 }
234 234
235 let (analysis, file_id) = fixture::file(&src); 235 let fixture = bench_fixture::big_struct();
236 let (analysis, file_id) = fixture::file(&fixture);
236 237
237 // let t = std::time::Instant::now(); 238 let hash = {
238 let _ = analysis.highlight(file_id).unwrap(); 239 let _pt = bench("syntax highlighting long struct");
239 // eprintln!("elapsed: {:?}", t.elapsed()); 240 analysis
241 .highlight(file_id)
242 .unwrap()
243 .iter()
244 .filter(|it| it.highlight.tag == HlTag::Symbol(SymbolKind::Struct))
245 .count()
246 };
247 assert_eq!(hash, 2001);
248}
249
250#[test]
251fn benchmark_syntax_highlighting_parser() {
252 if skip_slow_tests() {
253 return;
254 }
255
256 let fixture = bench_fixture::glorious_old_parser();
257 let (analysis, file_id) = fixture::file(&fixture);
258
259 let hash = {
260 let _pt = bench("syntax highlighting parser");
261 analysis
262 .highlight(file_id)
263 .unwrap()
264 .iter()
265 .filter(|it| it.highlight.tag == HlTag::Symbol(SymbolKind::Function))
266 .count()
267 };
268 assert_eq!(hash, 1629);
240} 269}
241 270
242#[test] 271#[test]
diff --git a/crates/ide/src/syntax_tree.rs b/crates/ide/src/syntax_tree.rs
index 4c63d3023..f979ba434 100644
--- a/crates/ide/src/syntax_tree.rs
+++ b/crates/ide/src/syntax_tree.rs
@@ -100,147 +100,137 @@ fn syntax_tree_for_token(node: &SyntaxToken, text_range: TextRange) -> Option<St
100 100
101#[cfg(test)] 101#[cfg(test)]
102mod tests { 102mod tests {
103 use test_utils::assert_eq_text; 103 use expect_test::expect;
104 104
105 use crate::fixture; 105 use crate::fixture;
106 106
107 fn check(ra_fixture: &str, expect: expect_test::Expect) {
108 let (analysis, file_id) = fixture::file(ra_fixture);
109 let syn = analysis.syntax_tree(file_id, None).unwrap();
110 expect.assert_eq(&syn)
111 }
112 fn check_range(ra_fixture: &str, expect: expect_test::Expect) {
113 let (analysis, frange) = fixture::range(ra_fixture);
114 let syn = analysis.syntax_tree(frange.file_id, Some(frange.range)).unwrap();
115 expect.assert_eq(&syn)
116 }
117
107 #[test] 118 #[test]
108 fn test_syntax_tree_without_range() { 119 fn test_syntax_tree_without_range() {
109 // Basic syntax 120 // Basic syntax
110 let (analysis, file_id) = fixture::file(r#"fn foo() {}"#); 121 check(
111 let syn = analysis.syntax_tree(file_id, None).unwrap(); 122 r#"fn foo() {}"#,
112 123 expect![[r#"
113 assert_eq_text!( 124 [email protected]
114 r#" 125 [email protected]
115[email protected] 126 [email protected] "fn"
116 [email protected] 127 [email protected] " "
117 [email protected] "fn" 128 [email protected]
118 [email protected] " " 129 [email protected] "foo"
119 [email protected] 130 [email protected]
120 [email protected] "foo" 131 [email protected] "("
121 [email protected] 132 [email protected] ")"
122 [email protected] "(" 133 [email protected] " "
123 [email protected] ")" 134 [email protected]
124 [email protected] " " 135 [email protected] "{"
125 [email protected] 136 [email protected] "}"
126 [email protected] "{" 137 "#]],
127 [email protected] "}"
128"#
129 .trim(),
130 syn.trim()
131 ); 138 );
132 139
133 let (analysis, file_id) = fixture::file( 140 check(
134 r#" 141 r#"
135fn test() { 142fn test() {
136 assert!(" 143 assert!("
137 fn foo() { 144 fn foo() {
138 } 145 }
139 ", ""); 146 ", "");
140}"# 147}"#,
141 .trim(), 148 expect![[r#"
142 ); 149 [email protected]
143 let syn = analysis.syntax_tree(file_id, None).unwrap(); 150 [email protected]
144 151 [email protected] "fn"
145 assert_eq_text!( 152 [email protected] " "
146 r#" 153 [email protected]
147[email protected] 154 [email protected] "test"
148 [email protected] 155 [email protected]
149 [email protected] "fn" 156 [email protected] "("
150 [email protected] " " 157 [email protected] ")"
151 [email protected] 158 [email protected] " "
152 [email protected] "test" 159 [email protected]
153 [email protected] 160 [email protected] "{"
154 [email protected] "(" 161 [email protected] "\n "
155 [email protected] ")" 162 [email protected]
156 [email protected] " " 163 [email protected]
157 [email protected] 164 [email protected]
158 [email protected] "{" 165 [email protected]
159 [email protected] "\n " 166 [email protected]
160 [email protected] 167 [email protected] "assert"
161 [email protected] 168 [email protected] "!"
162 [email protected] 169 [email protected]
163 [email protected] 170 [email protected] "("
164 [email protected] 171 [email protected] "\"\n fn foo() {\n ..."
165 [email protected] "assert" 172 [email protected] ","
166 [email protected] "!" 173 [email protected] " "
167 [email protected] 174 [email protected] "\"\""
168 [email protected] "(" 175 [email protected] ")"
169 [email protected] "\"\n fn foo() {\n ..." 176 [email protected] ";"
170 [email protected] "," 177 [email protected] "\n"
171 [email protected] " " 178 [email protected] "}"
172 [email protected] "\"\"" 179 "#]],
173 [email protected] ")" 180 )
174 [email protected] ";"
175 [email protected] "\n"
176 [email protected] "}"
177"#
178 .trim(),
179 syn.trim()
180 );
181 } 181 }
182 182
183 #[test] 183 #[test]
184 fn test_syntax_tree_with_range() { 184 fn test_syntax_tree_with_range() {
185 let (analysis, range) = fixture::range(r#"$0fn foo() {}$0"#.trim()); 185 check_range(
186 let syn = analysis.syntax_tree(range.file_id, Some(range.range)).unwrap(); 186 r#"$0fn foo() {}$0"#,
187 187 expect![[r#"
188 assert_eq_text!( 188 [email protected]
189 r#" 189 [email protected] "fn"
190[email protected] 190 [email protected] " "
191 [email protected] "fn" 191 [email protected]
192 [email protected] " " 192 [email protected] "foo"
193 [email protected] 193 [email protected]
194 [email protected] "foo" 194 [email protected] "("
195 [email protected] 195 [email protected] ")"
196 [email protected] "(" 196 [email protected] " "
197 [email protected] ")" 197 [email protected]
198 [email protected] " " 198 [email protected] "{"
199 [email protected] 199 [email protected] "}"
200 [email protected] "{" 200 "#]],
201 [email protected] "}"
202"#
203 .trim(),
204 syn.trim()
205 ); 201 );
206 202
207 let (analysis, range) = fixture::range( 203 check_range(
208 r#"fn test() { 204 r#"
205fn test() {
209 $0assert!(" 206 $0assert!("
210 fn foo() { 207 fn foo() {
211 } 208 }
212 ", "");$0 209 ", "");$0
213}"# 210}"#,
214 .trim(), 211 expect![[r#"
215 ); 212 [email protected]
216 let syn = analysis.syntax_tree(range.file_id, Some(range.range)).unwrap(); 213 [email protected]
217 214 [email protected]
218 assert_eq_text!( 215 [email protected]
219 r#" 216 [email protected]
220[email protected] 217 [email protected] "assert"
221 [email protected] 218 [email protected] "!"
222 [email protected] 219 [email protected]
223 [email protected] 220 [email protected] "("
224 [email protected] 221 [email protected] "\"\n fn foo() {\n ..."
225 [email protected] "assert" 222 [email protected] ","
226 [email protected] "!" 223 [email protected] " "
227 [email protected] 224 [email protected] "\"\""
228 [email protected] "(" 225 [email protected] ")"
229 [email protected] "\"\n fn foo() {\n ..." 226 [email protected] ";"
230 [email protected] "," 227 "#]],
231 [email protected] " "
232 [email protected] "\"\""
233 [email protected] ")"
234 [email protected] ";"
235"#
236 .trim(),
237 syn.trim()
238 ); 228 );
239 } 229 }
240 230
241 #[test] 231 #[test]
242 fn test_syntax_tree_inside_string() { 232 fn test_syntax_tree_inside_string() {
243 let (analysis, range) = fixture::range( 233 check_range(
244 r#"fn test() { 234 r#"fn test() {
245 assert!(" 235 assert!("
246$0fn foo() { 236$0fn foo() {
@@ -248,33 +238,27 @@ $0fn foo() {
248fn bar() { 238fn bar() {
249} 239}
250 ", ""); 240 ", "");
251}"# 241}"#,
252 .trim(), 242 expect![[r#"
253 ); 243 [email protected]
254 let syn = analysis.syntax_tree(range.file_id, Some(range.range)).unwrap(); 244 [email protected]
255 assert_eq_text!( 245 [email protected] "fn"
256 r#" 246 [email protected] " "
257[email protected] 247 [email protected]
258 [email protected] 248 [email protected] "foo"
259 [email protected] "fn" 249 [email protected]
260 [email protected] " " 250 [email protected] "("
261 [email protected] 251 [email protected] ")"
262 [email protected] "foo" 252 [email protected] " "
263 [email protected] 253 [email protected]
264 [email protected] "(" 254 [email protected] "{"
265 [email protected] ")" 255 [email protected] "\n"
266 [email protected] " " 256 [email protected] "}"
267 [email protected] 257 "#]],
268 [email protected] "{"
269 [email protected] "\n"
270 [email protected] "}"
271"#
272 .trim(),
273 syn.trim()
274 ); 258 );
275 259
276 // With a raw string 260 // With a raw string
277 let (analysis, range) = fixture::range( 261 check_range(
278 r###"fn test() { 262 r###"fn test() {
279 assert!(r#" 263 assert!(r#"
280$0fn foo() { 264$0fn foo() {
@@ -282,76 +266,64 @@ $0fn foo() {
282fn bar() { 266fn bar() {
283} 267}
284 "#, ""); 268 "#, "");
285}"### 269}"###,
286 .trim(), 270 expect![[r#"
287 ); 271 [email protected]
288 let syn = analysis.syntax_tree(range.file_id, Some(range.range)).unwrap(); 272 [email protected]
289 assert_eq_text!( 273 [email protected] "fn"
290 r#" 274 [email protected] " "
291[email protected] 275 [email protected]
292 [email protected] 276 [email protected] "foo"
293 [email protected] "fn" 277 [email protected]
294 [email protected] " " 278 [email protected] "("
295 [email protected] 279 [email protected] ")"
296 [email protected] "foo" 280 [email protected] " "
297 [email protected] 281 [email protected]
298 [email protected] "(" 282 [email protected] "{"
299 [email protected] ")" 283 [email protected] "\n"
300 [email protected] " " 284 [email protected] "}"
301 [email protected] 285 "#]],
302 [email protected] "{"
303 [email protected] "\n"
304 [email protected] "}"
305"#
306 .trim(),
307 syn.trim()
308 ); 286 );
309 287
310 // With a raw string 288 // With a raw string
311 let (analysis, range) = fixture::range( 289 check_range(
312 r###"fn test() { 290 r###"fn test() {
313 assert!(r$0#" 291 assert!(r$0#"
314fn foo() { 292fn foo() {
315} 293}
316fn bar() { 294fn bar() {
317}"$0#, ""); 295}"$0#, "");
318}"### 296}"###,
319 .trim(), 297 expect![[r#"
320 ); 298 [email protected]
321 let syn = analysis.syntax_tree(range.file_id, Some(range.range)).unwrap(); 299 [email protected]
322 assert_eq_text!( 300 [email protected] "fn"
323 r#" 301 [email protected] " "
324[email protected] 302 [email protected]
325 [email protected] 303 [email protected] "foo"
326 [email protected] "fn" 304 [email protected]
327 [email protected] " " 305 [email protected] "("
328 [email protected] 306 [email protected] ")"
329 [email protected] "foo" 307 [email protected] " "
330 [email protected] 308 [email protected]
331 [email protected] "(" 309 [email protected] "{"
332 [email protected] ")" 310 [email protected] "\n"
333 [email protected] " " 311 [email protected] "}"
334 [email protected] 312 [email protected] "\n"
335 [email protected] "{" 313 [email protected]
336 [email protected] "\n" 314 [email protected] "fn"
337 [email protected] "}" 315 [email protected] " "
338 [email protected] "\n" 316 [email protected]
339 [email protected] 317 [email protected] "bar"
340 [email protected] "fn" 318 [email protected]
341 [email protected] " " 319 [email protected] "("
342 [email protected] 320 [email protected] ")"
343 [email protected] "bar" 321 [email protected] " "
344 [email protected] 322 [email protected]
345 [email protected] "(" 323 [email protected] "{"
346 [email protected] ")" 324 [email protected] "\n"
347 [email protected] " " 325 [email protected] "}"
348 [email protected] 326 "#]],
349 [email protected] "{"
350 [email protected] "\n"
351 [email protected] "}"
352"#
353 .trim(),
354 syn.trim()
355 ); 327 );
356 } 328 }
357} 329}
diff --git a/crates/rust-analyzer/src/cli/analysis_bench.rs b/crates/rust-analyzer/src/cli/analysis_bench.rs
index a01b49822..6735b6388 100644
--- a/crates/rust-analyzer/src/cli/analysis_bench.rs
+++ b/crates/rust-analyzer/src/cli/analysis_bench.rs
@@ -16,7 +16,10 @@ use ide_db::{
16}; 16};
17use vfs::AbsPathBuf; 17use vfs::AbsPathBuf;
18 18
19use crate::cli::{load_cargo::load_cargo, print_memory_usage, Verbosity}; 19use crate::cli::{
20 load_cargo::{load_cargo, LoadCargoConfig},
21 print_memory_usage, Verbosity,
22};
20 23
21pub struct BenchCmd { 24pub struct BenchCmd {
22 pub path: PathBuf, 25 pub path: PathBuf,
@@ -59,7 +62,14 @@ impl BenchCmd {
59 62
60 let start = Instant::now(); 63 let start = Instant::now();
61 eprint!("loading: "); 64 eprint!("loading: ");
62 let (mut host, vfs) = load_cargo(&self.path, self.load_output_dirs, self.with_proc_macro)?; 65
66 let load_cargo_config = LoadCargoConfig {
67 cargo_config: Default::default(),
68 load_out_dirs_from_check: self.load_output_dirs,
69 with_proc_macro: self.with_proc_macro,
70 };
71
72 let (mut host, vfs) = load_cargo(&self.path, &load_cargo_config)?;
63 eprintln!("{:?}\n", start.elapsed()); 73 eprintln!("{:?}\n", start.elapsed());
64 74
65 let file_id = { 75 let file_id = {
diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs
index 66416f709..3417af687 100644
--- a/crates/rust-analyzer/src/cli/analysis_stats.rs
+++ b/crates/rust-analyzer/src/cli/analysis_stats.rs
@@ -25,8 +25,10 @@ use stdx::format_to;
25use syntax::AstNode; 25use syntax::AstNode;
26 26
27use crate::cli::{ 27use crate::cli::{
28 load_cargo::load_cargo, print_memory_usage, progress_report::ProgressReport, report_metric, 28 load_cargo::{load_cargo, LoadCargoConfig},
29 Result, Verbosity, 29 print_memory_usage,
30 progress_report::ProgressReport,
31 report_metric, Result, Verbosity,
30}; 32};
31use profile::StopWatch; 33use profile::StopWatch;
32 34
@@ -57,7 +59,12 @@ impl AnalysisStatsCmd {
57 }; 59 };
58 60
59 let mut db_load_sw = self.stop_watch(); 61 let mut db_load_sw = self.stop_watch();
60 let (host, vfs) = load_cargo(&self.path, self.load_output_dirs, self.with_proc_macro)?; 62 let load_cargo_config = LoadCargoConfig {
63 cargo_config: Default::default(),
64 load_out_dirs_from_check: self.load_output_dirs,
65 with_proc_macro: self.with_proc_macro,
66 };
67 let (host, vfs) = load_cargo(&self.path, &load_cargo_config)?;
61 let db = host.raw_database(); 68 let db = host.raw_database();
62 eprintln!("{:<20} {}", "Database loaded:", db_load_sw.elapsed()); 69 eprintln!("{:<20} {}", "Database loaded:", db_load_sw.elapsed());
63 70
diff --git a/crates/rust-analyzer/src/cli/diagnostics.rs b/crates/rust-analyzer/src/cli/diagnostics.rs
index 0090fd2c2..c60374c24 100644
--- a/crates/rust-analyzer/src/cli/diagnostics.rs
+++ b/crates/rust-analyzer/src/cli/diagnostics.rs
@@ -10,7 +10,10 @@ use hir::{db::HirDatabase, Crate, Module};
10use ide::{DiagnosticsConfig, Severity}; 10use ide::{DiagnosticsConfig, Severity};
11use ide_db::base_db::SourceDatabaseExt; 11use ide_db::base_db::SourceDatabaseExt;
12 12
13use crate::cli::{load_cargo::load_cargo, Result}; 13use crate::cli::{
14 load_cargo::{load_cargo, LoadCargoConfig},
15 Result,
16};
14 17
15fn all_modules(db: &dyn HirDatabase) -> Vec<Module> { 18fn all_modules(db: &dyn HirDatabase) -> Vec<Module> {
16 let mut worklist: Vec<_> = 19 let mut worklist: Vec<_> =
@@ -25,8 +28,17 @@ fn all_modules(db: &dyn HirDatabase) -> Vec<Module> {
25 modules 28 modules
26} 29}
27 30
28pub fn diagnostics(path: &Path, load_output_dirs: bool, with_proc_macro: bool) -> Result<()> { 31pub fn diagnostics(
29 let (host, _vfs) = load_cargo(path, load_output_dirs, with_proc_macro)?; 32 path: &Path,
33 load_out_dirs_from_check: bool,
34 with_proc_macro: bool,
35) -> Result<()> {
36 let load_cargo_config = LoadCargoConfig {
37 cargo_config: Default::default(),
38 load_out_dirs_from_check,
39 with_proc_macro,
40 };
41 let (host, _vfs) = load_cargo(path, &load_cargo_config)?;
30 let db = host.raw_database(); 42 let db = host.raw_database();
31 let analysis = host.analysis(); 43 let analysis = host.analysis();
32 44
diff --git a/crates/rust-analyzer/src/cli/load_cargo.rs b/crates/rust-analyzer/src/cli/load_cargo.rs
index e12e87180..cc63c6cc2 100644
--- a/crates/rust-analyzer/src/cli/load_cargo.rs
+++ b/crates/rust-analyzer/src/cli/load_cargo.rs
@@ -13,14 +13,16 @@ use vfs::{loader::Handle, AbsPath, AbsPathBuf};
13 13
14use crate::reload::{ProjectFolders, SourceRootConfig}; 14use crate::reload::{ProjectFolders, SourceRootConfig};
15 15
16pub fn load_cargo( 16pub struct LoadCargoConfig {
17 root: &Path, 17 pub cargo_config: CargoConfig,
18 load_out_dirs_from_check: bool, 18 pub load_out_dirs_from_check: bool,
19 with_proc_macro: bool, 19 pub with_proc_macro: bool,
20) -> Result<(AnalysisHost, vfs::Vfs)> { 20}
21
22pub fn load_cargo(root: &Path, config: &LoadCargoConfig) -> Result<(AnalysisHost, vfs::Vfs)> {
21 let root = AbsPathBuf::assert(std::env::current_dir()?.join(root)); 23 let root = AbsPathBuf::assert(std::env::current_dir()?.join(root));
22 let root = ProjectManifest::discover_single(&root)?; 24 let root = ProjectManifest::discover_single(&root)?;
23 let ws = ProjectWorkspace::load(root, &CargoConfig::default(), &|_| {})?; 25 let ws = ProjectWorkspace::load(root, &config.cargo_config, &|_| {})?;
24 26
25 let (sender, receiver) = unbounded(); 27 let (sender, receiver) = unbounded();
26 let mut vfs = vfs::Vfs::default(); 28 let mut vfs = vfs::Vfs::default();
@@ -30,14 +32,14 @@ pub fn load_cargo(
30 Box::new(loader) 32 Box::new(loader)
31 }; 33 };
32 34
33 let proc_macro_client = if with_proc_macro { 35 let proc_macro_client = if config.with_proc_macro {
34 let path = std::env::current_exe()?; 36 let path = std::env::current_exe()?;
35 Some(ProcMacroClient::extern_process(path, &["proc-macro"]).unwrap()) 37 Some(ProcMacroClient::extern_process(path, &["proc-macro"]).unwrap())
36 } else { 38 } else {
37 None 39 None
38 }; 40 };
39 41
40 let build_data = if load_out_dirs_from_check { 42 let build_data = if config.load_out_dirs_from_check {
41 let mut collector = BuildDataCollector::default(); 43 let mut collector = BuildDataCollector::default();
42 ws.collect_build_data_configs(&mut collector); 44 ws.collect_build_data_configs(&mut collector);
43 Some(collector.collect(&|_| {})?) 45 Some(collector.collect(&|_| {})?)
@@ -116,7 +118,13 @@ mod tests {
116 #[test] 118 #[test]
117 fn test_loading_rust_analyzer() { 119 fn test_loading_rust_analyzer() {
118 let path = Path::new(env!("CARGO_MANIFEST_DIR")).parent().unwrap().parent().unwrap(); 120 let path = Path::new(env!("CARGO_MANIFEST_DIR")).parent().unwrap().parent().unwrap();
119 let (host, _vfs) = load_cargo(path, false, false).unwrap(); 121 let load_cargo_config = LoadCargoConfig {
122 cargo_config: Default::default(),
123 load_out_dirs_from_check: false,
124 with_proc_macro: false,
125 };
126
127 let (host, _vfs) = load_cargo(path, &load_cargo_config).unwrap();
120 let n_crates = Crate::all(host.raw_database()).len(); 128 let n_crates = Crate::all(host.raw_database()).len();
121 // RA has quite a few crates, but the exact count doesn't matter 129 // RA has quite a few crates, but the exact count doesn't matter
122 assert!(n_crates > 20); 130 assert!(n_crates > 20);
diff --git a/crates/rust-analyzer/src/cli/ssr.rs b/crates/rust-analyzer/src/cli/ssr.rs
index bbb550ec9..8729ff0d9 100644
--- a/crates/rust-analyzer/src/cli/ssr.rs
+++ b/crates/rust-analyzer/src/cli/ssr.rs
@@ -1,11 +1,19 @@
1//! Applies structured search replace rules from the command line. 1//! Applies structured search replace rules from the command line.
2 2
3use crate::cli::{load_cargo::load_cargo, Result}; 3use crate::cli::{
4 load_cargo::{load_cargo, LoadCargoConfig},
5 Result,
6};
4use ssr::{MatchFinder, SsrPattern, SsrRule}; 7use ssr::{MatchFinder, SsrPattern, SsrRule};
5 8
6pub fn apply_ssr_rules(rules: Vec<SsrRule>) -> Result<()> { 9pub fn apply_ssr_rules(rules: Vec<SsrRule>) -> Result<()> {
7 use ide_db::base_db::SourceDatabaseExt; 10 use ide_db::base_db::SourceDatabaseExt;
8 let (host, vfs) = load_cargo(&std::env::current_dir()?, true, true)?; 11 let load_cargo_config = LoadCargoConfig {
12 cargo_config: Default::default(),
13 load_out_dirs_from_check: true,
14 with_proc_macro: true,
15 };
16 let (host, vfs) = load_cargo(&std::env::current_dir()?, &load_cargo_config)?;
9 let db = host.raw_database(); 17 let db = host.raw_database();
10 let mut match_finder = MatchFinder::at_first_file(db)?; 18 let mut match_finder = MatchFinder::at_first_file(db)?;
11 for rule in rules { 19 for rule in rules {
@@ -28,7 +36,12 @@ pub fn apply_ssr_rules(rules: Vec<SsrRule>) -> Result<()> {
28pub fn search_for_patterns(patterns: Vec<SsrPattern>, debug_snippet: Option<String>) -> Result<()> { 36pub fn search_for_patterns(patterns: Vec<SsrPattern>, debug_snippet: Option<String>) -> Result<()> {
29 use ide_db::base_db::SourceDatabaseExt; 37 use ide_db::base_db::SourceDatabaseExt;
30 use ide_db::symbol_index::SymbolsDatabase; 38 use ide_db::symbol_index::SymbolsDatabase;
31 let (host, _vfs) = load_cargo(&std::env::current_dir()?, true, true)?; 39 let load_cargo_config = LoadCargoConfig {
40 cargo_config: Default::default(),
41 load_out_dirs_from_check: true,
42 with_proc_macro: true,
43 };
44 let (host, _vfs) = load_cargo(&std::env::current_dir()?, &load_cargo_config)?;
32 let db = host.raw_database(); 45 let db = host.raw_database();
33 let mut match_finder = MatchFinder::at_first_file(db)?; 46 let mut match_finder = MatchFinder::at_first_file(db)?;
34 for pattern in patterns { 47 for pattern in patterns {
diff --git a/crates/syntax/Cargo.toml b/crates/syntax/Cargo.toml
index aa6f6e0b6..e3ef71650 100644
--- a/crates/syntax/Cargo.toml
+++ b/crates/syntax/Cargo.toml
@@ -13,7 +13,7 @@ doctest = false
13[dependencies] 13[dependencies]
14itertools = "0.10.0" 14itertools = "0.10.0"
15rowan = "0.12.2" 15rowan = "0.12.2"
16rustc_lexer = { version = "702.0.0", package = "rustc-ap-rustc_lexer" } 16rustc_lexer = { version = "705.0.0", package = "rustc-ap-rustc_lexer" }
17rustc-hash = "1.1.0" 17rustc-hash = "1.1.0"
18arrayvec = "0.5.1" 18arrayvec = "0.5.1"
19once_cell = "1.3.1" 19once_cell = "1.3.1"
diff --git a/crates/syntax/src/tests.rs b/crates/syntax/src/tests.rs
index 9d3433c9d..b2c06e24f 100644
--- a/crates/syntax/src/tests.rs
+++ b/crates/syntax/src/tests.rs
@@ -4,11 +4,12 @@ use std::{
4 path::{Path, PathBuf}, 4 path::{Path, PathBuf},
5}; 5};
6 6
7use ast::NameOwner;
7use expect_test::expect_file; 8use expect_test::expect_file;
8use rayon::prelude::*; 9use rayon::prelude::*;
9use test_utils::project_dir; 10use test_utils::{bench, bench_fixture, project_dir, skip_slow_tests};
10 11
11use crate::{fuzz, tokenize, SourceFile, SyntaxError, TextRange, TextSize, Token}; 12use crate::{ast, fuzz, tokenize, AstNode, SourceFile, SyntaxError, TextRange, TextSize, Token};
12 13
13#[test] 14#[test]
14fn lexer_tests() { 15fn lexer_tests() {
@@ -42,6 +43,28 @@ fn main() {
42} 43}
43 44
44#[test] 45#[test]
46fn benchmark_parser() {
47 if skip_slow_tests() {
48 return;
49 }
50 let data = bench_fixture::glorious_old_parser();
51 let tree = {
52 let _b = bench("parsing");
53 let p = SourceFile::parse(&data);
54 assert!(p.errors.is_empty());
55 assert_eq!(p.tree().syntax.text_range().len(), 352474.into());
56 p.tree()
57 };
58
59 {
60 let _b = bench("tree traversal");
61 let fn_names =
62 tree.syntax().descendants().filter_map(ast::Fn::cast).filter_map(|f| f.name()).count();
63 assert_eq!(fn_names, 268);
64 }
65}
66
67#[test]
45fn parser_tests() { 68fn parser_tests() {
46 dir_tests(&test_data_dir(), &["parser/inline/ok", "parser/ok"], "rast", |text, path| { 69 dir_tests(&test_data_dir(), &["parser/inline/ok", "parser/ok"], "rast", |text, path| {
47 let parse = SourceFile::parse(text); 70 let parse = SourceFile::parse(text);
@@ -128,7 +151,6 @@ fn reparse_fuzz_tests() {
128} 151}
129 152
130/// Test that Rust-analyzer can parse and validate the rust-analyzer 153/// Test that Rust-analyzer can parse and validate the rust-analyzer
131/// FIXME: Use this as a benchmark
132#[test] 154#[test]
133fn self_hosting_parsing() { 155fn self_hosting_parsing() {
134 let dir = project_dir().join("crates"); 156 let dir = project_dir().join("crates");
diff --git a/crates/syntax/test_data/accidentally_quadratic b/crates/syntax/test_data/accidentally_quadratic
deleted file mode 100644
index 428f83a62..000000000
--- a/crates/syntax/test_data/accidentally_quadratic
+++ /dev/null
@@ -1,3980 +0,0 @@
1#[doc = r" Register block"]
2#[repr(C)]
3pub struct RegisterBlock {
4 #[doc = "0x00 - Control Register"]
5 pub cr: CR,
6 #[doc = "0x04 - Error Status Register"]
7 pub es: ES,
8 _reserved0: [u8; 4usize],
9 #[doc = "0x0c - Enable Request Register"]
10 pub erq: ERQ,
11 _reserved1: [u8; 4usize],
12 #[doc = "0x14 - Enable Error Interrupt Register"]
13 pub eei: EEI,
14 #[doc = "0x18 - Clear Enable Error Interrupt Register"]
15 pub ceei: CEEI,
16 #[doc = "0x19 - Set Enable Error Interrupt Register"]
17 pub seei: SEEI,
18 #[doc = "0x1a - Clear Enable Request Register"]
19 pub cerq: CERQ,
20 #[doc = "0x1b - Set Enable Request Register"]
21 pub serq: SERQ,
22 #[doc = "0x1c - Clear DONE Status Bit Register"]
23 pub cdne: CDNE,
24 #[doc = "0x1d - Set START Bit Register"]
25 pub ssrt: SSRT,
26 #[doc = "0x1e - Clear Error Register"]
27 pub cerr: CERR,
28 #[doc = "0x1f - Clear Interrupt Request Register"]
29 pub cint: CINT,
30 _reserved2: [u8; 4usize],
31 #[doc = "0x24 - Interrupt Request Register"]
32 pub int: INT,
33 _reserved3: [u8; 4usize],
34 #[doc = "0x2c - Error Register"]
35 pub err: ERR,
36 _reserved4: [u8; 4usize],
37 #[doc = "0x34 - Hardware Request Status Register"]
38 pub hrs: HRS,
39 _reserved5: [u8; 12usize],
40 #[doc = "0x44 - Enable Asynchronous Request in Stop Register"]
41 pub ears: EARS,
42 _reserved6: [u8; 184usize],
43 #[doc = "0x100 - Channel n Priority Register"]
44 pub dchpri3: DCHPRI3,
45 #[doc = "0x101 - Channel n Priority Register"]
46 pub dchpri2: DCHPRI2,
47 #[doc = "0x102 - Channel n Priority Register"]
48 pub dchpri1: DCHPRI1,
49 #[doc = "0x103 - Channel n Priority Register"]
50 pub dchpri0: DCHPRI0,
51 #[doc = "0x104 - Channel n Priority Register"]
52 pub dchpri7: DCHPRI7,
53 #[doc = "0x105 - Channel n Priority Register"]
54 pub dchpri6: DCHPRI6,
55 #[doc = "0x106 - Channel n Priority Register"]
56 pub dchpri5: DCHPRI5,
57 #[doc = "0x107 - Channel n Priority Register"]
58 pub dchpri4: DCHPRI4,
59 #[doc = "0x108 - Channel n Priority Register"]
60 pub dchpri11: DCHPRI11,
61 #[doc = "0x109 - Channel n Priority Register"]
62 pub dchpri10: DCHPRI10,
63 #[doc = "0x10a - Channel n Priority Register"]
64 pub dchpri9: DCHPRI9,
65 #[doc = "0x10b - Channel n Priority Register"]
66 pub dchpri8: DCHPRI8,
67 #[doc = "0x10c - Channel n Priority Register"]
68 pub dchpri15: DCHPRI15,
69 #[doc = "0x10d - Channel n Priority Register"]
70 pub dchpri14: DCHPRI14,
71 #[doc = "0x10e - Channel n Priority Register"]
72 pub dchpri13: DCHPRI13,
73 #[doc = "0x10f - Channel n Priority Register"]
74 pub dchpri12: DCHPRI12,
75 #[doc = "0x110 - Channel n Priority Register"]
76 pub dchpri19: DCHPRI19,
77 #[doc = "0x111 - Channel n Priority Register"]
78 pub dchpri18: DCHPRI18,
79 #[doc = "0x112 - Channel n Priority Register"]
80 pub dchpri17: DCHPRI17,
81 #[doc = "0x113 - Channel n Priority Register"]
82 pub dchpri16: DCHPRI16,
83 #[doc = "0x114 - Channel n Priority Register"]
84 pub dchpri23: DCHPRI23,
85 #[doc = "0x115 - Channel n Priority Register"]
86 pub dchpri22: DCHPRI22,
87 #[doc = "0x116 - Channel n Priority Register"]
88 pub dchpri21: DCHPRI21,
89 #[doc = "0x117 - Channel n Priority Register"]
90 pub dchpri20: DCHPRI20,
91 #[doc = "0x118 - Channel n Priority Register"]
92 pub dchpri27: DCHPRI27,
93 #[doc = "0x119 - Channel n Priority Register"]
94 pub dchpri26: DCHPRI26,
95 #[doc = "0x11a - Channel n Priority Register"]
96 pub dchpri25: DCHPRI25,
97 #[doc = "0x11b - Channel n Priority Register"]
98 pub dchpri24: DCHPRI24,
99 #[doc = "0x11c - Channel n Priority Register"]
100 pub dchpri31: DCHPRI31,
101 #[doc = "0x11d - Channel n Priority Register"]
102 pub dchpri30: DCHPRI30,
103 #[doc = "0x11e - Channel n Priority Register"]
104 pub dchpri29: DCHPRI29,
105 #[doc = "0x11f - Channel n Priority Register"]
106 pub dchpri28: DCHPRI28,
107 _reserved7: [u8; 3808usize],
108 #[doc = "0x1000 - TCD Source Address"]
109 pub tcd0_saddr: TCD0_SADDR,
110 #[doc = "0x1004 - TCD Signed Source Address Offset"]
111 pub tcd0_soff: TCD0_SOFF,
112 #[doc = "0x1006 - TCD Transfer Attributes"]
113 pub tcd0_attr: TCD0_ATTR,
114 #[doc = "0x1008 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
115 pub tcd0_nbytes_mlno: TCD0_NBYTES_MLNO,
116 #[doc = "0x100c - TCD Last Source Address Adjustment"]
117 pub tcd0_slast: TCD0_SLAST,
118 #[doc = "0x1010 - TCD Destination Address"]
119 pub tcd0_daddr: TCD0_DADDR,
120 #[doc = "0x1014 - TCD Signed Destination Address Offset"]
121 pub tcd0_doff: TCD0_DOFF,
122 #[doc = "0x1016 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
123 pub tcd0_citer_elinkno: TCD0_CITER_ELINKNO,
124 #[doc = "0x1018 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
125 pub tcd0_dlastsga: TCD0_DLASTSGA,
126 #[doc = "0x101c - TCD Control and Status"]
127 pub tcd0_csr: TCD0_CSR,
128 #[doc = "0x101e - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
129 pub tcd0_biter_elinkno: TCD0_BITER_ELINKNO,
130 #[doc = "0x1020 - TCD Source Address"]
131 pub tcd1_saddr: TCD1_SADDR,
132 #[doc = "0x1024 - TCD Signed Source Address Offset"]
133 pub tcd1_soff: TCD1_SOFF,
134 #[doc = "0x1026 - TCD Transfer Attributes"]
135 pub tcd1_attr: TCD1_ATTR,
136 #[doc = "0x1028 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
137 pub tcd1_nbytes_mlno: TCD1_NBYTES_MLNO,
138 #[doc = "0x102c - TCD Last Source Address Adjustment"]
139 pub tcd1_slast: TCD1_SLAST,
140 #[doc = "0x1030 - TCD Destination Address"]
141 pub tcd1_daddr: TCD1_DADDR,
142 #[doc = "0x1034 - TCD Signed Destination Address Offset"]
143 pub tcd1_doff: TCD1_DOFF,
144 #[doc = "0x1036 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
145 pub tcd1_citer_elinkno: TCD1_CITER_ELINKNO,
146 #[doc = "0x1038 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
147 pub tcd1_dlastsga: TCD1_DLASTSGA,
148 #[doc = "0x103c - TCD Control and Status"]
149 pub tcd1_csr: TCD1_CSR,
150 #[doc = "0x103e - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
151 pub tcd1_biter_elinkno: TCD1_BITER_ELINKNO,
152 #[doc = "0x1040 - TCD Source Address"]
153 pub tcd2_saddr: TCD2_SADDR,
154 #[doc = "0x1044 - TCD Signed Source Address Offset"]
155 pub tcd2_soff: TCD2_SOFF,
156 #[doc = "0x1046 - TCD Transfer Attributes"]
157 pub tcd2_attr: TCD2_ATTR,
158 #[doc = "0x1048 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
159 pub tcd2_nbytes_mlno: TCD2_NBYTES_MLNO,
160 #[doc = "0x104c - TCD Last Source Address Adjustment"]
161 pub tcd2_slast: TCD2_SLAST,
162 #[doc = "0x1050 - TCD Destination Address"]
163 pub tcd2_daddr: TCD2_DADDR,
164 #[doc = "0x1054 - TCD Signed Destination Address Offset"]
165 pub tcd2_doff: TCD2_DOFF,
166 #[doc = "0x1056 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
167 pub tcd2_citer_elinkno: TCD2_CITER_ELINKNO,
168 #[doc = "0x1058 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
169 pub tcd2_dlastsga: TCD2_DLASTSGA,
170 #[doc = "0x105c - TCD Control and Status"]
171 pub tcd2_csr: TCD2_CSR,
172 #[doc = "0x105e - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
173 pub tcd2_biter_elinkno: TCD2_BITER_ELINKNO,
174 #[doc = "0x1060 - TCD Source Address"]
175 pub tcd3_saddr: TCD3_SADDR,
176 #[doc = "0x1064 - TCD Signed Source Address Offset"]
177 pub tcd3_soff: TCD3_SOFF,
178 #[doc = "0x1066 - TCD Transfer Attributes"]
179 pub tcd3_attr: TCD3_ATTR,
180 #[doc = "0x1068 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
181 pub tcd3_nbytes_mlno: TCD3_NBYTES_MLNO,
182 #[doc = "0x106c - TCD Last Source Address Adjustment"]
183 pub tcd3_slast: TCD3_SLAST,
184 #[doc = "0x1070 - TCD Destination Address"]
185 pub tcd3_daddr: TCD3_DADDR,
186 #[doc = "0x1074 - TCD Signed Destination Address Offset"]
187 pub tcd3_doff: TCD3_DOFF,
188 #[doc = "0x1076 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
189 pub tcd3_citer_elinkno: TCD3_CITER_ELINKNO,
190 #[doc = "0x1078 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
191 pub tcd3_dlastsga: TCD3_DLASTSGA,
192 #[doc = "0x107c - TCD Control and Status"]
193 pub tcd3_csr: TCD3_CSR,
194 #[doc = "0x107e - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
195 pub tcd3_biter_elinkno: TCD3_BITER_ELINKNO,
196 #[doc = "0x1080 - TCD Source Address"]
197 pub tcd4_saddr: TCD4_SADDR,
198 #[doc = "0x1084 - TCD Signed Source Address Offset"]
199 pub tcd4_soff: TCD4_SOFF,
200 #[doc = "0x1086 - TCD Transfer Attributes"]
201 pub tcd4_attr: TCD4_ATTR,
202 #[doc = "0x1088 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
203 pub tcd4_nbytes_mlno: TCD4_NBYTES_MLNO,
204 #[doc = "0x108c - TCD Last Source Address Adjustment"]
205 pub tcd4_slast: TCD4_SLAST,
206 #[doc = "0x1090 - TCD Destination Address"]
207 pub tcd4_daddr: TCD4_DADDR,
208 #[doc = "0x1094 - TCD Signed Destination Address Offset"]
209 pub tcd4_doff: TCD4_DOFF,
210 #[doc = "0x1096 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
211 pub tcd4_citer_elinkno: TCD4_CITER_ELINKNO,
212 #[doc = "0x1098 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
213 pub tcd4_dlastsga: TCD4_DLASTSGA,
214 #[doc = "0x109c - TCD Control and Status"]
215 pub tcd4_csr: TCD4_CSR,
216 #[doc = "0x109e - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
217 pub tcd4_biter_elinkno: TCD4_BITER_ELINKNO,
218 #[doc = "0x10a0 - TCD Source Address"]
219 pub tcd5_saddr: TCD5_SADDR,
220 #[doc = "0x10a4 - TCD Signed Source Address Offset"]
221 pub tcd5_soff: TCD5_SOFF,
222 #[doc = "0x10a6 - TCD Transfer Attributes"]
223 pub tcd5_attr: TCD5_ATTR,
224 #[doc = "0x10a8 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
225 pub tcd5_nbytes_mlno: TCD5_NBYTES_MLNO,
226 #[doc = "0x10ac - TCD Last Source Address Adjustment"]
227 pub tcd5_slast: TCD5_SLAST,
228 #[doc = "0x10b0 - TCD Destination Address"]
229 pub tcd5_daddr: TCD5_DADDR,
230 #[doc = "0x10b4 - TCD Signed Destination Address Offset"]
231 pub tcd5_doff: TCD5_DOFF,
232 #[doc = "0x10b6 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
233 pub tcd5_citer_elinkno: TCD5_CITER_ELINKNO,
234 #[doc = "0x10b8 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
235 pub tcd5_dlastsga: TCD5_DLASTSGA,
236 #[doc = "0x10bc - TCD Control and Status"]
237 pub tcd5_csr: TCD5_CSR,
238 #[doc = "0x10be - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
239 pub tcd5_biter_elinkno: TCD5_BITER_ELINKNO,
240 #[doc = "0x10c0 - TCD Source Address"]
241 pub tcd6_saddr: TCD6_SADDR,
242 #[doc = "0x10c4 - TCD Signed Source Address Offset"]
243 pub tcd6_soff: TCD6_SOFF,
244 #[doc = "0x10c6 - TCD Transfer Attributes"]
245 pub tcd6_attr: TCD6_ATTR,
246 #[doc = "0x10c8 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
247 pub tcd6_nbytes_mlno: TCD6_NBYTES_MLNO,
248 #[doc = "0x10cc - TCD Last Source Address Adjustment"]
249 pub tcd6_slast: TCD6_SLAST,
250 #[doc = "0x10d0 - TCD Destination Address"]
251 pub tcd6_daddr: TCD6_DADDR,
252 #[doc = "0x10d4 - TCD Signed Destination Address Offset"]
253 pub tcd6_doff: TCD6_DOFF,
254 #[doc = "0x10d6 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
255 pub tcd6_citer_elinkno: TCD6_CITER_ELINKNO,
256 #[doc = "0x10d8 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
257 pub tcd6_dlastsga: TCD6_DLASTSGA,
258 #[doc = "0x10dc - TCD Control and Status"]
259 pub tcd6_csr: TCD6_CSR,
260 #[doc = "0x10de - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
261 pub tcd6_biter_elinkno: TCD6_BITER_ELINKNO,
262 #[doc = "0x10e0 - TCD Source Address"]
263 pub tcd7_saddr: TCD7_SADDR,
264 #[doc = "0x10e4 - TCD Signed Source Address Offset"]
265 pub tcd7_soff: TCD7_SOFF,
266 #[doc = "0x10e6 - TCD Transfer Attributes"]
267 pub tcd7_attr: TCD7_ATTR,
268 #[doc = "0x10e8 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
269 pub tcd7_nbytes_mlno: TCD7_NBYTES_MLNO,
270 #[doc = "0x10ec - TCD Last Source Address Adjustment"]
271 pub tcd7_slast: TCD7_SLAST,
272 #[doc = "0x10f0 - TCD Destination Address"]
273 pub tcd7_daddr: TCD7_DADDR,
274 #[doc = "0x10f4 - TCD Signed Destination Address Offset"]
275 pub tcd7_doff: TCD7_DOFF,
276 #[doc = "0x10f6 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
277 pub tcd7_citer_elinkno: TCD7_CITER_ELINKNO,
278 #[doc = "0x10f8 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
279 pub tcd7_dlastsga: TCD7_DLASTSGA,
280 #[doc = "0x10fc - TCD Control and Status"]
281 pub tcd7_csr: TCD7_CSR,
282 #[doc = "0x10fe - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
283 pub tcd7_biter_elinkno: TCD7_BITER_ELINKNO,
284 #[doc = "0x1100 - TCD Source Address"]
285 pub tcd8_saddr: TCD8_SADDR,
286 #[doc = "0x1104 - TCD Signed Source Address Offset"]
287 pub tcd8_soff: TCD8_SOFF,
288 #[doc = "0x1106 - TCD Transfer Attributes"]
289 pub tcd8_attr: TCD8_ATTR,
290 #[doc = "0x1108 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
291 pub tcd8_nbytes_mlno: TCD8_NBYTES_MLNO,
292 #[doc = "0x110c - TCD Last Source Address Adjustment"]
293 pub tcd8_slast: TCD8_SLAST,
294 #[doc = "0x1110 - TCD Destination Address"]
295 pub tcd8_daddr: TCD8_DADDR,
296 #[doc = "0x1114 - TCD Signed Destination Address Offset"]
297 pub tcd8_doff: TCD8_DOFF,
298 #[doc = "0x1116 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
299 pub tcd8_citer_elinkno: TCD8_CITER_ELINKNO,
300 #[doc = "0x1118 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
301 pub tcd8_dlastsga: TCD8_DLASTSGA,
302 #[doc = "0x111c - TCD Control and Status"]
303 pub tcd8_csr: TCD8_CSR,
304 #[doc = "0x111e - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
305 pub tcd8_biter_elinkno: TCD8_BITER_ELINKNO,
306 #[doc = "0x1120 - TCD Source Address"]
307 pub tcd9_saddr: TCD9_SADDR,
308 #[doc = "0x1124 - TCD Signed Source Address Offset"]
309 pub tcd9_soff: TCD9_SOFF,
310 #[doc = "0x1126 - TCD Transfer Attributes"]
311 pub tcd9_attr: TCD9_ATTR,
312 #[doc = "0x1128 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
313 pub tcd9_nbytes_mlno: TCD9_NBYTES_MLNO,
314 #[doc = "0x112c - TCD Last Source Address Adjustment"]
315 pub tcd9_slast: TCD9_SLAST,
316 #[doc = "0x1130 - TCD Destination Address"]
317 pub tcd9_daddr: TCD9_DADDR,
318 #[doc = "0x1134 - TCD Signed Destination Address Offset"]
319 pub tcd9_doff: TCD9_DOFF,
320 #[doc = "0x1136 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
321 pub tcd9_citer_elinkno: TCD9_CITER_ELINKNO,
322 #[doc = "0x1138 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
323 pub tcd9_dlastsga: TCD9_DLASTSGA,
324 #[doc = "0x113c - TCD Control and Status"]
325 pub tcd9_csr: TCD9_CSR,
326 #[doc = "0x113e - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
327 pub tcd9_biter_elinkno: TCD9_BITER_ELINKNO,
328 #[doc = "0x1140 - TCD Source Address"]
329 pub tcd10_saddr: TCD10_SADDR,
330 #[doc = "0x1144 - TCD Signed Source Address Offset"]
331 pub tcd10_soff: TCD10_SOFF,
332 #[doc = "0x1146 - TCD Transfer Attributes"]
333 pub tcd10_attr: TCD10_ATTR,
334 #[doc = "0x1148 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
335 pub tcd10_nbytes_mlno: TCD10_NBYTES_MLNO,
336 #[doc = "0x114c - TCD Last Source Address Adjustment"]
337 pub tcd10_slast: TCD10_SLAST,
338 #[doc = "0x1150 - TCD Destination Address"]
339 pub tcd10_daddr: TCD10_DADDR,
340 #[doc = "0x1154 - TCD Signed Destination Address Offset"]
341 pub tcd10_doff: TCD10_DOFF,
342 #[doc = "0x1156 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
343 pub tcd10_citer_elinkno: TCD10_CITER_ELINKNO,
344 #[doc = "0x1158 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
345 pub tcd10_dlastsga: TCD10_DLASTSGA,
346 #[doc = "0x115c - TCD Control and Status"]
347 pub tcd10_csr: TCD10_CSR,
348 #[doc = "0x115e - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
349 pub tcd10_biter_elinkno: TCD10_BITER_ELINKNO,
350 #[doc = "0x1160 - TCD Source Address"]
351 pub tcd11_saddr: TCD11_SADDR,
352 #[doc = "0x1164 - TCD Signed Source Address Offset"]
353 pub tcd11_soff: TCD11_SOFF,
354 #[doc = "0x1166 - TCD Transfer Attributes"]
355 pub tcd11_attr: TCD11_ATTR,
356 #[doc = "0x1168 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
357 pub tcd11_nbytes_mlno: TCD11_NBYTES_MLNO,
358 #[doc = "0x116c - TCD Last Source Address Adjustment"]
359 pub tcd11_slast: TCD11_SLAST,
360 #[doc = "0x1170 - TCD Destination Address"]
361 pub tcd11_daddr: TCD11_DADDR,
362 #[doc = "0x1174 - TCD Signed Destination Address Offset"]
363 pub tcd11_doff: TCD11_DOFF,
364 #[doc = "0x1176 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
365 pub tcd11_citer_elinkno: TCD11_CITER_ELINKNO,
366 #[doc = "0x1178 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
367 pub tcd11_dlastsga: TCD11_DLASTSGA,
368 #[doc = "0x117c - TCD Control and Status"]
369 pub tcd11_csr: TCD11_CSR,
370 #[doc = "0x117e - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
371 pub tcd11_biter_elinkno: TCD11_BITER_ELINKNO,
372 #[doc = "0x1180 - TCD Source Address"]
373 pub tcd12_saddr: TCD12_SADDR,
374 #[doc = "0x1184 - TCD Signed Source Address Offset"]
375 pub tcd12_soff: TCD12_SOFF,
376 #[doc = "0x1186 - TCD Transfer Attributes"]
377 pub tcd12_attr: TCD12_ATTR,
378 #[doc = "0x1188 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
379 pub tcd12_nbytes_mlno: TCD12_NBYTES_MLNO,
380 #[doc = "0x118c - TCD Last Source Address Adjustment"]
381 pub tcd12_slast: TCD12_SLAST,
382 #[doc = "0x1190 - TCD Destination Address"]
383 pub tcd12_daddr: TCD12_DADDR,
384 #[doc = "0x1194 - TCD Signed Destination Address Offset"]
385 pub tcd12_doff: TCD12_DOFF,
386 #[doc = "0x1196 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
387 pub tcd12_citer_elinkno: TCD12_CITER_ELINKNO,
388 #[doc = "0x1198 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
389 pub tcd12_dlastsga: TCD12_DLASTSGA,
390 #[doc = "0x119c - TCD Control and Status"]
391 pub tcd12_csr: TCD12_CSR,
392 #[doc = "0x119e - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
393 pub tcd12_biter_elinkno: TCD12_BITER_ELINKNO,
394 #[doc = "0x11a0 - TCD Source Address"]
395 pub tcd13_saddr: TCD13_SADDR,
396 #[doc = "0x11a4 - TCD Signed Source Address Offset"]
397 pub tcd13_soff: TCD13_SOFF,
398 #[doc = "0x11a6 - TCD Transfer Attributes"]
399 pub tcd13_attr: TCD13_ATTR,
400 #[doc = "0x11a8 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
401 pub tcd13_nbytes_mlno: TCD13_NBYTES_MLNO,
402 #[doc = "0x11ac - TCD Last Source Address Adjustment"]
403 pub tcd13_slast: TCD13_SLAST,
404 #[doc = "0x11b0 - TCD Destination Address"]
405 pub tcd13_daddr: TCD13_DADDR,
406 #[doc = "0x11b4 - TCD Signed Destination Address Offset"]
407 pub tcd13_doff: TCD13_DOFF,
408 #[doc = "0x11b6 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
409 pub tcd13_citer_elinkno: TCD13_CITER_ELINKNO,
410 #[doc = "0x11b8 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
411 pub tcd13_dlastsga: TCD13_DLASTSGA,
412 #[doc = "0x11bc - TCD Control and Status"]
413 pub tcd13_csr: TCD13_CSR,
414 #[doc = "0x11be - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
415 pub tcd13_biter_elinkno: TCD13_BITER_ELINKNO,
416 #[doc = "0x11c0 - TCD Source Address"]
417 pub tcd14_saddr: TCD14_SADDR,
418 #[doc = "0x11c4 - TCD Signed Source Address Offset"]
419 pub tcd14_soff: TCD14_SOFF,
420 #[doc = "0x11c6 - TCD Transfer Attributes"]
421 pub tcd14_attr: TCD14_ATTR,
422 #[doc = "0x11c8 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
423 pub tcd14_nbytes_mlno: TCD14_NBYTES_MLNO,
424 #[doc = "0x11cc - TCD Last Source Address Adjustment"]
425 pub tcd14_slast: TCD14_SLAST,
426 #[doc = "0x11d0 - TCD Destination Address"]
427 pub tcd14_daddr: TCD14_DADDR,
428 #[doc = "0x11d4 - TCD Signed Destination Address Offset"]
429 pub tcd14_doff: TCD14_DOFF,
430 #[doc = "0x11d6 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
431 pub tcd14_citer_elinkno: TCD14_CITER_ELINKNO,
432 #[doc = "0x11d8 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
433 pub tcd14_dlastsga: TCD14_DLASTSGA,
434 #[doc = "0x11dc - TCD Control and Status"]
435 pub tcd14_csr: TCD14_CSR,
436 #[doc = "0x11de - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
437 pub tcd14_biter_elinkno: TCD14_BITER_ELINKNO,
438 #[doc = "0x11e0 - TCD Source Address"]
439 pub tcd15_saddr: TCD15_SADDR,
440 #[doc = "0x11e4 - TCD Signed Source Address Offset"]
441 pub tcd15_soff: TCD15_SOFF,
442 #[doc = "0x11e6 - TCD Transfer Attributes"]
443 pub tcd15_attr: TCD15_ATTR,
444 #[doc = "0x11e8 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
445 pub tcd15_nbytes_mlno: TCD15_NBYTES_MLNO,
446 #[doc = "0x11ec - TCD Last Source Address Adjustment"]
447 pub tcd15_slast: TCD15_SLAST,
448 #[doc = "0x11f0 - TCD Destination Address"]
449 pub tcd15_daddr: TCD15_DADDR,
450 #[doc = "0x11f4 - TCD Signed Destination Address Offset"]
451 pub tcd15_doff: TCD15_DOFF,
452 #[doc = "0x11f6 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
453 pub tcd15_citer_elinkno: TCD15_CITER_ELINKNO,
454 #[doc = "0x11f8 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
455 pub tcd15_dlastsga: TCD15_DLASTSGA,
456 #[doc = "0x11fc - TCD Control and Status"]
457 pub tcd15_csr: TCD15_CSR,
458 #[doc = "0x11fe - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
459 pub tcd15_biter_elinkno: TCD15_BITER_ELINKNO,
460 #[doc = "0x1200 - TCD Source Address"]
461 pub tcd16_saddr: TCD16_SADDR,
462 #[doc = "0x1204 - TCD Signed Source Address Offset"]
463 pub tcd16_soff: TCD16_SOFF,
464 #[doc = "0x1206 - TCD Transfer Attributes"]
465 pub tcd16_attr: TCD16_ATTR,
466 #[doc = "0x1208 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
467 pub tcd16_nbytes_mlno: TCD16_NBYTES_MLNO,
468 #[doc = "0x120c - TCD Last Source Address Adjustment"]
469 pub tcd16_slast: TCD16_SLAST,
470 #[doc = "0x1210 - TCD Destination Address"]
471 pub tcd16_daddr: TCD16_DADDR,
472 #[doc = "0x1214 - TCD Signed Destination Address Offset"]
473 pub tcd16_doff: TCD16_DOFF,
474 #[doc = "0x1216 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
475 pub tcd16_citer_elinkno: TCD16_CITER_ELINKNO,
476 #[doc = "0x1218 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
477 pub tcd16_dlastsga: TCD16_DLASTSGA,
478 #[doc = "0x121c - TCD Control and Status"]
479 pub tcd16_csr: TCD16_CSR,
480 #[doc = "0x121e - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
481 pub tcd16_biter_elinkno: TCD16_BITER_ELINKNO,
482 #[doc = "0x1220 - TCD Source Address"]
483 pub tcd17_saddr: TCD17_SADDR,
484 #[doc = "0x1224 - TCD Signed Source Address Offset"]
485 pub tcd17_soff: TCD17_SOFF,
486 #[doc = "0x1226 - TCD Transfer Attributes"]
487 pub tcd17_attr: TCD17_ATTR,
488 #[doc = "0x1228 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
489 pub tcd17_nbytes_mlno: TCD17_NBYTES_MLNO,
490 #[doc = "0x122c - TCD Last Source Address Adjustment"]
491 pub tcd17_slast: TCD17_SLAST,
492 #[doc = "0x1230 - TCD Destination Address"]
493 pub tcd17_daddr: TCD17_DADDR,
494 #[doc = "0x1234 - TCD Signed Destination Address Offset"]
495 pub tcd17_doff: TCD17_DOFF,
496 #[doc = "0x1236 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
497 pub tcd17_citer_elinkno: TCD17_CITER_ELINKNO,
498 #[doc = "0x1238 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
499 pub tcd17_dlastsga: TCD17_DLASTSGA,
500 #[doc = "0x123c - TCD Control and Status"]
501 pub tcd17_csr: TCD17_CSR,
502 #[doc = "0x123e - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
503 pub tcd17_biter_elinkno: TCD17_BITER_ELINKNO,
504 #[doc = "0x1240 - TCD Source Address"]
505 pub tcd18_saddr: TCD18_SADDR,
506 #[doc = "0x1244 - TCD Signed Source Address Offset"]
507 pub tcd18_soff: TCD18_SOFF,
508 #[doc = "0x1246 - TCD Transfer Attributes"]
509 pub tcd18_attr: TCD18_ATTR,
510 #[doc = "0x1248 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
511 pub tcd18_nbytes_mlno: TCD18_NBYTES_MLNO,
512 #[doc = "0x124c - TCD Last Source Address Adjustment"]
513 pub tcd18_slast: TCD18_SLAST,
514 #[doc = "0x1250 - TCD Destination Address"]
515 pub tcd18_daddr: TCD18_DADDR,
516 #[doc = "0x1254 - TCD Signed Destination Address Offset"]
517 pub tcd18_doff: TCD18_DOFF,
518 #[doc = "0x1256 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
519 pub tcd18_citer_elinkno: TCD18_CITER_ELINKNO,
520 #[doc = "0x1258 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
521 pub tcd18_dlastsga: TCD18_DLASTSGA,
522 #[doc = "0x125c - TCD Control and Status"]
523 pub tcd18_csr: TCD18_CSR,
524 #[doc = "0x125e - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
525 pub tcd18_biter_elinkno: TCD18_BITER_ELINKNO,
526 #[doc = "0x1260 - TCD Source Address"]
527 pub tcd19_saddr: TCD19_SADDR,
528 #[doc = "0x1264 - TCD Signed Source Address Offset"]
529 pub tcd19_soff: TCD19_SOFF,
530 #[doc = "0x1266 - TCD Transfer Attributes"]
531 pub tcd19_attr: TCD19_ATTR,
532 #[doc = "0x1268 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
533 pub tcd19_nbytes_mlno: TCD19_NBYTES_MLNO,
534 #[doc = "0x126c - TCD Last Source Address Adjustment"]
535 pub tcd19_slast: TCD19_SLAST,
536 #[doc = "0x1270 - TCD Destination Address"]
537 pub tcd19_daddr: TCD19_DADDR,
538 #[doc = "0x1274 - TCD Signed Destination Address Offset"]
539 pub tcd19_doff: TCD19_DOFF,
540 #[doc = "0x1276 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
541 pub tcd19_citer_elinkno: TCD19_CITER_ELINKNO,
542 #[doc = "0x1278 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
543 pub tcd19_dlastsga: TCD19_DLASTSGA,
544 #[doc = "0x127c - TCD Control and Status"]
545 pub tcd19_csr: TCD19_CSR,
546 #[doc = "0x127e - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
547 pub tcd19_biter_elinkno: TCD19_BITER_ELINKNO,
548 #[doc = "0x1280 - TCD Source Address"]
549 pub tcd20_saddr: TCD20_SADDR,
550 #[doc = "0x1284 - TCD Signed Source Address Offset"]
551 pub tcd20_soff: TCD20_SOFF,
552 #[doc = "0x1286 - TCD Transfer Attributes"]
553 pub tcd20_attr: TCD20_ATTR,
554 #[doc = "0x1288 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
555 pub tcd20_nbytes_mlno: TCD20_NBYTES_MLNO,
556 #[doc = "0x128c - TCD Last Source Address Adjustment"]
557 pub tcd20_slast: TCD20_SLAST,
558 #[doc = "0x1290 - TCD Destination Address"]
559 pub tcd20_daddr: TCD20_DADDR,
560 #[doc = "0x1294 - TCD Signed Destination Address Offset"]
561 pub tcd20_doff: TCD20_DOFF,
562 #[doc = "0x1296 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
563 pub tcd20_citer_elinkno: TCD20_CITER_ELINKNO,
564 #[doc = "0x1298 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
565 pub tcd20_dlastsga: TCD20_DLASTSGA,
566 #[doc = "0x129c - TCD Control and Status"]
567 pub tcd20_csr: TCD20_CSR,
568 #[doc = "0x129e - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
569 pub tcd20_biter_elinkno: TCD20_BITER_ELINKNO,
570 #[doc = "0x12a0 - TCD Source Address"]
571 pub tcd21_saddr: TCD21_SADDR,
572 #[doc = "0x12a4 - TCD Signed Source Address Offset"]
573 pub tcd21_soff: TCD21_SOFF,
574 #[doc = "0x12a6 - TCD Transfer Attributes"]
575 pub tcd21_attr: TCD21_ATTR,
576 #[doc = "0x12a8 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
577 pub tcd21_nbytes_mlno: TCD21_NBYTES_MLNO,
578 #[doc = "0x12ac - TCD Last Source Address Adjustment"]
579 pub tcd21_slast: TCD21_SLAST,
580 #[doc = "0x12b0 - TCD Destination Address"]
581 pub tcd21_daddr: TCD21_DADDR,
582 #[doc = "0x12b4 - TCD Signed Destination Address Offset"]
583 pub tcd21_doff: TCD21_DOFF,
584 #[doc = "0x12b6 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
585 pub tcd21_citer_elinkno: TCD21_CITER_ELINKNO,
586 #[doc = "0x12b8 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
587 pub tcd21_dlastsga: TCD21_DLASTSGA,
588 #[doc = "0x12bc - TCD Control and Status"]
589 pub tcd21_csr: TCD21_CSR,
590 #[doc = "0x12be - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
591 pub tcd21_biter_elinkno: TCD21_BITER_ELINKNO,
592 #[doc = "0x12c0 - TCD Source Address"]
593 pub tcd22_saddr: TCD22_SADDR,
594 #[doc = "0x12c4 - TCD Signed Source Address Offset"]
595 pub tcd22_soff: TCD22_SOFF,
596 #[doc = "0x12c6 - TCD Transfer Attributes"]
597 pub tcd22_attr: TCD22_ATTR,
598 #[doc = "0x12c8 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
599 pub tcd22_nbytes_mlno: TCD22_NBYTES_MLNO,
600 #[doc = "0x12cc - TCD Last Source Address Adjustment"]
601 pub tcd22_slast: TCD22_SLAST,
602 #[doc = "0x12d0 - TCD Destination Address"]
603 pub tcd22_daddr: TCD22_DADDR,
604 #[doc = "0x12d4 - TCD Signed Destination Address Offset"]
605 pub tcd22_doff: TCD22_DOFF,
606 #[doc = "0x12d6 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
607 pub tcd22_citer_elinkno: TCD22_CITER_ELINKNO,
608 #[doc = "0x12d8 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
609 pub tcd22_dlastsga: TCD22_DLASTSGA,
610 #[doc = "0x12dc - TCD Control and Status"]
611 pub tcd22_csr: TCD22_CSR,
612 #[doc = "0x12de - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
613 pub tcd22_biter_elinkno: TCD22_BITER_ELINKNO,
614 #[doc = "0x12e0 - TCD Source Address"]
615 pub tcd23_saddr: TCD23_SADDR,
616 #[doc = "0x12e4 - TCD Signed Source Address Offset"]
617 pub tcd23_soff: TCD23_SOFF,
618 #[doc = "0x12e6 - TCD Transfer Attributes"]
619 pub tcd23_attr: TCD23_ATTR,
620 #[doc = "0x12e8 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
621 pub tcd23_nbytes_mlno: TCD23_NBYTES_MLNO,
622 #[doc = "0x12ec - TCD Last Source Address Adjustment"]
623 pub tcd23_slast: TCD23_SLAST,
624 #[doc = "0x12f0 - TCD Destination Address"]
625 pub tcd23_daddr: TCD23_DADDR,
626 #[doc = "0x12f4 - TCD Signed Destination Address Offset"]
627 pub tcd23_doff: TCD23_DOFF,
628 #[doc = "0x12f6 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
629 pub tcd23_citer_elinkno: TCD23_CITER_ELINKNO,
630 #[doc = "0x12f8 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
631 pub tcd23_dlastsga: TCD23_DLASTSGA,
632 #[doc = "0x12fc - TCD Control and Status"]
633 pub tcd23_csr: TCD23_CSR,
634 #[doc = "0x12fe - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
635 pub tcd23_biter_elinkno: TCD23_BITER_ELINKNO,
636 #[doc = "0x1300 - TCD Source Address"]
637 pub tcd24_saddr: TCD24_SADDR,
638 #[doc = "0x1304 - TCD Signed Source Address Offset"]
639 pub tcd24_soff: TCD24_SOFF,
640 #[doc = "0x1306 - TCD Transfer Attributes"]
641 pub tcd24_attr: TCD24_ATTR,
642 #[doc = "0x1308 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
643 pub tcd24_nbytes_mlno: TCD24_NBYTES_MLNO,
644 #[doc = "0x130c - TCD Last Source Address Adjustment"]
645 pub tcd24_slast: TCD24_SLAST,
646 #[doc = "0x1310 - TCD Destination Address"]
647 pub tcd24_daddr: TCD24_DADDR,
648 #[doc = "0x1314 - TCD Signed Destination Address Offset"]
649 pub tcd24_doff: TCD24_DOFF,
650 #[doc = "0x1316 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
651 pub tcd24_citer_elinkno: TCD24_CITER_ELINKNO,
652 #[doc = "0x1318 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
653 pub tcd24_dlastsga: TCD24_DLASTSGA,
654 #[doc = "0x131c - TCD Control and Status"]
655 pub tcd24_csr: TCD24_CSR,
656 #[doc = "0x131e - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
657 pub tcd24_biter_elinkno: TCD24_BITER_ELINKNO,
658 #[doc = "0x1320 - TCD Source Address"]
659 pub tcd25_saddr: TCD25_SADDR,
660 #[doc = "0x1324 - TCD Signed Source Address Offset"]
661 pub tcd25_soff: TCD25_SOFF,
662 #[doc = "0x1326 - TCD Transfer Attributes"]
663 pub tcd25_attr: TCD25_ATTR,
664 #[doc = "0x1328 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
665 pub tcd25_nbytes_mlno: TCD25_NBYTES_MLNO,
666 #[doc = "0x132c - TCD Last Source Address Adjustment"]
667 pub tcd25_slast: TCD25_SLAST,
668 #[doc = "0x1330 - TCD Destination Address"]
669 pub tcd25_daddr: TCD25_DADDR,
670 #[doc = "0x1334 - TCD Signed Destination Address Offset"]
671 pub tcd25_doff: TCD25_DOFF,
672 #[doc = "0x1336 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
673 pub tcd25_citer_elinkno: TCD25_CITER_ELINKNO,
674 #[doc = "0x1338 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
675 pub tcd25_dlastsga: TCD25_DLASTSGA,
676 #[doc = "0x133c - TCD Control and Status"]
677 pub tcd25_csr: TCD25_CSR,
678 #[doc = "0x133e - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
679 pub tcd25_biter_elinkno: TCD25_BITER_ELINKNO,
680 #[doc = "0x1340 - TCD Source Address"]
681 pub tcd26_saddr: TCD26_SADDR,
682 #[doc = "0x1344 - TCD Signed Source Address Offset"]
683 pub tcd26_soff: TCD26_SOFF,
684 #[doc = "0x1346 - TCD Transfer Attributes"]
685 pub tcd26_attr: TCD26_ATTR,
686 #[doc = "0x1348 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
687 pub tcd26_nbytes_mlno: TCD26_NBYTES_MLNO,
688 #[doc = "0x134c - TCD Last Source Address Adjustment"]
689 pub tcd26_slast: TCD26_SLAST,
690 #[doc = "0x1350 - TCD Destination Address"]
691 pub tcd26_daddr: TCD26_DADDR,
692 #[doc = "0x1354 - TCD Signed Destination Address Offset"]
693 pub tcd26_doff: TCD26_DOFF,
694 #[doc = "0x1356 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
695 pub tcd26_citer_elinkno: TCD26_CITER_ELINKNO,
696 #[doc = "0x1358 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
697 pub tcd26_dlastsga: TCD26_DLASTSGA,
698 #[doc = "0x135c - TCD Control and Status"]
699 pub tcd26_csr: TCD26_CSR,
700 #[doc = "0x135e - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
701 pub tcd26_biter_elinkno: TCD26_BITER_ELINKNO,
702 #[doc = "0x1360 - TCD Source Address"]
703 pub tcd27_saddr: TCD27_SADDR,
704 #[doc = "0x1364 - TCD Signed Source Address Offset"]
705 pub tcd27_soff: TCD27_SOFF,
706 #[doc = "0x1366 - TCD Transfer Attributes"]
707 pub tcd27_attr: TCD27_ATTR,
708 #[doc = "0x1368 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
709 pub tcd27_nbytes_mlno: TCD27_NBYTES_MLNO,
710 #[doc = "0x136c - TCD Last Source Address Adjustment"]
711 pub tcd27_slast: TCD27_SLAST,
712 #[doc = "0x1370 - TCD Destination Address"]
713 pub tcd27_daddr: TCD27_DADDR,
714 #[doc = "0x1374 - TCD Signed Destination Address Offset"]
715 pub tcd27_doff: TCD27_DOFF,
716 #[doc = "0x1376 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
717 pub tcd27_citer_elinkno: TCD27_CITER_ELINKNO,
718 #[doc = "0x1378 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
719 pub tcd27_dlastsga: TCD27_DLASTSGA,
720 #[doc = "0x137c - TCD Control and Status"]
721 pub tcd27_csr: TCD27_CSR,
722 #[doc = "0x137e - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
723 pub tcd27_biter_elinkno: TCD27_BITER_ELINKNO,
724 #[doc = "0x1380 - TCD Source Address"]
725 pub tcd28_saddr: TCD28_SADDR,
726 #[doc = "0x1384 - TCD Signed Source Address Offset"]
727 pub tcd28_soff: TCD28_SOFF,
728 #[doc = "0x1386 - TCD Transfer Attributes"]
729 pub tcd28_attr: TCD28_ATTR,
730 #[doc = "0x1388 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
731 pub tcd28_nbytes_mlno: TCD28_NBYTES_MLNO,
732 #[doc = "0x138c - TCD Last Source Address Adjustment"]
733 pub tcd28_slast: TCD28_SLAST,
734 #[doc = "0x1390 - TCD Destination Address"]
735 pub tcd28_daddr: TCD28_DADDR,
736 #[doc = "0x1394 - TCD Signed Destination Address Offset"]
737 pub tcd28_doff: TCD28_DOFF,
738 #[doc = "0x1396 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
739 pub tcd28_citer_elinkno: TCD28_CITER_ELINKNO,
740 #[doc = "0x1398 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
741 pub tcd28_dlastsga: TCD28_DLASTSGA,
742 #[doc = "0x139c - TCD Control and Status"]
743 pub tcd28_csr: TCD28_CSR,
744 #[doc = "0x139e - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
745 pub tcd28_biter_elinkno: TCD28_BITER_ELINKNO,
746 #[doc = "0x13a0 - TCD Source Address"]
747 pub tcd29_saddr: TCD29_SADDR,
748 #[doc = "0x13a4 - TCD Signed Source Address Offset"]
749 pub tcd29_soff: TCD29_SOFF,
750 #[doc = "0x13a6 - TCD Transfer Attributes"]
751 pub tcd29_attr: TCD29_ATTR,
752 #[doc = "0x13a8 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
753 pub tcd29_nbytes_mlno: TCD29_NBYTES_MLNO,
754 #[doc = "0x13ac - TCD Last Source Address Adjustment"]
755 pub tcd29_slast: TCD29_SLAST,
756 #[doc = "0x13b0 - TCD Destination Address"]
757 pub tcd29_daddr: TCD29_DADDR,
758 #[doc = "0x13b4 - TCD Signed Destination Address Offset"]
759 pub tcd29_doff: TCD29_DOFF,
760 #[doc = "0x13b6 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
761 pub tcd29_citer_elinkno: TCD29_CITER_ELINKNO,
762 #[doc = "0x13b8 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
763 pub tcd29_dlastsga: TCD29_DLASTSGA,
764 #[doc = "0x13bc - TCD Control and Status"]
765 pub tcd29_csr: TCD29_CSR,
766 #[doc = "0x13be - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
767 pub tcd29_biter_elinkno: TCD29_BITER_ELINKNO,
768 #[doc = "0x13c0 - TCD Source Address"]
769 pub tcd30_saddr: TCD30_SADDR,
770 #[doc = "0x13c4 - TCD Signed Source Address Offset"]
771 pub tcd30_soff: TCD30_SOFF,
772 #[doc = "0x13c6 - TCD Transfer Attributes"]
773 pub tcd30_attr: TCD30_ATTR,
774 #[doc = "0x13c8 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
775 pub tcd30_nbytes_mlno: TCD30_NBYTES_MLNO,
776 #[doc = "0x13cc - TCD Last Source Address Adjustment"]
777 pub tcd30_slast: TCD30_SLAST,
778 #[doc = "0x13d0 - TCD Destination Address"]
779 pub tcd30_daddr: TCD30_DADDR,
780 #[doc = "0x13d4 - TCD Signed Destination Address Offset"]
781 pub tcd30_doff: TCD30_DOFF,
782 #[doc = "0x13d6 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
783 pub tcd30_citer_elinkno: TCD30_CITER_ELINKNO,
784 #[doc = "0x13d8 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
785 pub tcd30_dlastsga: TCD30_DLASTSGA,
786 #[doc = "0x13dc - TCD Control and Status"]
787 pub tcd30_csr: TCD30_CSR,
788 #[doc = "0x13de - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
789 pub tcd30_biter_elinkno: TCD30_BITER_ELINKNO,
790 #[doc = "0x13e0 - TCD Source Address"]
791 pub tcd31_saddr: TCD31_SADDR,
792 #[doc = "0x13e4 - TCD Signed Source Address Offset"]
793 pub tcd31_soff: TCD31_SOFF,
794 #[doc = "0x13e6 - TCD Transfer Attributes"]
795 pub tcd31_attr: TCD31_ATTR,
796 #[doc = "0x13e8 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
797 pub tcd31_nbytes_mlno: TCD31_NBYTES_MLNO,
798 #[doc = "0x13ec - TCD Last Source Address Adjustment"]
799 pub tcd31_slast: TCD31_SLAST,
800 #[doc = "0x13f0 - TCD Destination Address"]
801 pub tcd31_daddr: TCD31_DADDR,
802 #[doc = "0x13f4 - TCD Signed Destination Address Offset"]
803 pub tcd31_doff: TCD31_DOFF,
804 #[doc = "0x13f6 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
805 pub tcd31_citer_elinkno: TCD31_CITER_ELINKNO,
806 #[doc = "0x13f8 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
807 pub tcd31_dlastsga: TCD31_DLASTSGA,
808 #[doc = "0x13fc - TCD Control and Status"]
809 pub tcd31_csr: TCD31_CSR,
810 #[doc = "0x13fe - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
811 pub tcd31_biter_elinkno: TCD31_BITER_ELINKNO,
812}
813#[doc = "Control Register"]
814pub struct CR {
815 register: VolatileCell<u32>,
816}
817#[doc = "Control Register"]
818pub mod cr;
819#[doc = "Error Status Register"]
820pub struct ES {
821 register: VolatileCell<u32>,
822}
823#[doc = "Error Status Register"]
824pub mod es;
825#[doc = "Enable Request Register"]
826pub struct ERQ {
827 register: VolatileCell<u32>,
828}
829#[doc = "Enable Request Register"]
830pub mod erq;
831#[doc = "Enable Error Interrupt Register"]
832pub struct EEI {
833 register: VolatileCell<u32>,
834}
835#[doc = "Enable Error Interrupt Register"]
836pub mod eei;
837#[doc = "Clear Enable Error Interrupt Register"]
838pub struct CEEI {
839 register: VolatileCell<u8>,
840}
841#[doc = "Clear Enable Error Interrupt Register"]
842pub mod ceei;
843#[doc = "Set Enable Error Interrupt Register"]
844pub struct SEEI {
845 register: VolatileCell<u8>,
846}
847#[doc = "Set Enable Error Interrupt Register"]
848pub mod seei;
849#[doc = "Clear Enable Request Register"]
850pub struct CERQ {
851 register: VolatileCell<u8>,
852}
853#[doc = "Clear Enable Request Register"]
854pub mod cerq;
855#[doc = "Set Enable Request Register"]
856pub struct SERQ {
857 register: VolatileCell<u8>,
858}
859#[doc = "Set Enable Request Register"]
860pub mod serq;
861#[doc = "Clear DONE Status Bit Register"]
862pub struct CDNE {
863 register: VolatileCell<u8>,
864}
865#[doc = "Clear DONE Status Bit Register"]
866pub mod cdne;
867#[doc = "Set START Bit Register"]
868pub struct SSRT {
869 register: VolatileCell<u8>,
870}
871#[doc = "Set START Bit Register"]
872pub mod ssrt;
873#[doc = "Clear Error Register"]
874pub struct CERR {
875 register: VolatileCell<u8>,
876}
877#[doc = "Clear Error Register"]
878pub mod cerr;
879#[doc = "Clear Interrupt Request Register"]
880pub struct CINT {
881 register: VolatileCell<u8>,
882}
883#[doc = "Clear Interrupt Request Register"]
884pub mod cint;
885#[doc = "Interrupt Request Register"]
886pub struct INT {
887 register: VolatileCell<u32>,
888}
889#[doc = "Interrupt Request Register"]
890pub mod int;
891#[doc = "Error Register"]
892pub struct ERR {
893 register: VolatileCell<u32>,
894}
895#[doc = "Error Register"]
896pub mod err;
897#[doc = "Hardware Request Status Register"]
898pub struct HRS {
899 register: VolatileCell<u32>,
900}
901#[doc = "Hardware Request Status Register"]
902pub mod hrs;
903#[doc = "Enable Asynchronous Request in Stop Register"]
904pub struct EARS {
905 register: VolatileCell<u32>,
906}
907#[doc = "Enable Asynchronous Request in Stop Register"]
908pub mod ears;
909#[doc = "Channel n Priority Register"]
910pub struct DCHPRI3 {
911 register: VolatileCell<u8>,
912}
913#[doc = "Channel n Priority Register"]
914pub mod dchpri3;
915#[doc = "Channel n Priority Register"]
916pub struct DCHPRI2 {
917 register: VolatileCell<u8>,
918}
919#[doc = "Channel n Priority Register"]
920pub mod dchpri2;
921#[doc = "Channel n Priority Register"]
922pub struct DCHPRI1 {
923 register: VolatileCell<u8>,
924}
925#[doc = "Channel n Priority Register"]
926pub mod dchpri1;
927#[doc = "Channel n Priority Register"]
928pub struct DCHPRI0 {
929 register: VolatileCell<u8>,
930}
931#[doc = "Channel n Priority Register"]
932pub mod dchpri0;
933#[doc = "Channel n Priority Register"]
934pub struct DCHPRI7 {
935 register: VolatileCell<u8>,
936}
937#[doc = "Channel n Priority Register"]
938pub mod dchpri7;
939#[doc = "Channel n Priority Register"]
940pub struct DCHPRI6 {
941 register: VolatileCell<u8>,
942}
943#[doc = "Channel n Priority Register"]
944pub mod dchpri6;
945#[doc = "Channel n Priority Register"]
946pub struct DCHPRI5 {
947 register: VolatileCell<u8>,
948}
949#[doc = "Channel n Priority Register"]
950pub mod dchpri5;
951#[doc = "Channel n Priority Register"]
952pub struct DCHPRI4 {
953 register: VolatileCell<u8>,
954}
955#[doc = "Channel n Priority Register"]
956pub mod dchpri4;
957#[doc = "Channel n Priority Register"]
958pub struct DCHPRI11 {
959 register: VolatileCell<u8>,
960}
961#[doc = "Channel n Priority Register"]
962pub mod dchpri11;
963#[doc = "Channel n Priority Register"]
964pub struct DCHPRI10 {
965 register: VolatileCell<u8>,
966}
967#[doc = "Channel n Priority Register"]
968pub mod dchpri10;
969#[doc = "Channel n Priority Register"]
970pub struct DCHPRI9 {
971 register: VolatileCell<u8>,
972}
973#[doc = "Channel n Priority Register"]
974pub mod dchpri9;
975#[doc = "Channel n Priority Register"]
976pub struct DCHPRI8 {
977 register: VolatileCell<u8>,
978}
979#[doc = "Channel n Priority Register"]
980pub mod dchpri8;
981#[doc = "Channel n Priority Register"]
982pub struct DCHPRI15 {
983 register: VolatileCell<u8>,
984}
985#[doc = "Channel n Priority Register"]
986pub mod dchpri15;
987#[doc = "Channel n Priority Register"]
988pub struct DCHPRI14 {
989 register: VolatileCell<u8>,
990}
991#[doc = "Channel n Priority Register"]
992pub mod dchpri14;
993#[doc = "Channel n Priority Register"]
994pub struct DCHPRI13 {
995 register: VolatileCell<u8>,
996}
997#[doc = "Channel n Priority Register"]
998pub mod dchpri13;
999#[doc = "Channel n Priority Register"]
1000pub struct DCHPRI12 {
1001 register: VolatileCell<u8>,
1002}
1003#[doc = "Channel n Priority Register"]
1004pub mod dchpri12;
1005#[doc = "Channel n Priority Register"]
1006pub struct DCHPRI19 {
1007 register: VolatileCell<u8>,
1008}
1009#[doc = "Channel n Priority Register"]
1010pub mod dchpri19;
1011#[doc = "Channel n Priority Register"]
1012pub struct DCHPRI18 {
1013 register: VolatileCell<u8>,
1014}
1015#[doc = "Channel n Priority Register"]
1016pub mod dchpri18;
1017#[doc = "Channel n Priority Register"]
1018pub struct DCHPRI17 {
1019 register: VolatileCell<u8>,
1020}
1021#[doc = "Channel n Priority Register"]
1022pub mod dchpri17;
1023#[doc = "Channel n Priority Register"]
1024pub struct DCHPRI16 {
1025 register: VolatileCell<u8>,
1026}
1027#[doc = "Channel n Priority Register"]
1028pub mod dchpri16;
1029#[doc = "Channel n Priority Register"]
1030pub struct DCHPRI23 {
1031 register: VolatileCell<u8>,
1032}
1033#[doc = "Channel n Priority Register"]
1034pub mod dchpri23;
1035#[doc = "Channel n Priority Register"]
1036pub struct DCHPRI22 {
1037 register: VolatileCell<u8>,
1038}
1039#[doc = "Channel n Priority Register"]
1040pub mod dchpri22;
1041#[doc = "Channel n Priority Register"]
1042pub struct DCHPRI21 {
1043 register: VolatileCell<u8>,
1044}
1045#[doc = "Channel n Priority Register"]
1046pub mod dchpri21;
1047#[doc = "Channel n Priority Register"]
1048pub struct DCHPRI20 {
1049 register: VolatileCell<u8>,
1050}
1051#[doc = "Channel n Priority Register"]
1052pub mod dchpri20;
1053#[doc = "Channel n Priority Register"]
1054pub struct DCHPRI27 {
1055 register: VolatileCell<u8>,
1056}
1057#[doc = "Channel n Priority Register"]
1058pub mod dchpri27;
1059#[doc = "Channel n Priority Register"]
1060pub struct DCHPRI26 {
1061 register: VolatileCell<u8>,
1062}
1063#[doc = "Channel n Priority Register"]
1064pub mod dchpri26;
1065#[doc = "Channel n Priority Register"]
1066pub struct DCHPRI25 {
1067 register: VolatileCell<u8>,
1068}
1069#[doc = "Channel n Priority Register"]
1070pub mod dchpri25;
1071#[doc = "Channel n Priority Register"]
1072pub struct DCHPRI24 {
1073 register: VolatileCell<u8>,
1074}
1075#[doc = "Channel n Priority Register"]
1076pub mod dchpri24;
1077#[doc = "Channel n Priority Register"]
1078pub struct DCHPRI31 {
1079 register: VolatileCell<u8>,
1080}
1081#[doc = "Channel n Priority Register"]
1082pub mod dchpri31;
1083#[doc = "Channel n Priority Register"]
1084pub struct DCHPRI30 {
1085 register: VolatileCell<u8>,
1086}
1087#[doc = "Channel n Priority Register"]
1088pub mod dchpri30;
1089#[doc = "Channel n Priority Register"]
1090pub struct DCHPRI29 {
1091 register: VolatileCell<u8>,
1092}
1093#[doc = "Channel n Priority Register"]
1094pub mod dchpri29;
1095#[doc = "Channel n Priority Register"]
1096pub struct DCHPRI28 {
1097 register: VolatileCell<u8>,
1098}
1099#[doc = "Channel n Priority Register"]
1100pub mod dchpri28;
1101#[doc = "TCD Source Address"]
1102pub struct TCD0_SADDR {
1103 register: VolatileCell<u32>,
1104}
1105#[doc = "TCD Source Address"]
1106pub mod tcd0_saddr;
1107#[doc = "TCD Signed Source Address Offset"]
1108pub struct TCD0_SOFF {
1109 register: VolatileCell<u16>,
1110}
1111#[doc = "TCD Signed Source Address Offset"]
1112pub mod tcd0_soff;
1113#[doc = "TCD Transfer Attributes"]
1114pub struct TCD0_ATTR {
1115 register: VolatileCell<u16>,
1116}
1117#[doc = "TCD Transfer Attributes"]
1118pub mod tcd0_attr;
1119#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
1120pub struct TCD0_NBYTES_MLNO {
1121 register: VolatileCell<u32>,
1122}
1123#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
1124pub mod tcd0_nbytes_mlno;
1125#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
1126pub struct TCD0_NBYTES_MLOFFNO {
1127 register: VolatileCell<u32>,
1128}
1129#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
1130pub mod tcd0_nbytes_mloffno;
1131#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
1132pub struct TCD0_NBYTES_MLOFFYES {
1133 register: VolatileCell<u32>,
1134}
1135#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
1136pub mod tcd0_nbytes_mloffyes;
1137#[doc = "TCD Last Source Address Adjustment"]
1138pub struct TCD0_SLAST {
1139 register: VolatileCell<u32>,
1140}
1141#[doc = "TCD Last Source Address Adjustment"]
1142pub mod tcd0_slast;
1143#[doc = "TCD Destination Address"]
1144pub struct TCD0_DADDR {
1145 register: VolatileCell<u32>,
1146}
1147#[doc = "TCD Destination Address"]
1148pub mod tcd0_daddr;
1149#[doc = "TCD Signed Destination Address Offset"]
1150pub struct TCD0_DOFF {
1151 register: VolatileCell<u16>,
1152}
1153#[doc = "TCD Signed Destination Address Offset"]
1154pub mod tcd0_doff;
1155#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
1156pub struct TCD0_CITER_ELINKNO {
1157 register: VolatileCell<u16>,
1158}
1159#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
1160pub mod tcd0_citer_elinkno;
1161#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
1162pub struct TCD0_CITER_ELINKYES {
1163 register: VolatileCell<u16>,
1164}
1165#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
1166pub mod tcd0_citer_elinkyes;
1167#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
1168pub struct TCD0_DLASTSGA {
1169 register: VolatileCell<u32>,
1170}
1171#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
1172pub mod tcd0_dlastsga;
1173#[doc = "TCD Control and Status"]
1174pub struct TCD0_CSR {
1175 register: VolatileCell<u16>,
1176}
1177#[doc = "TCD Control and Status"]
1178pub mod tcd0_csr;
1179#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
1180pub struct TCD0_BITER_ELINKNO {
1181 register: VolatileCell<u16>,
1182}
1183#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
1184pub mod tcd0_biter_elinkno;
1185#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
1186pub struct TCD0_BITER_ELINKYES {
1187 register: VolatileCell<u16>,
1188}
1189#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
1190pub mod tcd0_biter_elinkyes;
1191#[doc = "TCD Source Address"]
1192pub struct TCD1_SADDR {
1193 register: VolatileCell<u32>,
1194}
1195#[doc = "TCD Source Address"]
1196pub mod tcd1_saddr;
1197#[doc = "TCD Signed Source Address Offset"]
1198pub struct TCD1_SOFF {
1199 register: VolatileCell<u16>,
1200}
1201#[doc = "TCD Signed Source Address Offset"]
1202pub mod tcd1_soff;
1203#[doc = "TCD Transfer Attributes"]
1204pub struct TCD1_ATTR {
1205 register: VolatileCell<u16>,
1206}
1207#[doc = "TCD Transfer Attributes"]
1208pub mod tcd1_attr;
1209#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
1210pub struct TCD1_NBYTES_MLNO {
1211 register: VolatileCell<u32>,
1212}
1213#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
1214pub mod tcd1_nbytes_mlno;
1215#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
1216pub struct TCD1_NBYTES_MLOFFNO {
1217 register: VolatileCell<u32>,
1218}
1219#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
1220pub mod tcd1_nbytes_mloffno;
1221#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
1222pub struct TCD1_NBYTES_MLOFFYES {
1223 register: VolatileCell<u32>,
1224}
1225#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
1226pub mod tcd1_nbytes_mloffyes;
1227#[doc = "TCD Last Source Address Adjustment"]
1228pub struct TCD1_SLAST {
1229 register: VolatileCell<u32>,
1230}
1231#[doc = "TCD Last Source Address Adjustment"]
1232pub mod tcd1_slast;
1233#[doc = "TCD Destination Address"]
1234pub struct TCD1_DADDR {
1235 register: VolatileCell<u32>,
1236}
1237#[doc = "TCD Destination Address"]
1238pub mod tcd1_daddr;
1239#[doc = "TCD Signed Destination Address Offset"]
1240pub struct TCD1_DOFF {
1241 register: VolatileCell<u16>,
1242}
1243#[doc = "TCD Signed Destination Address Offset"]
1244pub mod tcd1_doff;
1245#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
1246pub struct TCD1_CITER_ELINKNO {
1247 register: VolatileCell<u16>,
1248}
1249#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
1250pub mod tcd1_citer_elinkno;
1251#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
1252pub struct TCD1_CITER_ELINKYES {
1253 register: VolatileCell<u16>,
1254}
1255#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
1256pub mod tcd1_citer_elinkyes;
1257#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
1258pub struct TCD1_DLASTSGA {
1259 register: VolatileCell<u32>,
1260}
1261#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
1262pub mod tcd1_dlastsga;
1263#[doc = "TCD Control and Status"]
1264pub struct TCD1_CSR {
1265 register: VolatileCell<u16>,
1266}
1267#[doc = "TCD Control and Status"]
1268pub mod tcd1_csr;
1269#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
1270pub struct TCD1_BITER_ELINKNO {
1271 register: VolatileCell<u16>,
1272}
1273#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
1274pub mod tcd1_biter_elinkno;
1275#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
1276pub struct TCD1_BITER_ELINKYES {
1277 register: VolatileCell<u16>,
1278}
1279#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
1280pub mod tcd1_biter_elinkyes;
1281#[doc = "TCD Source Address"]
1282pub struct TCD2_SADDR {
1283 register: VolatileCell<u32>,
1284}
1285#[doc = "TCD Source Address"]
1286pub mod tcd2_saddr;
1287#[doc = "TCD Signed Source Address Offset"]
1288pub struct TCD2_SOFF {
1289 register: VolatileCell<u16>,
1290}
1291#[doc = "TCD Signed Source Address Offset"]
1292pub mod tcd2_soff;
1293#[doc = "TCD Transfer Attributes"]
1294pub struct TCD2_ATTR {
1295 register: VolatileCell<u16>,
1296}
1297#[doc = "TCD Transfer Attributes"]
1298pub mod tcd2_attr;
1299#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
1300pub struct TCD2_NBYTES_MLNO {
1301 register: VolatileCell<u32>,
1302}
1303#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
1304pub mod tcd2_nbytes_mlno;
1305#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
1306pub struct TCD2_NBYTES_MLOFFNO {
1307 register: VolatileCell<u32>,
1308}
1309#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
1310pub mod tcd2_nbytes_mloffno;
1311#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
1312pub struct TCD2_NBYTES_MLOFFYES {
1313 register: VolatileCell<u32>,
1314}
1315#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
1316pub mod tcd2_nbytes_mloffyes;
1317#[doc = "TCD Last Source Address Adjustment"]
1318pub struct TCD2_SLAST {
1319 register: VolatileCell<u32>,
1320}
1321#[doc = "TCD Last Source Address Adjustment"]
1322pub mod tcd2_slast;
1323#[doc = "TCD Destination Address"]
1324pub struct TCD2_DADDR {
1325 register: VolatileCell<u32>,
1326}
1327#[doc = "TCD Destination Address"]
1328pub mod tcd2_daddr;
1329#[doc = "TCD Signed Destination Address Offset"]
1330pub struct TCD2_DOFF {
1331 register: VolatileCell<u16>,
1332}
1333#[doc = "TCD Signed Destination Address Offset"]
1334pub mod tcd2_doff;
1335#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
1336pub struct TCD2_CITER_ELINKNO {
1337 register: VolatileCell<u16>,
1338}
1339#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
1340pub mod tcd2_citer_elinkno;
1341#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
1342pub struct TCD2_CITER_ELINKYES {
1343 register: VolatileCell<u16>,
1344}
1345#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
1346pub mod tcd2_citer_elinkyes;
1347#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
1348pub struct TCD2_DLASTSGA {
1349 register: VolatileCell<u32>,
1350}
1351#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
1352pub mod tcd2_dlastsga;
1353#[doc = "TCD Control and Status"]
1354pub struct TCD2_CSR {
1355 register: VolatileCell<u16>,
1356}
1357#[doc = "TCD Control and Status"]
1358pub mod tcd2_csr;
1359#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
1360pub struct TCD2_BITER_ELINKNO {
1361 register: VolatileCell<u16>,
1362}
1363#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
1364pub mod tcd2_biter_elinkno;
1365#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
1366pub struct TCD2_BITER_ELINKYES {
1367 register: VolatileCell<u16>,
1368}
1369#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
1370pub mod tcd2_biter_elinkyes;
1371#[doc = "TCD Source Address"]
1372pub struct TCD3_SADDR {
1373 register: VolatileCell<u32>,
1374}
1375#[doc = "TCD Source Address"]
1376pub mod tcd3_saddr;
1377#[doc = "TCD Signed Source Address Offset"]
1378pub struct TCD3_SOFF {
1379 register: VolatileCell<u16>,
1380}
1381#[doc = "TCD Signed Source Address Offset"]
1382pub mod tcd3_soff;
1383#[doc = "TCD Transfer Attributes"]
1384pub struct TCD3_ATTR {
1385 register: VolatileCell<u16>,
1386}
1387#[doc = "TCD Transfer Attributes"]
1388pub mod tcd3_attr;
1389#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
1390pub struct TCD3_NBYTES_MLNO {
1391 register: VolatileCell<u32>,
1392}
1393#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
1394pub mod tcd3_nbytes_mlno;
1395#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
1396pub struct TCD3_NBYTES_MLOFFNO {
1397 register: VolatileCell<u32>,
1398}
1399#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
1400pub mod tcd3_nbytes_mloffno;
1401#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
1402pub struct TCD3_NBYTES_MLOFFYES {
1403 register: VolatileCell<u32>,
1404}
1405#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
1406pub mod tcd3_nbytes_mloffyes;
1407#[doc = "TCD Last Source Address Adjustment"]
1408pub struct TCD3_SLAST {
1409 register: VolatileCell<u32>,
1410}
1411#[doc = "TCD Last Source Address Adjustment"]
1412pub mod tcd3_slast;
1413#[doc = "TCD Destination Address"]
1414pub struct TCD3_DADDR {
1415 register: VolatileCell<u32>,
1416}
1417#[doc = "TCD Destination Address"]
1418pub mod tcd3_daddr;
1419#[doc = "TCD Signed Destination Address Offset"]
1420pub struct TCD3_DOFF {
1421 register: VolatileCell<u16>,
1422}
1423#[doc = "TCD Signed Destination Address Offset"]
1424pub mod tcd3_doff;
1425#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
1426pub struct TCD3_CITER_ELINKNO {
1427 register: VolatileCell<u16>,
1428}
1429#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
1430pub mod tcd3_citer_elinkno;
1431#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
1432pub struct TCD3_CITER_ELINKYES {
1433 register: VolatileCell<u16>,
1434}
1435#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
1436pub mod tcd3_citer_elinkyes;
1437#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
1438pub struct TCD3_DLASTSGA {
1439 register: VolatileCell<u32>,
1440}
1441#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
1442pub mod tcd3_dlastsga;
1443#[doc = "TCD Control and Status"]
1444pub struct TCD3_CSR {
1445 register: VolatileCell<u16>,
1446}
1447#[doc = "TCD Control and Status"]
1448pub mod tcd3_csr;
1449#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
1450pub struct TCD3_BITER_ELINKNO {
1451 register: VolatileCell<u16>,
1452}
1453#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
1454pub mod tcd3_biter_elinkno;
1455#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
1456pub struct TCD3_BITER_ELINKYES {
1457 register: VolatileCell<u16>,
1458}
1459#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
1460pub mod tcd3_biter_elinkyes;
1461#[doc = "TCD Source Address"]
1462pub struct TCD4_SADDR {
1463 register: VolatileCell<u32>,
1464}
1465#[doc = "TCD Source Address"]
1466pub mod tcd4_saddr;
1467#[doc = "TCD Signed Source Address Offset"]
1468pub struct TCD4_SOFF {
1469 register: VolatileCell<u16>,
1470}
1471#[doc = "TCD Signed Source Address Offset"]
1472pub mod tcd4_soff;
1473#[doc = "TCD Transfer Attributes"]
1474pub struct TCD4_ATTR {
1475 register: VolatileCell<u16>,
1476}
1477#[doc = "TCD Transfer Attributes"]
1478pub mod tcd4_attr;
1479#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
1480pub struct TCD4_NBYTES_MLNO {
1481 register: VolatileCell<u32>,
1482}
1483#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
1484pub mod tcd4_nbytes_mlno;
1485#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
1486pub struct TCD4_NBYTES_MLOFFNO {
1487 register: VolatileCell<u32>,
1488}
1489#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
1490pub mod tcd4_nbytes_mloffno;
1491#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
1492pub struct TCD4_NBYTES_MLOFFYES {
1493 register: VolatileCell<u32>,
1494}
1495#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
1496pub mod tcd4_nbytes_mloffyes;
1497#[doc = "TCD Last Source Address Adjustment"]
1498pub struct TCD4_SLAST {
1499 register: VolatileCell<u32>,
1500}
1501#[doc = "TCD Last Source Address Adjustment"]
1502pub mod tcd4_slast;
1503#[doc = "TCD Destination Address"]
1504pub struct TCD4_DADDR {
1505 register: VolatileCell<u32>,
1506}
1507#[doc = "TCD Destination Address"]
1508pub mod tcd4_daddr;
1509#[doc = "TCD Signed Destination Address Offset"]
1510pub struct TCD4_DOFF {
1511 register: VolatileCell<u16>,
1512}
1513#[doc = "TCD Signed Destination Address Offset"]
1514pub mod tcd4_doff;
1515#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
1516pub struct TCD4_CITER_ELINKNO {
1517 register: VolatileCell<u16>,
1518}
1519#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
1520pub mod tcd4_citer_elinkno;
1521#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
1522pub struct TCD4_CITER_ELINKYES {
1523 register: VolatileCell<u16>,
1524}
1525#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
1526pub mod tcd4_citer_elinkyes;
1527#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
1528pub struct TCD4_DLASTSGA {
1529 register: VolatileCell<u32>,
1530}
1531#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
1532pub mod tcd4_dlastsga;
1533#[doc = "TCD Control and Status"]
1534pub struct TCD4_CSR {
1535 register: VolatileCell<u16>,
1536}
1537#[doc = "TCD Control and Status"]
1538pub mod tcd4_csr;
1539#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
1540pub struct TCD4_BITER_ELINKNO {
1541 register: VolatileCell<u16>,
1542}
1543#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
1544pub mod tcd4_biter_elinkno;
1545#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
1546pub struct TCD4_BITER_ELINKYES {
1547 register: VolatileCell<u16>,
1548}
1549#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
1550pub mod tcd4_biter_elinkyes;
1551#[doc = "TCD Source Address"]
1552pub struct TCD5_SADDR {
1553 register: VolatileCell<u32>,
1554}
1555#[doc = "TCD Source Address"]
1556pub mod tcd5_saddr;
1557#[doc = "TCD Signed Source Address Offset"]
1558pub struct TCD5_SOFF {
1559 register: VolatileCell<u16>,
1560}
1561#[doc = "TCD Signed Source Address Offset"]
1562pub mod tcd5_soff;
1563#[doc = "TCD Transfer Attributes"]
1564pub struct TCD5_ATTR {
1565 register: VolatileCell<u16>,
1566}
1567#[doc = "TCD Transfer Attributes"]
1568pub mod tcd5_attr;
1569#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
1570pub struct TCD5_NBYTES_MLNO {
1571 register: VolatileCell<u32>,
1572}
1573#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
1574pub mod tcd5_nbytes_mlno;
1575#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
1576pub struct TCD5_NBYTES_MLOFFNO {
1577 register: VolatileCell<u32>,
1578}
1579#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
1580pub mod tcd5_nbytes_mloffno;
1581#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
1582pub struct TCD5_NBYTES_MLOFFYES {
1583 register: VolatileCell<u32>,
1584}
1585#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
1586pub mod tcd5_nbytes_mloffyes;
1587#[doc = "TCD Last Source Address Adjustment"]
1588pub struct TCD5_SLAST {
1589 register: VolatileCell<u32>,
1590}
1591#[doc = "TCD Last Source Address Adjustment"]
1592pub mod tcd5_slast;
1593#[doc = "TCD Destination Address"]
1594pub struct TCD5_DADDR {
1595 register: VolatileCell<u32>,
1596}
1597#[doc = "TCD Destination Address"]
1598pub mod tcd5_daddr;
1599#[doc = "TCD Signed Destination Address Offset"]
1600pub struct TCD5_DOFF {
1601 register: VolatileCell<u16>,
1602}
1603#[doc = "TCD Signed Destination Address Offset"]
1604pub mod tcd5_doff;
1605#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
1606pub struct TCD5_CITER_ELINKNO {
1607 register: VolatileCell<u16>,
1608}
1609#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
1610pub mod tcd5_citer_elinkno;
1611#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
1612pub struct TCD5_CITER_ELINKYES {
1613 register: VolatileCell<u16>,
1614}
1615#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
1616pub mod tcd5_citer_elinkyes;
1617#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
1618pub struct TCD5_DLASTSGA {
1619 register: VolatileCell<u32>,
1620}
1621#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
1622pub mod tcd5_dlastsga;
1623#[doc = "TCD Control and Status"]
1624pub struct TCD5_CSR {
1625 register: VolatileCell<u16>,
1626}
1627#[doc = "TCD Control and Status"]
1628pub mod tcd5_csr;
1629#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
1630pub struct TCD5_BITER_ELINKNO {
1631 register: VolatileCell<u16>,
1632}
1633#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
1634pub mod tcd5_biter_elinkno;
1635#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
1636pub struct TCD5_BITER_ELINKYES {
1637 register: VolatileCell<u16>,
1638}
1639#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
1640pub mod tcd5_biter_elinkyes;
1641#[doc = "TCD Source Address"]
1642pub struct TCD6_SADDR {
1643 register: VolatileCell<u32>,
1644}
1645#[doc = "TCD Source Address"]
1646pub mod tcd6_saddr;
1647#[doc = "TCD Signed Source Address Offset"]
1648pub struct TCD6_SOFF {
1649 register: VolatileCell<u16>,
1650}
1651#[doc = "TCD Signed Source Address Offset"]
1652pub mod tcd6_soff;
1653#[doc = "TCD Transfer Attributes"]
1654pub struct TCD6_ATTR {
1655 register: VolatileCell<u16>,
1656}
1657#[doc = "TCD Transfer Attributes"]
1658pub mod tcd6_attr;
1659#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
1660pub struct TCD6_NBYTES_MLNO {
1661 register: VolatileCell<u32>,
1662}
1663#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
1664pub mod tcd6_nbytes_mlno;
1665#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
1666pub struct TCD6_NBYTES_MLOFFNO {
1667 register: VolatileCell<u32>,
1668}
1669#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
1670pub mod tcd6_nbytes_mloffno;
1671#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
1672pub struct TCD6_NBYTES_MLOFFYES {
1673 register: VolatileCell<u32>,
1674}
1675#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
1676pub mod tcd6_nbytes_mloffyes;
1677#[doc = "TCD Last Source Address Adjustment"]
1678pub struct TCD6_SLAST {
1679 register: VolatileCell<u32>,
1680}
1681#[doc = "TCD Last Source Address Adjustment"]
1682pub mod tcd6_slast;
1683#[doc = "TCD Destination Address"]
1684pub struct TCD6_DADDR {
1685 register: VolatileCell<u32>,
1686}
1687#[doc = "TCD Destination Address"]
1688pub mod tcd6_daddr;
1689#[doc = "TCD Signed Destination Address Offset"]
1690pub struct TCD6_DOFF {
1691 register: VolatileCell<u16>,
1692}
1693#[doc = "TCD Signed Destination Address Offset"]
1694pub mod tcd6_doff;
1695#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
1696pub struct TCD6_CITER_ELINKNO {
1697 register: VolatileCell<u16>,
1698}
1699#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
1700pub mod tcd6_citer_elinkno;
1701#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
1702pub struct TCD6_CITER_ELINKYES {
1703 register: VolatileCell<u16>,
1704}
1705#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
1706pub mod tcd6_citer_elinkyes;
1707#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
1708pub struct TCD6_DLASTSGA {
1709 register: VolatileCell<u32>,
1710}
1711#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
1712pub mod tcd6_dlastsga;
1713#[doc = "TCD Control and Status"]
1714pub struct TCD6_CSR {
1715 register: VolatileCell<u16>,
1716}
1717#[doc = "TCD Control and Status"]
1718pub mod tcd6_csr;
1719#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
1720pub struct TCD6_BITER_ELINKNO {
1721 register: VolatileCell<u16>,
1722}
1723#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
1724pub mod tcd6_biter_elinkno;
1725#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
1726pub struct TCD6_BITER_ELINKYES {
1727 register: VolatileCell<u16>,
1728}
1729#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
1730pub mod tcd6_biter_elinkyes;
1731#[doc = "TCD Source Address"]
1732pub struct TCD7_SADDR {
1733 register: VolatileCell<u32>,
1734}
1735#[doc = "TCD Source Address"]
1736pub mod tcd7_saddr;
1737#[doc = "TCD Signed Source Address Offset"]
1738pub struct TCD7_SOFF {
1739 register: VolatileCell<u16>,
1740}
1741#[doc = "TCD Signed Source Address Offset"]
1742pub mod tcd7_soff;
1743#[doc = "TCD Transfer Attributes"]
1744pub struct TCD7_ATTR {
1745 register: VolatileCell<u16>,
1746}
1747#[doc = "TCD Transfer Attributes"]
1748pub mod tcd7_attr;
1749#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
1750pub struct TCD7_NBYTES_MLNO {
1751 register: VolatileCell<u32>,
1752}
1753#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
1754pub mod tcd7_nbytes_mlno;
1755#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
1756pub struct TCD7_NBYTES_MLOFFNO {
1757 register: VolatileCell<u32>,
1758}
1759#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
1760pub mod tcd7_nbytes_mloffno;
1761#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
1762pub struct TCD7_NBYTES_MLOFFYES {
1763 register: VolatileCell<u32>,
1764}
1765#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
1766pub mod tcd7_nbytes_mloffyes;
1767#[doc = "TCD Last Source Address Adjustment"]
1768pub struct TCD7_SLAST {
1769 register: VolatileCell<u32>,
1770}
1771#[doc = "TCD Last Source Address Adjustment"]
1772pub mod tcd7_slast;
1773#[doc = "TCD Destination Address"]
1774pub struct TCD7_DADDR {
1775 register: VolatileCell<u32>,
1776}
1777#[doc = "TCD Destination Address"]
1778pub mod tcd7_daddr;
1779#[doc = "TCD Signed Destination Address Offset"]
1780pub struct TCD7_DOFF {
1781 register: VolatileCell<u16>,
1782}
1783#[doc = "TCD Signed Destination Address Offset"]
1784pub mod tcd7_doff;
1785#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
1786pub struct TCD7_CITER_ELINKNO {
1787 register: VolatileCell<u16>,
1788}
1789#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
1790pub mod tcd7_citer_elinkno;
1791#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
1792pub struct TCD7_CITER_ELINKYES {
1793 register: VolatileCell<u16>,
1794}
1795#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
1796pub mod tcd7_citer_elinkyes;
1797#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
1798pub struct TCD7_DLASTSGA {
1799 register: VolatileCell<u32>,
1800}
1801#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
1802pub mod tcd7_dlastsga;
1803#[doc = "TCD Control and Status"]
1804pub struct TCD7_CSR {
1805 register: VolatileCell<u16>,
1806}
1807#[doc = "TCD Control and Status"]
1808pub mod tcd7_csr;
1809#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
1810pub struct TCD7_BITER_ELINKNO {
1811 register: VolatileCell<u16>,
1812}
1813#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
1814pub mod tcd7_biter_elinkno;
1815#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
1816pub struct TCD7_BITER_ELINKYES {
1817 register: VolatileCell<u16>,
1818}
1819#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
1820pub mod tcd7_biter_elinkyes;
1821#[doc = "TCD Source Address"]
1822pub struct TCD8_SADDR {
1823 register: VolatileCell<u32>,
1824}
1825#[doc = "TCD Source Address"]
1826pub mod tcd8_saddr;
1827#[doc = "TCD Signed Source Address Offset"]
1828pub struct TCD8_SOFF {
1829 register: VolatileCell<u16>,
1830}
1831#[doc = "TCD Signed Source Address Offset"]
1832pub mod tcd8_soff;
1833#[doc = "TCD Transfer Attributes"]
1834pub struct TCD8_ATTR {
1835 register: VolatileCell<u16>,
1836}
1837#[doc = "TCD Transfer Attributes"]
1838pub mod tcd8_attr;
1839#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
1840pub struct TCD8_NBYTES_MLNO {
1841 register: VolatileCell<u32>,
1842}
1843#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
1844pub mod tcd8_nbytes_mlno;
1845#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
1846pub struct TCD8_NBYTES_MLOFFNO {
1847 register: VolatileCell<u32>,
1848}
1849#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
1850pub mod tcd8_nbytes_mloffno;
1851#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
1852pub struct TCD8_NBYTES_MLOFFYES {
1853 register: VolatileCell<u32>,
1854}
1855#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
1856pub mod tcd8_nbytes_mloffyes;
1857#[doc = "TCD Last Source Address Adjustment"]
1858pub struct TCD8_SLAST {
1859 register: VolatileCell<u32>,
1860}
1861#[doc = "TCD Last Source Address Adjustment"]
1862pub mod tcd8_slast;
1863#[doc = "TCD Destination Address"]
1864pub struct TCD8_DADDR {
1865 register: VolatileCell<u32>,
1866}
1867#[doc = "TCD Destination Address"]
1868pub mod tcd8_daddr;
1869#[doc = "TCD Signed Destination Address Offset"]
1870pub struct TCD8_DOFF {
1871 register: VolatileCell<u16>,
1872}
1873#[doc = "TCD Signed Destination Address Offset"]
1874pub mod tcd8_doff;
1875#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
1876pub struct TCD8_CITER_ELINKNO {
1877 register: VolatileCell<u16>,
1878}
1879#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
1880pub mod tcd8_citer_elinkno;
1881#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
1882pub struct TCD8_CITER_ELINKYES {
1883 register: VolatileCell<u16>,
1884}
1885#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
1886pub mod tcd8_citer_elinkyes;
1887#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
1888pub struct TCD8_DLASTSGA {
1889 register: VolatileCell<u32>,
1890}
1891#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
1892pub mod tcd8_dlastsga;
1893#[doc = "TCD Control and Status"]
1894pub struct TCD8_CSR {
1895 register: VolatileCell<u16>,
1896}
1897#[doc = "TCD Control and Status"]
1898pub mod tcd8_csr;
1899#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
1900pub struct TCD8_BITER_ELINKNO {
1901 register: VolatileCell<u16>,
1902}
1903#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
1904pub mod tcd8_biter_elinkno;
1905#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
1906pub struct TCD8_BITER_ELINKYES {
1907 register: VolatileCell<u16>,
1908}
1909#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
1910pub mod tcd8_biter_elinkyes;
1911#[doc = "TCD Source Address"]
1912pub struct TCD9_SADDR {
1913 register: VolatileCell<u32>,
1914}
1915#[doc = "TCD Source Address"]
1916pub mod tcd9_saddr;
1917#[doc = "TCD Signed Source Address Offset"]
1918pub struct TCD9_SOFF {
1919 register: VolatileCell<u16>,
1920}
1921#[doc = "TCD Signed Source Address Offset"]
1922pub mod tcd9_soff;
1923#[doc = "TCD Transfer Attributes"]
1924pub struct TCD9_ATTR {
1925 register: VolatileCell<u16>,
1926}
1927#[doc = "TCD Transfer Attributes"]
1928pub mod tcd9_attr;
1929#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
1930pub struct TCD9_NBYTES_MLNO {
1931 register: VolatileCell<u32>,
1932}
1933#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
1934pub mod tcd9_nbytes_mlno;
1935#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
1936pub struct TCD9_NBYTES_MLOFFNO {
1937 register: VolatileCell<u32>,
1938}
1939#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
1940pub mod tcd9_nbytes_mloffno;
1941#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
1942pub struct TCD9_NBYTES_MLOFFYES {
1943 register: VolatileCell<u32>,
1944}
1945#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
1946pub mod tcd9_nbytes_mloffyes;
1947#[doc = "TCD Last Source Address Adjustment"]
1948pub struct TCD9_SLAST {
1949 register: VolatileCell<u32>,
1950}
1951#[doc = "TCD Last Source Address Adjustment"]
1952pub mod tcd9_slast;
1953#[doc = "TCD Destination Address"]
1954pub struct TCD9_DADDR {
1955 register: VolatileCell<u32>,
1956}
1957#[doc = "TCD Destination Address"]
1958pub mod tcd9_daddr;
1959#[doc = "TCD Signed Destination Address Offset"]
1960pub struct TCD9_DOFF {
1961 register: VolatileCell<u16>,
1962}
1963#[doc = "TCD Signed Destination Address Offset"]
1964pub mod tcd9_doff;
1965#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
1966pub struct TCD9_CITER_ELINKNO {
1967 register: VolatileCell<u16>,
1968}
1969#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
1970pub mod tcd9_citer_elinkno;
1971#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
1972pub struct TCD9_CITER_ELINKYES {
1973 register: VolatileCell<u16>,
1974}
1975#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
1976pub mod tcd9_citer_elinkyes;
1977#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
1978pub struct TCD9_DLASTSGA {
1979 register: VolatileCell<u32>,
1980}
1981#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
1982pub mod tcd9_dlastsga;
1983#[doc = "TCD Control and Status"]
1984pub struct TCD9_CSR {
1985 register: VolatileCell<u16>,
1986}
1987#[doc = "TCD Control and Status"]
1988pub mod tcd9_csr;
1989#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
1990pub struct TCD9_BITER_ELINKNO {
1991 register: VolatileCell<u16>,
1992}
1993#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
1994pub mod tcd9_biter_elinkno;
1995#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
1996pub struct TCD9_BITER_ELINKYES {
1997 register: VolatileCell<u16>,
1998}
1999#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
2000pub mod tcd9_biter_elinkyes;
2001#[doc = "TCD Source Address"]
2002pub struct TCD10_SADDR {
2003 register: VolatileCell<u32>,
2004}
2005#[doc = "TCD Source Address"]
2006pub mod tcd10_saddr;
2007#[doc = "TCD Signed Source Address Offset"]
2008pub struct TCD10_SOFF {
2009 register: VolatileCell<u16>,
2010}
2011#[doc = "TCD Signed Source Address Offset"]
2012pub mod tcd10_soff;
2013#[doc = "TCD Transfer Attributes"]
2014pub struct TCD10_ATTR {
2015 register: VolatileCell<u16>,
2016}
2017#[doc = "TCD Transfer Attributes"]
2018pub mod tcd10_attr;
2019#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
2020pub struct TCD10_NBYTES_MLNO {
2021 register: VolatileCell<u32>,
2022}
2023#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
2024pub mod tcd10_nbytes_mlno;
2025#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
2026pub struct TCD10_NBYTES_MLOFFNO {
2027 register: VolatileCell<u32>,
2028}
2029#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
2030pub mod tcd10_nbytes_mloffno;
2031#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
2032pub struct TCD10_NBYTES_MLOFFYES {
2033 register: VolatileCell<u32>,
2034}
2035#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
2036pub mod tcd10_nbytes_mloffyes;
2037#[doc = "TCD Last Source Address Adjustment"]
2038pub struct TCD10_SLAST {
2039 register: VolatileCell<u32>,
2040}
2041#[doc = "TCD Last Source Address Adjustment"]
2042pub mod tcd10_slast;
2043#[doc = "TCD Destination Address"]
2044pub struct TCD10_DADDR {
2045 register: VolatileCell<u32>,
2046}
2047#[doc = "TCD Destination Address"]
2048pub mod tcd10_daddr;
2049#[doc = "TCD Signed Destination Address Offset"]
2050pub struct TCD10_DOFF {
2051 register: VolatileCell<u16>,
2052}
2053#[doc = "TCD Signed Destination Address Offset"]
2054pub mod tcd10_doff;
2055#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
2056pub struct TCD10_CITER_ELINKNO {
2057 register: VolatileCell<u16>,
2058}
2059#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
2060pub mod tcd10_citer_elinkno;
2061#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
2062pub struct TCD10_CITER_ELINKYES {
2063 register: VolatileCell<u16>,
2064}
2065#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
2066pub mod tcd10_citer_elinkyes;
2067#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
2068pub struct TCD10_DLASTSGA {
2069 register: VolatileCell<u32>,
2070}
2071#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
2072pub mod tcd10_dlastsga;
2073#[doc = "TCD Control and Status"]
2074pub struct TCD10_CSR {
2075 register: VolatileCell<u16>,
2076}
2077#[doc = "TCD Control and Status"]
2078pub mod tcd10_csr;
2079#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
2080pub struct TCD10_BITER_ELINKNO {
2081 register: VolatileCell<u16>,
2082}
2083#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
2084pub mod tcd10_biter_elinkno;
2085#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
2086pub struct TCD10_BITER_ELINKYES {
2087 register: VolatileCell<u16>,
2088}
2089#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
2090pub mod tcd10_biter_elinkyes;
2091#[doc = "TCD Source Address"]
2092pub struct TCD11_SADDR {
2093 register: VolatileCell<u32>,
2094}
2095#[doc = "TCD Source Address"]
2096pub mod tcd11_saddr;
2097#[doc = "TCD Signed Source Address Offset"]
2098pub struct TCD11_SOFF {
2099 register: VolatileCell<u16>,
2100}
2101#[doc = "TCD Signed Source Address Offset"]
2102pub mod tcd11_soff;
2103#[doc = "TCD Transfer Attributes"]
2104pub struct TCD11_ATTR {
2105 register: VolatileCell<u16>,
2106}
2107#[doc = "TCD Transfer Attributes"]
2108pub mod tcd11_attr;
2109#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
2110pub struct TCD11_NBYTES_MLNO {
2111 register: VolatileCell<u32>,
2112}
2113#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
2114pub mod tcd11_nbytes_mlno;
2115#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
2116pub struct TCD11_NBYTES_MLOFFNO {
2117 register: VolatileCell<u32>,
2118}
2119#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
2120pub mod tcd11_nbytes_mloffno;
2121#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
2122pub struct TCD11_NBYTES_MLOFFYES {
2123 register: VolatileCell<u32>,
2124}
2125#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
2126pub mod tcd11_nbytes_mloffyes;
2127#[doc = "TCD Last Source Address Adjustment"]
2128pub struct TCD11_SLAST {
2129 register: VolatileCell<u32>,
2130}
2131#[doc = "TCD Last Source Address Adjustment"]
2132pub mod tcd11_slast;
2133#[doc = "TCD Destination Address"]
2134pub struct TCD11_DADDR {
2135 register: VolatileCell<u32>,
2136}
2137#[doc = "TCD Destination Address"]
2138pub mod tcd11_daddr;
2139#[doc = "TCD Signed Destination Address Offset"]
2140pub struct TCD11_DOFF {
2141 register: VolatileCell<u16>,
2142}
2143#[doc = "TCD Signed Destination Address Offset"]
2144pub mod tcd11_doff;
2145#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
2146pub struct TCD11_CITER_ELINKNO {
2147 register: VolatileCell<u16>,
2148}
2149#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
2150pub mod tcd11_citer_elinkno;
2151#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
2152pub struct TCD11_CITER_ELINKYES {
2153 register: VolatileCell<u16>,
2154}
2155#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
2156pub mod tcd11_citer_elinkyes;
2157#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
2158pub struct TCD11_DLASTSGA {
2159 register: VolatileCell<u32>,
2160}
2161#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
2162pub mod tcd11_dlastsga;
2163#[doc = "TCD Control and Status"]
2164pub struct TCD11_CSR {
2165 register: VolatileCell<u16>,
2166}
2167#[doc = "TCD Control and Status"]
2168pub mod tcd11_csr;
2169#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
2170pub struct TCD11_BITER_ELINKNO {
2171 register: VolatileCell<u16>,
2172}
2173#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
2174pub mod tcd11_biter_elinkno;
2175#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
2176pub struct TCD11_BITER_ELINKYES {
2177 register: VolatileCell<u16>,
2178}
2179#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
2180pub mod tcd11_biter_elinkyes;
2181#[doc = "TCD Source Address"]
2182pub struct TCD12_SADDR {
2183 register: VolatileCell<u32>,
2184}
2185#[doc = "TCD Source Address"]
2186pub mod tcd12_saddr;
2187#[doc = "TCD Signed Source Address Offset"]
2188pub struct TCD12_SOFF {
2189 register: VolatileCell<u16>,
2190}
2191#[doc = "TCD Signed Source Address Offset"]
2192pub mod tcd12_soff;
2193#[doc = "TCD Transfer Attributes"]
2194pub struct TCD12_ATTR {
2195 register: VolatileCell<u16>,
2196}
2197#[doc = "TCD Transfer Attributes"]
2198pub mod tcd12_attr;
2199#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
2200pub struct TCD12_NBYTES_MLNO {
2201 register: VolatileCell<u32>,
2202}
2203#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
2204pub mod tcd12_nbytes_mlno;
2205#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
2206pub struct TCD12_NBYTES_MLOFFNO {
2207 register: VolatileCell<u32>,
2208}
2209#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
2210pub mod tcd12_nbytes_mloffno;
2211#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
2212pub struct TCD12_NBYTES_MLOFFYES {
2213 register: VolatileCell<u32>,
2214}
2215#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
2216pub mod tcd12_nbytes_mloffyes;
2217#[doc = "TCD Last Source Address Adjustment"]
2218pub struct TCD12_SLAST {
2219 register: VolatileCell<u32>,
2220}
2221#[doc = "TCD Last Source Address Adjustment"]
2222pub mod tcd12_slast;
2223#[doc = "TCD Destination Address"]
2224pub struct TCD12_DADDR {
2225 register: VolatileCell<u32>,
2226}
2227#[doc = "TCD Destination Address"]
2228pub mod tcd12_daddr;
2229#[doc = "TCD Signed Destination Address Offset"]
2230pub struct TCD12_DOFF {
2231 register: VolatileCell<u16>,
2232}
2233#[doc = "TCD Signed Destination Address Offset"]
2234pub mod tcd12_doff;
2235#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
2236pub struct TCD12_CITER_ELINKNO {
2237 register: VolatileCell<u16>,
2238}
2239#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
2240pub mod tcd12_citer_elinkno;
2241#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
2242pub struct TCD12_CITER_ELINKYES {
2243 register: VolatileCell<u16>,
2244}
2245#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
2246pub mod tcd12_citer_elinkyes;
2247#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
2248pub struct TCD12_DLASTSGA {
2249 register: VolatileCell<u32>,
2250}
2251#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
2252pub mod tcd12_dlastsga;
2253#[doc = "TCD Control and Status"]
2254pub struct TCD12_CSR {
2255 register: VolatileCell<u16>,
2256}
2257#[doc = "TCD Control and Status"]
2258pub mod tcd12_csr;
2259#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
2260pub struct TCD12_BITER_ELINKNO {
2261 register: VolatileCell<u16>,
2262}
2263#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
2264pub mod tcd12_biter_elinkno;
2265#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
2266pub struct TCD12_BITER_ELINKYES {
2267 register: VolatileCell<u16>,
2268}
2269#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
2270pub mod tcd12_biter_elinkyes;
2271#[doc = "TCD Source Address"]
2272pub struct TCD13_SADDR {
2273 register: VolatileCell<u32>,
2274}
2275#[doc = "TCD Source Address"]
2276pub mod tcd13_saddr;
2277#[doc = "TCD Signed Source Address Offset"]
2278pub struct TCD13_SOFF {
2279 register: VolatileCell<u16>,
2280}
2281#[doc = "TCD Signed Source Address Offset"]
2282pub mod tcd13_soff;
2283#[doc = "TCD Transfer Attributes"]
2284pub struct TCD13_ATTR {
2285 register: VolatileCell<u16>,
2286}
2287#[doc = "TCD Transfer Attributes"]
2288pub mod tcd13_attr;
2289#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
2290pub struct TCD13_NBYTES_MLNO {
2291 register: VolatileCell<u32>,
2292}
2293#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
2294pub mod tcd13_nbytes_mlno;
2295#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
2296pub struct TCD13_NBYTES_MLOFFNO {
2297 register: VolatileCell<u32>,
2298}
2299#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
2300pub mod tcd13_nbytes_mloffno;
2301#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
2302pub struct TCD13_NBYTES_MLOFFYES {
2303 register: VolatileCell<u32>,
2304}
2305#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
2306pub mod tcd13_nbytes_mloffyes;
2307#[doc = "TCD Last Source Address Adjustment"]
2308pub struct TCD13_SLAST {
2309 register: VolatileCell<u32>,
2310}
2311#[doc = "TCD Last Source Address Adjustment"]
2312pub mod tcd13_slast;
2313#[doc = "TCD Destination Address"]
2314pub struct TCD13_DADDR {
2315 register: VolatileCell<u32>,
2316}
2317#[doc = "TCD Destination Address"]
2318pub mod tcd13_daddr;
2319#[doc = "TCD Signed Destination Address Offset"]
2320pub struct TCD13_DOFF {
2321 register: VolatileCell<u16>,
2322}
2323#[doc = "TCD Signed Destination Address Offset"]
2324pub mod tcd13_doff;
2325#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
2326pub struct TCD13_CITER_ELINKNO {
2327 register: VolatileCell<u16>,
2328}
2329#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
2330pub mod tcd13_citer_elinkno;
2331#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
2332pub struct TCD13_CITER_ELINKYES {
2333 register: VolatileCell<u16>,
2334}
2335#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
2336pub mod tcd13_citer_elinkyes;
2337#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
2338pub struct TCD13_DLASTSGA {
2339 register: VolatileCell<u32>,
2340}
2341#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
2342pub mod tcd13_dlastsga;
2343#[doc = "TCD Control and Status"]
2344pub struct TCD13_CSR {
2345 register: VolatileCell<u16>,
2346}
2347#[doc = "TCD Control and Status"]
2348pub mod tcd13_csr;
2349#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
2350pub struct TCD13_BITER_ELINKNO {
2351 register: VolatileCell<u16>,
2352}
2353#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
2354pub mod tcd13_biter_elinkno;
2355#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
2356pub struct TCD13_BITER_ELINKYES {
2357 register: VolatileCell<u16>,
2358}
2359#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
2360pub mod tcd13_biter_elinkyes;
2361#[doc = "TCD Source Address"]
2362pub struct TCD14_SADDR {
2363 register: VolatileCell<u32>,
2364}
2365#[doc = "TCD Source Address"]
2366pub mod tcd14_saddr;
2367#[doc = "TCD Signed Source Address Offset"]
2368pub struct TCD14_SOFF {
2369 register: VolatileCell<u16>,
2370}
2371#[doc = "TCD Signed Source Address Offset"]
2372pub mod tcd14_soff;
2373#[doc = "TCD Transfer Attributes"]
2374pub struct TCD14_ATTR {
2375 register: VolatileCell<u16>,
2376}
2377#[doc = "TCD Transfer Attributes"]
2378pub mod tcd14_attr;
2379#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
2380pub struct TCD14_NBYTES_MLNO {
2381 register: VolatileCell<u32>,
2382}
2383#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
2384pub mod tcd14_nbytes_mlno;
2385#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
2386pub struct TCD14_NBYTES_MLOFFNO {
2387 register: VolatileCell<u32>,
2388}
2389#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
2390pub mod tcd14_nbytes_mloffno;
2391#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
2392pub struct TCD14_NBYTES_MLOFFYES {
2393 register: VolatileCell<u32>,
2394}
2395#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
2396pub mod tcd14_nbytes_mloffyes;
2397#[doc = "TCD Last Source Address Adjustment"]
2398pub struct TCD14_SLAST {
2399 register: VolatileCell<u32>,
2400}
2401#[doc = "TCD Last Source Address Adjustment"]
2402pub mod tcd14_slast;
2403#[doc = "TCD Destination Address"]
2404pub struct TCD14_DADDR {
2405 register: VolatileCell<u32>,
2406}
2407#[doc = "TCD Destination Address"]
2408pub mod tcd14_daddr;
2409#[doc = "TCD Signed Destination Address Offset"]
2410pub struct TCD14_DOFF {
2411 register: VolatileCell<u16>,
2412}
2413#[doc = "TCD Signed Destination Address Offset"]
2414pub mod tcd14_doff;
2415#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
2416pub struct TCD14_CITER_ELINKNO {
2417 register: VolatileCell<u16>,
2418}
2419#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
2420pub mod tcd14_citer_elinkno;
2421#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
2422pub struct TCD14_CITER_ELINKYES {
2423 register: VolatileCell<u16>,
2424}
2425#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
2426pub mod tcd14_citer_elinkyes;
2427#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
2428pub struct TCD14_DLASTSGA {
2429 register: VolatileCell<u32>,
2430}
2431#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
2432pub mod tcd14_dlastsga;
2433#[doc = "TCD Control and Status"]
2434pub struct TCD14_CSR {
2435 register: VolatileCell<u16>,
2436}
2437#[doc = "TCD Control and Status"]
2438pub mod tcd14_csr;
2439#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
2440pub struct TCD14_BITER_ELINKNO {
2441 register: VolatileCell<u16>,
2442}
2443#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
2444pub mod tcd14_biter_elinkno;
2445#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
2446pub struct TCD14_BITER_ELINKYES {
2447 register: VolatileCell<u16>,
2448}
2449#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
2450pub mod tcd14_biter_elinkyes;
2451#[doc = "TCD Source Address"]
2452pub struct TCD15_SADDR {
2453 register: VolatileCell<u32>,
2454}
2455#[doc = "TCD Source Address"]
2456pub mod tcd15_saddr;
2457#[doc = "TCD Signed Source Address Offset"]
2458pub struct TCD15_SOFF {
2459 register: VolatileCell<u16>,
2460}
2461#[doc = "TCD Signed Source Address Offset"]
2462pub mod tcd15_soff;
2463#[doc = "TCD Transfer Attributes"]
2464pub struct TCD15_ATTR {
2465 register: VolatileCell<u16>,
2466}
2467#[doc = "TCD Transfer Attributes"]
2468pub mod tcd15_attr;
2469#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
2470pub struct TCD15_NBYTES_MLNO {
2471 register: VolatileCell<u32>,
2472}
2473#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
2474pub mod tcd15_nbytes_mlno;
2475#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
2476pub struct TCD15_NBYTES_MLOFFNO {
2477 register: VolatileCell<u32>,
2478}
2479#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
2480pub mod tcd15_nbytes_mloffno;
2481#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
2482pub struct TCD15_NBYTES_MLOFFYES {
2483 register: VolatileCell<u32>,
2484}
2485#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
2486pub mod tcd15_nbytes_mloffyes;
2487#[doc = "TCD Last Source Address Adjustment"]
2488pub struct TCD15_SLAST {
2489 register: VolatileCell<u32>,
2490}
2491#[doc = "TCD Last Source Address Adjustment"]
2492pub mod tcd15_slast;
2493#[doc = "TCD Destination Address"]
2494pub struct TCD15_DADDR {
2495 register: VolatileCell<u32>,
2496}
2497#[doc = "TCD Destination Address"]
2498pub mod tcd15_daddr;
2499#[doc = "TCD Signed Destination Address Offset"]
2500pub struct TCD15_DOFF {
2501 register: VolatileCell<u16>,
2502}
2503#[doc = "TCD Signed Destination Address Offset"]
2504pub mod tcd15_doff;
2505#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
2506pub struct TCD15_CITER_ELINKNO {
2507 register: VolatileCell<u16>,
2508}
2509#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
2510pub mod tcd15_citer_elinkno;
2511#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
2512pub struct TCD15_CITER_ELINKYES {
2513 register: VolatileCell<u16>,
2514}
2515#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
2516pub mod tcd15_citer_elinkyes;
2517#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
2518pub struct TCD15_DLASTSGA {
2519 register: VolatileCell<u32>,
2520}
2521#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
2522pub mod tcd15_dlastsga;
2523#[doc = "TCD Control and Status"]
2524pub struct TCD15_CSR {
2525 register: VolatileCell<u16>,
2526}
2527#[doc = "TCD Control and Status"]
2528pub mod tcd15_csr;
2529#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
2530pub struct TCD15_BITER_ELINKNO {
2531 register: VolatileCell<u16>,
2532}
2533#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
2534pub mod tcd15_biter_elinkno;
2535#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
2536pub struct TCD15_BITER_ELINKYES {
2537 register: VolatileCell<u16>,
2538}
2539#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
2540pub mod tcd15_biter_elinkyes;
2541#[doc = "TCD Source Address"]
2542pub struct TCD16_SADDR {
2543 register: VolatileCell<u32>,
2544}
2545#[doc = "TCD Source Address"]
2546pub mod tcd16_saddr;
2547#[doc = "TCD Signed Source Address Offset"]
2548pub struct TCD16_SOFF {
2549 register: VolatileCell<u16>,
2550}
2551#[doc = "TCD Signed Source Address Offset"]
2552pub mod tcd16_soff;
2553#[doc = "TCD Transfer Attributes"]
2554pub struct TCD16_ATTR {
2555 register: VolatileCell<u16>,
2556}
2557#[doc = "TCD Transfer Attributes"]
2558pub mod tcd16_attr;
2559#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
2560pub struct TCD16_NBYTES_MLNO {
2561 register: VolatileCell<u32>,
2562}
2563#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
2564pub mod tcd16_nbytes_mlno;
2565#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
2566pub struct TCD16_NBYTES_MLOFFNO {
2567 register: VolatileCell<u32>,
2568}
2569#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
2570pub mod tcd16_nbytes_mloffno;
2571#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
2572pub struct TCD16_NBYTES_MLOFFYES {
2573 register: VolatileCell<u32>,
2574}
2575#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
2576pub mod tcd16_nbytes_mloffyes;
2577#[doc = "TCD Last Source Address Adjustment"]
2578pub struct TCD16_SLAST {
2579 register: VolatileCell<u32>,
2580}
2581#[doc = "TCD Last Source Address Adjustment"]
2582pub mod tcd16_slast;
2583#[doc = "TCD Destination Address"]
2584pub struct TCD16_DADDR {
2585 register: VolatileCell<u32>,
2586}
2587#[doc = "TCD Destination Address"]
2588pub mod tcd16_daddr;
2589#[doc = "TCD Signed Destination Address Offset"]
2590pub struct TCD16_DOFF {
2591 register: VolatileCell<u16>,
2592}
2593#[doc = "TCD Signed Destination Address Offset"]
2594pub mod tcd16_doff;
2595#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
2596pub struct TCD16_CITER_ELINKNO {
2597 register: VolatileCell<u16>,
2598}
2599#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
2600pub mod tcd16_citer_elinkno;
2601#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
2602pub struct TCD16_CITER_ELINKYES {
2603 register: VolatileCell<u16>,
2604}
2605#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
2606pub mod tcd16_citer_elinkyes;
2607#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
2608pub struct TCD16_DLASTSGA {
2609 register: VolatileCell<u32>,
2610}
2611#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
2612pub mod tcd16_dlastsga;
2613#[doc = "TCD Control and Status"]
2614pub struct TCD16_CSR {
2615 register: VolatileCell<u16>,
2616}
2617#[doc = "TCD Control and Status"]
2618pub mod tcd16_csr;
2619#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
2620pub struct TCD16_BITER_ELINKNO {
2621 register: VolatileCell<u16>,
2622}
2623#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
2624pub mod tcd16_biter_elinkno;
2625#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
2626pub struct TCD16_BITER_ELINKYES {
2627 register: VolatileCell<u16>,
2628}
2629#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
2630pub mod tcd16_biter_elinkyes;
2631#[doc = "TCD Source Address"]
2632pub struct TCD17_SADDR {
2633 register: VolatileCell<u32>,
2634}
2635#[doc = "TCD Source Address"]
2636pub mod tcd17_saddr;
2637#[doc = "TCD Signed Source Address Offset"]
2638pub struct TCD17_SOFF {
2639 register: VolatileCell<u16>,
2640}
2641#[doc = "TCD Signed Source Address Offset"]
2642pub mod tcd17_soff;
2643#[doc = "TCD Transfer Attributes"]
2644pub struct TCD17_ATTR {
2645 register: VolatileCell<u16>,
2646}
2647#[doc = "TCD Transfer Attributes"]
2648pub mod tcd17_attr;
2649#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
2650pub struct TCD17_NBYTES_MLNO {
2651 register: VolatileCell<u32>,
2652}
2653#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
2654pub mod tcd17_nbytes_mlno;
2655#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
2656pub struct TCD17_NBYTES_MLOFFNO {
2657 register: VolatileCell<u32>,
2658}
2659#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
2660pub mod tcd17_nbytes_mloffno;
2661#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
2662pub struct TCD17_NBYTES_MLOFFYES {
2663 register: VolatileCell<u32>,
2664}
2665#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
2666pub mod tcd17_nbytes_mloffyes;
2667#[doc = "TCD Last Source Address Adjustment"]
2668pub struct TCD17_SLAST {
2669 register: VolatileCell<u32>,
2670}
2671#[doc = "TCD Last Source Address Adjustment"]
2672pub mod tcd17_slast;
2673#[doc = "TCD Destination Address"]
2674pub struct TCD17_DADDR {
2675 register: VolatileCell<u32>,
2676}
2677#[doc = "TCD Destination Address"]
2678pub mod tcd17_daddr;
2679#[doc = "TCD Signed Destination Address Offset"]
2680pub struct TCD17_DOFF {
2681 register: VolatileCell<u16>,
2682}
2683#[doc = "TCD Signed Destination Address Offset"]
2684pub mod tcd17_doff;
2685#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
2686pub struct TCD17_CITER_ELINKNO {
2687 register: VolatileCell<u16>,
2688}
2689#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
2690pub mod tcd17_citer_elinkno;
2691#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
2692pub struct TCD17_CITER_ELINKYES {
2693 register: VolatileCell<u16>,
2694}
2695#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
2696pub mod tcd17_citer_elinkyes;
2697#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
2698pub struct TCD17_DLASTSGA {
2699 register: VolatileCell<u32>,
2700}
2701#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
2702pub mod tcd17_dlastsga;
2703#[doc = "TCD Control and Status"]
2704pub struct TCD17_CSR {
2705 register: VolatileCell<u16>,
2706}
2707#[doc = "TCD Control and Status"]
2708pub mod tcd17_csr;
2709#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
2710pub struct TCD17_BITER_ELINKNO {
2711 register: VolatileCell<u16>,
2712}
2713#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
2714pub mod tcd17_biter_elinkno;
2715#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
2716pub struct TCD17_BITER_ELINKYES {
2717 register: VolatileCell<u16>,
2718}
2719#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
2720pub mod tcd17_biter_elinkyes;
2721#[doc = "TCD Source Address"]
2722pub struct TCD18_SADDR {
2723 register: VolatileCell<u32>,
2724}
2725#[doc = "TCD Source Address"]
2726pub mod tcd18_saddr;
2727#[doc = "TCD Signed Source Address Offset"]
2728pub struct TCD18_SOFF {
2729 register: VolatileCell<u16>,
2730}
2731#[doc = "TCD Signed Source Address Offset"]
2732pub mod tcd18_soff;
2733#[doc = "TCD Transfer Attributes"]
2734pub struct TCD18_ATTR {
2735 register: VolatileCell<u16>,
2736}
2737#[doc = "TCD Transfer Attributes"]
2738pub mod tcd18_attr;
2739#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
2740pub struct TCD18_NBYTES_MLNO {
2741 register: VolatileCell<u32>,
2742}
2743#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
2744pub mod tcd18_nbytes_mlno;
2745#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
2746pub struct TCD18_NBYTES_MLOFFNO {
2747 register: VolatileCell<u32>,
2748}
2749#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
2750pub mod tcd18_nbytes_mloffno;
2751#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
2752pub struct TCD18_NBYTES_MLOFFYES {
2753 register: VolatileCell<u32>,
2754}
2755#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
2756pub mod tcd18_nbytes_mloffyes;
2757#[doc = "TCD Last Source Address Adjustment"]
2758pub struct TCD18_SLAST {
2759 register: VolatileCell<u32>,
2760}
2761#[doc = "TCD Last Source Address Adjustment"]
2762pub mod tcd18_slast;
2763#[doc = "TCD Destination Address"]
2764pub struct TCD18_DADDR {
2765 register: VolatileCell<u32>,
2766}
2767#[doc = "TCD Destination Address"]
2768pub mod tcd18_daddr;
2769#[doc = "TCD Signed Destination Address Offset"]
2770pub struct TCD18_DOFF {
2771 register: VolatileCell<u16>,
2772}
2773#[doc = "TCD Signed Destination Address Offset"]
2774pub mod tcd18_doff;
2775#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
2776pub struct TCD18_CITER_ELINKNO {
2777 register: VolatileCell<u16>,
2778}
2779#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
2780pub mod tcd18_citer_elinkno;
2781#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
2782pub struct TCD18_CITER_ELINKYES {
2783 register: VolatileCell<u16>,
2784}
2785#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
2786pub mod tcd18_citer_elinkyes;
2787#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
2788pub struct TCD18_DLASTSGA {
2789 register: VolatileCell<u32>,
2790}
2791#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
2792pub mod tcd18_dlastsga;
2793#[doc = "TCD Control and Status"]
2794pub struct TCD18_CSR {
2795 register: VolatileCell<u16>,
2796}
2797#[doc = "TCD Control and Status"]
2798pub mod tcd18_csr;
2799#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
2800pub struct TCD18_BITER_ELINKNO {
2801 register: VolatileCell<u16>,
2802}
2803#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
2804pub mod tcd18_biter_elinkno;
2805#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
2806pub struct TCD18_BITER_ELINKYES {
2807 register: VolatileCell<u16>,
2808}
2809#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
2810pub mod tcd18_biter_elinkyes;
2811#[doc = "TCD Source Address"]
2812pub struct TCD19_SADDR {
2813 register: VolatileCell<u32>,
2814}
2815#[doc = "TCD Source Address"]
2816pub mod tcd19_saddr;
2817#[doc = "TCD Signed Source Address Offset"]
2818pub struct TCD19_SOFF {
2819 register: VolatileCell<u16>,
2820}
2821#[doc = "TCD Signed Source Address Offset"]
2822pub mod tcd19_soff;
2823#[doc = "TCD Transfer Attributes"]
2824pub struct TCD19_ATTR {
2825 register: VolatileCell<u16>,
2826}
2827#[doc = "TCD Transfer Attributes"]
2828pub mod tcd19_attr;
2829#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
2830pub struct TCD19_NBYTES_MLNO {
2831 register: VolatileCell<u32>,
2832}
2833#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
2834pub mod tcd19_nbytes_mlno;
2835#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
2836pub struct TCD19_NBYTES_MLOFFNO {
2837 register: VolatileCell<u32>,
2838}
2839#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
2840pub mod tcd19_nbytes_mloffno;
2841#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
2842pub struct TCD19_NBYTES_MLOFFYES {
2843 register: VolatileCell<u32>,
2844}
2845#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
2846pub mod tcd19_nbytes_mloffyes;
2847#[doc = "TCD Last Source Address Adjustment"]
2848pub struct TCD19_SLAST {
2849 register: VolatileCell<u32>,
2850}
2851#[doc = "TCD Last Source Address Adjustment"]
2852pub mod tcd19_slast;
2853#[doc = "TCD Destination Address"]
2854pub struct TCD19_DADDR {
2855 register: VolatileCell<u32>,
2856}
2857#[doc = "TCD Destination Address"]
2858pub mod tcd19_daddr;
2859#[doc = "TCD Signed Destination Address Offset"]
2860pub struct TCD19_DOFF {
2861 register: VolatileCell<u16>,
2862}
2863#[doc = "TCD Signed Destination Address Offset"]
2864pub mod tcd19_doff;
2865#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
2866pub struct TCD19_CITER_ELINKNO {
2867 register: VolatileCell<u16>,
2868}
2869#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
2870pub mod tcd19_citer_elinkno;
2871#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
2872pub struct TCD19_CITER_ELINKYES {
2873 register: VolatileCell<u16>,
2874}
2875#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
2876pub mod tcd19_citer_elinkyes;
2877#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
2878pub struct TCD19_DLASTSGA {
2879 register: VolatileCell<u32>,
2880}
2881#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
2882pub mod tcd19_dlastsga;
2883#[doc = "TCD Control and Status"]
2884pub struct TCD19_CSR {
2885 register: VolatileCell<u16>,
2886}
2887#[doc = "TCD Control and Status"]
2888pub mod tcd19_csr;
2889#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
2890pub struct TCD19_BITER_ELINKNO {
2891 register: VolatileCell<u16>,
2892}
2893#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
2894pub mod tcd19_biter_elinkno;
2895#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
2896pub struct TCD19_BITER_ELINKYES {
2897 register: VolatileCell<u16>,
2898}
2899#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
2900pub mod tcd19_biter_elinkyes;
2901#[doc = "TCD Source Address"]
2902pub struct TCD20_SADDR {
2903 register: VolatileCell<u32>,
2904}
2905#[doc = "TCD Source Address"]
2906pub mod tcd20_saddr;
2907#[doc = "TCD Signed Source Address Offset"]
2908pub struct TCD20_SOFF {
2909 register: VolatileCell<u16>,
2910}
2911#[doc = "TCD Signed Source Address Offset"]
2912pub mod tcd20_soff;
2913#[doc = "TCD Transfer Attributes"]
2914pub struct TCD20_ATTR {
2915 register: VolatileCell<u16>,
2916}
2917#[doc = "TCD Transfer Attributes"]
2918pub mod tcd20_attr;
2919#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
2920pub struct TCD20_NBYTES_MLNO {
2921 register: VolatileCell<u32>,
2922}
2923#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
2924pub mod tcd20_nbytes_mlno;
2925#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
2926pub struct TCD20_NBYTES_MLOFFNO {
2927 register: VolatileCell<u32>,
2928}
2929#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
2930pub mod tcd20_nbytes_mloffno;
2931#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
2932pub struct TCD20_NBYTES_MLOFFYES {
2933 register: VolatileCell<u32>,
2934}
2935#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
2936pub mod tcd20_nbytes_mloffyes;
2937#[doc = "TCD Last Source Address Adjustment"]
2938pub struct TCD20_SLAST {
2939 register: VolatileCell<u32>,
2940}
2941#[doc = "TCD Last Source Address Adjustment"]
2942pub mod tcd20_slast;
2943#[doc = "TCD Destination Address"]
2944pub struct TCD20_DADDR {
2945 register: VolatileCell<u32>,
2946}
2947#[doc = "TCD Destination Address"]
2948pub mod tcd20_daddr;
2949#[doc = "TCD Signed Destination Address Offset"]
2950pub struct TCD20_DOFF {
2951 register: VolatileCell<u16>,
2952}
2953#[doc = "TCD Signed Destination Address Offset"]
2954pub mod tcd20_doff;
2955#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
2956pub struct TCD20_CITER_ELINKNO {
2957 register: VolatileCell<u16>,
2958}
2959#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
2960pub mod tcd20_citer_elinkno;
2961#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
2962pub struct TCD20_CITER_ELINKYES {
2963 register: VolatileCell<u16>,
2964}
2965#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
2966pub mod tcd20_citer_elinkyes;
2967#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
2968pub struct TCD20_DLASTSGA {
2969 register: VolatileCell<u32>,
2970}
2971#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
2972pub mod tcd20_dlastsga;
2973#[doc = "TCD Control and Status"]
2974pub struct TCD20_CSR {
2975 register: VolatileCell<u16>,
2976}
2977#[doc = "TCD Control and Status"]
2978pub mod tcd20_csr;
2979#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
2980pub struct TCD20_BITER_ELINKNO {
2981 register: VolatileCell<u16>,
2982}
2983#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
2984pub mod tcd20_biter_elinkno;
2985#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
2986pub struct TCD20_BITER_ELINKYES {
2987 register: VolatileCell<u16>,
2988}
2989#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
2990pub mod tcd20_biter_elinkyes;
2991#[doc = "TCD Source Address"]
2992pub struct TCD21_SADDR {
2993 register: VolatileCell<u32>,
2994}
2995#[doc = "TCD Source Address"]
2996pub mod tcd21_saddr;
2997#[doc = "TCD Signed Source Address Offset"]
2998pub struct TCD21_SOFF {
2999 register: VolatileCell<u16>,
3000}
3001#[doc = "TCD Signed Source Address Offset"]
3002pub mod tcd21_soff;
3003#[doc = "TCD Transfer Attributes"]
3004pub struct TCD21_ATTR {
3005 register: VolatileCell<u16>,
3006}
3007#[doc = "TCD Transfer Attributes"]
3008pub mod tcd21_attr;
3009#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
3010pub struct TCD21_NBYTES_MLNO {
3011 register: VolatileCell<u32>,
3012}
3013#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
3014pub mod tcd21_nbytes_mlno;
3015#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
3016pub struct TCD21_NBYTES_MLOFFNO {
3017 register: VolatileCell<u32>,
3018}
3019#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
3020pub mod tcd21_nbytes_mloffno;
3021#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
3022pub struct TCD21_NBYTES_MLOFFYES {
3023 register: VolatileCell<u32>,
3024}
3025#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
3026pub mod tcd21_nbytes_mloffyes;
3027#[doc = "TCD Last Source Address Adjustment"]
3028pub struct TCD21_SLAST {
3029 register: VolatileCell<u32>,
3030}
3031#[doc = "TCD Last Source Address Adjustment"]
3032pub mod tcd21_slast;
3033#[doc = "TCD Destination Address"]
3034pub struct TCD21_DADDR {
3035 register: VolatileCell<u32>,
3036}
3037#[doc = "TCD Destination Address"]
3038pub mod tcd21_daddr;
3039#[doc = "TCD Signed Destination Address Offset"]
3040pub struct TCD21_DOFF {
3041 register: VolatileCell<u16>,
3042}
3043#[doc = "TCD Signed Destination Address Offset"]
3044pub mod tcd21_doff;
3045#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
3046pub struct TCD21_CITER_ELINKNO {
3047 register: VolatileCell<u16>,
3048}
3049#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
3050pub mod tcd21_citer_elinkno;
3051#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
3052pub struct TCD21_CITER_ELINKYES {
3053 register: VolatileCell<u16>,
3054}
3055#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
3056pub mod tcd21_citer_elinkyes;
3057#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
3058pub struct TCD21_DLASTSGA {
3059 register: VolatileCell<u32>,
3060}
3061#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
3062pub mod tcd21_dlastsga;
3063#[doc = "TCD Control and Status"]
3064pub struct TCD21_CSR {
3065 register: VolatileCell<u16>,
3066}
3067#[doc = "TCD Control and Status"]
3068pub mod tcd21_csr;
3069#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
3070pub struct TCD21_BITER_ELINKNO {
3071 register: VolatileCell<u16>,
3072}
3073#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
3074pub mod tcd21_biter_elinkno;
3075#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
3076pub struct TCD21_BITER_ELINKYES {
3077 register: VolatileCell<u16>,
3078}
3079#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
3080pub mod tcd21_biter_elinkyes;
3081#[doc = "TCD Source Address"]
3082pub struct TCD22_SADDR {
3083 register: VolatileCell<u32>,
3084}
3085#[doc = "TCD Source Address"]
3086pub mod tcd22_saddr;
3087#[doc = "TCD Signed Source Address Offset"]
3088pub struct TCD22_SOFF {
3089 register: VolatileCell<u16>,
3090}
3091#[doc = "TCD Signed Source Address Offset"]
3092pub mod tcd22_soff;
3093#[doc = "TCD Transfer Attributes"]
3094pub struct TCD22_ATTR {
3095 register: VolatileCell<u16>,
3096}
3097#[doc = "TCD Transfer Attributes"]
3098pub mod tcd22_attr;
3099#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
3100pub struct TCD22_NBYTES_MLNO {
3101 register: VolatileCell<u32>,
3102}
3103#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
3104pub mod tcd22_nbytes_mlno;
3105#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
3106pub struct TCD22_NBYTES_MLOFFNO {
3107 register: VolatileCell<u32>,
3108}
3109#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
3110pub mod tcd22_nbytes_mloffno;
3111#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
3112pub struct TCD22_NBYTES_MLOFFYES {
3113 register: VolatileCell<u32>,
3114}
3115#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
3116pub mod tcd22_nbytes_mloffyes;
3117#[doc = "TCD Last Source Address Adjustment"]
3118pub struct TCD22_SLAST {
3119 register: VolatileCell<u32>,
3120}
3121#[doc = "TCD Last Source Address Adjustment"]
3122pub mod tcd22_slast;
3123#[doc = "TCD Destination Address"]
3124pub struct TCD22_DADDR {
3125 register: VolatileCell<u32>,
3126}
3127#[doc = "TCD Destination Address"]
3128pub mod tcd22_daddr;
3129#[doc = "TCD Signed Destination Address Offset"]
3130pub struct TCD22_DOFF {
3131 register: VolatileCell<u16>,
3132}
3133#[doc = "TCD Signed Destination Address Offset"]
3134pub mod tcd22_doff;
3135#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
3136pub struct TCD22_CITER_ELINKNO {
3137 register: VolatileCell<u16>,
3138}
3139#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
3140pub mod tcd22_citer_elinkno;
3141#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
3142pub struct TCD22_CITER_ELINKYES {
3143 register: VolatileCell<u16>,
3144}
3145#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
3146pub mod tcd22_citer_elinkyes;
3147#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
3148pub struct TCD22_DLASTSGA {
3149 register: VolatileCell<u32>,
3150}
3151#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
3152pub mod tcd22_dlastsga;
3153#[doc = "TCD Control and Status"]
3154pub struct TCD22_CSR {
3155 register: VolatileCell<u16>,
3156}
3157#[doc = "TCD Control and Status"]
3158pub mod tcd22_csr;
3159#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
3160pub struct TCD22_BITER_ELINKNO {
3161 register: VolatileCell<u16>,
3162}
3163#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
3164pub mod tcd22_biter_elinkno;
3165#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
3166pub struct TCD22_BITER_ELINKYES {
3167 register: VolatileCell<u16>,
3168}
3169#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
3170pub mod tcd22_biter_elinkyes;
3171#[doc = "TCD Source Address"]
3172pub struct TCD23_SADDR {
3173 register: VolatileCell<u32>,
3174}
3175#[doc = "TCD Source Address"]
3176pub mod tcd23_saddr;
3177#[doc = "TCD Signed Source Address Offset"]
3178pub struct TCD23_SOFF {
3179 register: VolatileCell<u16>,
3180}
3181#[doc = "TCD Signed Source Address Offset"]
3182pub mod tcd23_soff;
3183#[doc = "TCD Transfer Attributes"]
3184pub struct TCD23_ATTR {
3185 register: VolatileCell<u16>,
3186}
3187#[doc = "TCD Transfer Attributes"]
3188pub mod tcd23_attr;
3189#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
3190pub struct TCD23_NBYTES_MLNO {
3191 register: VolatileCell<u32>,
3192}
3193#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
3194pub mod tcd23_nbytes_mlno;
3195#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
3196pub struct TCD23_NBYTES_MLOFFNO {
3197 register: VolatileCell<u32>,
3198}
3199#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
3200pub mod tcd23_nbytes_mloffno;
3201#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
3202pub struct TCD23_NBYTES_MLOFFYES {
3203 register: VolatileCell<u32>,
3204}
3205#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
3206pub mod tcd23_nbytes_mloffyes;
3207#[doc = "TCD Last Source Address Adjustment"]
3208pub struct TCD23_SLAST {
3209 register: VolatileCell<u32>,
3210}
3211#[doc = "TCD Last Source Address Adjustment"]
3212pub mod tcd23_slast;
3213#[doc = "TCD Destination Address"]
3214pub struct TCD23_DADDR {
3215 register: VolatileCell<u32>,
3216}
3217#[doc = "TCD Destination Address"]
3218pub mod tcd23_daddr;
3219#[doc = "TCD Signed Destination Address Offset"]
3220pub struct TCD23_DOFF {
3221 register: VolatileCell<u16>,
3222}
3223#[doc = "TCD Signed Destination Address Offset"]
3224pub mod tcd23_doff;
3225#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
3226pub struct TCD23_CITER_ELINKNO {
3227 register: VolatileCell<u16>,
3228}
3229#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
3230pub mod tcd23_citer_elinkno;
3231#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
3232pub struct TCD23_CITER_ELINKYES {
3233 register: VolatileCell<u16>,
3234}
3235#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
3236pub mod tcd23_citer_elinkyes;
3237#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
3238pub struct TCD23_DLASTSGA {
3239 register: VolatileCell<u32>,
3240}
3241#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
3242pub mod tcd23_dlastsga;
3243#[doc = "TCD Control and Status"]
3244pub struct TCD23_CSR {
3245 register: VolatileCell<u16>,
3246}
3247#[doc = "TCD Control and Status"]
3248pub mod tcd23_csr;
3249#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
3250pub struct TCD23_BITER_ELINKNO {
3251 register: VolatileCell<u16>,
3252}
3253#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
3254pub mod tcd23_biter_elinkno;
3255#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
3256pub struct TCD23_BITER_ELINKYES {
3257 register: VolatileCell<u16>,
3258}
3259#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
3260pub mod tcd23_biter_elinkyes;
3261#[doc = "TCD Source Address"]
3262pub struct TCD24_SADDR {
3263 register: VolatileCell<u32>,
3264}
3265#[doc = "TCD Source Address"]
3266pub mod tcd24_saddr;
3267#[doc = "TCD Signed Source Address Offset"]
3268pub struct TCD24_SOFF {
3269 register: VolatileCell<u16>,
3270}
3271#[doc = "TCD Signed Source Address Offset"]
3272pub mod tcd24_soff;
3273#[doc = "TCD Transfer Attributes"]
3274pub struct TCD24_ATTR {
3275 register: VolatileCell<u16>,
3276}
3277#[doc = "TCD Transfer Attributes"]
3278pub mod tcd24_attr;
3279#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
3280pub struct TCD24_NBYTES_MLNO {
3281 register: VolatileCell<u32>,
3282}
3283#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
3284pub mod tcd24_nbytes_mlno;
3285#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
3286pub struct TCD24_NBYTES_MLOFFNO {
3287 register: VolatileCell<u32>,
3288}
3289#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
3290pub mod tcd24_nbytes_mloffno;
3291#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
3292pub struct TCD24_NBYTES_MLOFFYES {
3293 register: VolatileCell<u32>,
3294}
3295#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
3296pub mod tcd24_nbytes_mloffyes;
3297#[doc = "TCD Last Source Address Adjustment"]
3298pub struct TCD24_SLAST {
3299 register: VolatileCell<u32>,
3300}
3301#[doc = "TCD Last Source Address Adjustment"]
3302pub mod tcd24_slast;
3303#[doc = "TCD Destination Address"]
3304pub struct TCD24_DADDR {
3305 register: VolatileCell<u32>,
3306}
3307#[doc = "TCD Destination Address"]
3308pub mod tcd24_daddr;
3309#[doc = "TCD Signed Destination Address Offset"]
3310pub struct TCD24_DOFF {
3311 register: VolatileCell<u16>,
3312}
3313#[doc = "TCD Signed Destination Address Offset"]
3314pub mod tcd24_doff;
3315#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
3316pub struct TCD24_CITER_ELINKNO {
3317 register: VolatileCell<u16>,
3318}
3319#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
3320pub mod tcd24_citer_elinkno;
3321#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
3322pub struct TCD24_CITER_ELINKYES {
3323 register: VolatileCell<u16>,
3324}
3325#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
3326pub mod tcd24_citer_elinkyes;
3327#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
3328pub struct TCD24_DLASTSGA {
3329 register: VolatileCell<u32>,
3330}
3331#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
3332pub mod tcd24_dlastsga;
3333#[doc = "TCD Control and Status"]
3334pub struct TCD24_CSR {
3335 register: VolatileCell<u16>,
3336}
3337#[doc = "TCD Control and Status"]
3338pub mod tcd24_csr;
3339#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
3340pub struct TCD24_BITER_ELINKNO {
3341 register: VolatileCell<u16>,
3342}
3343#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
3344pub mod tcd24_biter_elinkno;
3345#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
3346pub struct TCD24_BITER_ELINKYES {
3347 register: VolatileCell<u16>,
3348}
3349#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
3350pub mod tcd24_biter_elinkyes;
3351#[doc = "TCD Source Address"]
3352pub struct TCD25_SADDR {
3353 register: VolatileCell<u32>,
3354}
3355#[doc = "TCD Source Address"]
3356pub mod tcd25_saddr;
3357#[doc = "TCD Signed Source Address Offset"]
3358pub struct TCD25_SOFF {
3359 register: VolatileCell<u16>,
3360}
3361#[doc = "TCD Signed Source Address Offset"]
3362pub mod tcd25_soff;
3363#[doc = "TCD Transfer Attributes"]
3364pub struct TCD25_ATTR {
3365 register: VolatileCell<u16>,
3366}
3367#[doc = "TCD Transfer Attributes"]
3368pub mod tcd25_attr;
3369#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
3370pub struct TCD25_NBYTES_MLNO {
3371 register: VolatileCell<u32>,
3372}
3373#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
3374pub mod tcd25_nbytes_mlno;
3375#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
3376pub struct TCD25_NBYTES_MLOFFNO {
3377 register: VolatileCell<u32>,
3378}
3379#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
3380pub mod tcd25_nbytes_mloffno;
3381#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
3382pub struct TCD25_NBYTES_MLOFFYES {
3383 register: VolatileCell<u32>,
3384}
3385#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
3386pub mod tcd25_nbytes_mloffyes;
3387#[doc = "TCD Last Source Address Adjustment"]
3388pub struct TCD25_SLAST {
3389 register: VolatileCell<u32>,
3390}
3391#[doc = "TCD Last Source Address Adjustment"]
3392pub mod tcd25_slast;
3393#[doc = "TCD Destination Address"]
3394pub struct TCD25_DADDR {
3395 register: VolatileCell<u32>,
3396}
3397#[doc = "TCD Destination Address"]
3398pub mod tcd25_daddr;
3399#[doc = "TCD Signed Destination Address Offset"]
3400pub struct TCD25_DOFF {
3401 register: VolatileCell<u16>,
3402}
3403#[doc = "TCD Signed Destination Address Offset"]
3404pub mod tcd25_doff;
3405#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
3406pub struct TCD25_CITER_ELINKNO {
3407 register: VolatileCell<u16>,
3408}
3409#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
3410pub mod tcd25_citer_elinkno;
3411#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
3412pub struct TCD25_CITER_ELINKYES {
3413 register: VolatileCell<u16>,
3414}
3415#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
3416pub mod tcd25_citer_elinkyes;
3417#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
3418pub struct TCD25_DLASTSGA {
3419 register: VolatileCell<u32>,
3420}
3421#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
3422pub mod tcd25_dlastsga;
3423#[doc = "TCD Control and Status"]
3424pub struct TCD25_CSR {
3425 register: VolatileCell<u16>,
3426}
3427#[doc = "TCD Control and Status"]
3428pub mod tcd25_csr;
3429#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
3430pub struct TCD25_BITER_ELINKNO {
3431 register: VolatileCell<u16>,
3432}
3433#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
3434pub mod tcd25_biter_elinkno;
3435#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
3436pub struct TCD25_BITER_ELINKYES {
3437 register: VolatileCell<u16>,
3438}
3439#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
3440pub mod tcd25_biter_elinkyes;
3441#[doc = "TCD Source Address"]
3442pub struct TCD26_SADDR {
3443 register: VolatileCell<u32>,
3444}
3445#[doc = "TCD Source Address"]
3446pub mod tcd26_saddr;
3447#[doc = "TCD Signed Source Address Offset"]
3448pub struct TCD26_SOFF {
3449 register: VolatileCell<u16>,
3450}
3451#[doc = "TCD Signed Source Address Offset"]
3452pub mod tcd26_soff;
3453#[doc = "TCD Transfer Attributes"]
3454pub struct TCD26_ATTR {
3455 register: VolatileCell<u16>,
3456}
3457#[doc = "TCD Transfer Attributes"]
3458pub mod tcd26_attr;
3459#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
3460pub struct TCD26_NBYTES_MLNO {
3461 register: VolatileCell<u32>,
3462}
3463#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
3464pub mod tcd26_nbytes_mlno;
3465#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
3466pub struct TCD26_NBYTES_MLOFFNO {
3467 register: VolatileCell<u32>,
3468}
3469#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
3470pub mod tcd26_nbytes_mloffno;
3471#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
3472pub struct TCD26_NBYTES_MLOFFYES {
3473 register: VolatileCell<u32>,
3474}
3475#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
3476pub mod tcd26_nbytes_mloffyes;
3477#[doc = "TCD Last Source Address Adjustment"]
3478pub struct TCD26_SLAST {
3479 register: VolatileCell<u32>,
3480}
3481#[doc = "TCD Last Source Address Adjustment"]
3482pub mod tcd26_slast;
3483#[doc = "TCD Destination Address"]
3484pub struct TCD26_DADDR {
3485 register: VolatileCell<u32>,
3486}
3487#[doc = "TCD Destination Address"]
3488pub mod tcd26_daddr;
3489#[doc = "TCD Signed Destination Address Offset"]
3490pub struct TCD26_DOFF {
3491 register: VolatileCell<u16>,
3492}
3493#[doc = "TCD Signed Destination Address Offset"]
3494pub mod tcd26_doff;
3495#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
3496pub struct TCD26_CITER_ELINKNO {
3497 register: VolatileCell<u16>,
3498}
3499#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
3500pub mod tcd26_citer_elinkno;
3501#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
3502pub struct TCD26_CITER_ELINKYES {
3503 register: VolatileCell<u16>,
3504}
3505#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
3506pub mod tcd26_citer_elinkyes;
3507#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
3508pub struct TCD26_DLASTSGA {
3509 register: VolatileCell<u32>,
3510}
3511#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
3512pub mod tcd26_dlastsga;
3513#[doc = "TCD Control and Status"]
3514pub struct TCD26_CSR {
3515 register: VolatileCell<u16>,
3516}
3517#[doc = "TCD Control and Status"]
3518pub mod tcd26_csr;
3519#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
3520pub struct TCD26_BITER_ELINKNO {
3521 register: VolatileCell<u16>,
3522}
3523#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
3524pub mod tcd26_biter_elinkno;
3525#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
3526pub struct TCD26_BITER_ELINKYES {
3527 register: VolatileCell<u16>,
3528}
3529#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
3530pub mod tcd26_biter_elinkyes;
3531#[doc = "TCD Source Address"]
3532pub struct TCD27_SADDR {
3533 register: VolatileCell<u32>,
3534}
3535#[doc = "TCD Source Address"]
3536pub mod tcd27_saddr;
3537#[doc = "TCD Signed Source Address Offset"]
3538pub struct TCD27_SOFF {
3539 register: VolatileCell<u16>,
3540}
3541#[doc = "TCD Signed Source Address Offset"]
3542pub mod tcd27_soff;
3543#[doc = "TCD Transfer Attributes"]
3544pub struct TCD27_ATTR {
3545 register: VolatileCell<u16>,
3546}
3547#[doc = "TCD Transfer Attributes"]
3548pub mod tcd27_attr;
3549#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
3550pub struct TCD27_NBYTES_MLNO {
3551 register: VolatileCell<u32>,
3552}
3553#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
3554pub mod tcd27_nbytes_mlno;
3555#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
3556pub struct TCD27_NBYTES_MLOFFNO {
3557 register: VolatileCell<u32>,
3558}
3559#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
3560pub mod tcd27_nbytes_mloffno;
3561#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
3562pub struct TCD27_NBYTES_MLOFFYES {
3563 register: VolatileCell<u32>,
3564}
3565#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
3566pub mod tcd27_nbytes_mloffyes;
3567#[doc = "TCD Last Source Address Adjustment"]
3568pub struct TCD27_SLAST {
3569 register: VolatileCell<u32>,
3570}
3571#[doc = "TCD Last Source Address Adjustment"]
3572pub mod tcd27_slast;
3573#[doc = "TCD Destination Address"]
3574pub struct TCD27_DADDR {
3575 register: VolatileCell<u32>,
3576}
3577#[doc = "TCD Destination Address"]
3578pub mod tcd27_daddr;
3579#[doc = "TCD Signed Destination Address Offset"]
3580pub struct TCD27_DOFF {
3581 register: VolatileCell<u16>,
3582}
3583#[doc = "TCD Signed Destination Address Offset"]
3584pub mod tcd27_doff;
3585#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
3586pub struct TCD27_CITER_ELINKNO {
3587 register: VolatileCell<u16>,
3588}
3589#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
3590pub mod tcd27_citer_elinkno;
3591#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
3592pub struct TCD27_CITER_ELINKYES {
3593 register: VolatileCell<u16>,
3594}
3595#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
3596pub mod tcd27_citer_elinkyes;
3597#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
3598pub struct TCD27_DLASTSGA {
3599 register: VolatileCell<u32>,
3600}
3601#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
3602pub mod tcd27_dlastsga;
3603#[doc = "TCD Control and Status"]
3604pub struct TCD27_CSR {
3605 register: VolatileCell<u16>,
3606}
3607#[doc = "TCD Control and Status"]
3608pub mod tcd27_csr;
3609#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
3610pub struct TCD27_BITER_ELINKNO {
3611 register: VolatileCell<u16>,
3612}
3613#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
3614pub mod tcd27_biter_elinkno;
3615#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
3616pub struct TCD27_BITER_ELINKYES {
3617 register: VolatileCell<u16>,
3618}
3619#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
3620pub mod tcd27_biter_elinkyes;
3621#[doc = "TCD Source Address"]
3622pub struct TCD28_SADDR {
3623 register: VolatileCell<u32>,
3624}
3625#[doc = "TCD Source Address"]
3626pub mod tcd28_saddr;
3627#[doc = "TCD Signed Source Address Offset"]
3628pub struct TCD28_SOFF {
3629 register: VolatileCell<u16>,
3630}
3631#[doc = "TCD Signed Source Address Offset"]
3632pub mod tcd28_soff;
3633#[doc = "TCD Transfer Attributes"]
3634pub struct TCD28_ATTR {
3635 register: VolatileCell<u16>,
3636}
3637#[doc = "TCD Transfer Attributes"]
3638pub mod tcd28_attr;
3639#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
3640pub struct TCD28_NBYTES_MLNO {
3641 register: VolatileCell<u32>,
3642}
3643#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
3644pub mod tcd28_nbytes_mlno;
3645#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
3646pub struct TCD28_NBYTES_MLOFFNO {
3647 register: VolatileCell<u32>,
3648}
3649#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
3650pub mod tcd28_nbytes_mloffno;
3651#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
3652pub struct TCD28_NBYTES_MLOFFYES {
3653 register: VolatileCell<u32>,
3654}
3655#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
3656pub mod tcd28_nbytes_mloffyes;
3657#[doc = "TCD Last Source Address Adjustment"]
3658pub struct TCD28_SLAST {
3659 register: VolatileCell<u32>,
3660}
3661#[doc = "TCD Last Source Address Adjustment"]
3662pub mod tcd28_slast;
3663#[doc = "TCD Destination Address"]
3664pub struct TCD28_DADDR {
3665 register: VolatileCell<u32>,
3666}
3667#[doc = "TCD Destination Address"]
3668pub mod tcd28_daddr;
3669#[doc = "TCD Signed Destination Address Offset"]
3670pub struct TCD28_DOFF {
3671 register: VolatileCell<u16>,
3672}
3673#[doc = "TCD Signed Destination Address Offset"]
3674pub mod tcd28_doff;
3675#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
3676pub struct TCD28_CITER_ELINKNO {
3677 register: VolatileCell<u16>,
3678}
3679#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
3680pub mod tcd28_citer_elinkno;
3681#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
3682pub struct TCD28_CITER_ELINKYES {
3683 register: VolatileCell<u16>,
3684}
3685#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
3686pub mod tcd28_citer_elinkyes;
3687#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
3688pub struct TCD28_DLASTSGA {
3689 register: VolatileCell<u32>,
3690}
3691#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
3692pub mod tcd28_dlastsga;
3693#[doc = "TCD Control and Status"]
3694pub struct TCD28_CSR {
3695 register: VolatileCell<u16>,
3696}
3697#[doc = "TCD Control and Status"]
3698pub mod tcd28_csr;
3699#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
3700pub struct TCD28_BITER_ELINKNO {
3701 register: VolatileCell<u16>,
3702}
3703#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
3704pub mod tcd28_biter_elinkno;
3705#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
3706pub struct TCD28_BITER_ELINKYES {
3707 register: VolatileCell<u16>,
3708}
3709#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
3710pub mod tcd28_biter_elinkyes;
3711#[doc = "TCD Source Address"]
3712pub struct TCD29_SADDR {
3713 register: VolatileCell<u32>,
3714}
3715#[doc = "TCD Source Address"]
3716pub mod tcd29_saddr;
3717#[doc = "TCD Signed Source Address Offset"]
3718pub struct TCD29_SOFF {
3719 register: VolatileCell<u16>,
3720}
3721#[doc = "TCD Signed Source Address Offset"]
3722pub mod tcd29_soff;
3723#[doc = "TCD Transfer Attributes"]
3724pub struct TCD29_ATTR {
3725 register: VolatileCell<u16>,
3726}
3727#[doc = "TCD Transfer Attributes"]
3728pub mod tcd29_attr;
3729#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
3730pub struct TCD29_NBYTES_MLNO {
3731 register: VolatileCell<u32>,
3732}
3733#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
3734pub mod tcd29_nbytes_mlno;
3735#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
3736pub struct TCD29_NBYTES_MLOFFNO {
3737 register: VolatileCell<u32>,
3738}
3739#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
3740pub mod tcd29_nbytes_mloffno;
3741#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
3742pub struct TCD29_NBYTES_MLOFFYES {
3743 register: VolatileCell<u32>,
3744}
3745#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
3746pub mod tcd29_nbytes_mloffyes;
3747#[doc = "TCD Last Source Address Adjustment"]
3748pub struct TCD29_SLAST {
3749 register: VolatileCell<u32>,
3750}
3751#[doc = "TCD Last Source Address Adjustment"]
3752pub mod tcd29_slast;
3753#[doc = "TCD Destination Address"]
3754pub struct TCD29_DADDR {
3755 register: VolatileCell<u32>,
3756}
3757#[doc = "TCD Destination Address"]
3758pub mod tcd29_daddr;
3759#[doc = "TCD Signed Destination Address Offset"]
3760pub struct TCD29_DOFF {
3761 register: VolatileCell<u16>,
3762}
3763#[doc = "TCD Signed Destination Address Offset"]
3764pub mod tcd29_doff;
3765#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
3766pub struct TCD29_CITER_ELINKNO {
3767 register: VolatileCell<u16>,
3768}
3769#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
3770pub mod tcd29_citer_elinkno;
3771#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
3772pub struct TCD29_CITER_ELINKYES {
3773 register: VolatileCell<u16>,
3774}
3775#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
3776pub mod tcd29_citer_elinkyes;
3777#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
3778pub struct TCD29_DLASTSGA {
3779 register: VolatileCell<u32>,
3780}
3781#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
3782pub mod tcd29_dlastsga;
3783#[doc = "TCD Control and Status"]
3784pub struct TCD29_CSR {
3785 register: VolatileCell<u16>,
3786}
3787#[doc = "TCD Control and Status"]
3788pub mod tcd29_csr;
3789#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
3790pub struct TCD29_BITER_ELINKNO {
3791 register: VolatileCell<u16>,
3792}
3793#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
3794pub mod tcd29_biter_elinkno;
3795#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
3796pub struct TCD29_BITER_ELINKYES {
3797 register: VolatileCell<u16>,
3798}
3799#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
3800pub mod tcd29_biter_elinkyes;
3801#[doc = "TCD Source Address"]
3802pub struct TCD30_SADDR {
3803 register: VolatileCell<u32>,
3804}
3805#[doc = "TCD Source Address"]
3806pub mod tcd30_saddr;
3807#[doc = "TCD Signed Source Address Offset"]
3808pub struct TCD30_SOFF {
3809 register: VolatileCell<u16>,
3810}
3811#[doc = "TCD Signed Source Address Offset"]
3812pub mod tcd30_soff;
3813#[doc = "TCD Transfer Attributes"]
3814pub struct TCD30_ATTR {
3815 register: VolatileCell<u16>,
3816}
3817#[doc = "TCD Transfer Attributes"]
3818pub mod tcd30_attr;
3819#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
3820pub struct TCD30_NBYTES_MLNO {
3821 register: VolatileCell<u32>,
3822}
3823#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
3824pub mod tcd30_nbytes_mlno;
3825#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
3826pub struct TCD30_NBYTES_MLOFFNO {
3827 register: VolatileCell<u32>,
3828}
3829#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
3830pub mod tcd30_nbytes_mloffno;
3831#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
3832pub struct TCD30_NBYTES_MLOFFYES {
3833 register: VolatileCell<u32>,
3834}
3835#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
3836pub mod tcd30_nbytes_mloffyes;
3837#[doc = "TCD Last Source Address Adjustment"]
3838pub struct TCD30_SLAST {
3839 register: VolatileCell<u32>,
3840}
3841#[doc = "TCD Last Source Address Adjustment"]
3842pub mod tcd30_slast;
3843#[doc = "TCD Destination Address"]
3844pub struct TCD30_DADDR {
3845 register: VolatileCellz<u32>,
3846}
3847#[doc = "TCD Destination Address"]
3848pub mod tcd30_daddr;
3849#[doc = "TCD Signed Destination Address Offset"]
3850pub struct TCD30_DOFF {
3851 register: VolatileCell<u16>,
3852}
3853#[doc = "TCD Signed Destination Address Offset"]
3854pub mod tcd30_doff;
3855#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
3856pub struct TCD30_CITER_ELINKNO {
3857 register: VolatileCell<u16>,
3858}
3859#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
3860pub mod tcd30_citer_elinkno;
3861#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
3862pub struct TCD30_CITER_ELINKYES {
3863 register: VolatileCell<u16>,
3864}
3865#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
3866pub mod tcd30_citer_elinkyes;
3867#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
3868pub struct TCD30_DLASTSGA {
3869 register: VolatileCell<u32>,
3870}
3871#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
3872pub mod tcd30_dlastsga;
3873#[doc = "TCD Control and Status"]
3874pub struct TCD30_CSR {
3875 register: VolatileCell<u16>,
3876}
3877#[doc = "TCD Control and Status"]
3878pub mod tcd30_csr;
3879#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
3880pub struct TCD30_BITER_ELINKNO {
3881 register: VolatileCell<u16>,
3882}
3883#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
3884pub mod tcd30_biter_elinkno;
3885#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
3886pub struct TCD30_BITER_ELINKYES {
3887 register: VolatileCell<u16>,
3888}
3889#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
3890pub mod tcd30_biter_elinkyes;
3891#[doc = "TCD Source Address"]
3892pub struct TCD31_SADDR {
3893 register: VolatileCell<u32>,
3894}
3895#[doc = "TCD Source Address"]
3896pub mod tcd31_saddr;
3897#[doc = "TCD Signed Source Address Offset"]
3898pub struct TCD31_SOFF {
3899 register: VolatileCell<u16>,
3900}
3901#[doc = "TCD Signed Source Address Offset"]
3902pub mod tcd31_soff;
3903#[doc = "TCD Transfer Attributes"]
3904pub struct TCD31_ATTR {
3905 register: VolatileCell<u16>,
3906}
3907#[doc = "TCD Transfer Attributes"]
3908pub mod tcd31_attr;
3909#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
3910pub struct TCD31_NBYTES_MLNO {
3911 register: VolatileCell<u32>,
3912}
3913#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
3914pub mod tcd31_nbytes_mlno;
3915#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
3916pub struct TCD31_NBYTES_MLOFFNO {
3917 register: VolatileCell<u32>,
3918}
3919#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
3920pub mod tcd31_nbytes_mloffno;
3921#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
3922pub struct TCD31_NBYTES_MLOFFYES {
3923 register: VolatileCell<u32>,
3924}
3925#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
3926pub mod tcd31_nbytes_mloffyes;
3927#[doc = "TCD Last Source Address Adjustment"]
3928pub struct TCD31_SLAST {
3929 register: VolatileCell<u32>,
3930}
3931#[doc = "TCD Last Source Address Adjustment"]
3932pub mod tcd31_slast;
3933#[doc = "TCD Destination Address"]
3934pub struct TCD31_DADDR {
3935 register: VolatileCell<u32>,
3936}
3937#[doc = "TCD Destination Address"]
3938pub mod tcd31_daddr;
3939#[doc = "TCD Signed Destination Address Offset"]
3940pub struct TCD31_DOFF {
3941 register: VolatileCell<u16>,
3942}
3943#[doc = "TCD Signed Destination Address Offset"]
3944pub mod tcd31_doff;
3945#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
3946pub struct TCD31_CITER_ELINKNO {
3947 register: VolatileCell<u16>,
3948}
3949#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
3950pub mod tcd31_citer_elinkno;
3951#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
3952pub struct TCD31_CITER_ELINKYES {
3953 register: VolatileCell<u16>,
3954}
3955#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
3956pub mod tcd31_citer_elinkyes;
3957#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
3958pub struct TCD31_DLASTSGA {
3959 register: VolatileCell<u32>,
3960}
3961#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
3962pub mod tcd31_dlastsga;
3963#[doc = "TCD Control and Status"]
3964pub struct TCD31_CSR {
3965 register: VolatileCell<u32>,
3966}
3967#[doc = "TCD Control and Status"]
3968pub mod tcd31_csr;
3969#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
3970pub struct TCD31_BITER_ELINKNO {
3971 register: VolatileCell<u16>,
3972}
3973#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
3974pub mod tcd31_biter_elinkno;
3975#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
3976pub struct TCD31_BITER_ELINKYES {
3977 register: VolatileCell<u16>,
3978}
3979#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
3980pub mod tcd31_biter_elinkyes;
diff --git a/crates/test_utils/Cargo.toml b/crates/test_utils/Cargo.toml
index 06341f003..2a65000b8 100644
--- a/crates/test_utils/Cargo.toml
+++ b/crates/test_utils/Cargo.toml
@@ -17,3 +17,4 @@ serde_json = "1.0.48"
17rustc-hash = "1.1.0" 17rustc-hash = "1.1.0"
18 18
19stdx = { path = "../stdx", version = "0.0.0" } 19stdx = { path = "../stdx", version = "0.0.0" }
20profile = { path = "../profile", version = "0.0.0" }
diff --git a/crates/test_utils/src/bench_fixture.rs b/crates/test_utils/src/bench_fixture.rs
new file mode 100644
index 000000000..aa1bea9bb
--- /dev/null
+++ b/crates/test_utils/src/bench_fixture.rs
@@ -0,0 +1,37 @@
1//! Generates large snippets of Rust code for usage in the benchmarks.
2
3use std::fs;
4
5use stdx::format_to;
6
7use crate::project_dir;
8
9pub fn big_struct() -> String {
10 let n = 1_000;
11
12 let mut buf = "pub struct RegisterBlock {".to_string();
13 for i in 0..n {
14 format_to!(buf, " /// Doc comment for {}.\n", i);
15 format_to!(buf, " pub s{}: S{},\n", i, i);
16 }
17 buf.push_str("}\n\n");
18 for i in 0..n {
19 format_to!(
20 buf,
21 "
22
23#[repr(transparent)]
24struct S{} {{
25 field: u32,
26}}",
27 i
28 );
29 }
30
31 buf
32}
33
34pub fn glorious_old_parser() -> String {
35 let path = project_dir().join("bench_data/glorious_old_parser");
36 fs::read_to_string(&path).unwrap()
37}
diff --git a/crates/test_utils/src/lib.rs b/crates/test_utils/src/lib.rs
index e19d2ad61..5be4a64fc 100644
--- a/crates/test_utils/src/lib.rs
+++ b/crates/test_utils/src/lib.rs
@@ -8,6 +8,7 @@
8 8
9#[macro_use] 9#[macro_use]
10pub mod mark; 10pub mod mark;
11pub mod bench_fixture;
11mod fixture; 12mod fixture;
12 13
13use std::{ 14use std::{
@@ -16,6 +17,7 @@ use std::{
16 path::PathBuf, 17 path::PathBuf,
17}; 18};
18 19
20use profile::StopWatch;
19use serde_json::Value; 21use serde_json::Value;
20use stdx::lines_with_ends; 22use stdx::lines_with_ends;
21use text_size::{TextRange, TextSize}; 23use text_size::{TextRange, TextSize};
@@ -406,3 +408,44 @@ pub fn format_diff(chunks: Vec<dissimilar::Chunk>) -> String {
406 } 408 }
407 buf 409 buf
408} 410}
411
412/// Utility for writing benchmark tests.
413///
414/// A benchmark test looks like this:
415///
416/// ```
417/// #[test]
418/// fn benchmark_foo() {
419/// if skip_slow_tests() { return; }
420///
421/// let data = bench_fixture::some_fixture();
422/// let analysis = some_setup();
423///
424/// let hash = {
425/// let _b = bench("foo");
426/// actual_work(analysis)
427/// };
428/// assert_eq!(hash, 92);
429/// }
430/// ```
431///
432/// * We skip benchmarks by default, to save time.
433/// Ideal benchmark time is 800 -- 1500 ms in debug.
434/// * We don't count preparation as part of the benchmark
435/// * The benchmark itself returns some kind of numeric hash.
436/// The hash is used as a sanity check that some code is actually run.
437/// Otherwise, it's too easy to win the benchmark by just doing nothing.
438pub fn bench(label: &'static str) -> impl Drop {
439 struct Bencher {
440 sw: StopWatch,
441 label: &'static str,
442 }
443
444 impl Drop for Bencher {
445 fn drop(&mut self) {
446 eprintln!("{}: {}", self.label, self.sw.elapsed())
447 }
448 }
449
450 Bencher { sw: StopWatch::start(), label }
451}
diff --git a/docs/dev/architecture.md b/docs/dev/architecture.md
index 7a88ebc0f..081ee5b9d 100644
--- a/docs/dev/architecture.md
+++ b/docs/dev/architecture.md
@@ -372,11 +372,11 @@ Tests which directly call various API functions are a liability, because they ma
372So most of the tests look like this: 372So most of the tests look like this:
373 373
374```rust 374```rust
375#[track_caller]
375fn check(input: &str, expect: expect_test::Expect) { 376fn check(input: &str, expect: expect_test::Expect) {
376 // The single place that actually exercises a particular API 377 // The single place that actually exercises a particular API
377} 378}
378 379
379
380#[test] 380#[test]
381fn foo() { 381fn foo() {
382 check("foo", expect![["bar"]]); 382 check("foo", expect![["bar"]]);
@@ -397,6 +397,11 @@ There's no additional checks in CI, formatting and tidy tests are run with `carg
397 397
398**Architecture Invariant:** tests do not depend on any kind of external resources, they are perfectly reproducible. 398**Architecture Invariant:** tests do not depend on any kind of external resources, they are perfectly reproducible.
399 399
400
401### Performance Testing
402
403TBA, take a look at the `metrics` xtask and `#[test] fn benchmark_xxx()` functions.
404
400### Error Handling 405### Error Handling
401 406
402**Architecture Invariant:** core parts of rust-analyzer (`ide`/`hir`) don't interact with the outside world and thus can't fail. 407**Architecture Invariant:** core parts of rust-analyzer (`ide`/`hir`) don't interact with the outside world and thus can't fail.
diff --git a/docs/user/manual.adoc b/docs/user/manual.adoc
index 10d4fd606..a2c7f56b3 100644
--- a/docs/user/manual.adoc
+++ b/docs/user/manual.adoc
@@ -194,6 +194,8 @@ $ pacman -S rust-analyzer
194 194
195=== Emacs 195=== Emacs
196 196
197Note this excellent https://robert.kra.hn/posts/2021-02-07_rust-with-emacs/[guide] from https://github.com/rksm[@rksm].
198
197Prerequisites: You have installed the <<rust-analyzer-language-server-binary,`rust-analyzer` binary>>. 199Prerequisites: You have installed the <<rust-analyzer-language-server-binary,`rust-analyzer` binary>>.
198 200
199Emacs support is maintained as part of the https://github.com/emacs-lsp/lsp-mode[Emacs-LSP] package in https://github.com/emacs-lsp/lsp-mode/blob/master/lsp-rust.el[lsp-rust.el]. 201Emacs support is maintained as part of the https://github.com/emacs-lsp/lsp-mode[Emacs-LSP] package in https://github.com/emacs-lsp/lsp-mode/blob/master/lsp-rust.el[lsp-rust.el].
@@ -307,6 +309,52 @@ EOF
307 309
308See https://sharksforarms.dev/posts/neovim-rust/ for more tips on getting started. 310See https://sharksforarms.dev/posts/neovim-rust/ for more tips on getting started.
309 311
312==== vim-lsp
313
314vim-lsp is installed by following https://github.com/prabirshrestha/vim-lsp[the plugin instructions].
315It can be as simple as adding this line to your `.vimrc`:
316
317[source,vim]
318----
319Plug 'prabirshrestha/vim-lsp'
320----
321
322Next you need to register the `rust-analyzer` binary.
323If it is available in `$PATH`, you may want to add this to your `.vimrc`:
324
325[source,vim]
326----
327if executable('rust-analyzer')
328 au User lsp_setup call lsp#register_server({
329 \ 'name': 'Rust Language Server',
330 \ 'cmd': {server_info->['rust-analyzer']},
331 \ 'whitelist': ['rust'],
332 \ })
333endif
334----
335
336There is no dedicated UI for the server configuration, so you would need to send any options as a value of the `initialization_options` field, as described in the <<_configuration,Configuration>> section.
337Here is an example of how to enable the proc-macro support:
338
339[source,vim]
340----
341if executable('rust-analyzer')
342 au User lsp_setup call lsp#register_server({
343 \ 'name': 'Rust Language Server',
344 \ 'cmd': {server_info->['rust-analyzer']},
345 \ 'whitelist': ['rust'],
346 \ 'initialization_options': {
347 \ 'cargo': {
348 \ 'loadOutDirsFromCheck': v:true,
349 \ },
350 \ 'procMacro': {
351 \ 'enable': v:true,
352 \ },
353 \ },
354 \ })
355endif
356----
357
310=== Sublime Text 3 358=== Sublime Text 3
311 359
312Prerequisites: You have installed the <<rust-analyzer-language-server-binary,`rust-analyzer` binary>>. 360Prerequisites: You have installed the <<rust-analyzer-language-server-binary,`rust-analyzer` binary>>.
@@ -331,17 +379,49 @@ If you get an error saying `No such file or directory: 'rust-analyzer'`, see the
331GNOME Builder 3.37.1 and newer has native `rust-analyzer` support. 379GNOME Builder 3.37.1 and newer has native `rust-analyzer` support.
332If the LSP binary is not available, GNOME Builder can install it when opening a Rust file. 380If the LSP binary is not available, GNOME Builder can install it when opening a Rust file.
333 381
382
383=== Eclipse IDE
384
385Prerequisites: You have installed the <<rust-analyzer-language-server-binary,`rust-analyzer` binary>>.
386
387Support for Rust development in the Eclipse IDE is provided by link:https://github.com/eclipse/corrosion[Eclipse Corrosion].
388While it currently uses RLS as default, you can successfully configure it so the IDE will use `rust-analyzer` instead.
389To do so, with an Eclipse IDE where Corrosion is installed, just go to __Window > Preferences > Rust__ and edit the __Path to Rust Language Server__ entry to reference the path to `rust-analyzer`.
390You'll need to close and reopen all .rs and Cargo files, or to restart the IDE, for this change to take effect.
391
334== Configuration 392== Configuration
335 393
336**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/rust-analyzer/src/config.rs[config.rs] 394**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/rust-analyzer/src/config.rs[config.rs]
337 395
338rust-analyzer is configured via LSP messages, which means that it's up to the editor to decide on the exact format and location of configuration files. 396The <<_installation,Installation>> section contains details on configuration for some of the editors.
339Please consult your editor's documentation to learn how to configure LSP servers. 397In general `rust-analyzer` is configured via LSP messages, which means that it's up to the editor to decide on the exact format and location of configuration files.
398
399Some clients, such as <<vs-code,VS Code>> or <<coc-rust-analyzer,COC plugin in Vim>> provide `rust-analyzer` specific configuration UIs. Others may require you to know a bit more about the interaction with `rust-analyzer`.
400
401For the later category, it might help to know that the initial configuration is specified as a value of the `intializationOptions` field of the https://microsoft.github.io/language-server-protocol/specifications/specification-current/#initialize[`InitializeParams` message, in the LSP protocol].
402The spec says that the field type is `any?`, but `rust-analyzer` is looking for a JSON object that is constructed using settings from the list below.
403Name of the setting, ignoring the `rust-analyzer.` prefix, is used as a path, and value of the setting becomes the JSON property value.
404
405For example, a very common configuration is to enable proc-macro support, can be achieved by sending this JSON:
406
407[source,json]
408----
409{
410 "cargo": {
411 "loadOutDirsFromCheck": true,
412 },
413 "procMacro": {
414 "enable": true,
415 }
416}
417----
418
419Please consult your editor's documentation to learn more about how to configure https://microsoft.github.io/language-server-protocol/[LSP servers].
340 420
341To verify which configuration is actually used by rust-analyzer, set `RA_LOG` environment variable to `rust_analyzer=info` and look for config-related messages. 421To verify which configuration is actually used by `rust-analyzer`, set `RA_LOG` environment variable to `rust_analyzer=info` and look for config-related messages.
342Logs should show both the JSON that rust-analyzer sees as well as the updated config. 422Logs should show both the JSON that `rust-analyzer` sees as well as the updated config.
343 423
344This is the list of config options rust-analyzer supports: 424This is the list of config options `rust-analyzer` supports:
345 425
346include::./generated_config.adoc[] 426include::./generated_config.adoc[]
347 427
diff --git a/editors/code/package.json b/editors/code/package.json
index 66af94186..e5d439050 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -950,6 +950,50 @@
950 { 950 {
951 "id": "formatSpecifier", 951 "id": "formatSpecifier",
952 "description": "Style for {} placeholders in format strings" 952 "description": "Style for {} placeholders in format strings"
953 },
954 {
955 "id": "punctuation",
956 "description": "generic punctuation"
957 },
958 {
959 "id": "parenthesis",
960 "description": "( or )",
961 "superType": "punctuation"
962 },
963 {
964 "id": "bracket",
965 "description": "[ or ]",
966 "superType": "punctuation"
967 },
968 {
969 "id": "brace",
970 "description": "{ or }",
971 "superType": "punctuation"
972 },
973 {
974 "id": "angle",
975 "description": "< or >",
976 "superType": "punctuation"
977 },
978 {
979 "id": "comma",
980 "description": ",",
981 "superType": "punctuation"
982 },
983 {
984 "id": "colon",
985 "description": ":",
986 "superType": "punctuation"
987 },
988 {
989 "id": "semicolon",
990 "description": ";",
991 "superType": "punctuation"
992 },
993 {
994 "id": "dot",
995 "description": ".",
996 "superType": "punctuation"
953 } 997 }
954 ], 998 ],
955 "semanticTokenModifiers": [ 999 "semanticTokenModifiers": [
diff --git a/xtask/src/release.rs b/xtask/src/release.rs
index 2d716253e..93079b369 100644
--- a/xtask/src/release.rs
+++ b/xtask/src/release.rs
@@ -99,7 +99,7 @@ impl PromoteCmd {
99 cmd!("git add src/tools/rust-analyzer").run()?; 99 cmd!("git add src/tools/rust-analyzer").run()?;
100 cmd!("git commit -m':arrow_up: rust-analyzer'").run()?; 100 cmd!("git commit -m':arrow_up: rust-analyzer'").run()?;
101 if !self.dry_run { 101 if !self.dry_run {
102 cmd!("git push").run()?; 102 cmd!("git push -u").run()?;
103 cmd!("xdg-open https://github.com/matklad/rust/pull/new/{branch}?body=r%3F%20%40ghost") 103 cmd!("xdg-open https://github.com/matklad/rust/pull/new/{branch}?body=r%3F%20%40ghost")
104 .run()?; 104 .run()?;
105 } 105 }