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