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