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