]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_ast_passes/src/ast_validation.rs
Auto merge of #79945 - jackh726:existential_trait_ref, r=nikomatsakis
[rust.git] / compiler / rustc_ast_passes / src / ast_validation.rs
1 // Validate AST before lowering it to HIR.
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
9 use itertools::{Either, Itertools};
10 use rustc_ast::ptr::P;
11 use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
12 use rustc_ast::walk_list;
13 use rustc_ast::*;
14 use rustc_ast_pretty::pprust;
15 use rustc_data_structures::fx::FxHashMap;
16 use rustc_errors::{error_code, pluralize, struct_span_err, Applicability};
17 use rustc_parse::validate_attr;
18 use rustc_session::lint::builtin::PATTERNS_IN_FNS_WITHOUT_BODY;
19 use rustc_session::lint::LintBuffer;
20 use rustc_session::Session;
21 use rustc_span::symbol::{kw, sym, Ident};
22 use rustc_span::Span;
23 use std::mem;
24 use std::ops::DerefMut;
25
26 const MORE_EXTERN: &str =
27     "for more information, visit https://doc.rust-lang.org/std/keyword.extern.html";
28
29 /// Is `self` allowed semantically as the first parameter in an `FnDecl`?
30 enum SelfSemantic {
31     Yes,
32     No,
33 }
34
35 /// A syntactic context that disallows certain kinds of bounds (e.g., `?Trait` or `?const Trait`).
36 #[derive(Clone, Copy)]
37 enum BoundContext {
38     ImplTrait,
39     TraitBounds,
40     TraitObject,
41 }
42
43 impl BoundContext {
44     fn description(&self) -> &'static str {
45         match self {
46             Self::ImplTrait => "`impl Trait`",
47             Self::TraitBounds => "supertraits",
48             Self::TraitObject => "trait objects",
49         }
50     }
51 }
52
53 struct AstValidator<'a> {
54     session: &'a Session,
55
56     /// The span of the `extern` in an `extern { ... }` block, if any.
57     extern_mod: Option<&'a Item>,
58
59     /// Are we inside a trait impl?
60     in_trait_impl: bool,
61
62     has_proc_macro_decls: bool,
63
64     /// Used to ban nested `impl Trait`, e.g., `impl Into<impl Debug>`.
65     /// Nested `impl Trait` _is_ allowed in associated type position,
66     /// e.g., `impl Iterator<Item = impl Debug>`.
67     outer_impl_trait: Option<Span>,
68
69     /// Keeps track of the `BoundContext` as we recurse.
70     ///
71     /// This is used to forbid `?const Trait` bounds in, e.g.,
72     /// `impl Iterator<Item = Box<dyn ?const Trait>`.
73     bound_context: Option<BoundContext>,
74
75     /// Used to ban `impl Trait` in path projections like `<impl Iterator>::Item`
76     /// or `Foo::Bar<impl Trait>`
77     is_impl_trait_banned: bool,
78
79     /// Used to ban associated type bounds (i.e., `Type<AssocType: Bounds>`) in
80     /// certain positions.
81     is_assoc_ty_bound_banned: bool,
82
83     lint_buffer: &'a mut LintBuffer,
84 }
85
86 impl<'a> AstValidator<'a> {
87     fn with_in_trait_impl(&mut self, is_in: bool, f: impl FnOnce(&mut Self)) {
88         let old = mem::replace(&mut self.in_trait_impl, is_in);
89         f(self);
90         self.in_trait_impl = old;
91     }
92
93     fn with_banned_impl_trait(&mut self, f: impl FnOnce(&mut Self)) {
94         let old = mem::replace(&mut self.is_impl_trait_banned, true);
95         f(self);
96         self.is_impl_trait_banned = old;
97     }
98
99     fn with_banned_assoc_ty_bound(&mut self, f: impl FnOnce(&mut Self)) {
100         let old = mem::replace(&mut self.is_assoc_ty_bound_banned, true);
101         f(self);
102         self.is_assoc_ty_bound_banned = old;
103     }
104
105     fn with_impl_trait(&mut self, outer: Option<Span>, f: impl FnOnce(&mut Self)) {
106         let old = mem::replace(&mut self.outer_impl_trait, outer);
107         if outer.is_some() {
108             self.with_bound_context(BoundContext::ImplTrait, |this| f(this));
109         } else {
110             f(self)
111         }
112         self.outer_impl_trait = old;
113     }
114
115     fn with_bound_context(&mut self, ctx: BoundContext, f: impl FnOnce(&mut Self)) {
116         let old = self.bound_context.replace(ctx);
117         f(self);
118         self.bound_context = old;
119     }
120
121     fn visit_assoc_ty_constraint_from_generic_args(&mut self, constraint: &'a AssocTyConstraint) {
122         match constraint.kind {
123             AssocTyConstraintKind::Equality { .. } => {}
124             AssocTyConstraintKind::Bound { .. } => {
125                 if self.is_assoc_ty_bound_banned {
126                     self.err_handler().span_err(
127                         constraint.span,
128                         "associated type bounds are not allowed within structs, enums, or unions",
129                     );
130                 }
131             }
132         }
133         self.visit_assoc_ty_constraint(constraint);
134     }
135
136     // Mirrors `visit::walk_ty`, but tracks relevant state.
137     fn walk_ty(&mut self, t: &'a Ty) {
138         match t.kind {
139             TyKind::ImplTrait(..) => {
140                 self.with_impl_trait(Some(t.span), |this| visit::walk_ty(this, t))
141             }
142             TyKind::TraitObject(..) => {
143                 self.with_bound_context(BoundContext::TraitObject, |this| visit::walk_ty(this, t));
144             }
145             TyKind::Path(ref qself, ref path) => {
146                 // We allow these:
147                 //  - `Option<impl Trait>`
148                 //  - `option::Option<impl Trait>`
149                 //  - `option::Option<T>::Foo<impl Trait>
150                 //
151                 // But not these:
152                 //  - `<impl Trait>::Foo`
153                 //  - `option::Option<impl Trait>::Foo`.
154                 //
155                 // To implement this, we disallow `impl Trait` from `qself`
156                 // (for cases like `<impl Trait>::Foo>`)
157                 // but we allow `impl Trait` in `GenericArgs`
158                 // iff there are no more PathSegments.
159                 if let Some(ref qself) = *qself {
160                     // `impl Trait` in `qself` is always illegal
161                     self.with_banned_impl_trait(|this| this.visit_ty(&qself.ty));
162                 }
163
164                 // Note that there should be a call to visit_path here,
165                 // so if any logic is added to process `Path`s a call to it should be
166                 // added both in visit_path and here. This code mirrors visit::walk_path.
167                 for (i, segment) in path.segments.iter().enumerate() {
168                     // Allow `impl Trait` iff we're on the final path segment
169                     if i == path.segments.len() - 1 {
170                         self.visit_path_segment(path.span, segment);
171                     } else {
172                         self.with_banned_impl_trait(|this| {
173                             this.visit_path_segment(path.span, segment)
174                         });
175                     }
176                 }
177             }
178             _ => visit::walk_ty(self, t),
179         }
180     }
181
182     fn err_handler(&self) -> &rustc_errors::Handler {
183         &self.session.diagnostic()
184     }
185
186     fn check_lifetime(&self, ident: Ident) {
187         let valid_names = [kw::UnderscoreLifetime, kw::StaticLifetime, kw::Invalid];
188         if !valid_names.contains(&ident.name) && ident.without_first_quote().is_reserved() {
189             self.err_handler().span_err(ident.span, "lifetimes cannot use keyword names");
190         }
191     }
192
193     fn check_label(&self, ident: Ident) {
194         if ident.without_first_quote().is_reserved() {
195             self.err_handler()
196                 .span_err(ident.span, &format!("invalid label name `{}`", ident.name));
197         }
198     }
199
200     fn invalid_visibility(&self, vis: &Visibility, note: Option<&str>) {
201         if let VisibilityKind::Inherited = vis.kind {
202             return;
203         }
204
205         let mut err =
206             struct_span_err!(self.session, vis.span, E0449, "unnecessary visibility qualifier");
207         if vis.kind.is_pub() {
208             err.span_label(vis.span, "`pub` not permitted here because it's implied");
209         }
210         if let Some(note) = note {
211             err.note(note);
212         }
213         err.emit();
214     }
215
216     fn check_decl_no_pat(decl: &FnDecl, mut report_err: impl FnMut(Span, bool)) {
217         for Param { pat, .. } in &decl.inputs {
218             match pat.kind {
219                 PatKind::Ident(BindingMode::ByValue(Mutability::Not), _, None) | PatKind::Wild => {}
220                 PatKind::Ident(BindingMode::ByValue(Mutability::Mut), _, None) => {
221                     report_err(pat.span, true)
222                 }
223                 _ => report_err(pat.span, false),
224             }
225         }
226     }
227
228     fn check_trait_fn_not_async(&self, fn_span: Span, asyncness: Async) {
229         if let Async::Yes { span, .. } = asyncness {
230             struct_span_err!(
231                 self.session,
232                 fn_span,
233                 E0706,
234                 "functions in traits cannot be declared `async`"
235             )
236             .span_label(span, "`async` because of this")
237             .note("`async` trait functions are not currently supported")
238             .note("consider using the `async-trait` crate: https://crates.io/crates/async-trait")
239             .emit();
240         }
241     }
242
243     fn check_trait_fn_not_const(&self, constness: Const) {
244         if let Const::Yes(span) = constness {
245             struct_span_err!(
246                 self.session,
247                 span,
248                 E0379,
249                 "functions in traits cannot be declared const"
250             )
251             .span_label(span, "functions in traits cannot be const")
252             .emit();
253         }
254     }
255
256     // FIXME(ecstaticmorse): Instead, use `bound_context` to check this in `visit_param_bound`.
257     fn no_questions_in_bounds(&self, bounds: &GenericBounds, where_: &str, is_trait: bool) {
258         for bound in bounds {
259             if let GenericBound::Trait(ref poly, TraitBoundModifier::Maybe) = *bound {
260                 let mut err = self.err_handler().struct_span_err(
261                     poly.span,
262                     &format!("`?Trait` is not permitted in {}", where_),
263                 );
264                 if is_trait {
265                     let path_str = pprust::path_to_string(&poly.trait_ref.path);
266                     err.note(&format!("traits are `?{}` by default", path_str));
267                 }
268                 err.emit();
269             }
270         }
271     }
272
273     /// Matches `'-' lit | lit (cf. parser::Parser::parse_literal_maybe_minus)`,
274     /// or paths for ranges.
275     //
276     // FIXME: do we want to allow `expr -> pattern` conversion to create path expressions?
277     // That means making this work:
278     //
279     // ```rust,ignore (FIXME)
280     // struct S;
281     // macro_rules! m {
282     //     ($a:expr) => {
283     //         let $a = S;
284     //     }
285     // }
286     // m!(S);
287     // ```
288     fn check_expr_within_pat(&self, expr: &Expr, allow_paths: bool) {
289         match expr.kind {
290             ExprKind::Lit(..) | ExprKind::ConstBlock(..) | ExprKind::Err => {}
291             ExprKind::Path(..) if allow_paths => {}
292             ExprKind::Unary(UnOp::Neg, ref inner) if matches!(inner.kind, ExprKind::Lit(_)) => {}
293             _ => self.err_handler().span_err(
294                 expr.span,
295                 "arbitrary expressions aren't allowed \
296                                                          in patterns",
297             ),
298         }
299     }
300
301     fn check_late_bound_lifetime_defs(&self, params: &[GenericParam]) {
302         // Check only lifetime parameters are present and that the lifetime
303         // parameters that are present have no bounds.
304         let non_lt_param_spans: Vec<_> = params
305             .iter()
306             .filter_map(|param| match param.kind {
307                 GenericParamKind::Lifetime { .. } => {
308                     if !param.bounds.is_empty() {
309                         let spans: Vec<_> = param.bounds.iter().map(|b| b.span()).collect();
310                         self.err_handler()
311                             .span_err(spans, "lifetime bounds cannot be used in this context");
312                     }
313                     None
314                 }
315                 _ => Some(param.ident.span),
316             })
317             .collect();
318         if !non_lt_param_spans.is_empty() {
319             self.err_handler().span_err(
320                 non_lt_param_spans,
321                 "only lifetime parameters can be used in this context",
322             );
323         }
324     }
325
326     fn check_fn_decl(&self, fn_decl: &FnDecl, self_semantic: SelfSemantic) {
327         self.check_decl_cvaradic_pos(fn_decl);
328         self.check_decl_attrs(fn_decl);
329         self.check_decl_self_param(fn_decl, self_semantic);
330     }
331
332     fn check_decl_cvaradic_pos(&self, fn_decl: &FnDecl) {
333         match &*fn_decl.inputs {
334             [Param { ty, span, .. }] => {
335                 if let TyKind::CVarArgs = ty.kind {
336                     self.err_handler().span_err(
337                         *span,
338                         "C-variadic function must be declared with at least one named argument",
339                     );
340                 }
341             }
342             [ps @ .., _] => {
343                 for Param { ty, span, .. } in ps {
344                     if let TyKind::CVarArgs = ty.kind {
345                         self.err_handler().span_err(
346                             *span,
347                             "`...` must be the last argument of a C-variadic function",
348                         );
349                     }
350                 }
351             }
352             _ => {}
353         }
354     }
355
356     fn check_decl_attrs(&self, fn_decl: &FnDecl) {
357         fn_decl
358             .inputs
359             .iter()
360             .flat_map(|i| i.attrs.as_ref())
361             .filter(|attr| {
362                 let arr = [sym::allow, sym::cfg, sym::cfg_attr, sym::deny, sym::forbid, sym::warn];
363                 !arr.contains(&attr.name_or_empty()) && rustc_attr::is_builtin_attr(attr)
364             })
365             .for_each(|attr| {
366                 if attr.is_doc_comment() {
367                     self.err_handler()
368                         .struct_span_err(
369                             attr.span,
370                             "documentation comments cannot be applied to function parameters",
371                         )
372                         .span_label(attr.span, "doc comments are not allowed here")
373                         .emit();
374                 } else {
375                     self.err_handler().span_err(
376                         attr.span,
377                         "allow, cfg, cfg_attr, deny, \
378                 forbid, and warn are the only allowed built-in attributes in function parameters",
379                     )
380                 }
381             });
382     }
383
384     fn check_decl_self_param(&self, fn_decl: &FnDecl, self_semantic: SelfSemantic) {
385         if let (SelfSemantic::No, [param, ..]) = (self_semantic, &*fn_decl.inputs) {
386             if param.is_self() {
387                 self.err_handler()
388                     .struct_span_err(
389                         param.span,
390                         "`self` parameter is only allowed in associated functions",
391                     )
392                     .span_label(param.span, "not semantically valid as function parameter")
393                     .note("associated functions are those in `impl` or `trait` definitions")
394                     .emit();
395             }
396         }
397     }
398
399     fn check_defaultness(&self, span: Span, defaultness: Defaultness) {
400         if let Defaultness::Default(def_span) = defaultness {
401             let span = self.session.source_map().guess_head_span(span);
402             self.err_handler()
403                 .struct_span_err(span, "`default` is only allowed on items in trait impls")
404                 .span_label(def_span, "`default` because of this")
405                 .emit();
406         }
407     }
408
409     fn error_item_without_body(&self, sp: Span, ctx: &str, msg: &str, sugg: &str) {
410         self.err_handler()
411             .struct_span_err(sp, msg)
412             .span_suggestion(
413                 self.session.source_map().end_point(sp),
414                 &format!("provide a definition for the {}", ctx),
415                 sugg.to_string(),
416                 Applicability::HasPlaceholders,
417             )
418             .emit();
419     }
420
421     fn check_impl_item_provided<T>(&self, sp: Span, body: &Option<T>, ctx: &str, sugg: &str) {
422         if body.is_none() {
423             let msg = format!("associated {} in `impl` without body", ctx);
424             self.error_item_without_body(sp, ctx, &msg, sugg);
425         }
426     }
427
428     fn check_type_no_bounds(&self, bounds: &[GenericBound], ctx: &str) {
429         let span = match bounds {
430             [] => return,
431             [b0] => b0.span(),
432             [b0, .., bl] => b0.span().to(bl.span()),
433         };
434         self.err_handler()
435             .struct_span_err(span, &format!("bounds on `type`s in {} have no effect", ctx))
436             .emit();
437     }
438
439     fn check_foreign_ty_genericless(&self, generics: &Generics) {
440         let cannot_have = |span, descr, remove_descr| {
441             self.err_handler()
442                 .struct_span_err(
443                     span,
444                     &format!("`type`s inside `extern` blocks cannot have {}", descr),
445                 )
446                 .span_suggestion(
447                     span,
448                     &format!("remove the {}", remove_descr),
449                     String::new(),
450                     Applicability::MaybeIncorrect,
451                 )
452                 .span_label(self.current_extern_span(), "`extern` block begins here")
453                 .note(MORE_EXTERN)
454                 .emit();
455         };
456
457         if !generics.params.is_empty() {
458             cannot_have(generics.span, "generic parameters", "generic parameters");
459         }
460
461         if !generics.where_clause.predicates.is_empty() {
462             cannot_have(generics.where_clause.span, "`where` clauses", "`where` clause");
463         }
464     }
465
466     fn check_foreign_kind_bodyless(&self, ident: Ident, kind: &str, body: Option<Span>) {
467         let body = match body {
468             None => return,
469             Some(body) => body,
470         };
471         self.err_handler()
472             .struct_span_err(ident.span, &format!("incorrect `{}` inside `extern` block", kind))
473             .span_label(ident.span, "cannot have a body")
474             .span_label(body, "the invalid body")
475             .span_label(
476                 self.current_extern_span(),
477                 format!(
478                     "`extern` blocks define existing foreign {0}s and {0}s \
479                     inside of them cannot have a body",
480                     kind
481                 ),
482             )
483             .note(MORE_EXTERN)
484             .emit();
485     }
486
487     /// An `fn` in `extern { ... }` cannot have a body `{ ... }`.
488     fn check_foreign_fn_bodyless(&self, ident: Ident, body: Option<&Block>) {
489         let body = match body {
490             None => return,
491             Some(body) => body,
492         };
493         self.err_handler()
494             .struct_span_err(ident.span, "incorrect function inside `extern` block")
495             .span_label(ident.span, "cannot have a body")
496             .span_suggestion(
497                 body.span,
498                 "remove the invalid body",
499                 ";".to_string(),
500                 Applicability::MaybeIncorrect,
501             )
502             .help(
503                 "you might have meant to write a function accessible through FFI, \
504                 which can be done by writing `extern fn` outside of the `extern` block",
505             )
506             .span_label(
507                 self.current_extern_span(),
508                 "`extern` blocks define existing foreign functions and functions \
509                 inside of them cannot have a body",
510             )
511             .note(MORE_EXTERN)
512             .emit();
513     }
514
515     fn current_extern_span(&self) -> Span {
516         self.session.source_map().guess_head_span(self.extern_mod.unwrap().span)
517     }
518
519     /// An `fn` in `extern { ... }` cannot have qualifiers, e.g. `async fn`.
520     fn check_foreign_fn_headerless(&self, ident: Ident, span: Span, header: FnHeader) {
521         if header.has_qualifiers() {
522             self.err_handler()
523                 .struct_span_err(ident.span, "functions in `extern` blocks cannot have qualifiers")
524                 .span_label(self.current_extern_span(), "in this `extern` block")
525                 .span_suggestion_verbose(
526                     span.until(ident.span.shrink_to_lo()),
527                     "remove the qualifiers",
528                     "fn ".to_string(),
529                     Applicability::MaybeIncorrect,
530                 )
531                 .emit();
532         }
533     }
534
535     /// Reject C-varadic type unless the function is foreign,
536     /// or free and `unsafe extern "C"` semantically.
537     fn check_c_varadic_type(&self, fk: FnKind<'a>) {
538         match (fk.ctxt(), fk.header()) {
539             (Some(FnCtxt::Foreign), _) => return,
540             (Some(FnCtxt::Free), Some(header)) => match header.ext {
541                 Extern::Explicit(StrLit { symbol_unescaped: sym::C, .. }) | Extern::Implicit
542                     if matches!(header.unsafety, Unsafe::Yes(_)) =>
543                 {
544                     return;
545                 }
546                 _ => {}
547             },
548             _ => {}
549         };
550
551         for Param { ty, span, .. } in &fk.decl().inputs {
552             if let TyKind::CVarArgs = ty.kind {
553                 self.err_handler()
554                     .struct_span_err(
555                         *span,
556                         "only foreign or `unsafe extern \"C\" functions may be C-variadic",
557                     )
558                     .emit();
559             }
560         }
561     }
562
563     fn check_item_named(&self, ident: Ident, kind: &str) {
564         if ident.name != kw::Underscore {
565             return;
566         }
567         self.err_handler()
568             .struct_span_err(ident.span, &format!("`{}` items in this context need a name", kind))
569             .span_label(ident.span, format!("`_` is not a valid name for this `{}` item", kind))
570             .emit();
571     }
572
573     fn check_nomangle_item_asciionly(&self, ident: Ident, item_span: Span) {
574         if ident.name.as_str().is_ascii() {
575             return;
576         }
577         let head_span = self.session.source_map().guess_head_span(item_span);
578         struct_span_err!(
579             self.session,
580             head_span,
581             E0754,
582             "`#[no_mangle]` requires ASCII identifier"
583         )
584         .emit();
585     }
586
587     fn check_mod_file_item_asciionly(&self, ident: Ident) {
588         if ident.name.as_str().is_ascii() {
589             return;
590         }
591         struct_span_err!(
592             self.session,
593             ident.span,
594             E0754,
595             "trying to load file for module `{}` with non ascii identifer name",
596             ident.name
597         )
598         .help("consider using `#[path]` attribute to specify filesystem path")
599         .emit();
600     }
601
602     fn deny_generic_params(&self, generics: &Generics, ident_span: Span) {
603         if !generics.params.is_empty() {
604             struct_span_err!(
605                 self.session,
606                 generics.span,
607                 E0567,
608                 "auto traits cannot have generic parameters"
609             )
610             .span_label(ident_span, "auto trait cannot have generic parameters")
611             .span_suggestion(
612                 generics.span,
613                 "remove the parameters",
614                 String::new(),
615                 Applicability::MachineApplicable,
616             )
617             .emit();
618         }
619     }
620
621     fn deny_super_traits(&self, bounds: &GenericBounds, ident_span: Span) {
622         if let [first @ last] | [first, .., last] = &bounds[..] {
623             let span = first.span().to(last.span());
624             struct_span_err!(self.session, span, E0568, "auto traits cannot have super traits")
625                 .span_label(ident_span, "auto trait cannot have super traits")
626                 .span_suggestion(
627                     span,
628                     "remove the super traits",
629                     String::new(),
630                     Applicability::MachineApplicable,
631                 )
632                 .emit();
633         }
634     }
635
636     fn deny_items(&self, trait_items: &[P<AssocItem>], ident_span: Span) {
637         if !trait_items.is_empty() {
638             let spans: Vec<_> = trait_items.iter().map(|i| i.ident.span).collect();
639             struct_span_err!(
640                 self.session,
641                 spans,
642                 E0380,
643                 "auto traits cannot have methods or associated items"
644             )
645             .span_label(ident_span, "auto trait cannot have items")
646             .emit();
647         }
648     }
649
650     fn correct_generic_order_suggestion(&self, data: &AngleBracketedArgs) -> String {
651         // Lifetimes always come first.
652         let lt_sugg = data.args.iter().filter_map(|arg| match arg {
653             AngleBracketedArg::Arg(lt @ GenericArg::Lifetime(_)) => {
654                 Some(pprust::to_string(|s| s.print_generic_arg(lt)))
655             }
656             _ => None,
657         });
658         let args_sugg = data.args.iter().filter_map(|a| match a {
659             AngleBracketedArg::Arg(GenericArg::Lifetime(_)) | AngleBracketedArg::Constraint(_) => {
660                 None
661             }
662             AngleBracketedArg::Arg(arg) => Some(pprust::to_string(|s| s.print_generic_arg(arg))),
663         });
664         // Constraints always come last.
665         let constraint_sugg = data.args.iter().filter_map(|a| match a {
666             AngleBracketedArg::Arg(_) => None,
667             AngleBracketedArg::Constraint(c) => {
668                 Some(pprust::to_string(|s| s.print_assoc_constraint(c)))
669             }
670         });
671         format!(
672             "<{}>",
673             lt_sugg.chain(args_sugg).chain(constraint_sugg).collect::<Vec<String>>().join(", ")
674         )
675     }
676
677     /// Enforce generic args coming before constraints in `<...>` of a path segment.
678     fn check_generic_args_before_constraints(&self, data: &AngleBracketedArgs) {
679         // Early exit in case it's partitioned as it should be.
680         if data.args.iter().is_partitioned(|arg| matches!(arg, AngleBracketedArg::Arg(_))) {
681             return;
682         }
683         // Find all generic argument coming after the first constraint...
684         let (constraint_spans, arg_spans): (Vec<Span>, Vec<Span>) =
685             data.args.iter().partition_map(|arg| match arg {
686                 AngleBracketedArg::Constraint(c) => Either::Left(c.span),
687                 AngleBracketedArg::Arg(a) => Either::Right(a.span()),
688             });
689         let args_len = arg_spans.len();
690         let constraint_len = constraint_spans.len();
691         // ...and then error:
692         self.err_handler()
693             .struct_span_err(
694                 arg_spans.clone(),
695                 "generic arguments must come before the first constraint",
696             )
697             .span_label(constraint_spans[0], &format!("constraint{}", pluralize!(constraint_len)))
698             .span_label(
699                 *arg_spans.iter().last().unwrap(),
700                 &format!("generic argument{}", pluralize!(args_len)),
701             )
702             .span_labels(constraint_spans, "")
703             .span_labels(arg_spans, "")
704             .span_suggestion_verbose(
705                 data.span,
706                 &format!(
707                     "move the constraint{} after the generic argument{}",
708                     pluralize!(constraint_len),
709                     pluralize!(args_len)
710                 ),
711                 self.correct_generic_order_suggestion(&data),
712                 Applicability::MachineApplicable,
713             )
714             .emit();
715     }
716 }
717
718 /// Checks that generic parameters are in the correct order,
719 /// which is lifetimes, then types and then consts. (`<'a, T, const N: usize>`)
720 fn validate_generic_param_order<'a>(
721     sess: &Session,
722     handler: &rustc_errors::Handler,
723     generics: impl Iterator<Item = (ParamKindOrd, Option<&'a [GenericBound]>, Span, Option<String>)>,
724     span: Span,
725 ) {
726     let mut max_param: Option<ParamKindOrd> = None;
727     let mut out_of_order = FxHashMap::default();
728     let mut param_idents = vec![];
729
730     for (kind, bounds, span, ident) in generics {
731         if let Some(ident) = ident {
732             param_idents.push((kind, bounds, param_idents.len(), ident));
733         }
734         let max_param = &mut max_param;
735         match max_param {
736             Some(max_param) if *max_param > kind => {
737                 let entry = out_of_order.entry(kind).or_insert((*max_param, vec![]));
738                 entry.1.push(span);
739             }
740             Some(_) | None => *max_param = Some(kind),
741         };
742     }
743
744     let mut ordered_params = "<".to_string();
745     if !out_of_order.is_empty() {
746         param_idents.sort_by_key(|&(po, _, i, _)| (po, i));
747         let mut first = true;
748         for (_, bounds, _, ident) in param_idents {
749             if !first {
750                 ordered_params += ", ";
751             }
752             ordered_params += &ident;
753             if let Some(bounds) = bounds {
754                 if !bounds.is_empty() {
755                     ordered_params += ": ";
756                     ordered_params += &pprust::bounds_to_string(&bounds);
757                 }
758             }
759             first = false;
760         }
761     }
762     ordered_params += ">";
763
764     for (param_ord, (max_param, spans)) in &out_of_order {
765         let mut err =
766             handler.struct_span_err(
767                 spans.clone(),
768                 &format!(
769                     "{} parameters must be declared prior to {} parameters",
770                     param_ord, max_param,
771                 ),
772             );
773         err.span_suggestion(
774             span,
775             &format!(
776                 "reorder the parameters: lifetimes{}",
777                 if sess.features_untracked().const_generics {
778                     ", then consts and types"
779                 } else if sess.features_untracked().min_const_generics {
780                     ", then types, then consts"
781                 } else {
782                     ", then types"
783                 },
784             ),
785             ordered_params.clone(),
786             Applicability::MachineApplicable,
787         );
788         err.emit();
789     }
790 }
791
792 impl<'a> Visitor<'a> for AstValidator<'a> {
793     fn visit_attribute(&mut self, attr: &Attribute) {
794         validate_attr::check_meta(&self.session.parse_sess, attr);
795     }
796
797     fn visit_expr(&mut self, expr: &'a Expr) {
798         match &expr.kind {
799             ExprKind::LlvmInlineAsm(..) if !self.session.target.allow_asm => {
800                 struct_span_err!(
801                     self.session,
802                     expr.span,
803                     E0472,
804                     "llvm_asm! is unsupported on this target"
805                 )
806                 .emit();
807             }
808             _ => {}
809         }
810
811         visit::walk_expr(self, expr);
812     }
813
814     fn visit_ty(&mut self, ty: &'a Ty) {
815         match ty.kind {
816             TyKind::BareFn(ref bfty) => {
817                 self.check_fn_decl(&bfty.decl, SelfSemantic::No);
818                 Self::check_decl_no_pat(&bfty.decl, |span, _| {
819                     struct_span_err!(
820                         self.session,
821                         span,
822                         E0561,
823                         "patterns aren't allowed in function pointer types"
824                     )
825                     .emit();
826                 });
827                 self.check_late_bound_lifetime_defs(&bfty.generic_params);
828             }
829             TyKind::TraitObject(ref bounds, ..) => {
830                 let mut any_lifetime_bounds = false;
831                 for bound in bounds {
832                     if let GenericBound::Outlives(ref lifetime) = *bound {
833                         if any_lifetime_bounds {
834                             struct_span_err!(
835                                 self.session,
836                                 lifetime.ident.span,
837                                 E0226,
838                                 "only a single explicit lifetime bound is permitted"
839                             )
840                             .emit();
841                             break;
842                         }
843                         any_lifetime_bounds = true;
844                     }
845                 }
846                 self.no_questions_in_bounds(bounds, "trait object types", false);
847             }
848             TyKind::ImplTrait(_, ref bounds) => {
849                 if self.is_impl_trait_banned {
850                     struct_span_err!(
851                         self.session,
852                         ty.span,
853                         E0667,
854                         "`impl Trait` is not allowed in path parameters"
855                     )
856                     .emit();
857                 }
858
859                 if let Some(outer_impl_trait_sp) = self.outer_impl_trait {
860                     struct_span_err!(
861                         self.session,
862                         ty.span,
863                         E0666,
864                         "nested `impl Trait` is not allowed"
865                     )
866                     .span_label(outer_impl_trait_sp, "outer `impl Trait`")
867                     .span_label(ty.span, "nested `impl Trait` here")
868                     .emit();
869                 }
870
871                 if !bounds.iter().any(|b| matches!(b, GenericBound::Trait(..))) {
872                     self.err_handler().span_err(ty.span, "at least one trait must be specified");
873                 }
874
875                 self.walk_ty(ty);
876                 return;
877             }
878             _ => {}
879         }
880
881         self.walk_ty(ty)
882     }
883
884     fn visit_label(&mut self, label: &'a Label) {
885         self.check_label(label.ident);
886         visit::walk_label(self, label);
887     }
888
889     fn visit_lifetime(&mut self, lifetime: &'a Lifetime) {
890         self.check_lifetime(lifetime.ident);
891         visit::walk_lifetime(self, lifetime);
892     }
893
894     fn visit_item(&mut self, item: &'a Item) {
895         if item.attrs.iter().any(|attr| self.session.is_proc_macro_attr(attr)) {
896             self.has_proc_macro_decls = true;
897         }
898
899         if self.session.contains_name(&item.attrs, sym::no_mangle) {
900             self.check_nomangle_item_asciionly(item.ident, item.span);
901         }
902
903         match item.kind {
904             ItemKind::Impl {
905                 unsafety,
906                 polarity,
907                 defaultness: _,
908                 constness: _,
909                 generics: _,
910                 of_trait: Some(ref t),
911                 ref self_ty,
912                 items: _,
913             } => {
914                 self.with_in_trait_impl(true, |this| {
915                     this.invalid_visibility(&item.vis, None);
916                     if let TyKind::Err = self_ty.kind {
917                         this.err_handler()
918                             .struct_span_err(
919                                 item.span,
920                                 "`impl Trait for .. {}` is an obsolete syntax",
921                             )
922                             .help("use `auto trait Trait {}` instead")
923                             .emit();
924                     }
925                     if let (Unsafe::Yes(span), ImplPolarity::Negative(sp)) = (unsafety, polarity) {
926                         struct_span_err!(
927                             this.session,
928                             sp.to(t.path.span),
929                             E0198,
930                             "negative impls cannot be unsafe"
931                         )
932                         .span_label(sp, "negative because of this")
933                         .span_label(span, "unsafe because of this")
934                         .emit();
935                     }
936
937                     visit::walk_item(this, item);
938                 });
939                 return; // Avoid visiting again.
940             }
941             ItemKind::Impl {
942                 unsafety,
943                 polarity,
944                 defaultness,
945                 constness,
946                 generics: _,
947                 of_trait: None,
948                 ref self_ty,
949                 items: _,
950             } => {
951                 let error = |annotation_span, annotation| {
952                     let mut err = self.err_handler().struct_span_err(
953                         self_ty.span,
954                         &format!("inherent impls cannot be {}", annotation),
955                     );
956                     err.span_label(annotation_span, &format!("{} because of this", annotation));
957                     err.span_label(self_ty.span, "inherent impl for this type");
958                     err
959                 };
960
961                 self.invalid_visibility(
962                     &item.vis,
963                     Some("place qualifiers on individual impl items instead"),
964                 );
965                 if let Unsafe::Yes(span) = unsafety {
966                     error(span, "unsafe").code(error_code!(E0197)).emit();
967                 }
968                 if let ImplPolarity::Negative(span) = polarity {
969                     error(span, "negative").emit();
970                 }
971                 if let Defaultness::Default(def_span) = defaultness {
972                     error(def_span, "`default`")
973                         .note("only trait implementations may be annotated with `default`")
974                         .emit();
975                 }
976                 if let Const::Yes(span) = constness {
977                     error(span, "`const`")
978                         .note("only trait implementations may be annotated with `const`")
979                         .emit();
980                 }
981             }
982             ItemKind::Fn(def, _, _, ref body) => {
983                 self.check_defaultness(item.span, def);
984
985                 if body.is_none() {
986                     let msg = "free function without a body";
987                     self.error_item_without_body(item.span, "function", msg, " { <body> }");
988                 }
989             }
990             ItemKind::ForeignMod(ForeignMod { unsafety, .. }) => {
991                 let old_item = mem::replace(&mut self.extern_mod, Some(item));
992                 self.invalid_visibility(
993                     &item.vis,
994                     Some("place qualifiers on individual foreign items instead"),
995                 );
996                 if let Unsafe::Yes(span) = unsafety {
997                     self.err_handler().span_err(span, "extern block cannot be declared unsafe");
998                 }
999                 visit::walk_item(self, item);
1000                 self.extern_mod = old_item;
1001                 return; // Avoid visiting again.
1002             }
1003             ItemKind::Enum(ref def, _) => {
1004                 for variant in &def.variants {
1005                     self.invalid_visibility(&variant.vis, None);
1006                     for field in variant.data.fields() {
1007                         self.invalid_visibility(&field.vis, None);
1008                     }
1009                 }
1010             }
1011             ItemKind::Trait(is_auto, _, ref generics, ref bounds, ref trait_items) => {
1012                 if is_auto == IsAuto::Yes {
1013                     // Auto traits cannot have generics, super traits nor contain items.
1014                     self.deny_generic_params(generics, item.ident.span);
1015                     self.deny_super_traits(bounds, item.ident.span);
1016                     self.deny_items(trait_items, item.ident.span);
1017                 }
1018                 self.no_questions_in_bounds(bounds, "supertraits", true);
1019
1020                 // Equivalent of `visit::walk_item` for `ItemKind::Trait` that inserts a bound
1021                 // context for the supertraits.
1022                 self.visit_vis(&item.vis);
1023                 self.visit_ident(item.ident);
1024                 self.visit_generics(generics);
1025                 self.with_bound_context(BoundContext::TraitBounds, |this| {
1026                     walk_list!(this, visit_param_bound, bounds);
1027                 });
1028                 walk_list!(self, visit_assoc_item, trait_items, AssocCtxt::Trait);
1029                 walk_list!(self, visit_attribute, &item.attrs);
1030                 return;
1031             }
1032             ItemKind::Mod(Mod { inline, unsafety, .. }) => {
1033                 if let Unsafe::Yes(span) = unsafety {
1034                     self.err_handler().span_err(span, "module cannot be declared unsafe");
1035                 }
1036                 // Ensure that `path` attributes on modules are recorded as used (cf. issue #35584).
1037                 if !inline && !self.session.contains_name(&item.attrs, sym::path) {
1038                     self.check_mod_file_item_asciionly(item.ident);
1039                 }
1040             }
1041             ItemKind::Union(ref vdata, _) => {
1042                 if let VariantData::Tuple(..) | VariantData::Unit(..) = vdata {
1043                     self.err_handler()
1044                         .span_err(item.span, "tuple and unit unions are not permitted");
1045                 }
1046                 if vdata.fields().is_empty() {
1047                     self.err_handler().span_err(item.span, "unions cannot have zero fields");
1048                 }
1049             }
1050             ItemKind::Const(def, .., None) => {
1051                 self.check_defaultness(item.span, def);
1052                 let msg = "free constant item without body";
1053                 self.error_item_without_body(item.span, "constant", msg, " = <expr>;");
1054             }
1055             ItemKind::Static(.., None) => {
1056                 let msg = "free static item without body";
1057                 self.error_item_without_body(item.span, "static", msg, " = <expr>;");
1058             }
1059             ItemKind::TyAlias(def, _, ref bounds, ref body) => {
1060                 self.check_defaultness(item.span, def);
1061                 if body.is_none() {
1062                     let msg = "free type alias without body";
1063                     self.error_item_without_body(item.span, "type", msg, " = <type>;");
1064                 }
1065                 self.check_type_no_bounds(bounds, "this context");
1066             }
1067             _ => {}
1068         }
1069
1070         visit::walk_item(self, item)
1071     }
1072
1073     fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
1074         match &fi.kind {
1075             ForeignItemKind::Fn(def, sig, _, body) => {
1076                 self.check_defaultness(fi.span, *def);
1077                 self.check_foreign_fn_bodyless(fi.ident, body.as_deref());
1078                 self.check_foreign_fn_headerless(fi.ident, fi.span, sig.header);
1079             }
1080             ForeignItemKind::TyAlias(def, generics, bounds, body) => {
1081                 self.check_defaultness(fi.span, *def);
1082                 self.check_foreign_kind_bodyless(fi.ident, "type", body.as_ref().map(|b| b.span));
1083                 self.check_type_no_bounds(bounds, "`extern` blocks");
1084                 self.check_foreign_ty_genericless(generics);
1085             }
1086             ForeignItemKind::Static(_, _, body) => {
1087                 self.check_foreign_kind_bodyless(fi.ident, "static", body.as_ref().map(|b| b.span));
1088             }
1089             ForeignItemKind::MacCall(..) => {}
1090         }
1091
1092         visit::walk_foreign_item(self, fi)
1093     }
1094
1095     // Mirrors `visit::walk_generic_args`, but tracks relevant state.
1096     fn visit_generic_args(&mut self, _: Span, generic_args: &'a GenericArgs) {
1097         match *generic_args {
1098             GenericArgs::AngleBracketed(ref data) => {
1099                 self.check_generic_args_before_constraints(data);
1100
1101                 for arg in &data.args {
1102                     match arg {
1103                         AngleBracketedArg::Arg(arg) => self.visit_generic_arg(arg),
1104                         // Type bindings such as `Item = impl Debug` in `Iterator<Item = Debug>`
1105                         // are allowed to contain nested `impl Trait`.
1106                         AngleBracketedArg::Constraint(constraint) => {
1107                             self.with_impl_trait(None, |this| {
1108                                 this.visit_assoc_ty_constraint_from_generic_args(constraint);
1109                             });
1110                         }
1111                     }
1112                 }
1113             }
1114             GenericArgs::Parenthesized(ref data) => {
1115                 walk_list!(self, visit_ty, &data.inputs);
1116                 if let FnRetTy::Ty(ty) = &data.output {
1117                     // `-> Foo` syntax is essentially an associated type binding,
1118                     // so it is also allowed to contain nested `impl Trait`.
1119                     self.with_impl_trait(None, |this| this.visit_ty(ty));
1120                 }
1121             }
1122         }
1123     }
1124
1125     fn visit_generics(&mut self, generics: &'a Generics) {
1126         let mut prev_ty_default = None;
1127         for param in &generics.params {
1128             match param.kind {
1129                 GenericParamKind::Lifetime => (),
1130                 GenericParamKind::Type { default: Some(_), .. } => {
1131                     prev_ty_default = Some(param.ident.span);
1132                 }
1133                 GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {
1134                     if let Some(span) = prev_ty_default {
1135                         let mut err = self.err_handler().struct_span_err(
1136                             span,
1137                             "type parameters with a default must be trailing",
1138                         );
1139                         if matches!(param.kind, GenericParamKind::Const { .. }) {
1140                             err.note(
1141                                 "using type defaults and const parameters \
1142                                  in the same parameter list is currently not permitted",
1143                             );
1144                         }
1145                         err.emit();
1146                         break;
1147                     }
1148                 }
1149             }
1150         }
1151
1152         validate_generic_param_order(
1153             self.session,
1154             self.err_handler(),
1155             generics.params.iter().map(|param| {
1156                 let ident = Some(param.ident.to_string());
1157                 let (kind, ident) = match &param.kind {
1158                     GenericParamKind::Lifetime => (ParamKindOrd::Lifetime, ident),
1159                     GenericParamKind::Type { default: _ } => (ParamKindOrd::Type, ident),
1160                     GenericParamKind::Const { ref ty, kw_span: _ } => {
1161                         let ty = pprust::ty_to_string(ty);
1162                         let unordered = self.session.features_untracked().const_generics;
1163                         (
1164                             ParamKindOrd::Const { unordered },
1165                             Some(format!("const {}: {}", param.ident, ty)),
1166                         )
1167                     }
1168                 };
1169                 (kind, Some(&*param.bounds), param.ident.span, ident)
1170             }),
1171             generics.span,
1172         );
1173
1174         for predicate in &generics.where_clause.predicates {
1175             if let WherePredicate::EqPredicate(ref predicate) = *predicate {
1176                 deny_equality_constraints(self, predicate, generics);
1177             }
1178         }
1179
1180         visit::walk_generics(self, generics)
1181     }
1182
1183     fn visit_generic_param(&mut self, param: &'a GenericParam) {
1184         if let GenericParamKind::Lifetime { .. } = param.kind {
1185             self.check_lifetime(param.ident);
1186         }
1187         visit::walk_generic_param(self, param);
1188     }
1189
1190     fn visit_param_bound(&mut self, bound: &'a GenericBound) {
1191         match bound {
1192             GenericBound::Trait(_, TraitBoundModifier::MaybeConst) => {
1193                 if let Some(ctx) = self.bound_context {
1194                     let msg = format!("`?const` is not permitted in {}", ctx.description());
1195                     self.err_handler().span_err(bound.span(), &msg);
1196                 }
1197             }
1198
1199             GenericBound::Trait(_, TraitBoundModifier::MaybeConstMaybe) => {
1200                 self.err_handler()
1201                     .span_err(bound.span(), "`?const` and `?` are mutually exclusive");
1202             }
1203
1204             _ => {}
1205         }
1206
1207         visit::walk_param_bound(self, bound)
1208     }
1209
1210     fn visit_pat(&mut self, pat: &'a Pat) {
1211         match pat.kind {
1212             PatKind::Lit(ref expr) => {
1213                 self.check_expr_within_pat(expr, false);
1214             }
1215             PatKind::Range(ref start, ref end, _) => {
1216                 if let Some(expr) = start {
1217                     self.check_expr_within_pat(expr, true);
1218                 }
1219                 if let Some(expr) = end {
1220                     self.check_expr_within_pat(expr, true);
1221                 }
1222             }
1223             _ => {}
1224         }
1225
1226         visit::walk_pat(self, pat)
1227     }
1228
1229     fn visit_where_predicate(&mut self, p: &'a WherePredicate) {
1230         if let &WherePredicate::BoundPredicate(ref bound_predicate) = p {
1231             // A type binding, eg `for<'c> Foo: Send+Clone+'c`
1232             self.check_late_bound_lifetime_defs(&bound_predicate.bound_generic_params);
1233         }
1234         visit::walk_where_predicate(self, p);
1235     }
1236
1237     fn visit_poly_trait_ref(&mut self, t: &'a PolyTraitRef, m: &'a TraitBoundModifier) {
1238         self.check_late_bound_lifetime_defs(&t.bound_generic_params);
1239         visit::walk_poly_trait_ref(self, t, m);
1240     }
1241
1242     fn visit_variant_data(&mut self, s: &'a VariantData) {
1243         self.with_banned_assoc_ty_bound(|this| visit::walk_struct_def(this, s))
1244     }
1245
1246     fn visit_enum_def(
1247         &mut self,
1248         enum_definition: &'a EnumDef,
1249         generics: &'a Generics,
1250         item_id: NodeId,
1251         _: Span,
1252     ) {
1253         self.with_banned_assoc_ty_bound(|this| {
1254             visit::walk_enum_def(this, enum_definition, generics, item_id)
1255         })
1256     }
1257
1258     fn visit_fn(&mut self, fk: FnKind<'a>, span: Span, id: NodeId) {
1259         // Only associated `fn`s can have `self` parameters.
1260         let self_semantic = match fk.ctxt() {
1261             Some(FnCtxt::Assoc(_)) => SelfSemantic::Yes,
1262             _ => SelfSemantic::No,
1263         };
1264         self.check_fn_decl(fk.decl(), self_semantic);
1265
1266         self.check_c_varadic_type(fk);
1267
1268         // Functions cannot both be `const async`
1269         if let Some(FnHeader {
1270             constness: Const::Yes(cspan),
1271             asyncness: Async::Yes { span: aspan, .. },
1272             ..
1273         }) = fk.header()
1274         {
1275             self.err_handler()
1276                 .struct_span_err(
1277                     vec![*cspan, *aspan],
1278                     "functions cannot be both `const` and `async`",
1279                 )
1280                 .span_label(*cspan, "`const` because of this")
1281                 .span_label(*aspan, "`async` because of this")
1282                 .span_label(span, "") // Point at the fn header.
1283                 .emit();
1284         }
1285
1286         // Functions without bodies cannot have patterns.
1287         if let FnKind::Fn(ctxt, _, sig, _, None) = fk {
1288             Self::check_decl_no_pat(&sig.decl, |span, mut_ident| {
1289                 let (code, msg, label) = match ctxt {
1290                     FnCtxt::Foreign => (
1291                         error_code!(E0130),
1292                         "patterns aren't allowed in foreign function declarations",
1293                         "pattern not allowed in foreign function",
1294                     ),
1295                     _ => (
1296                         error_code!(E0642),
1297                         "patterns aren't allowed in functions without bodies",
1298                         "pattern not allowed in function without body",
1299                     ),
1300                 };
1301                 if mut_ident && matches!(ctxt, FnCtxt::Assoc(_)) {
1302                     self.lint_buffer.buffer_lint(PATTERNS_IN_FNS_WITHOUT_BODY, id, span, msg);
1303                 } else {
1304                     self.err_handler()
1305                         .struct_span_err(span, msg)
1306                         .span_label(span, label)
1307                         .code(code)
1308                         .emit();
1309                 }
1310             });
1311         }
1312
1313         visit::walk_fn(self, fk, span);
1314     }
1315
1316     fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
1317         if ctxt == AssocCtxt::Trait || !self.in_trait_impl {
1318             self.check_defaultness(item.span, item.kind.defaultness());
1319         }
1320
1321         if ctxt == AssocCtxt::Impl {
1322             match &item.kind {
1323                 AssocItemKind::Const(_, _, body) => {
1324                     self.check_impl_item_provided(item.span, body, "constant", " = <expr>;");
1325                 }
1326                 AssocItemKind::Fn(_, _, _, body) => {
1327                     self.check_impl_item_provided(item.span, body, "function", " { <body> }");
1328                 }
1329                 AssocItemKind::TyAlias(_, _, bounds, body) => {
1330                     self.check_impl_item_provided(item.span, body, "type", " = <type>;");
1331                     self.check_type_no_bounds(bounds, "`impl`s");
1332                 }
1333                 _ => {}
1334             }
1335         }
1336
1337         if ctxt == AssocCtxt::Trait || self.in_trait_impl {
1338             self.invalid_visibility(&item.vis, None);
1339             if let AssocItemKind::Fn(_, sig, _, _) = &item.kind {
1340                 self.check_trait_fn_not_const(sig.header.constness);
1341                 self.check_trait_fn_not_async(item.span, sig.header.asyncness);
1342             }
1343         }
1344
1345         if let AssocItemKind::Const(..) = item.kind {
1346             self.check_item_named(item.ident, "const");
1347         }
1348
1349         self.with_in_trait_impl(false, |this| visit::walk_assoc_item(this, item, ctxt));
1350     }
1351 }
1352
1353 /// When encountering an equality constraint in a `where` clause, emit an error. If the code seems
1354 /// like it's setting an associated type, provide an appropriate suggestion.
1355 fn deny_equality_constraints(
1356     this: &mut AstValidator<'_>,
1357     predicate: &WhereEqPredicate,
1358     generics: &Generics,
1359 ) {
1360     let mut err = this.err_handler().struct_span_err(
1361         predicate.span,
1362         "equality constraints are not yet supported in `where` clauses",
1363     );
1364     err.span_label(predicate.span, "not supported");
1365
1366     // Given `<A as Foo>::Bar = RhsTy`, suggest `A: Foo<Bar = RhsTy>`.
1367     if let TyKind::Path(Some(qself), full_path) = &predicate.lhs_ty.kind {
1368         if let TyKind::Path(None, path) = &qself.ty.kind {
1369             match &path.segments[..] {
1370                 [PathSegment { ident, args: None, .. }] => {
1371                     for param in &generics.params {
1372                         if param.ident == *ident {
1373                             let param = ident;
1374                             match &full_path.segments[qself.position..] {
1375                                 [PathSegment { ident, args, .. }] => {
1376                                     // Make a new `Path` from `foo::Bar` to `Foo<Bar = RhsTy>`.
1377                                     let mut assoc_path = full_path.clone();
1378                                     // Remove `Bar` from `Foo::Bar`.
1379                                     assoc_path.segments.pop();
1380                                     let len = assoc_path.segments.len() - 1;
1381                                     let gen_args = args.as_ref().map(|p| (**p).clone());
1382                                     // Build `<Bar = RhsTy>`.
1383                                     let arg = AngleBracketedArg::Constraint(AssocTyConstraint {
1384                                         id: rustc_ast::node_id::DUMMY_NODE_ID,
1385                                         ident: *ident,
1386                                         gen_args,
1387                                         kind: AssocTyConstraintKind::Equality {
1388                                             ty: predicate.rhs_ty.clone(),
1389                                         },
1390                                         span: ident.span,
1391                                     });
1392                                     // Add `<Bar = RhsTy>` to `Foo`.
1393                                     match &mut assoc_path.segments[len].args {
1394                                         Some(args) => match args.deref_mut() {
1395                                             GenericArgs::Parenthesized(_) => continue,
1396                                             GenericArgs::AngleBracketed(args) => {
1397                                                 args.args.push(arg);
1398                                             }
1399                                         },
1400                                         empty_args => {
1401                                             *empty_args = AngleBracketedArgs {
1402                                                 span: ident.span,
1403                                                 args: vec![arg],
1404                                             }
1405                                             .into();
1406                                         }
1407                                     }
1408                                     err.span_suggestion_verbose(
1409                                         predicate.span,
1410                                         &format!(
1411                                             "if `{}` is an associated type you're trying to set, \
1412                                             use the associated type binding syntax",
1413                                             ident
1414                                         ),
1415                                         format!(
1416                                             "{}: {}",
1417                                             param,
1418                                             pprust::path_to_string(&assoc_path)
1419                                         ),
1420                                         Applicability::MaybeIncorrect,
1421                                     );
1422                                 }
1423                                 _ => {}
1424                             };
1425                         }
1426                     }
1427                 }
1428                 _ => {}
1429             }
1430         }
1431     }
1432     err.note(
1433         "see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information",
1434     );
1435     err.emit();
1436 }
1437
1438 pub fn check_crate(session: &Session, krate: &Crate, lints: &mut LintBuffer) -> bool {
1439     let mut validator = AstValidator {
1440         session,
1441         extern_mod: None,
1442         in_trait_impl: false,
1443         has_proc_macro_decls: false,
1444         outer_impl_trait: None,
1445         bound_context: None,
1446         is_impl_trait_banned: false,
1447         is_assoc_ty_bound_banned: false,
1448         lint_buffer: lints,
1449     };
1450     visit::walk_crate(&mut validator, krate);
1451
1452     validator.has_proc_macro_decls
1453 }