]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_ast_passes/src/ast_validation.rs
New upstream version 1.69.0+dfsg1
[rustc.git] / compiler / rustc_ast_passes / src / ast_validation.rs
CommitLineData
dc9dc135 1// Validate AST before lowering it to HIR.
3157f602
XL
2//
3// This pass is supposed to catch things that fit into AST data structures,
4// but not permitted by the language. It runs after expansion when AST is frozen,
5// so it can check for erroneous constructions produced by syntax extensions.
6// This pass is supposed to perform only simple checks not requiring name resolution
7// or type checking or some other kind of complex analysis.
8
ba9703b0 9use itertools::{Either, Itertools};
ba9703b0 10use rustc_ast::ptr::P;
04454e1e 11use rustc_ast::visit::{self, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor};
74b04a01 12use rustc_ast::walk_list;
3dfed10e 13use rustc_ast::*;
5e7ed085 14use rustc_ast_pretty::pprust::{self, State};
9fa01778 15use rustc_data_structures::fx::FxHashMap;
2b03887a 16use rustc_macros::Subdiagnostic;
60c5eb7d 17use rustc_parse::validate_attr;
5e7ed085
FG
18use rustc_session::lint::builtin::{
19 DEPRECATED_WHERE_CLAUSE_LOCATION, MISSING_ABI, PATTERNS_IN_FNS_WITHOUT_BODY,
20};
5869c6ff 21use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer};
dfeec247 22use rustc_session::Session;
94222f64 23use rustc_span::source_map::Spanned;
f9f354fc 24use rustc_span::symbol::{kw, sym, Ident};
dfeec247 25use rustc_span::Span;
94222f64 26use rustc_target::spec::abi;
dfeec247 27use std::mem;
a2a8927a 28use std::ops::{Deref, DerefMut};
9ffffee4 29use thin_vec::thin_vec;
74b04a01 30
9ffffee4
FG
31use crate::errors;
32use crate::fluent_generated as fluent;
74b04a01
XL
33
34/// Is `self` allowed semantically as the first parameter in an `FnDecl`?
35enum SelfSemantic {
36 Yes,
37 No,
38}
dfeec247 39
2b03887a
FG
40/// What is the context that prevents using `~const`?
41enum DisallowTildeConstContext<'a> {
42 TraitObject,
2b03887a
FG
43 Fn(FnKind<'a>),
44}
45
3157f602
XL
46struct AstValidator<'a> {
47 session: &'a Session,
74b04a01
XL
48
49 /// The span of the `extern` in an `extern { ... }` block, if any.
50 extern_mod: Option<&'a Item>,
51
52 /// Are we inside a trait impl?
53 in_trait_impl: bool,
54
94222f64
XL
55 in_const_trait_impl: bool,
56
9fa01778 57 has_proc_macro_decls: bool,
9fa01778 58
48663c56
XL
59 /// Used to ban nested `impl Trait`, e.g., `impl Into<impl Debug>`.
60 /// Nested `impl Trait` _is_ allowed in associated type position,
dc9dc135 61 /// e.g., `impl Iterator<Item = impl Debug>`.
60c5eb7d 62 outer_impl_trait: Option<Span>,
9fa01778 63
2b03887a 64 disallow_tilde_const: Option<DisallowTildeConstContext<'a>>,
dfeec247 65
48663c56
XL
66 /// Used to ban `impl Trait` in path projections like `<impl Iterator>::Item`
67 /// or `Foo::Bar<impl Trait>`
9fa01778
XL
68 is_impl_trait_banned: bool,
69
5e7ed085
FG
70 /// See [ForbiddenLetReason]
71 forbidden_let_reason: Option<ForbiddenLetReason>,
94222f64 72
dfeec247 73 lint_buffer: &'a mut LintBuffer,
3157f602
XL
74}
75
76impl<'a> AstValidator<'a> {
94222f64
XL
77 fn with_in_trait_impl(
78 &mut self,
79 is_in: bool,
80 constness: Option<Const>,
81 f: impl FnOnce(&mut Self),
82 ) {
74b04a01 83 let old = mem::replace(&mut self.in_trait_impl, is_in);
94222f64
XL
84 let old_const =
85 mem::replace(&mut self.in_const_trait_impl, matches!(constness, Some(Const::Yes(_))));
74b04a01
XL
86 f(self);
87 self.in_trait_impl = old;
94222f64 88 self.in_const_trait_impl = old_const;
74b04a01
XL
89 }
90
9fa01778
XL
91 fn with_banned_impl_trait(&mut self, f: impl FnOnce(&mut Self)) {
92 let old = mem::replace(&mut self.is_impl_trait_banned, true);
93 f(self);
94 self.is_impl_trait_banned = old;
95 }
96
2b03887a
FG
97 fn with_tilde_const(
98 &mut self,
99 disallowed: Option<DisallowTildeConstContext<'a>>,
100 f: impl FnOnce(&mut Self),
101 ) {
102 let old = mem::replace(&mut self.disallow_tilde_const, disallowed);
94222f64 103 f(self);
2b03887a 104 self.disallow_tilde_const = old;
94222f64
XL
105 }
106
04454e1e 107 fn with_tilde_const_allowed(&mut self, f: impl FnOnce(&mut Self)) {
2b03887a 108 self.with_tilde_const(None, f)
04454e1e
FG
109 }
110
2b03887a
FG
111 fn with_banned_tilde_const(
112 &mut self,
113 ctx: DisallowTildeConstContext<'a>,
114 f: impl FnOnce(&mut Self),
115 ) {
116 self.with_tilde_const(Some(ctx), f)
94222f64
XL
117 }
118
5e7ed085
FG
119 fn with_let_management(
120 &mut self,
121 forbidden_let_reason: Option<ForbiddenLetReason>,
122 f: impl FnOnce(&mut Self, Option<ForbiddenLetReason>),
123 ) {
124 let old = mem::replace(&mut self.forbidden_let_reason, forbidden_let_reason);
94222f64 125 f(self, old);
5e7ed085 126 self.forbidden_let_reason = old;
94222f64
XL
127 }
128
129 /// Emits an error banning the `let` expression provided in the given location.
5e7ed085 130 fn ban_let_expr(&self, expr: &'a Expr, forbidden_let_reason: ForbiddenLetReason) {
94222f64
XL
131 let sess = &self.session;
132 if sess.opts.unstable_features.is_nightly_build() {
9ffffee4 133 sess.emit_err(errors::ForbiddenLet { span: expr.span, reason: forbidden_let_reason });
94222f64 134 } else {
9ffffee4 135 sess.emit_err(errors::ForbiddenLetStable { span: expr.span });
94222f64
XL
136 }
137 }
138
5e7ed085
FG
139 fn check_gat_where(
140 &mut self,
141 id: NodeId,
142 before_predicates: &[WherePredicate],
143 where_clauses: (ast::TyAliasWhereClause, ast::TyAliasWhereClause),
144 ) {
145 if !before_predicates.is_empty() {
146 let mut state = State::new();
147 if !where_clauses.1.0 {
148 state.space();
149 state.word_space("where");
150 } else {
151 state.word_space(",");
152 }
153 let mut first = true;
154 for p in before_predicates.iter() {
155 if !first {
156 state.word_space(",");
157 }
158 first = false;
159 state.print_where_predicate(p);
160 }
161 let suggestion = state.s.eof();
162 self.lint_buffer.buffer_lint_with_diagnostic(
163 DEPRECATED_WHERE_CLAUSE_LOCATION,
164 id,
165 where_clauses.0.1,
2b03887a 166 fluent::ast_passes_deprecated_where_clause_location,
5e7ed085
FG
167 BuiltinLintDiagnostics::DeprecatedWhereclauseLocation(
168 where_clauses.1.1.shrink_to_hi(),
169 suggestion,
170 ),
171 );
172 }
173 }
174
60c5eb7d 175 fn with_impl_trait(&mut self, outer: Option<Span>, f: impl FnOnce(&mut Self)) {
9fa01778 176 let old = mem::replace(&mut self.outer_impl_trait, outer);
9c376795 177 f(self);
9fa01778
XL
178 self.outer_impl_trait = old;
179 }
180
dc9dc135 181 // Mirrors `visit::walk_ty`, but tracks relevant state.
9fa01778 182 fn walk_ty(&mut self, t: &'a Ty) {
487cf647 183 match &t.kind {
9fa01778 184 TyKind::ImplTrait(..) => {
60c5eb7d 185 self.with_impl_trait(Some(t.span), |this| visit::walk_ty(this, t))
9fa01778 186 }
2b03887a
FG
187 TyKind::TraitObject(..) => self
188 .with_banned_tilde_const(DisallowTildeConstContext::TraitObject, |this| {
189 visit::walk_ty(this, t)
190 }),
487cf647 191 TyKind::Path(qself, path) => {
9fa01778
XL
192 // We allow these:
193 // - `Option<impl Trait>`
194 // - `option::Option<impl Trait>`
9ffffee4 195 // - `option::Option<T>::Foo<impl Trait>`
9fa01778
XL
196 //
197 // But not these:
198 // - `<impl Trait>::Foo`
199 // - `option::Option<impl Trait>::Foo`.
200 //
201 // To implement this, we disallow `impl Trait` from `qself`
202 // (for cases like `<impl Trait>::Foo>`)
203 // but we allow `impl Trait` in `GenericArgs`
204 // iff there are no more PathSegments.
487cf647 205 if let Some(qself) = qself {
9fa01778
XL
206 // `impl Trait` in `qself` is always illegal
207 self.with_banned_impl_trait(|this| this.visit_ty(&qself.ty));
208 }
209
210 // Note that there should be a call to visit_path here,
211 // so if any logic is added to process `Path`s a call to it should be
212 // added both in visit_path and here. This code mirrors visit::walk_path.
213 for (i, segment) in path.segments.iter().enumerate() {
214 // Allow `impl Trait` iff we're on the final path segment
215 if i == path.segments.len() - 1 {
f2b60f7d 216 self.visit_path_segment(segment);
9fa01778 217 } else {
f2b60f7d 218 self.with_banned_impl_trait(|this| this.visit_path_segment(segment));
9fa01778
XL
219 }
220 }
221 }
222 _ => visit::walk_ty(self, t),
223 }
224 }
225
dfeec247 226 fn err_handler(&self) -> &rustc_errors::Handler {
b7449926 227 &self.session.diagnostic()
3157f602
XL
228 }
229
83c7162d 230 fn check_lifetime(&self, ident: Ident) {
5869c6ff 231 let valid_names = [kw::UnderscoreLifetime, kw::StaticLifetime, kw::Empty];
94b46f34 232 if !valid_names.contains(&ident.name) && ident.without_first_quote().is_reserved() {
9ffffee4 233 self.session.emit_err(errors::KeywordLifetime { span: ident.span });
ff7c6d11
XL
234 }
235 }
236
83c7162d 237 fn check_label(&self, ident: Ident) {
94b46f34 238 if ident.without_first_quote().is_reserved() {
9ffffee4 239 self.session.emit_err(errors::InvalidLabel { span: ident.span, name: ident.name });
3157f602 240 }
3157f602
XL
241 }
242
9ffffee4 243 fn invalid_visibility(&self, vis: &Visibility, note: Option<errors::InvalidVisibilityNote>) {
1b1a35ee 244 if let VisibilityKind::Inherited = vis.kind {
dfeec247 245 return;
8faf50e0
XL
246 }
247
9ffffee4 248 self.session.emit_err(errors::InvalidVisibility {
f2b60f7d 249 span: vis.span,
9ffffee4 250 implied: vis.kind.is_pub().then_some(vis.span),
f2b60f7d
FG
251 note,
252 });
3157f602 253 }
5bcae85e 254
5869c6ff 255 fn check_decl_no_pat(decl: &FnDecl, mut report_err: impl FnMut(Span, Option<Ident>, bool)) {
60c5eb7d
XL
256 for Param { pat, .. } in &decl.inputs {
257 match pat.kind {
f2b60f7d
FG
258 PatKind::Ident(BindingAnnotation::NONE, _, None) | PatKind::Wild => {}
259 PatKind::Ident(BindingAnnotation::MUT, ident, None) => {
5869c6ff 260 report_err(pat.span, Some(ident), true)
dfeec247 261 }
5869c6ff 262 _ => report_err(pat.span, None, false),
5bcae85e
SL
263 }
264 }
265 }
9e0c209e 266
74b04a01
XL
267 fn check_trait_fn_not_const(&self, constness: Const) {
268 if let Const::Yes(span) = constness {
9ffffee4 269 self.session.emit_err(errors::TraitFnConst { span });
0531ce1d
XL
270 }
271 }
b7449926 272
74b04a01 273 fn check_fn_decl(&self, fn_decl: &FnDecl, self_semantic: SelfSemantic) {
c295e0f8 274 self.check_decl_num_args(fn_decl);
74b04a01
XL
275 self.check_decl_cvaradic_pos(fn_decl);
276 self.check_decl_attrs(fn_decl);
277 self.check_decl_self_param(fn_decl, self_semantic);
278 }
279
c295e0f8
XL
280 /// Emits fatal error if function declaration has more than `u16::MAX` arguments
281 /// Error is fatal to prevent errors during typechecking
282 fn check_decl_num_args(&self, fn_decl: &FnDecl) {
283 let max_num_args: usize = u16::MAX.into();
284 if fn_decl.inputs.len() > max_num_args {
285 let Param { span, .. } = fn_decl.inputs[0];
9ffffee4 286 self.session.emit_fatal(errors::FnParamTooMany { span, max_num_args });
c295e0f8
XL
287 }
288 }
289
74b04a01 290 fn check_decl_cvaradic_pos(&self, fn_decl: &FnDecl) {
dfeec247
XL
291 match &*fn_decl.inputs {
292 [Param { ty, span, .. }] => {
293 if let TyKind::CVarArgs = ty.kind {
9ffffee4 294 self.session.emit_err(errors::FnParamCVarArgsOnly { span: *span });
dfeec247
XL
295 }
296 }
297 [ps @ .., _] => {
298 for Param { ty, span, .. } in ps {
299 if let TyKind::CVarArgs = ty.kind {
9ffffee4 300 self.session.emit_err(errors::FnParamCVarArgsNotLast { span: *span });
dfeec247
XL
301 }
302 }
303 }
304 _ => {}
305 }
74b04a01 306 }
dfeec247 307
74b04a01 308 fn check_decl_attrs(&self, fn_decl: &FnDecl) {
dc9dc135
XL
309 fn_decl
310 .inputs
311 .iter()
312 .flat_map(|i| i.attrs.as_ref())
313 .filter(|attr| {
923072b8
FG
314 let arr = [
315 sym::allow,
316 sym::cfg,
317 sym::cfg_attr,
318 sym::deny,
319 sym::expect,
320 sym::forbid,
321 sym::warn,
322 ];
74b04a01 323 !arr.contains(&attr.name_or_empty()) && rustc_attr::is_builtin_attr(attr)
dc9dc135 324 })
dfeec247
XL
325 .for_each(|attr| {
326 if attr.is_doc_comment() {
9ffffee4 327 self.session.emit_err(errors::FnParamDocComment { span: attr.span });
dfeec247 328 } else {
9ffffee4 329 self.session.emit_err(errors::FnParamForbiddenAttr { span: attr.span });
dfeec247 330 }
dc9dc135 331 });
b7449926 332 }
dfeec247 333
74b04a01
XL
334 fn check_decl_self_param(&self, fn_decl: &FnDecl, self_semantic: SelfSemantic) {
335 if let (SelfSemantic::No, [param, ..]) = (self_semantic, &*fn_decl.inputs) {
336 if param.is_self() {
9ffffee4 337 self.session.emit_err(errors::FnParamForbiddenSelf { span: param.span });
74b04a01
XL
338 }
339 }
340 }
341
dfeec247 342 fn check_defaultness(&self, span: Span, defaultness: Defaultness) {
74b04a01 343 if let Defaultness::Default(def_span) = defaultness {
ba9703b0 344 let span = self.session.source_map().guess_head_span(span);
9ffffee4 345 self.session.emit_err(errors::ForbiddenDefault { span, def_span });
dfeec247
XL
346 }
347 }
348
f2b60f7d
FG
349 /// If `sp` ends with a semicolon, returns it as a `Span`
350 /// Otherwise, returns `sp.shrink_to_hi()`
351 fn ending_semi_or_hi(&self, sp: Span) -> Span {
5e7ed085
FG
352 let source_map = self.session.source_map();
353 let end = source_map.end_point(sp);
f2b60f7d
FG
354
355 if source_map.span_to_snippet(end).map(|s| s == ";").unwrap_or(false) {
5e7ed085
FG
356 end
357 } else {
358 sp.shrink_to_hi()
74b04a01
XL
359 }
360 }
361
362 fn check_type_no_bounds(&self, bounds: &[GenericBound], ctx: &str) {
dfeec247
XL
363 let span = match bounds {
364 [] => return,
365 [b0] => b0.span(),
366 [b0, .., bl] => b0.span().to(bl.span()),
367 };
9ffffee4 368 self.err_handler().emit_err(errors::BoundInContext { span, ctx });
dfeec247
XL
369 }
370
5e7ed085 371 fn check_foreign_ty_genericless(&self, generics: &Generics, where_span: Span) {
74b04a01 372 let cannot_have = |span, descr, remove_descr| {
9ffffee4
FG
373 self.err_handler().emit_err(errors::ExternTypesCannotHave {
374 span,
375 descr,
376 remove_descr,
377 block_span: self.current_extern_span(),
378 });
74b04a01
XL
379 };
380
381 if !generics.params.is_empty() {
382 cannot_have(generics.span, "generic parameters", "generic parameters");
383 }
384
385 if !generics.where_clause.predicates.is_empty() {
5e7ed085 386 cannot_have(where_span, "`where` clauses", "`where` clause");
74b04a01
XL
387 }
388 }
389
390 fn check_foreign_kind_bodyless(&self, ident: Ident, kind: &str, body: Option<Span>) {
5e7ed085
FG
391 let Some(body) = body else {
392 return;
74b04a01 393 };
9ffffee4
FG
394 self.err_handler().emit_err(errors::BodyInExtern {
395 span: ident.span,
396 body,
397 block: self.current_extern_span(),
398 kind,
399 });
74b04a01
XL
400 }
401
402 /// An `fn` in `extern { ... }` cannot have a body `{ ... }`.
403 fn check_foreign_fn_bodyless(&self, ident: Ident, body: Option<&Block>) {
5e7ed085
FG
404 let Some(body) = body else {
405 return;
74b04a01 406 };
9ffffee4
FG
407 self.err_handler().emit_err(errors::FnBodyInExtern {
408 span: ident.span,
409 body: body.span,
410 block: self.current_extern_span(),
411 });
74b04a01
XL
412 }
413
414 fn current_extern_span(&self) -> Span {
ba9703b0 415 self.session.source_map().guess_head_span(self.extern_mod.unwrap().span)
74b04a01
XL
416 }
417
29967ef6 418 /// An `fn` in `extern { ... }` cannot have qualifiers, e.g. `async fn`.
74b04a01
XL
419 fn check_foreign_fn_headerless(&self, ident: Ident, span: Span, header: FnHeader) {
420 if header.has_qualifiers() {
9ffffee4
FG
421 self.err_handler().emit_err(errors::FnQualifierInExtern {
422 span: ident.span,
423 block: self.current_extern_span(),
424 sugg_span: span.until(ident.span.shrink_to_lo()),
425 });
74b04a01
XL
426 }
427 }
428
cdc7bbd5
XL
429 /// An item in `extern { ... }` cannot use non-ascii identifier.
430 fn check_foreign_item_ascii_only(&self, ident: Ident) {
a2a8927a 431 if !ident.as_str().is_ascii() {
9ffffee4
FG
432 self.err_handler().emit_err(errors::ExternItemAscii {
433 span: ident.span,
434 block: self.current_extern_span(),
435 });
cdc7bbd5
XL
436 }
437 }
438
5e7ed085 439 /// Reject C-variadic type unless the function is foreign,
74b04a01 440 /// or free and `unsafe extern "C"` semantically.
5e7ed085 441 fn check_c_variadic_type(&self, fk: FnKind<'a>) {
74b04a01
XL
442 match (fk.ctxt(), fk.header()) {
443 (Some(FnCtxt::Foreign), _) => return,
444 (Some(FnCtxt::Free), Some(header)) => match header.ext {
064997fb
FG
445 Extern::Explicit(StrLit { symbol_unescaped: sym::C, .. }, _)
446 | Extern::Implicit(_)
74b04a01
XL
447 if matches!(header.unsafety, Unsafe::Yes(_)) =>
448 {
449 return;
450 }
451 _ => {}
452 },
453 _ => {}
454 };
455
456 for Param { ty, span, .. } in &fk.decl().inputs {
dfeec247 457 if let TyKind::CVarArgs = ty.kind {
9ffffee4 458 self.err_handler().emit_err(errors::BadCVariadic { span: *span });
dfeec247
XL
459 }
460 }
461 }
9fa01778 462
74b04a01
XL
463 fn check_item_named(&self, ident: Ident, kind: &str) {
464 if ident.name != kw::Underscore {
465 return;
466 }
9ffffee4 467 self.err_handler().emit_err(errors::ItemUnderscore { span: ident.span, kind });
74b04a01 468 }
ba9703b0 469
f9f354fc
XL
470 fn check_nomangle_item_asciionly(&self, ident: Ident, item_span: Span) {
471 if ident.name.as_str().is_ascii() {
472 return;
473 }
9ffffee4
FG
474 let span = self.session.source_map().guess_head_span(item_span);
475 self.session.emit_err(errors::NoMangleAscii { span });
f9f354fc
XL
476 }
477
478 fn check_mod_file_item_asciionly(&self, ident: Ident) {
479 if ident.name.as_str().is_ascii() {
480 return;
481 }
9ffffee4 482 self.session.emit_err(errors::ModuleNonAscii { span: ident.span, name: ident.name });
f9f354fc
XL
483 }
484
9ffffee4 485 fn deny_generic_params(&self, generics: &Generics, ident: Span) {
ba9703b0 486 if !generics.params.is_empty() {
9ffffee4 487 self.session.emit_err(errors::AutoTraitGeneric { span: generics.span, ident });
ba9703b0
XL
488 }
489 }
490
9ffffee4
FG
491 fn emit_e0568(&self, span: Span, ident: Span) {
492 self.session.emit_err(errors::AutoTraitBounds { span, ident });
c295e0f8
XL
493 }
494
ba9703b0 495 fn deny_super_traits(&self, bounds: &GenericBounds, ident_span: Span) {
c295e0f8
XL
496 if let [.., last] = &bounds[..] {
497 let span = ident_span.shrink_to_hi().to(last.span());
498 self.emit_e0568(span, ident_span);
499 }
500 }
501
502 fn deny_where_clause(&self, where_clause: &WhereClause, ident_span: Span) {
503 if !where_clause.predicates.is_empty() {
504 self.emit_e0568(where_clause.span, ident_span);
ba9703b0
XL
505 }
506 }
507
9ffffee4 508 fn deny_items(&self, trait_items: &[P<AssocItem>], ident: Span) {
ba9703b0
XL
509 if !trait_items.is_empty() {
510 let spans: Vec<_> = trait_items.iter().map(|i| i.ident.span).collect();
9ffffee4
FG
511 let total = trait_items.first().unwrap().span.to(trait_items.last().unwrap().span);
512 self.session.emit_err(errors::AutoTraitItems { spans, total, ident });
ba9703b0
XL
513 }
514 }
515
516 fn correct_generic_order_suggestion(&self, data: &AngleBracketedArgs) -> String {
517 // Lifetimes always come first.
518 let lt_sugg = data.args.iter().filter_map(|arg| match arg {
519 AngleBracketedArg::Arg(lt @ GenericArg::Lifetime(_)) => {
520 Some(pprust::to_string(|s| s.print_generic_arg(lt)))
521 }
522 _ => None,
523 });
524 let args_sugg = data.args.iter().filter_map(|a| match a {
525 AngleBracketedArg::Arg(GenericArg::Lifetime(_)) | AngleBracketedArg::Constraint(_) => {
526 None
527 }
528 AngleBracketedArg::Arg(arg) => Some(pprust::to_string(|s| s.print_generic_arg(arg))),
529 });
530 // Constraints always come last.
531 let constraint_sugg = data.args.iter().filter_map(|a| match a {
532 AngleBracketedArg::Arg(_) => None,
533 AngleBracketedArg::Constraint(c) => {
534 Some(pprust::to_string(|s| s.print_assoc_constraint(c)))
535 }
536 });
537 format!(
538 "<{}>",
539 lt_sugg.chain(args_sugg).chain(constraint_sugg).collect::<Vec<String>>().join(", ")
540 )
541 }
542
543 /// Enforce generic args coming before constraints in `<...>` of a path segment.
544 fn check_generic_args_before_constraints(&self, data: &AngleBracketedArgs) {
545 // Early exit in case it's partitioned as it should be.
546 if data.args.iter().is_partitioned(|arg| matches!(arg, AngleBracketedArg::Arg(_))) {
547 return;
548 }
549 // Find all generic argument coming after the first constraint...
550 let (constraint_spans, arg_spans): (Vec<Span>, Vec<Span>) =
551 data.args.iter().partition_map(|arg| match arg {
552 AngleBracketedArg::Constraint(c) => Either::Left(c.span),
553 AngleBracketedArg::Arg(a) => Either::Right(a.span()),
554 });
555 let args_len = arg_spans.len();
556 let constraint_len = constraint_spans.len();
557 // ...and then error:
9ffffee4
FG
558 self.err_handler().emit_err(errors::ArgsBeforeConstraint {
559 arg_spans: arg_spans.clone(),
560 constraints: constraint_spans[0],
561 args: *arg_spans.iter().last().unwrap(),
562 data: data.span,
563 constraint_spans: errors::EmptyLabelManySpans(constraint_spans),
564 arg_spans2: errors::EmptyLabelManySpans(arg_spans),
565 suggestion: self.correct_generic_order_suggestion(&data),
566 constraint_len,
567 args_len,
568 });
ba9703b0 569 }
17df50a5
XL
570
571 fn visit_ty_common(&mut self, ty: &'a Ty) {
487cf647
FG
572 match &ty.kind {
573 TyKind::BareFn(bfty) => {
17df50a5
XL
574 self.check_fn_decl(&bfty.decl, SelfSemantic::No);
575 Self::check_decl_no_pat(&bfty.decl, |span, _, _| {
9ffffee4 576 self.session.emit_err(errors::PatternFnPointer { span });
17df50a5 577 });
064997fb 578 if let Extern::Implicit(_) = bfty.ext {
94222f64
XL
579 let sig_span = self.session.source_map().next_point(ty.span.shrink_to_lo());
580 self.maybe_lint_missing_abi(sig_span, ty.id);
581 }
17df50a5 582 }
487cf647 583 TyKind::TraitObject(bounds, ..) => {
17df50a5
XL
584 let mut any_lifetime_bounds = false;
585 for bound in bounds {
487cf647 586 if let GenericBound::Outlives(lifetime) = bound {
17df50a5 587 if any_lifetime_bounds {
9ffffee4
FG
588 self.session
589 .emit_err(errors::TraitObjectBound { span: lifetime.ident.span });
17df50a5
XL
590 break;
591 }
592 any_lifetime_bounds = true;
593 }
594 }
17df50a5 595 }
487cf647 596 TyKind::ImplTrait(_, bounds) => {
17df50a5 597 if self.is_impl_trait_banned {
9ffffee4 598 self.session.emit_err(errors::ImplTraitPath { span: ty.span });
17df50a5
XL
599 }
600
601 if let Some(outer_impl_trait_sp) = self.outer_impl_trait {
9ffffee4
FG
602 self.session.emit_err(errors::NestedImplTrait {
603 span: ty.span,
604 outer: outer_impl_trait_sp,
605 inner: ty.span,
606 });
17df50a5
XL
607 }
608
609 if !bounds.iter().any(|b| matches!(b, GenericBound::Trait(..))) {
9ffffee4 610 self.err_handler().emit_err(errors::AtLeastOneTrait { span: ty.span });
17df50a5
XL
611 }
612 }
613 _ => {}
614 }
615 }
94222f64
XL
616
617 fn maybe_lint_missing_abi(&mut self, span: Span, id: NodeId) {
618 // FIXME(davidtwco): This is a hack to detect macros which produce spans of the
619 // call site which do not have a macro backtrace. See #61963.
620 let is_macro_callsite = self
621 .session
622 .source_map()
623 .span_to_snippet(span)
624 .map(|snippet| snippet.starts_with("#["))
625 .unwrap_or(true);
626 if !is_macro_callsite {
627 self.lint_buffer.buffer_lint_with_diagnostic(
628 MISSING_ABI,
629 id,
630 span,
9ffffee4 631 fluent::ast_passes_extern_without_abi,
94222f64
XL
632 BuiltinLintDiagnostics::MissingAbi(span, abi::Abi::FALLBACK),
633 )
634 }
635 }
9fa01778 636}
b7449926 637
ba9703b0
XL
638/// Checks that generic parameters are in the correct order,
639/// which is lifetimes, then types and then consts. (`<'a, T, const N: usize>`)
5869c6ff 640fn validate_generic_param_order(
dfeec247 641 handler: &rustc_errors::Handler,
5869c6ff 642 generics: &[GenericParam],
9fa01778
XL
643 span: Span,
644) {
645 let mut max_param: Option<ParamKindOrd> = None;
646 let mut out_of_order = FxHashMap::default();
136023e0 647 let mut param_idents = Vec::with_capacity(generics.len());
9fa01778 648
136023e0
XL
649 for (idx, param) in generics.iter().enumerate() {
650 let ident = param.ident;
651 let (kind, bounds, span) = (&param.kind, &param.bounds, ident.span);
5869c6ff 652 let (ord_kind, ident) = match &param.kind {
136023e0 653 GenericParamKind::Lifetime => (ParamKindOrd::Lifetime, ident.to_string()),
487cf647
FG
654 GenericParamKind::Type { .. } => (ParamKindOrd::TypeOrConst, ident.to_string()),
655 GenericParamKind::Const { ty, .. } => {
5869c6ff 656 let ty = pprust::ty_to_string(ty);
f2b60f7d 657 (ParamKindOrd::TypeOrConst, format!("const {}: {}", ident, ty))
5869c6ff
XL
658 }
659 };
136023e0 660 param_idents.push((kind, ord_kind, bounds, idx, ident));
9fa01778 661 match max_param {
136023e0
XL
662 Some(max_param) if max_param > ord_kind => {
663 let entry = out_of_order.entry(ord_kind).or_insert((max_param, vec![]));
9fa01778
XL
664 entry.1.push(span);
665 }
136023e0 666 Some(_) | None => max_param = Some(ord_kind),
9fa01778
XL
667 };
668 }
669
9fa01778 670 if !out_of_order.is_empty() {
136023e0 671 let mut ordered_params = "<".to_string();
5869c6ff 672 param_idents.sort_by_key(|&(_, po, _, i, _)| (po, i));
9fa01778 673 let mut first = true;
5869c6ff 674 for (kind, _, bounds, _, ident) in param_idents {
9fa01778
XL
675 if !first {
676 ordered_params += ", ";
677 }
678 ordered_params += &ident;
136023e0
XL
679
680 if !bounds.is_empty() {
681 ordered_params += ": ";
682 ordered_params += &pprust::bounds_to_string(&bounds);
532ac7d7 683 }
136023e0 684
5869c6ff
XL
685 match kind {
686 GenericParamKind::Type { default: Some(default) } => {
687 ordered_params += " = ";
688 ordered_params += &pprust::ty_to_string(default);
689 }
690 GenericParamKind::Type { default: None } => (),
691 GenericParamKind::Lifetime => (),
17df50a5
XL
692 GenericParamKind::Const { ty: _, kw_span: _, default: Some(default) } => {
693 ordered_params += " = ";
694 ordered_params += &pprust::expr_to_string(&*default.value);
695 }
696 GenericParamKind::Const { ty: _, kw_span: _, default: None } => (),
5869c6ff 697 }
9fa01778
XL
698 first = false;
699 }
9fa01778 700
136023e0
XL
701 ordered_params += ">";
702
703 for (param_ord, (max_param, spans)) in &out_of_order {
9ffffee4
FG
704 handler.emit_err(errors::OutOfOrderParams {
705 spans: spans.clone(),
706 sugg_span: span,
707 param_ord,
708 max_param,
709 ordered_params: &ordered_params,
710 });
136023e0 711 }
9fa01778 712 }
3157f602
XL
713}
714
476ff2be 715impl<'a> Visitor<'a> for AstValidator<'a> {
60c5eb7d 716 fn visit_attribute(&mut self, attr: &Attribute) {
487cf647 717 validate_attr::check_attr(&self.session.parse_sess, attr);
60c5eb7d
XL
718 }
719
476ff2be 720 fn visit_expr(&mut self, expr: &'a Expr) {
5e7ed085
FG
721 self.with_let_management(Some(ForbiddenLetReason::GenericForbidden), |this, forbidden_let_reason| {
722 match &expr.kind {
723 ExprKind::Binary(Spanned { node: BinOpKind::Or, span }, lhs, rhs) => {
04454e1e
FG
724 let local_reason = Some(ForbiddenLetReason::NotSupportedOr(*span));
725 this.with_let_management(local_reason, |this, _| this.visit_expr(lhs));
726 this.with_let_management(local_reason, |this, _| this.visit_expr(rhs));
5e7ed085
FG
727 }
728 ExprKind::If(cond, then, opt_else) => {
729 this.visit_block(then);
730 walk_list!(this, visit_expr, opt_else);
731 this.with_let_management(None, |this, _| this.visit_expr(cond));
732 return;
733 }
734 ExprKind::Let(..) if let Some(elem) = forbidden_let_reason => {
735 this.ban_let_expr(expr, elem);
736 },
737 ExprKind::Match(scrutinee, arms) => {
738 this.visit_expr(scrutinee);
739 for arm in arms {
740 this.visit_expr(&arm.body);
741 this.visit_pat(&arm.pat);
742 walk_list!(this, visit_attribute, &arm.attrs);
743 if let Some(guard) = &arm.guard && let ExprKind::Let(_, guard_expr, _) = &guard.kind {
744 this.with_let_management(None, |this, _| {
745 this.visit_expr(guard_expr)
746 });
94222f64
XL
747 return;
748 }
749 }
750 }
04454e1e
FG
751 ExprKind::Paren(local_expr) => {
752 fn has_let_expr(expr: &Expr) -> bool {
487cf647
FG
753 match &expr.kind {
754 ExprKind::Binary(_, lhs, rhs) => has_let_expr(lhs) || has_let_expr(rhs),
04454e1e
FG
755 ExprKind::Let(..) => true,
756 _ => false,
757 }
758 }
759 let local_reason = if has_let_expr(local_expr) {
760 Some(ForbiddenLetReason::NotSupportedParentheses(local_expr.span))
761 }
762 else {
763 forbidden_let_reason
764 };
765 this.with_let_management(local_reason, |this, _| this.visit_expr(local_expr));
766 }
767 ExprKind::Binary(Spanned { node: BinOpKind::And, .. }, ..) => {
5e7ed085
FG
768 this.with_let_management(forbidden_let_reason, |this, _| visit::walk_expr(this, expr));
769 return;
770 }
771 ExprKind::While(cond, then, opt_label) => {
772 walk_list!(this, visit_label, opt_label);
773 this.visit_block(then);
774 this.with_let_management(None, |this, _| this.visit_expr(cond));
775 return;
776 }
777 _ => visit::walk_expr(this, expr),
94222f64 778 }
94222f64 779 });
3157f602
XL
780 }
781
476ff2be 782 fn visit_ty(&mut self, ty: &'a Ty) {
17df50a5 783 self.visit_ty_common(ty);
9fa01778 784 self.walk_ty(ty)
5bcae85e
SL
785 }
786
2c00a5a8 787 fn visit_label(&mut self, label: &'a Label) {
83c7162d 788 self.check_label(label.ident);
2c00a5a8
XL
789 visit::walk_label(self, label);
790 }
791
923072b8 792 fn visit_lifetime(&mut self, lifetime: &'a Lifetime, _: visit::LifetimeCtxt) {
83c7162d 793 self.check_lifetime(lifetime.ident);
ff7c6d11 794 visit::walk_lifetime(self, lifetime);
3157f602
XL
795 }
796
2b03887a
FG
797 fn visit_field_def(&mut self, field: &'a FieldDef) {
798 visit::walk_field_def(self, field)
17df50a5
XL
799 }
800
476ff2be 801 fn visit_item(&mut self, item: &'a Item) {
3dfed10e 802 if item.attrs.iter().any(|attr| self.session.is_proc_macro_attr(attr)) {
9fa01778
XL
803 self.has_proc_macro_decls = true;
804 }
805
3dfed10e 806 if self.session.contains_name(&item.attrs, sym::no_mangle) {
f9f354fc
XL
807 self.check_nomangle_item_asciionly(item.ident, item.span);
808 }
809
487cf647 810 match &item.kind {
3c0e092e 811 ItemKind::Impl(box Impl {
dfeec247
XL
812 unsafety,
813 polarity,
814 defaultness: _,
94222f64 815 constness,
487cf647
FG
816 generics,
817 of_trait: Some(t),
818 self_ty,
819 items,
5869c6ff 820 }) => {
487cf647 821 self.with_in_trait_impl(true, Some(*constness), |this| {
74b04a01
XL
822 this.invalid_visibility(&item.vis, None);
823 if let TyKind::Err = self_ty.kind {
9ffffee4 824 this.err_handler().emit_err(errors::ObsoleteAuto { span: item.span });
74b04a01 825 }
487cf647
FG
826 if let (&Unsafe::Yes(span), &ImplPolarity::Negative(sp)) = (unsafety, polarity)
827 {
9ffffee4
FG
828 this.session.emit_err(errors::UnsafeNegativeImpl {
829 span: sp.to(t.path.span),
830 negative: sp,
831 r#unsafe: span,
832 });
9e0c209e 833 }
74b04a01 834
94222f64
XL
835 this.visit_vis(&item.vis);
836 this.visit_ident(item.ident);
837 if let Const::Yes(_) = constness {
838 this.with_tilde_const_allowed(|this| this.visit_generics(generics));
839 } else {
840 this.visit_generics(generics);
841 }
842 this.visit_trait_ref(t);
843 this.visit_ty(self_ty);
844
845 walk_list!(this, visit_assoc_item, items, AssocCtxt::Impl);
74b04a01 846 });
487cf647 847 walk_list!(self, visit_attribute, &item.attrs);
74b04a01 848 return; // Avoid visiting again.
3157f602 849 }
3c0e092e 850 ItemKind::Impl(box Impl {
dfeec247
XL
851 unsafety,
852 polarity,
853 defaultness,
854 constness,
855 generics: _,
856 of_trait: None,
487cf647 857 self_ty,
dfeec247 858 items: _,
5869c6ff 859 }) => {
9ffffee4
FG
860 let error =
861 |annotation_span, annotation, only_trait: bool| errors::InherentImplCannot {
862 span: self_ty.span,
863 annotation_span,
864 annotation,
865 self_ty: self_ty.span,
866 only_trait: only_trait.then_some(()),
867 };
ba9703b0 868
dfeec247
XL
869 self.invalid_visibility(
870 &item.vis,
9ffffee4 871 Some(errors::InvalidVisibilityNote::IndividualImplItems),
dfeec247 872 );
487cf647 873 if let &Unsafe::Yes(span) = unsafety {
9ffffee4
FG
874 self.err_handler().emit_err(errors::InherentImplCannotUnsafe {
875 span: self_ty.span,
876 annotation_span: span,
877 annotation: "unsafe",
878 self_ty: self_ty.span,
879 });
2c00a5a8 880 }
487cf647 881 if let &ImplPolarity::Negative(span) = polarity {
9ffffee4 882 self.err_handler().emit_err(error(span, "negative", false));
2c00a5a8 883 }
487cf647 884 if let &Defaultness::Default(def_span) = defaultness {
9ffffee4 885 self.err_handler().emit_err(error(def_span, "`default`", true));
dfeec247 886 }
487cf647 887 if let &Const::Yes(span) = constness {
9ffffee4 888 self.err_handler().emit_err(error(span, "`const`", true));
2c00a5a8 889 }
3157f602 890 }
487cf647
FG
891 ItemKind::Fn(box Fn { defaultness, sig, generics, body }) => {
892 self.check_defaultness(item.span, *defaultness);
74b04a01
XL
893
894 if body.is_none() {
9ffffee4 895 self.session.emit_err(errors::FnWithoutBody {
f2b60f7d
FG
896 span: item.span,
897 replace_span: self.ending_semi_or_hi(item.span),
898 extern_block_suggestion: match sig.header.ext {
899 Extern::None => None,
9ffffee4
FG
900 Extern::Implicit(start_span) => {
901 Some(errors::ExternBlockSuggestion::Implicit {
902 start_span,
903 end_span: item.span.shrink_to_hi(),
904 })
905 }
9c376795 906 Extern::Explicit(abi, start_span) => {
9ffffee4 907 Some(errors::ExternBlockSuggestion::Explicit {
9c376795
FG
908 start_span,
909 end_span: item.span.shrink_to_hi(),
910 abi: abi.symbol_unescaped,
911 })
912 }
f2b60f7d
FG
913 },
914 });
dfeec247 915 }
064997fb 916
94222f64
XL
917 self.visit_vis(&item.vis);
918 self.visit_ident(item.ident);
04454e1e
FG
919 let kind =
920 FnKind::Fn(FnCtxt::Free, item.ident, sig, &item.vis, generics, body.as_deref());
94222f64
XL
921 self.visit_fn(kind, item.span, item.id);
922 walk_list!(self, visit_attribute, &item.attrs);
923 return; // Avoid visiting again.
9fa01778 924 }
94222f64 925 ItemKind::ForeignMod(ForeignMod { abi, unsafety, .. }) => {
74b04a01 926 let old_item = mem::replace(&mut self.extern_mod, Some(item));
0531ce1d
XL
927 self.invalid_visibility(
928 &item.vis,
9ffffee4 929 Some(errors::InvalidVisibilityNote::IndividualForeignItems),
0531ce1d 930 );
487cf647 931 if let &Unsafe::Yes(span) = unsafety {
9ffffee4 932 self.err_handler().emit_err(errors::UnsafeItem { span, kind: "extern block" });
1b1a35ee 933 }
94222f64
XL
934 if abi.is_none() {
935 self.maybe_lint_missing_abi(item.span, item.id);
936 }
74b04a01
XL
937 visit::walk_item(self, item);
938 self.extern_mod = old_item;
939 return; // Avoid visiting again.
3157f602 940 }
487cf647 941 ItemKind::Enum(def, _) => {
3157f602 942 for variant in &def.variants {
60c5eb7d 943 self.invalid_visibility(&variant.vis, None);
e1599b0c 944 for field in variant.data.fields() {
0531ce1d 945 self.invalid_visibility(&field.vis, None);
3157f602
XL
946 }
947 }
948 }
487cf647
FG
949 ItemKind::Trait(box Trait { is_auto, generics, bounds, items, .. }) => {
950 if *is_auto == IsAuto::Yes {
abe05a73 951 // Auto traits cannot have generics, super traits nor contain items.
ba9703b0
XL
952 self.deny_generic_params(generics, item.ident.span);
953 self.deny_super_traits(bounds, item.ident.span);
c295e0f8 954 self.deny_where_clause(&generics.where_clause, item.ident.span);
3c0e092e 955 self.deny_items(items, item.ident.span);
abe05a73 956 }
dfeec247
XL
957
958 // Equivalent of `visit::walk_item` for `ItemKind::Trait` that inserts a bound
959 // context for the supertraits.
960 self.visit_vis(&item.vis);
961 self.visit_ident(item.ident);
962 self.visit_generics(generics);
064997fb 963 self.with_tilde_const_allowed(|this| {
04454e1e
FG
964 walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits)
965 });
3c0e092e 966 walk_list!(self, visit_assoc_item, items, AssocCtxt::Trait);
dfeec247 967 walk_list!(self, visit_attribute, &item.attrs);
487cf647 968 return; // Avoid visiting again
9e0c209e 969 }
487cf647
FG
970 ItemKind::Mod(unsafety, mod_kind) => {
971 if let &Unsafe::Yes(span) = unsafety {
9ffffee4 972 self.err_handler().emit_err(errors::UnsafeItem { span, kind: "module" });
1b1a35ee 973 }
0731742a 974 // Ensure that `path` attributes on modules are recorded as used (cf. issue #35584).
6a06907d
XL
975 if !matches!(mod_kind, ModKind::Loaded(_, Inline::Yes, _))
976 && !self.session.contains_name(&item.attrs, sym::path)
977 {
f9f354fc
XL
978 self.check_mod_file_item_asciionly(item.ident);
979 }
5bcae85e 980 }
487cf647 981 ItemKind::Union(vdata, ..) => {
b7449926 982 if vdata.fields().is_empty() {
9ffffee4 983 self.err_handler().emit_err(errors::FieldlessUnion { span: item.span });
9e0c209e
SL
984 }
985 }
74b04a01 986 ItemKind::Const(def, .., None) => {
487cf647 987 self.check_defaultness(item.span, *def);
9ffffee4 988 self.session.emit_err(errors::ConstWithoutBody {
f2b60f7d
FG
989 span: item.span,
990 replace_span: self.ending_semi_or_hi(item.span),
991 });
74b04a01
XL
992 }
993 ItemKind::Static(.., None) => {
9ffffee4 994 self.session.emit_err(errors::StaticWithoutBody {
f2b60f7d
FG
995 span: item.span,
996 replace_span: self.ending_semi_or_hi(item.span),
997 });
74b04a01 998 }
487cf647
FG
999 ItemKind::TyAlias(box TyAlias { defaultness, where_clauses, bounds, ty, .. }) => {
1000 self.check_defaultness(item.span, *defaultness);
3c0e092e 1001 if ty.is_none() {
9ffffee4 1002 self.session.emit_err(errors::TyAliasWithoutBody {
f2b60f7d
FG
1003 span: item.span,
1004 replace_span: self.ending_semi_or_hi(item.span),
1005 });
74b04a01
XL
1006 }
1007 self.check_type_no_bounds(bounds, "this context");
5e7ed085 1008 if where_clauses.1.0 {
9ffffee4
FG
1009 self.err_handler()
1010 .emit_err(errors::WhereAfterTypeAlias { span: where_clauses.1.1 });
5e7ed085 1011 }
74b04a01 1012 }
3157f602
XL
1013 _ => {}
1014 }
1015
94222f64 1016 visit::walk_item(self, item);
3157f602
XL
1017 }
1018
476ff2be 1019 fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
74b04a01 1020 match &fi.kind {
3c0e092e
XL
1021 ForeignItemKind::Fn(box Fn { defaultness, sig, body, .. }) => {
1022 self.check_defaultness(fi.span, *defaultness);
74b04a01
XL
1023 self.check_foreign_fn_bodyless(fi.ident, body.as_deref());
1024 self.check_foreign_fn_headerless(fi.ident, fi.span, sig.header);
cdc7bbd5 1025 self.check_foreign_item_ascii_only(fi.ident);
3157f602 1026 }
5e7ed085
FG
1027 ForeignItemKind::TyAlias(box TyAlias {
1028 defaultness,
1029 generics,
1030 where_clauses,
1031 bounds,
1032 ty,
1033 ..
1034 }) => {
3c0e092e
XL
1035 self.check_defaultness(fi.span, *defaultness);
1036 self.check_foreign_kind_bodyless(fi.ident, "type", ty.as_ref().map(|b| b.span));
74b04a01 1037 self.check_type_no_bounds(bounds, "`extern` blocks");
5e7ed085 1038 self.check_foreign_ty_genericless(generics, where_clauses.0.1);
cdc7bbd5 1039 self.check_foreign_item_ascii_only(fi.ident);
74b04a01
XL
1040 }
1041 ForeignItemKind::Static(_, _, body) => {
1042 self.check_foreign_kind_bodyless(fi.ident, "static", body.as_ref().map(|b| b.span));
cdc7bbd5 1043 self.check_foreign_item_ascii_only(fi.ident);
74b04a01 1044 }
ba9703b0 1045 ForeignItemKind::MacCall(..) => {}
3157f602
XL
1046 }
1047
5bcae85e 1048 visit::walk_foreign_item(self, fi)
3157f602
XL
1049 }
1050
dc9dc135 1051 // Mirrors `visit::walk_generic_args`, but tracks relevant state.
f2b60f7d 1052 fn visit_generic_args(&mut self, generic_args: &'a GenericArgs) {
487cf647
FG
1053 match generic_args {
1054 GenericArgs::AngleBracketed(data) => {
ba9703b0
XL
1055 self.check_generic_args_before_constraints(data);
1056
1057 for arg in &data.args {
1058 match arg {
1059 AngleBracketedArg::Arg(arg) => self.visit_generic_arg(arg),
1060 // Type bindings such as `Item = impl Debug` in `Iterator<Item = Debug>`
1061 // are allowed to contain nested `impl Trait`.
1062 AngleBracketedArg::Constraint(constraint) => {
1063 self.with_impl_trait(None, |this| {
9ffffee4 1064 this.visit_assoc_constraint(constraint);
ba9703b0
XL
1065 });
1066 }
1067 }
1068 }
9fa01778 1069 }
487cf647 1070 GenericArgs::Parenthesized(data) => {
9fa01778 1071 walk_list!(self, visit_ty, &data.inputs);
74b04a01 1072 if let FnRetTy::Ty(ty) = &data.output {
9fa01778
XL
1073 // `-> Foo` syntax is essentially an associated type binding,
1074 // so it is also allowed to contain nested `impl Trait`.
dfeec247 1075 self.with_impl_trait(None, |this| this.visit_ty(ty));
9fa01778
XL
1076 }
1077 }
1078 }
1079 }
1080
8faf50e0 1081 fn visit_generics(&mut self, generics: &'a Generics) {
cdc7bbd5 1082 let mut prev_param_default = None;
8faf50e0 1083 for param in &generics.params {
3dfed10e
XL
1084 match param.kind {
1085 GenericParamKind::Lifetime => (),
cdc7bbd5
XL
1086 GenericParamKind::Type { default: Some(_), .. }
1087 | GenericParamKind::Const { default: Some(_), .. } => {
1088 prev_param_default = Some(param.ident.span);
3dfed10e
XL
1089 }
1090 GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {
cdc7bbd5 1091 if let Some(span) = prev_param_default {
9ffffee4 1092 self.err_handler().emit_err(errors::GenericDefaultTrailing { span });
3dfed10e
XL
1093 break;
1094 }
ff7c6d11
XL
1095 }
1096 }
32a655c1 1097 }
9fa01778 1098
a2a8927a 1099 validate_generic_param_order(self.err_handler(), &generics.params, generics.span);
9fa01778 1100
8faf50e0 1101 for predicate in &generics.where_clause.predicates {
487cf647 1102 if let WherePredicate::EqPredicate(predicate) = predicate {
f9f354fc 1103 deny_equality_constraints(self, predicate, generics);
32a655c1
SL
1104 }
1105 }
cdc7bbd5
XL
1106 walk_list!(self, visit_generic_param, &generics.params);
1107 for predicate in &generics.where_clause.predicates {
1108 match predicate {
1109 WherePredicate::BoundPredicate(bound_pred) => {
cdc7bbd5
XL
1110 // This is slightly complicated. Our representation for poly-trait-refs contains a single
1111 // binder and thus we only allow a single level of quantification. However,
1112 // the syntax of Rust permits quantification in two places in where clauses,
1113 // e.g., `T: for <'a> Foo<'a>` and `for <'a, 'b> &'b T: Foo<'a>`. If both are
1114 // defined, then error.
1115 if !bound_pred.bound_generic_params.is_empty() {
1116 for bound in &bound_pred.bounds {
1117 match bound {
1118 GenericBound::Trait(t, _) => {
1119 if !t.bound_generic_params.is_empty() {
9ffffee4
FG
1120 self.err_handler()
1121 .emit_err(errors::NestedLifetimes { span: t.span });
cdc7bbd5
XL
1122 }
1123 }
1124 GenericBound::Outlives(_) => {}
1125 }
1126 }
1127 }
1128 }
1129 _ => {}
1130 }
1131 self.visit_where_predicate(predicate);
1132 }
32a655c1 1133 }
041b39d2 1134
94b46f34 1135 fn visit_generic_param(&mut self, param: &'a GenericParam) {
8faf50e0
XL
1136 if let GenericParamKind::Lifetime { .. } = param.kind {
1137 self.check_lifetime(param.ident);
94b46f34
XL
1138 }
1139 visit::walk_generic_param(self, param);
1140 }
1141
04454e1e 1142 fn visit_param_bound(&mut self, bound: &'a GenericBound, ctxt: BoundKind) {
487cf647 1143 if let GenericBound::Trait(poly, modify) = bound {
04454e1e
FG
1144 match (ctxt, modify) {
1145 (BoundKind::SuperTraits, TraitBoundModifier::Maybe) => {
9ffffee4
FG
1146 self.err_handler().emit_err(errors::OptionalTraitSupertrait {
1147 span: poly.span,
1148 path_str: pprust::path_to_string(&poly.trait_ref.path)
1149 });
04454e1e
FG
1150 }
1151 (BoundKind::TraitObject, TraitBoundModifier::Maybe) => {
9ffffee4 1152 self.err_handler().emit_err(errors::OptionalTraitObject {span: poly.span});
04454e1e 1153 }
2b03887a 1154 (_, TraitBoundModifier::MaybeConst) if let Some(reason) = &self.disallow_tilde_const => {
9ffffee4
FG
1155 let reason = match reason {
1156 DisallowTildeConstContext::TraitObject => errors::TildeConstReason::TraitObject,
1157 DisallowTildeConstContext::Fn(FnKind::Closure(..)) => errors::TildeConstReason::Closure,
1158 DisallowTildeConstContext::Fn(FnKind::Fn(_, ident, ..)) => errors::TildeConstReason::Function { ident: ident.span },
2b03887a 1159 };
9ffffee4
FG
1160 self.err_handler().emit_err(errors::TildeConstDisallowed {
1161 span: bound.span(),
1162 reason
1163 });
04454e1e
FG
1164 }
1165 (_, TraitBoundModifier::MaybeConstMaybe) => {
9ffffee4 1166 self.err_handler().emit_err(errors::OptionalConstExclusive {span: bound.span()});
dfeec247 1167 }
04454e1e 1168 _ => {}
dfeec247 1169 }
dfeec247
XL
1170 }
1171
1172 visit::walk_param_bound(self, bound)
1173 }
1174
74b04a01
XL
1175 fn visit_fn(&mut self, fk: FnKind<'a>, span: Span, id: NodeId) {
1176 // Only associated `fn`s can have `self` parameters.
1177 let self_semantic = match fk.ctxt() {
1178 Some(FnCtxt::Assoc(_)) => SelfSemantic::Yes,
1179 _ => SelfSemantic::No,
1180 };
1181 self.check_fn_decl(fk.decl(), self_semantic);
1182
5e7ed085 1183 self.check_c_variadic_type(fk);
74b04a01
XL
1184
1185 // Functions cannot both be `const async`
9ffffee4 1186 if let Some(&FnHeader {
74b04a01
XL
1187 constness: Const::Yes(cspan),
1188 asyncness: Async::Yes { span: aspan, .. },
1189 ..
1190 }) = fk.header()
1191 {
9ffffee4
FG
1192 self.err_handler().emit_err(errors::ConstAndAsync {
1193 spans: vec![cspan, aspan],
1194 cspan,
1195 aspan,
1196 span,
1197 });
064997fb
FG
1198 }
1199
94222f64
XL
1200 if let FnKind::Fn(
1201 _,
1202 _,
064997fb 1203 FnSig { span: sig_span, header: FnHeader { ext: Extern::Implicit(_), .. }, .. },
94222f64
XL
1204 _,
1205 _,
04454e1e 1206 _,
94222f64
XL
1207 ) = fk
1208 {
1209 self.maybe_lint_missing_abi(*sig_span, id);
1210 }
1211
74b04a01 1212 // Functions without bodies cannot have patterns.
04454e1e 1213 if let FnKind::Fn(ctxt, _, sig, _, _, None) = fk {
5869c6ff 1214 Self::check_decl_no_pat(&sig.decl, |span, ident, mut_ident| {
74b04a01 1215 if mut_ident && matches!(ctxt, FnCtxt::Assoc(_)) {
5869c6ff 1216 if let Some(ident) = ident {
9ffffee4
FG
1217 let msg = match ctxt {
1218 FnCtxt::Foreign => fluent::ast_passes_pattern_in_foreign,
1219 _ => fluent::ast_passes_pattern_in_bodiless,
1220 };
5869c6ff
XL
1221 let diag = BuiltinLintDiagnostics::PatternsInFnsWithoutBody(span, ident);
1222 self.lint_buffer.buffer_lint_with_diagnostic(
1223 PATTERNS_IN_FNS_WITHOUT_BODY,
1224 id,
1225 span,
1226 msg,
1227 diag,
1228 )
1229 }
74b04a01 1230 } else {
9ffffee4
FG
1231 match ctxt {
1232 FnCtxt::Foreign => {
1233 self.err_handler().emit_err(errors::PatternInForeign { span })
1234 }
1235 _ => self.err_handler().emit_err(errors::PatternInBodiless { span }),
1236 };
74b04a01
XL
1237 }
1238 });
dfeec247
XL
1239 }
1240
04454e1e 1241 let tilde_const_allowed =
2b03887a 1242 matches!(fk.header(), Some(FnHeader { constness: ast::Const::Yes(_), .. }))
04454e1e
FG
1243 || matches!(fk.ctxt(), Some(FnCtxt::Assoc(_)));
1244
2b03887a
FG
1245 let disallowed = (!tilde_const_allowed).then(|| DisallowTildeConstContext::Fn(fk));
1246
1247 self.with_tilde_const(disallowed, |this| visit::walk_fn(this, fk));
60c5eb7d 1248 }
dfeec247 1249
74b04a01 1250 fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
94222f64
XL
1251 if self.session.contains_name(&item.attrs, sym::no_mangle) {
1252 self.check_nomangle_item_asciionly(item.ident, item.span);
1253 }
1254
74b04a01
XL
1255 if ctxt == AssocCtxt::Trait || !self.in_trait_impl {
1256 self.check_defaultness(item.span, item.kind.defaultness());
1257 }
1258
1259 if ctxt == AssocCtxt::Impl {
1260 match &item.kind {
1261 AssocItemKind::Const(_, _, body) => {
f2b60f7d 1262 if body.is_none() {
9ffffee4 1263 self.session.emit_err(errors::AssocConstWithoutBody {
f2b60f7d
FG
1264 span: item.span,
1265 replace_span: self.ending_semi_or_hi(item.span),
1266 });
1267 }
74b04a01 1268 }
3c0e092e 1269 AssocItemKind::Fn(box Fn { body, .. }) => {
f2b60f7d 1270 if body.is_none() {
9ffffee4 1271 self.session.emit_err(errors::AssocFnWithoutBody {
f2b60f7d
FG
1272 span: item.span,
1273 replace_span: self.ending_semi_or_hi(item.span),
1274 });
1275 }
74b04a01 1276 }
2b03887a 1277 AssocItemKind::Type(box TyAlias {
5e7ed085
FG
1278 generics,
1279 where_clauses,
1280 where_predicates_split,
1281 bounds,
1282 ty,
1283 ..
1284 }) => {
f2b60f7d 1285 if ty.is_none() {
9ffffee4 1286 self.session.emit_err(errors::AssocTypeWithoutBody {
f2b60f7d
FG
1287 span: item.span,
1288 replace_span: self.ending_semi_or_hi(item.span),
1289 });
1290 }
74b04a01 1291 self.check_type_no_bounds(bounds, "`impl`s");
5e7ed085
FG
1292 if ty.is_some() {
1293 self.check_gat_where(
1294 item.id,
1295 generics.where_clause.predicates.split_at(*where_predicates_split).0,
1296 *where_clauses,
1297 );
1298 }
74b04a01
XL
1299 }
1300 _ => {}
1301 }
dfeec247 1302 }
74b04a01
XL
1303
1304 if ctxt == AssocCtxt::Trait || self.in_trait_impl {
1305 self.invalid_visibility(&item.vis, None);
3c0e092e 1306 if let AssocItemKind::Fn(box Fn { sig, .. }) = &item.kind {
74b04a01 1307 self.check_trait_fn_not_const(sig.header.constness);
74b04a01
XL
1308 }
1309 }
1310
1311 if let AssocItemKind::Const(..) = item.kind {
1312 self.check_item_named(item.ident, "const");
1313 }
1314
487cf647
FG
1315 match &item.kind {
1316 AssocItemKind::Type(box TyAlias { generics, bounds, ty, .. })
94222f64
XL
1317 if ctxt == AssocCtxt::Trait =>
1318 {
1319 self.visit_vis(&item.vis);
1320 self.visit_ident(item.ident);
1321 walk_list!(self, visit_attribute, &item.attrs);
1322 self.with_tilde_const_allowed(|this| {
1323 this.visit_generics(generics);
04454e1e 1324 walk_list!(this, visit_param_bound, bounds, BoundKind::Bound);
94222f64
XL
1325 });
1326 walk_list!(self, visit_ty, ty);
1327 }
487cf647 1328 AssocItemKind::Fn(box Fn { sig, generics, body, .. })
c295e0f8
XL
1329 if self.in_const_trait_impl
1330 || ctxt == AssocCtxt::Trait
1331 || matches!(sig.header.constness, Const::Yes(_)) =>
94222f64
XL
1332 {
1333 self.visit_vis(&item.vis);
1334 self.visit_ident(item.ident);
04454e1e
FG
1335 let kind = FnKind::Fn(
1336 FnCtxt::Assoc(ctxt),
1337 item.ident,
1338 sig,
1339 &item.vis,
1340 generics,
1341 body.as_deref(),
1342 );
94222f64
XL
1343 self.visit_fn(kind, item.span, item.id);
1344 }
1345 _ => self
1346 .with_in_trait_impl(false, None, |this| visit::walk_assoc_item(this, item, ctxt)),
1347 }
dfeec247 1348 }
0531ce1d
XL
1349}
1350
f9f354fc
XL
1351/// When encountering an equality constraint in a `where` clause, emit an error. If the code seems
1352/// like it's setting an associated type, provide an appropriate suggestion.
1353fn deny_equality_constraints(
1354 this: &mut AstValidator<'_>,
1355 predicate: &WhereEqPredicate,
1356 generics: &Generics,
1357) {
9ffffee4 1358 let mut err = errors::EqualityInWhere { span: predicate.span, assoc: None, assoc2: None };
f9f354fc
XL
1359
1360 // Given `<A as Foo>::Bar = RhsTy`, suggest `A: Foo<Bar = RhsTy>`.
1361 if let TyKind::Path(Some(qself), full_path) = &predicate.lhs_ty.kind {
1362 if let TyKind::Path(None, path) = &qself.ty.kind {
1363 match &path.segments[..] {
1364 [PathSegment { ident, args: None, .. }] => {
1365 for param in &generics.params {
1366 if param.ident == *ident {
1367 let param = ident;
1368 match &full_path.segments[qself.position..] {
fc512014 1369 [PathSegment { ident, args, .. }] => {
f9f354fc
XL
1370 // Make a new `Path` from `foo::Bar` to `Foo<Bar = RhsTy>`.
1371 let mut assoc_path = full_path.clone();
1372 // Remove `Bar` from `Foo::Bar`.
1373 assoc_path.segments.pop();
1374 let len = assoc_path.segments.len() - 1;
487cf647 1375 let gen_args = args.as_deref().cloned();
f9f354fc 1376 // Build `<Bar = RhsTy>`.
5099ac24 1377 let arg = AngleBracketedArg::Constraint(AssocConstraint {
f9f354fc
XL
1378 id: rustc_ast::node_id::DUMMY_NODE_ID,
1379 ident: *ident,
fc512014 1380 gen_args,
5099ac24
FG
1381 kind: AssocConstraintKind::Equality {
1382 term: predicate.rhs_ty.clone().into(),
f9f354fc
XL
1383 },
1384 span: ident.span,
1385 });
1386 // Add `<Bar = RhsTy>` to `Foo`.
1387 match &mut assoc_path.segments[len].args {
1388 Some(args) => match args.deref_mut() {
1389 GenericArgs::Parenthesized(_) => continue,
1390 GenericArgs::AngleBracketed(args) => {
1391 args.args.push(arg);
1392 }
1393 },
1394 empty_args => {
1395 *empty_args = AngleBracketedArgs {
1396 span: ident.span,
9ffffee4 1397 args: thin_vec![arg],
f9f354fc
XL
1398 }
1399 .into();
1400 }
1401 }
9ffffee4
FG
1402 err.assoc = Some(errors::AssociatedSuggestion {
1403 span: predicate.span,
1404 ident: *ident,
1405 param: *param,
1406 path: pprust::path_to_string(&assoc_path),
1407 })
f9f354fc
XL
1408 }
1409 _ => {}
1410 };
1411 }
1412 }
1413 }
1414 _ => {}
1415 }
1416 }
1417 }
a2a8927a
XL
1418 // Given `A: Foo, A::Bar = RhsTy`, suggest `A: Foo<Bar = RhsTy>`.
1419 if let TyKind::Path(None, full_path) = &predicate.lhs_ty.kind {
1420 if let [potential_param, potential_assoc] = &full_path.segments[..] {
1421 for param in &generics.params {
1422 if param.ident == potential_param.ident {
1423 for bound in &param.bounds {
1424 if let ast::GenericBound::Trait(trait_ref, TraitBoundModifier::None) = bound
1425 {
1426 if let [trait_segment] = &trait_ref.trait_ref.path.segments[..] {
1427 let assoc = pprust::path_to_string(&ast::Path::from_ident(
1428 potential_assoc.ident,
1429 ));
1430 let ty = pprust::ty_to_string(&predicate.rhs_ty);
1431 let (args, span) = match &trait_segment.args {
1432 Some(args) => match args.deref() {
1433 ast::GenericArgs::AngleBracketed(args) => {
1434 let Some(arg) = args.args.last() else {
1435 continue;
1436 };
1437 (
1438 format!(", {} = {}", assoc, ty),
1439 arg.span().shrink_to_hi(),
1440 )
1441 }
1442 _ => continue,
1443 },
1444 None => (
1445 format!("<{} = {}>", assoc, ty),
1446 trait_segment.span().shrink_to_hi(),
1447 ),
1448 };
9ffffee4
FG
1449 err.assoc2 = Some(errors::AssociatedSuggestion2 {
1450 span,
1451 args,
1452 predicate: predicate.span,
1453 trait_segment: trait_segment.ident,
1454 potential_assoc: potential_assoc.ident,
1455 });
a2a8927a
XL
1456 }
1457 }
1458 }
1459 }
1460 }
1461 }
1462 }
9ffffee4 1463 this.err_handler().emit_err(err);
f9f354fc
XL
1464}
1465
dfeec247 1466pub fn check_crate(session: &Session, krate: &Crate, lints: &mut LintBuffer) -> bool {
9fa01778
XL
1467 let mut validator = AstValidator {
1468 session,
74b04a01
XL
1469 extern_mod: None,
1470 in_trait_impl: false,
94222f64 1471 in_const_trait_impl: false,
9fa01778 1472 has_proc_macro_decls: false,
9fa01778 1473 outer_impl_trait: None,
2b03887a 1474 disallow_tilde_const: None,
9fa01778 1475 is_impl_trait_banned: false,
5e7ed085 1476 forbidden_let_reason: Some(ForbiddenLetReason::GenericForbidden),
e74abb32 1477 lint_buffer: lints,
9fa01778
XL
1478 };
1479 visit::walk_crate(&mut validator, krate);
1480
416331ca 1481 validator.has_proc_macro_decls
3157f602 1482}
5e7ed085
FG
1483
1484/// Used to forbid `let` expressions in certain syntactic locations.
2b03887a 1485#[derive(Clone, Copy, Subdiagnostic)]
f2b60f7d 1486pub(crate) enum ForbiddenLetReason {
5e7ed085
FG
1487 /// `let` is not valid and the source environment is not important
1488 GenericForbidden,
04454e1e 1489 /// A let chain with the `||` operator
9ffffee4 1490 #[note(ast_passes_not_supported_or)]
2b03887a 1491 NotSupportedOr(#[primary_span] Span),
04454e1e
FG
1492 /// A let chain with invalid parentheses
1493 ///
f2b60f7d 1494 /// For example, `let 1 = 1 && (expr && expr)` is allowed
04454e1e 1495 /// but `(let 1 = 1 && (let 1 = 1 && (let 1 = 1))) && let a = 1` is not
9ffffee4 1496 #[note(ast_passes_not_supported_parentheses)]
2b03887a 1497 NotSupportedParentheses(#[primary_span] Span),
5e7ed085 1498}