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