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