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