1use std::mem;
20use std::ops::{Deref, DerefMut};
21use std::str::FromStr;
22
23use itertools::{Either, Itertools};
24use rustc_abi::{CVariadicStatus, CanonAbi, ExternAbi, InterruptKind};
25use rustc_ast::visit::{AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor, walk_list};
26use rustc_ast::*;
27use rustc_ast_pretty::pprust::{self, State};
28use rustc_attr_parsing::validate_attr;
29use rustc_data_structures::fx::FxIndexMap;
30use rustc_errors::{DiagCtxtHandle, Diagnostic, LintBuffer};
31use rustc_feature::Features;
32use rustc_session::Session;
33use rustc_session::lint::builtin::{
34 DEPRECATED_WHERE_CLAUSE_LOCATION, MISSING_ABI, MISSING_UNSAFE_ON_EXTERN,
35 PATTERNS_IN_FNS_WITHOUT_BODY, UNUSED_VISIBILITIES,
36};
37use rustc_session::parse::feature_err;
38use rustc_span::{Ident, Span, kw, sym};
39use rustc_target::spec::{AbiMap, AbiMapping};
40use thin_vec::thin_vec;
41
42use crate::errors::{self, TildeConstReason};
43
44enum SelfSemantic {
46 Yes,
47 No,
48}
49
50enum TraitOrImpl {
51 Trait { vis: Span, constness: Const },
52 TraitImpl { constness: Const, polarity: ImplPolarity, trait_ref_span: Span },
53 Impl { constness: Const },
54}
55
56impl TraitOrImpl {
57 fn constness(&self) -> Option<Span> {
58 match self {
59 Self::Trait { constness: Const::Yes(span), .. }
60 | Self::Impl { constness: Const::Yes(span), .. }
61 | Self::TraitImpl { constness: Const::Yes(span), .. } => Some(*span),
62 _ => None,
63 }
64 }
65}
66
67enum AllowDefault {
68 Yes,
69 No,
70}
71
72impl AllowDefault {
73 fn when(b: bool) -> Self {
74 if b { Self::Yes } else { Self::No }
75 }
76}
77
78enum AllowFinal {
79 Yes,
80 No,
81}
82
83impl AllowFinal {
84 fn when(b: bool) -> Self {
85 if b { Self::Yes } else { Self::No }
86 }
87}
88
89struct AstValidator<'a> {
90 sess: &'a Session,
91 features: &'a Features,
92
93 extern_mod_span: Option<Span>,
95
96 outer_trait_or_trait_impl: Option<TraitOrImpl>,
97
98 has_proc_macro_decls: bool,
99
100 outer_impl_trait_span: Option<Span>,
104
105 disallow_tilde_const: Option<TildeConstReason>,
106
107 extern_mod_safety: Option<Safety>,
109 extern_mod_abi: Option<ExternAbi>,
110
111 lint_node_id: NodeId,
112
113 is_sdylib_interface: bool,
114
115 lint_buffer: &'a mut LintBuffer,
116}
117
118impl<'a> AstValidator<'a> {
119 fn with_in_trait_or_impl(
120 &mut self,
121 in_trait_or_impl: Option<TraitOrImpl>,
122 f: impl FnOnce(&mut Self),
123 ) {
124 let old = mem::replace(&mut self.outer_trait_or_trait_impl, in_trait_or_impl);
125 f(self);
126 self.outer_trait_or_trait_impl = old;
127 }
128
129 fn with_in_trait(&mut self, vis: Span, constness: Const, f: impl FnOnce(&mut Self)) {
130 let old = mem::replace(
131 &mut self.outer_trait_or_trait_impl,
132 Some(TraitOrImpl::Trait { vis, constness }),
133 );
134 f(self);
135 self.outer_trait_or_trait_impl = old;
136 }
137
138 fn with_in_extern_mod(
139 &mut self,
140 extern_mod_safety: Safety,
141 abi: Option<ExternAbi>,
142 f: impl FnOnce(&mut Self),
143 ) {
144 let old_safety = mem::replace(&mut self.extern_mod_safety, Some(extern_mod_safety));
145 let old_abi = mem::replace(&mut self.extern_mod_abi, abi);
146 f(self);
147 self.extern_mod_safety = old_safety;
148 self.extern_mod_abi = old_abi;
149 }
150
151 fn with_tilde_const(
152 &mut self,
153 disallowed: Option<TildeConstReason>,
154 f: impl FnOnce(&mut Self),
155 ) {
156 let old = mem::replace(&mut self.disallow_tilde_const, disallowed);
157 f(self);
158 self.disallow_tilde_const = old;
159 }
160
161 fn check_type_alias_where_clause_location(
162 &mut self,
163 ty_alias: &TyAlias,
164 ) -> Result<(), errors::WhereClauseBeforeTypeAlias> {
165 if ty_alias.ty.is_none() || !ty_alias.generics.where_clause.has_where_token {
166 return Ok(());
167 }
168
169 let span = ty_alias.generics.where_clause.span;
170
171 let sugg = if !ty_alias.generics.where_clause.predicates.is_empty()
172 || !ty_alias.after_where_clause.has_where_token
173 {
174 let mut state = State::new();
175
176 let mut needs_comma = !ty_alias.after_where_clause.predicates.is_empty();
177 if !ty_alias.after_where_clause.has_where_token {
178 state.space();
179 state.word_space("where");
180 } else if !needs_comma {
181 state.space();
182 }
183
184 for p in &ty_alias.generics.where_clause.predicates {
185 if needs_comma {
186 state.word_space(",");
187 }
188 needs_comma = true;
189 state.print_where_predicate(p);
190 }
191
192 errors::WhereClauseBeforeTypeAliasSugg::Move {
193 left: span,
194 snippet: state.s.eof(),
195 right: ty_alias.after_where_clause.span.shrink_to_hi(),
196 }
197 } else {
198 errors::WhereClauseBeforeTypeAliasSugg::Remove { span }
199 };
200
201 Err(errors::WhereClauseBeforeTypeAlias { span, sugg })
202 }
203
204 fn with_impl_trait(&mut self, outer_span: Option<Span>, f: impl FnOnce(&mut Self)) {
205 let old = mem::replace(&mut self.outer_impl_trait_span, outer_span);
206 f(self);
207 self.outer_impl_trait_span = old;
208 }
209
210 fn walk_ty(&mut self, t: &'a Ty) {
212 match &t.kind {
213 TyKind::ImplTrait(_, bounds) => {
214 self.with_impl_trait(Some(t.span), |this| visit::walk_ty(this, t));
215
216 let mut use_bounds = bounds
220 .iter()
221 .filter_map(|bound| match bound {
222 GenericBound::Use(_, span) => Some(span),
223 _ => None,
224 })
225 .copied();
226 if let Some(bound1) = use_bounds.next()
227 && let Some(bound2) = use_bounds.next()
228 {
229 self.dcx().emit_err(errors::DuplicatePreciseCapturing { bound1, bound2 });
230 }
231 }
232 TyKind::TraitObject(..) => self
233 .with_tilde_const(Some(TildeConstReason::TraitObject), |this| {
234 visit::walk_ty(this, t)
235 }),
236 _ => visit::walk_ty(self, t),
237 }
238 }
239
240 fn dcx(&self) -> DiagCtxtHandle<'a> {
241 self.sess.dcx()
242 }
243
244 fn visibility_not_permitted(&self, vis: &Visibility, note: errors::VisibilityNotPermittedNote) {
245 if let VisibilityKind::Inherited = vis.kind {
246 return;
247 }
248
249 self.dcx().emit_err(errors::VisibilityNotPermitted {
250 span: vis.span,
251 note,
252 remove_qualifier_sugg: vis.span,
253 });
254 }
255
256 fn check_decl_no_pat(decl: &FnDecl, mut report_err: impl FnMut(Span, Option<Ident>, bool)) {
257 for Param { pat, .. } in &decl.inputs {
258 match pat.kind {
259 PatKind::Missing | PatKind::Ident(BindingMode::NONE, _, None) | PatKind::Wild => {}
260 PatKind::Ident(BindingMode::MUT, ident, None) => {
261 report_err(pat.span, Some(ident), true)
262 }
263 _ => report_err(pat.span, None, false),
264 }
265 }
266 }
267
268 fn check_impl_fn_not_const(&self, constness: Const, parent_constness: Const) {
269 let Const::Yes(span) = constness else {
270 return;
271 };
272
273 let span = self.sess.source_map().span_extend_while_whitespace(span);
274
275 let Const::Yes(parent_constness) = parent_constness else {
276 return;
277 };
278
279 self.dcx().emit_err(errors::ImplFnConst { span, parent_constness });
280 }
281
282 fn check_trait_fn_not_const(&self, constness: Const, parent: &TraitOrImpl) {
283 let Const::Yes(span) = constness else {
284 return;
285 };
286
287 let const_trait_impl = self.features.const_trait_impl();
288 let make_impl_const_sugg = if const_trait_impl
289 && let TraitOrImpl::TraitImpl {
290 constness: Const::No,
291 polarity: ImplPolarity::Positive,
292 trait_ref_span,
293 ..
294 } = parent
295 {
296 Some(trait_ref_span.shrink_to_lo())
297 } else {
298 None
299 };
300
301 let map = self.sess.source_map();
302
303 let make_trait_const_sugg = if const_trait_impl
304 && let &TraitOrImpl::Trait { vis, constness: ast::Const::No } = parent
305 {
306 Some(map.span_extend_while_whitespace(vis).shrink_to_hi())
307 } else {
308 None
309 };
310
311 let parent_constness = parent.constness();
312 self.dcx().emit_err(errors::TraitFnConst {
313 span,
314 in_impl: #[allow(non_exhaustive_omitted_patterns)] match parent {
TraitOrImpl::TraitImpl { .. } => true,
_ => false,
}matches!(parent, TraitOrImpl::TraitImpl { .. }),
315 const_context_label: parent_constness,
316 remove_const_sugg: (
317 map.span_extend_while_whitespace(span),
318 match parent_constness {
319 Some(_) => rustc_errors::Applicability::MachineApplicable,
320 None => rustc_errors::Applicability::MaybeIncorrect,
321 },
322 ),
323 requires_multiple_changes: make_impl_const_sugg.is_some()
324 || make_trait_const_sugg.is_some(),
325 make_impl_const_sugg,
326 make_trait_const_sugg,
327 });
328 }
329
330 fn check_async_fn_in_const_trait_or_impl(&self, sig: &FnSig, parent: &TraitOrImpl) {
331 let Some(const_keyword) = parent.constness() else { return };
332
333 let Some(CoroutineKind::Async { span: async_keyword, .. }) = sig.header.coroutine_kind
334 else {
335 return;
336 };
337
338 let context = match parent {
339 TraitOrImpl::Trait { .. } => "trait",
340 TraitOrImpl::TraitImpl { .. } => "trait_impl",
341 TraitOrImpl::Impl { .. } => "impl",
342 };
343
344 self.dcx().emit_err(errors::AsyncFnInConstTraitOrTraitImpl {
345 async_keyword,
346 context,
347 const_keyword,
348 });
349 }
350
351 fn check_fn_decl(&self, fn_decl: &FnDecl, self_semantic: SelfSemantic) {
352 self.check_decl_num_args(fn_decl);
353 self.check_decl_cvariadic_pos(fn_decl);
354 self.check_decl_attrs(fn_decl);
355 self.check_decl_self_param(fn_decl, self_semantic);
356 }
357
358 fn check_decl_num_args(&self, fn_decl: &FnDecl) {
361 let max_num_args: usize = u16::MAX.into();
362 if fn_decl.inputs.len() > max_num_args {
363 let Param { span, .. } = fn_decl.inputs[0];
364 self.dcx().emit_fatal(errors::FnParamTooMany { span, max_num_args });
365 }
366 }
367
368 fn check_decl_cvariadic_pos(&self, fn_decl: &FnDecl) {
372 match &*fn_decl.inputs {
373 [ps @ .., _] => {
374 for Param { ty, span, .. } in ps {
375 if let TyKind::CVarArgs = ty.kind {
376 self.dcx().emit_err(errors::FnParamCVarArgsNotLast { span: *span });
377 }
378 }
379 }
380 _ => {}
381 }
382 }
383
384 fn check_decl_attrs(&self, fn_decl: &FnDecl) {
385 fn_decl
386 .inputs
387 .iter()
388 .flat_map(|i| i.attrs.as_ref())
389 .filter(|attr| {
390 let arr = [
391 sym::allow,
392 sym::cfg_trace,
393 sym::cfg_attr_trace,
394 sym::deny,
395 sym::expect,
396 sym::forbid,
397 sym::warn,
398 ];
399 !attr.has_any_name(&arr) && rustc_attr_parsing::is_builtin_attr(*attr)
400 })
401 .for_each(|attr| {
402 if attr.is_doc_comment() {
403 self.dcx().emit_err(errors::FnParamDocComment { span: attr.span });
404 } else {
405 self.dcx().emit_err(errors::FnParamForbiddenAttr { span: attr.span });
406 }
407 });
408 }
409
410 fn check_decl_self_param(&self, fn_decl: &FnDecl, self_semantic: SelfSemantic) {
411 if let (SelfSemantic::No, [param, ..]) = (self_semantic, &*fn_decl.inputs) {
412 if param.is_self() {
413 self.dcx().emit_err(errors::FnParamForbiddenSelf { span: param.span });
414 }
415 }
416 }
417
418 fn check_extern_fn_signature(&self, abi: ExternAbi, ctxt: FnCtxt, ident: &Ident, sig: &FnSig) {
420 match AbiMap::from_target(&self.sess.target).canonize_abi(abi, false) {
421 AbiMapping::Direct(canon_abi) | AbiMapping::Deprecated(canon_abi) => {
422 match canon_abi {
423 CanonAbi::C
424 | CanonAbi::Rust
425 | CanonAbi::RustCold
426 | CanonAbi::RustPreserveNone
427 | CanonAbi::Arm(_)
428 | CanonAbi::X86(_) => { }
429
430 CanonAbi::GpuKernel => {
431 self.reject_coroutine(abi, sig);
433
434 self.reject_return(abi, sig);
436 }
437
438 CanonAbi::Custom => {
439 self.reject_safe_fn(abi, ctxt, sig);
441
442 self.reject_coroutine(abi, sig);
444
445 self.reject_params_or_return(abi, ident, sig);
447 }
448
449 CanonAbi::Interrupt(interrupt_kind) => {
450 self.reject_coroutine(abi, sig);
452
453 if let InterruptKind::X86 = interrupt_kind {
454 let inputs = &sig.decl.inputs;
457 let param_count = inputs.len();
458 if !#[allow(non_exhaustive_omitted_patterns)] match param_count {
1 | 2 => true,
_ => false,
}matches!(param_count, 1 | 2) {
459 let mut spans: Vec<Span> =
460 inputs.iter().map(|arg| arg.span).collect();
461 if spans.is_empty() {
462 spans = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[sig.span]))vec![sig.span];
463 }
464 self.dcx().emit_err(errors::AbiX86Interrupt { spans, param_count });
465 }
466
467 self.reject_return(abi, sig);
468 } else {
469 self.reject_params_or_return(abi, ident, sig);
471 }
472 }
473 }
474 }
475 AbiMapping::Invalid => { }
476 }
477 }
478
479 fn reject_safe_fn(&self, abi: ExternAbi, ctxt: FnCtxt, sig: &FnSig) {
480 let dcx = self.dcx();
481
482 match sig.header.safety {
483 Safety::Unsafe(_) => { }
484 Safety::Safe(safe_span) => {
485 let source_map = self.sess.psess.source_map();
486 let safe_span = source_map.span_until_non_whitespace(safe_span.to(sig.span));
487 dcx.emit_err(errors::AbiCustomSafeForeignFunction { span: sig.span, safe_span });
488 }
489 Safety::Default => match ctxt {
490 FnCtxt::Foreign => { }
491 FnCtxt::Free | FnCtxt::Assoc(_) => {
492 dcx.emit_err(errors::AbiCustomSafeFunction {
493 span: sig.span,
494 abi,
495 unsafe_span: sig.span.shrink_to_lo(),
496 });
497 }
498 },
499 }
500 }
501
502 fn reject_coroutine(&self, abi: ExternAbi, sig: &FnSig) {
503 if let Some(coroutine_kind) = sig.header.coroutine_kind {
504 let coroutine_kind_span = self
505 .sess
506 .psess
507 .source_map()
508 .span_until_non_whitespace(coroutine_kind.span().to(sig.span));
509
510 self.dcx().emit_err(errors::AbiCannotBeCoroutine {
511 span: sig.span,
512 abi,
513 coroutine_kind_span,
514 coroutine_kind_str: coroutine_kind.as_str(),
515 });
516 }
517 }
518
519 fn reject_return(&self, abi: ExternAbi, sig: &FnSig) {
520 if let FnRetTy::Ty(ref ret_ty) = sig.decl.output
521 && match &ret_ty.kind {
522 TyKind::Never => false,
523 TyKind::Tup(tup) if tup.is_empty() => false,
524 _ => true,
525 }
526 {
527 self.dcx().emit_err(errors::AbiMustNotHaveReturnType { span: ret_ty.span, abi });
528 }
529 }
530
531 fn reject_params_or_return(&self, abi: ExternAbi, ident: &Ident, sig: &FnSig) {
532 let mut spans: Vec<_> = sig.decl.inputs.iter().map(|p| p.span).collect();
533 if let FnRetTy::Ty(ref ret_ty) = sig.decl.output
534 && match &ret_ty.kind {
535 TyKind::Never => false,
536 TyKind::Tup(tup) if tup.is_empty() => false,
537 _ => true,
538 }
539 {
540 spans.push(ret_ty.span);
541 }
542
543 if !spans.is_empty() {
544 let header_span = sig.header_span();
545 let suggestion_span = header_span.shrink_to_hi().to(sig.decl.output.span());
546 let padding = if header_span.is_empty() { "" } else { " " };
547
548 self.dcx().emit_err(errors::AbiMustNotHaveParametersOrReturnType {
549 spans,
550 symbol: ident.name,
551 suggestion_span,
552 padding,
553 abi,
554 });
555 }
556 }
557
558 fn check_item_safety(&self, span: Span, safety: Safety) {
564 match self.extern_mod_safety {
565 Some(extern_safety) => {
566 if #[allow(non_exhaustive_omitted_patterns)] match safety {
Safety::Unsafe(_) | Safety::Safe(_) => true,
_ => false,
}matches!(safety, Safety::Unsafe(_) | Safety::Safe(_))
567 && extern_safety == Safety::Default
568 {
569 self.dcx().emit_err(errors::InvalidSafetyOnExtern {
570 item_span: span,
571 block: Some(self.current_extern_span().shrink_to_lo()),
572 });
573 }
574 }
575 None => {
576 if #[allow(non_exhaustive_omitted_patterns)] match safety {
Safety::Safe(_) => true,
_ => false,
}matches!(safety, Safety::Safe(_)) {
577 self.dcx().emit_err(errors::InvalidSafetyOnItem { span });
578 }
579 }
580 }
581 }
582
583 fn check_fn_ptr_safety(&self, span: Span, safety: Safety) {
584 if #[allow(non_exhaustive_omitted_patterns)] match safety {
Safety::Safe(_) => true,
_ => false,
}matches!(safety, Safety::Safe(_)) {
585 self.dcx().emit_err(errors::InvalidSafetyOnFnPtr { span });
586 }
587 }
588
589 fn check_defaultness(
590 &self,
591 span: Span,
592 defaultness: Defaultness,
593 allow_default: AllowDefault,
594 allow_final: AllowFinal,
595 ) {
596 match defaultness {
597 Defaultness::Default(def_span) if #[allow(non_exhaustive_omitted_patterns)] match allow_default {
AllowDefault::No => true,
_ => false,
}matches!(allow_default, AllowDefault::No) => {
598 let span = self.sess.source_map().guess_head_span(span);
599 self.dcx().emit_err(errors::ForbiddenDefault { span, def_span });
600 }
601 Defaultness::Final(def_span) if #[allow(non_exhaustive_omitted_patterns)] match allow_final {
AllowFinal::No => true,
_ => false,
}matches!(allow_final, AllowFinal::No) => {
602 let span = self.sess.source_map().guess_head_span(span);
603 self.dcx().emit_err(errors::ForbiddenFinal { span, def_span });
604 }
605 _ => (),
606 }
607 }
608
609 fn check_final_has_body(&self, item: &Item<AssocItemKind>, defaultness: Defaultness) {
610 if let AssocItemKind::Fn(box Fn { body: None, .. }) = &item.kind
611 && let Defaultness::Final(def_span) = defaultness
612 {
613 let span = self.sess.source_map().guess_head_span(item.span);
614 self.dcx().emit_err(errors::ForbiddenFinalWithoutBody { span, def_span });
615 }
616 }
617
618 fn ending_semi_or_hi(&self, sp: Span) -> Span {
621 let source_map = self.sess.source_map();
622 let end = source_map.end_point(sp);
623
624 if source_map.span_to_snippet(end).is_ok_and(|s| s == ";") {
625 end
626 } else {
627 sp.shrink_to_hi()
628 }
629 }
630
631 fn check_type_no_bounds(&self, bounds: &[GenericBound], ctx: &str) {
632 let span = match bounds {
633 [] => return,
634 [b0] => b0.span(),
635 [b0, .., bl] => b0.span().to(bl.span()),
636 };
637 self.dcx().emit_err(errors::BoundInContext { span, ctx });
638 }
639
640 fn check_foreign_ty_genericless(&self, generics: &Generics, after_where_clause: &WhereClause) {
641 let cannot_have = |span, descr, remove_descr| {
642 self.dcx().emit_err(errors::ExternTypesCannotHave {
643 span,
644 descr,
645 remove_descr,
646 block_span: self.current_extern_span(),
647 });
648 };
649
650 if !generics.params.is_empty() {
651 cannot_have(generics.span, "generic parameters", "generic parameters");
652 }
653
654 let check_where_clause = |where_clause: &WhereClause| {
655 if where_clause.has_where_token {
656 cannot_have(where_clause.span, "`where` clauses", "`where` clause");
657 }
658 };
659
660 check_where_clause(&generics.where_clause);
661 check_where_clause(&after_where_clause);
662 }
663
664 fn check_foreign_kind_bodyless(&self, ident: Ident, kind: &str, body_span: Option<Span>) {
665 let Some(body_span) = body_span else {
666 return;
667 };
668 self.dcx().emit_err(errors::BodyInExtern {
669 span: ident.span,
670 body: body_span,
671 block: self.current_extern_span(),
672 kind,
673 });
674 }
675
676 fn check_foreign_fn_bodyless(&self, ident: Ident, body: Option<&Block>) {
678 let Some(body) = body else {
679 return;
680 };
681 self.dcx().emit_err(errors::FnBodyInExtern {
682 span: ident.span,
683 body: body.span,
684 block: self.current_extern_span(),
685 });
686 }
687
688 fn current_extern_span(&self) -> Span {
689 self.sess.source_map().guess_head_span(self.extern_mod_span.unwrap())
690 }
691
692 fn check_foreign_fn_headerless(
694 &self,
695 FnHeader { safety: _, coroutine_kind, constness, ext }: FnHeader,
697 ) {
698 let report_err = |span, kw| {
699 self.dcx().emit_err(errors::FnQualifierInExtern {
700 span,
701 kw,
702 block: self.current_extern_span(),
703 });
704 };
705 match coroutine_kind {
706 Some(kind) => report_err(kind.span(), kind.as_str()),
707 None => (),
708 }
709 match constness {
710 Const::Yes(span) => report_err(span, "const"),
711 Const::No => (),
712 }
713 match ext {
714 Extern::None => (),
715 Extern::Implicit(span) | Extern::Explicit(_, span) => report_err(span, "extern"),
716 }
717 }
718
719 fn check_foreign_item_ascii_only(&self, ident: Ident) {
721 if !ident.as_str().is_ascii() {
722 self.dcx().emit_err(errors::ExternItemAscii {
723 span: ident.span,
724 block: self.current_extern_span(),
725 });
726 }
727 }
728
729 fn check_c_variadic_type(&self, fk: FnKind<'a>, attrs: &'a AttrVec) {
735 let variadic_param = match fk.decl().inputs.last() {
737 Some(param) if #[allow(non_exhaustive_omitted_patterns)] match param.ty.kind {
TyKind::CVarArgs => true,
_ => false,
}matches!(param.ty.kind, TyKind::CVarArgs) => param,
738 _ => return,
739 };
740
741 let FnKind::Fn(fn_ctxt, _, Fn { sig, .. }) = fk else {
742 {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("C variable argument list cannot be used in closures")));
}unreachable!("C variable argument list cannot be used in closures")
744 };
745
746 if let Const::Yes(_) = sig.header.constness
747 && !self.features.enabled(sym::const_c_variadic)
748 {
749 let msg = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("c-variadic const function definitions are unstable"))
})format!("c-variadic const function definitions are unstable");
750 feature_err(&self.sess, sym::const_c_variadic, sig.span, msg).emit();
751 }
752
753 if let Some(coroutine_kind) = sig.header.coroutine_kind {
754 self.dcx().emit_err(errors::CoroutineAndCVariadic {
755 spans: ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[coroutine_kind.span(), variadic_param.span]))vec![coroutine_kind.span(), variadic_param.span],
756 coroutine_kind: coroutine_kind.as_str(),
757 coroutine_span: coroutine_kind.span(),
758 variadic_span: variadic_param.span,
759 });
760 }
761
762 match fn_ctxt {
763 FnCtxt::Foreign => return,
764 FnCtxt::Free | FnCtxt::Assoc(_) => {
765 if !self.sess.target.supports_c_variadic_definitions() {
766 self.dcx().emit_err(errors::CVariadicNotSupported {
767 variadic_span: variadic_param.span,
768 target: &*self.sess.target.llvm_target,
769 });
770 return;
771 }
772
773 match sig.header.ext {
774 Extern::Implicit(_) => {
775 if !#[allow(non_exhaustive_omitted_patterns)] match sig.header.safety {
Safety::Unsafe(_) => true,
_ => false,
}matches!(sig.header.safety, Safety::Unsafe(_)) {
776 self.dcx().emit_err(errors::CVariadicMustBeUnsafe {
777 span: variadic_param.span,
778 unsafe_span: sig.safety_span(),
779 });
780 }
781 }
782 Extern::Explicit(StrLit { symbol_unescaped, .. }, _) => {
783 let Ok(abi) = ExternAbi::from_str(symbol_unescaped.as_str()) else {
785 return;
786 };
787
788 self.check_c_variadic_abi(abi, attrs, variadic_param.span, sig);
789
790 if !#[allow(non_exhaustive_omitted_patterns)] match sig.header.safety {
Safety::Unsafe(_) => true,
_ => false,
}matches!(sig.header.safety, Safety::Unsafe(_)) {
791 self.dcx().emit_err(errors::CVariadicMustBeUnsafe {
792 span: variadic_param.span,
793 unsafe_span: sig.safety_span(),
794 });
795 }
796 }
797 Extern::None => {
798 let err = errors::CVariadicNoExtern { span: variadic_param.span };
799 self.dcx().emit_err(err);
800 }
801 }
802 }
803 }
804 }
805
806 fn check_c_variadic_abi(
807 &self,
808 abi: ExternAbi,
809 attrs: &'a AttrVec,
810 dotdotdot_span: Span,
811 sig: &FnSig,
812 ) {
813 if attr::contains_name(attrs, sym::naked) {
816 match abi.supports_c_variadic() {
817 CVariadicStatus::Stable if let ExternAbi::C { .. } = abi => {
818 }
820 CVariadicStatus::Stable => {
821 if !self.features.enabled(sym::c_variadic_naked_functions) {
823 let msg = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Naked c-variadic `extern {0}` functions are unstable",
abi))
})format!("Naked c-variadic `extern {abi}` functions are unstable");
824 feature_err(&self.sess, sym::c_variadic_naked_functions, sig.span, msg)
825 .emit();
826 }
827 }
828 CVariadicStatus::Unstable { feature } => {
829 if !self.features.enabled(sym::c_variadic_naked_functions) {
831 let msg = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Naked c-variadic `extern {0}` functions are unstable",
abi))
})format!("Naked c-variadic `extern {abi}` functions are unstable");
832 feature_err(&self.sess, sym::c_variadic_naked_functions, sig.span, msg)
833 .emit();
834 }
835
836 if !self.features.enabled(feature) {
837 let msg = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("C-variadic functions with the {0} calling convention are unstable",
abi))
})format!(
838 "C-variadic functions with the {abi} calling convention are unstable"
839 );
840 feature_err(&self.sess, feature, sig.span, msg).emit();
841 }
842 }
843 CVariadicStatus::NotSupported => {
844 self.dcx().emit_err(errors::CVariadicBadNakedExtern {
846 span: dotdotdot_span,
847 abi: abi.as_str(),
848 extern_span: sig.extern_span(),
849 });
850 }
851 }
852 } else if !#[allow(non_exhaustive_omitted_patterns)] match abi {
ExternAbi::C { .. } => true,
_ => false,
}matches!(abi, ExternAbi::C { .. }) {
853 self.dcx().emit_err(errors::CVariadicBadExtern {
854 span: dotdotdot_span,
855 abi: abi.as_str(),
856 extern_span: sig.extern_span(),
857 });
858 }
859 }
860
861 fn check_item_named(&self, ident: Ident, kind: &str) {
862 if ident.name != kw::Underscore {
863 return;
864 }
865 self.dcx().emit_err(errors::ItemUnderscore { span: ident.span, kind });
866 }
867
868 fn check_nomangle_item_asciionly(&self, ident: Ident, item_span: Span) {
869 if ident.name.as_str().is_ascii() {
870 return;
871 }
872 let span = self.sess.source_map().guess_head_span(item_span);
873 self.dcx().emit_err(errors::NoMangleAscii { span });
874 }
875
876 fn check_mod_file_item_asciionly(&self, ident: Ident) {
877 if ident.name.as_str().is_ascii() {
878 return;
879 }
880 self.dcx().emit_err(errors::ModuleNonAscii { span: ident.span, name: ident.name });
881 }
882
883 fn deny_const_auto_traits(&self, constness: Const) {
884 if let Const::Yes(span) = constness {
885 self.dcx().emit_err(errors::ConstAutoTrait { span });
886 }
887 }
888
889 fn deny_generic_params(&self, generics: &Generics, ident_span: Span) {
890 if !generics.params.is_empty() {
891 self.dcx()
892 .emit_err(errors::AutoTraitGeneric { span: generics.span, ident: ident_span });
893 }
894 }
895
896 fn deny_super_traits(&self, bounds: &GenericBounds, ident: Span) {
897 if let [.., last] = &bounds[..] {
898 let span = bounds.iter().map(|b| b.span()).collect();
899 let removal = ident.shrink_to_hi().to(last.span());
900 self.dcx().emit_err(errors::AutoTraitBounds { span, removal, ident });
901 }
902 }
903
904 fn deny_where_clause(&self, where_clause: &WhereClause, ident: Span) {
905 if !where_clause.predicates.is_empty() {
906 self.dcx().emit_err(errors::AutoTraitBounds {
909 span: ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[where_clause.span]))vec![where_clause.span],
910 removal: where_clause.span,
911 ident,
912 });
913 }
914 }
915
916 fn deny_items(&self, trait_items: &[Box<AssocItem>], ident_span: Span) {
917 if !trait_items.is_empty() {
918 let spans: Vec<_> = trait_items.iter().map(|i| i.kind.ident().unwrap().span).collect();
919 let total = trait_items.first().unwrap().span.to(trait_items.last().unwrap().span);
920 self.dcx().emit_err(errors::AutoTraitItems { spans, total, ident: ident_span });
921 }
922 }
923
924 fn correct_generic_order_suggestion(&self, data: &AngleBracketedArgs) -> String {
925 let lt_sugg = data.args.iter().filter_map(|arg| match arg {
927 AngleBracketedArg::Arg(lt @ GenericArg::Lifetime(_)) => {
928 Some(pprust::to_string(|s| s.print_generic_arg(lt)))
929 }
930 _ => None,
931 });
932 let args_sugg = data.args.iter().filter_map(|a| match a {
933 AngleBracketedArg::Arg(GenericArg::Lifetime(_)) | AngleBracketedArg::Constraint(_) => {
934 None
935 }
936 AngleBracketedArg::Arg(arg) => Some(pprust::to_string(|s| s.print_generic_arg(arg))),
937 });
938 let constraint_sugg = data.args.iter().filter_map(|a| match a {
940 AngleBracketedArg::Arg(_) => None,
941 AngleBracketedArg::Constraint(c) => {
942 Some(pprust::to_string(|s| s.print_assoc_item_constraint(c)))
943 }
944 });
945 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("<{0}>",
lt_sugg.chain(args_sugg).chain(constraint_sugg).collect::<Vec<String>>().join(", ")))
})format!(
946 "<{}>",
947 lt_sugg.chain(args_sugg).chain(constraint_sugg).collect::<Vec<String>>().join(", ")
948 )
949 }
950
951 fn check_generic_args_before_constraints(&self, data: &AngleBracketedArgs) {
953 if data.args.iter().is_partitioned(|arg| #[allow(non_exhaustive_omitted_patterns)] match arg {
AngleBracketedArg::Arg(_) => true,
_ => false,
}matches!(arg, AngleBracketedArg::Arg(_))) {
955 return;
956 }
957 let (constraint_spans, arg_spans): (Vec<Span>, Vec<Span>) =
959 data.args.iter().partition_map(|arg| match arg {
960 AngleBracketedArg::Constraint(c) => Either::Left(c.span),
961 AngleBracketedArg::Arg(a) => Either::Right(a.span()),
962 });
963 let args_len = arg_spans.len();
964 let constraint_len = constraint_spans.len();
965 self.dcx().emit_err(errors::ArgsBeforeConstraint {
967 arg_spans: arg_spans.clone(),
968 constraints: constraint_spans[0],
969 args: *arg_spans.iter().last().unwrap(),
970 data: data.span,
971 constraint_spans: errors::EmptyLabelManySpans(constraint_spans),
972 arg_spans2: errors::EmptyLabelManySpans(arg_spans),
973 suggestion: self.correct_generic_order_suggestion(data),
974 constraint_len,
975 args_len,
976 });
977 }
978
979 fn visit_ty_common(&mut self, ty: &'a Ty) {
980 match &ty.kind {
981 TyKind::FnPtr(bfty) => {
982 self.check_fn_ptr_safety(bfty.decl_span, bfty.safety);
983 self.check_fn_decl(&bfty.decl, SelfSemantic::No);
984 Self::check_decl_no_pat(&bfty.decl, |span, _, _| {
985 self.dcx().emit_err(errors::PatternFnPointer { span });
986 });
987 if let Extern::Implicit(extern_span) = bfty.ext {
988 self.handle_missing_abi(extern_span, ty.id);
989 }
990 }
991 TyKind::TraitObject(bounds, ..) => {
992 let mut any_lifetime_bounds = false;
993 for bound in bounds {
994 if let GenericBound::Outlives(lifetime) = bound {
995 if any_lifetime_bounds {
996 self.dcx()
997 .emit_err(errors::TraitObjectBound { span: lifetime.ident.span });
998 break;
999 }
1000 any_lifetime_bounds = true;
1001 }
1002 }
1003 }
1004 TyKind::ImplTrait(_, bounds) => {
1005 if let Some(outer_impl_trait_sp) = self.outer_impl_trait_span {
1006 self.dcx().emit_err(errors::NestedImplTrait {
1007 span: ty.span,
1008 outer: outer_impl_trait_sp,
1009 inner: ty.span,
1010 });
1011 }
1012
1013 if !bounds.iter().any(|b| #[allow(non_exhaustive_omitted_patterns)] match b {
GenericBound::Trait(..) => true,
_ => false,
}matches!(b, GenericBound::Trait(..))) {
1014 self.dcx().emit_err(errors::AtLeastOneTrait { span: ty.span });
1015 }
1016 }
1017 _ => {}
1018 }
1019 }
1020
1021 fn handle_missing_abi(&mut self, span: Span, id: NodeId) {
1022 if span.edition().at_least_edition_future() && self.features.explicit_extern_abis() {
1025 self.dcx().emit_err(errors::MissingAbi { span });
1026 } else if self
1027 .sess
1028 .source_map()
1029 .span_to_snippet(span)
1030 .is_ok_and(|snippet| !snippet.starts_with("#["))
1031 {
1032 self.lint_buffer.buffer_lint(
1033 MISSING_ABI,
1034 id,
1035 span,
1036 errors::MissingAbiSugg { span, default_abi: ExternAbi::FALLBACK },
1037 )
1038 }
1039 }
1040
1041 fn visit_attrs_vis(&mut self, attrs: &'a AttrVec, vis: &'a Visibility) {
1043 for elem in attrs {
match ::rustc_ast_ir::visit::VisitorResult::branch(self.visit_attribute(elem))
{
core::ops::ControlFlow::Continue(()) =>
(),
#[allow(unreachable_code)]
core::ops::ControlFlow::Break(r) => {
return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
}
};
};walk_list!(self, visit_attribute, attrs);
1044 self.visit_vis(vis);
1045 }
1046
1047 fn visit_attrs_vis_ident(&mut self, attrs: &'a AttrVec, vis: &'a Visibility, ident: &'a Ident) {
1049 for elem in attrs {
match ::rustc_ast_ir::visit::VisitorResult::branch(self.visit_attribute(elem))
{
core::ops::ControlFlow::Continue(()) =>
(),
#[allow(unreachable_code)]
core::ops::ControlFlow::Break(r) => {
return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
}
};
};walk_list!(self, visit_attribute, attrs);
1050 self.visit_vis(vis);
1051 self.visit_ident(ident);
1052 }
1053}
1054
1055fn validate_generic_param_order(dcx: DiagCtxtHandle<'_>, generics: &[GenericParam], span: Span) {
1058 let mut max_param: Option<ParamKindOrd> = None;
1059 let mut out_of_order = FxIndexMap::default();
1060 let mut param_idents = Vec::with_capacity(generics.len());
1061
1062 for (idx, param) in generics.iter().enumerate() {
1063 let ident = param.ident;
1064 let (kind, bounds, span) = (¶m.kind, ¶m.bounds, ident.span);
1065 let (ord_kind, ident) = match ¶m.kind {
1066 GenericParamKind::Lifetime => (ParamKindOrd::Lifetime, ident.to_string()),
1067 GenericParamKind::Type { .. } => (ParamKindOrd::TypeOrConst, ident.to_string()),
1068 GenericParamKind::Const { ty, .. } => {
1069 let ty = pprust::ty_to_string(ty);
1070 (ParamKindOrd::TypeOrConst, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("const {0}: {1}", ident, ty))
})format!("const {ident}: {ty}"))
1071 }
1072 };
1073 param_idents.push((kind, ord_kind, bounds, idx, ident));
1074 match max_param {
1075 Some(max_param) if max_param > ord_kind => {
1076 let entry = out_of_order.entry(ord_kind).or_insert((max_param, ::alloc::vec::Vec::new()vec![]));
1077 entry.1.push(span);
1078 }
1079 Some(_) | None => max_param = Some(ord_kind),
1080 };
1081 }
1082
1083 if !out_of_order.is_empty() {
1084 let mut ordered_params = "<".to_string();
1085 param_idents.sort_by_key(|&(_, po, _, i, _)| (po, i));
1086 let mut first = true;
1087 for (kind, _, bounds, _, ident) in param_idents {
1088 if !first {
1089 ordered_params += ", ";
1090 }
1091 ordered_params += &ident;
1092
1093 if !bounds.is_empty() {
1094 ordered_params += ": ";
1095 ordered_params += &pprust::bounds_to_string(bounds);
1096 }
1097
1098 match kind {
1099 GenericParamKind::Type { default: Some(default) } => {
1100 ordered_params += " = ";
1101 ordered_params += &pprust::ty_to_string(default);
1102 }
1103 GenericParamKind::Type { default: None } => (),
1104 GenericParamKind::Lifetime => (),
1105 GenericParamKind::Const { ty: _, span: _, default: Some(default) } => {
1106 ordered_params += " = ";
1107 ordered_params += &pprust::expr_to_string(&default.value);
1108 }
1109 GenericParamKind::Const { ty: _, span: _, default: None } => (),
1110 }
1111 first = false;
1112 }
1113
1114 ordered_params += ">";
1115
1116 for (param_ord, (max_param, spans)) in &out_of_order {
1117 dcx.emit_err(errors::OutOfOrderParams {
1118 spans: spans.clone(),
1119 sugg_span: span,
1120 param_ord,
1121 max_param,
1122 ordered_params: &ordered_params,
1123 });
1124 }
1125 }
1126}
1127
1128impl<'a> Visitor<'a> for AstValidator<'a> {
1129 fn visit_attribute(&mut self, attr: &Attribute) {
1130 validate_attr::check_attr(&self.sess.psess, attr);
1131 }
1132
1133 fn visit_ty(&mut self, ty: &'a Ty) {
1134 self.visit_ty_common(ty);
1135 self.walk_ty(ty)
1136 }
1137
1138 fn visit_item(&mut self, item: &'a Item) {
1139 if item.attrs.iter().any(|attr| attr.is_proc_macro_attr()) {
1140 self.has_proc_macro_decls = true;
1141 }
1142
1143 let previous_lint_node_id = mem::replace(&mut self.lint_node_id, item.id);
1144
1145 if let Some(ident) = item.kind.ident()
1146 && attr::contains_name(&item.attrs, sym::no_mangle)
1147 {
1148 self.check_nomangle_item_asciionly(ident, item.span);
1149 }
1150
1151 match &item.kind {
1152 ItemKind::Impl(Impl {
1153 generics,
1154 constness,
1155 of_trait:
1156 Some(box TraitImplHeader { safety, polarity, defaultness: _, trait_ref: t }),
1157 self_ty,
1158 items,
1159 }) => {
1160 self.visit_attrs_vis(&item.attrs, &item.vis);
1161 self.visibility_not_permitted(
1162 &item.vis,
1163 errors::VisibilityNotPermittedNote::TraitImpl,
1164 );
1165 if let TyKind::Dummy = self_ty.kind {
1166 self.dcx().emit_fatal(errors::ObsoleteAuto { span: item.span });
1169 }
1170 if let (&Safety::Unsafe(span), &ImplPolarity::Negative(sp)) = (safety, polarity) {
1171 self.dcx().emit_err(errors::UnsafeNegativeImpl {
1172 span: sp.to(t.path.span),
1173 negative: sp,
1174 r#unsafe: span,
1175 });
1176 }
1177
1178 let disallowed = #[allow(non_exhaustive_omitted_patterns)] match constness {
Const::No => true,
_ => false,
}matches!(constness, Const::No)
1179 .then(|| TildeConstReason::TraitImpl { span: item.span });
1180 self.with_tilde_const(disallowed, |this| this.visit_generics(generics));
1181 self.visit_trait_ref(t);
1182 self.visit_ty(self_ty);
1183
1184 self.with_in_trait_or_impl(
1185 Some(TraitOrImpl::TraitImpl {
1186 constness: *constness,
1187 polarity: *polarity,
1188 trait_ref_span: t.path.span,
1189 }),
1190 |this| {
1191 for elem in items {
match ::rustc_ast_ir::visit::VisitorResult::branch(this.visit_assoc_item(elem,
AssocCtxt::Impl { of_trait: true })) {
core::ops::ControlFlow::Continue(()) =>
(),
#[allow(unreachable_code)]
core::ops::ControlFlow::Break(r) => {
return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
}
};
};walk_list!(
1192 this,
1193 visit_assoc_item,
1194 items,
1195 AssocCtxt::Impl { of_trait: true }
1196 );
1197 },
1198 );
1199 }
1200 ItemKind::Impl(Impl { generics, of_trait: None, self_ty, items, constness }) => {
1201 self.visit_attrs_vis(&item.attrs, &item.vis);
1202 self.visibility_not_permitted(
1203 &item.vis,
1204 errors::VisibilityNotPermittedNote::IndividualImplItems,
1205 );
1206
1207 let disallowed = #[allow(non_exhaustive_omitted_patterns)] match constness {
ast::Const::No => true,
_ => false,
}matches!(constness, ast::Const::No)
1208 .then(|| TildeConstReason::Impl { span: item.span });
1209
1210 self.with_tilde_const(disallowed, |this| this.visit_generics(generics));
1211
1212 self.visit_ty(self_ty);
1213 self.with_in_trait_or_impl(
1214 Some(TraitOrImpl::Impl { constness: *constness }),
1215 |this| {
1216 for elem in items {
match ::rustc_ast_ir::visit::VisitorResult::branch(this.visit_assoc_item(elem,
AssocCtxt::Impl { of_trait: false })) {
core::ops::ControlFlow::Continue(()) =>
(),
#[allow(unreachable_code)]
core::ops::ControlFlow::Break(r) => {
return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
}
};
};walk_list!(
1217 this,
1218 visit_assoc_item,
1219 items,
1220 AssocCtxt::Impl { of_trait: false }
1221 );
1222 },
1223 );
1224 }
1225 ItemKind::Fn(
1226 func @ box Fn {
1227 defaultness,
1228 ident,
1229 generics: _,
1230 sig,
1231 contract: _,
1232 body,
1233 define_opaque: _,
1234 eii_impls,
1235 },
1236 ) => {
1237 self.visit_attrs_vis_ident(&item.attrs, &item.vis, ident);
1238 self.check_defaultness(item.span, *defaultness, AllowDefault::No, AllowFinal::No);
1239
1240 for EiiImpl { eii_macro_path, .. } in eii_impls {
1241 self.visit_path(eii_macro_path);
1242 }
1243
1244 let is_intrinsic = item.attrs.iter().any(|a| a.has_name(sym::rustc_intrinsic));
1245 if body.is_none() && !is_intrinsic && !self.is_sdylib_interface {
1246 self.dcx().emit_err(errors::FnWithoutBody {
1247 span: item.span,
1248 replace_span: self.ending_semi_or_hi(item.span),
1249 extern_block_suggestion: match sig.header.ext {
1250 Extern::None => None,
1251 Extern::Implicit(start_span) => {
1252 Some(errors::ExternBlockSuggestion::Implicit {
1253 start_span,
1254 end_span: item.span.shrink_to_hi(),
1255 })
1256 }
1257 Extern::Explicit(abi, start_span) => {
1258 Some(errors::ExternBlockSuggestion::Explicit {
1259 start_span,
1260 end_span: item.span.shrink_to_hi(),
1261 abi: abi.symbol_unescaped,
1262 })
1263 }
1264 },
1265 });
1266 }
1267
1268 let kind = FnKind::Fn(FnCtxt::Free, &item.vis, &*func);
1269 self.visit_fn(kind, &item.attrs, item.span, item.id);
1270 }
1271 ItemKind::ForeignMod(ForeignMod { extern_span, abi, safety, .. }) => {
1272 let old_item = mem::replace(&mut self.extern_mod_span, Some(item.span));
1273 self.visibility_not_permitted(
1274 &item.vis,
1275 errors::VisibilityNotPermittedNote::IndividualForeignItems,
1276 );
1277
1278 if &Safety::Default == safety {
1279 if item.span.at_least_rust_2024() {
1280 self.dcx().emit_err(errors::MissingUnsafeOnExtern { span: item.span });
1281 } else {
1282 self.lint_buffer.buffer_lint(
1283 MISSING_UNSAFE_ON_EXTERN,
1284 item.id,
1285 item.span,
1286 errors::MissingUnsafeOnExternLint {
1287 suggestion: item.span.shrink_to_lo(),
1288 },
1289 );
1290 }
1291 }
1292
1293 if abi.is_none() {
1294 self.handle_missing_abi(*extern_span, item.id);
1295 }
1296
1297 let extern_abi = abi.and_then(|abi| ExternAbi::from_str(abi.symbol.as_str()).ok());
1298 self.with_in_extern_mod(*safety, extern_abi, |this| {
1299 visit::walk_item(this, item);
1300 });
1301 self.extern_mod_span = old_item;
1302 }
1303 ItemKind::Enum(_, _, def) => {
1304 for variant in &def.variants {
1305 self.visibility_not_permitted(
1306 &variant.vis,
1307 errors::VisibilityNotPermittedNote::EnumVariant,
1308 );
1309 for field in variant.data.fields() {
1310 self.visibility_not_permitted(
1311 &field.vis,
1312 errors::VisibilityNotPermittedNote::EnumVariant,
1313 );
1314 }
1315 }
1316 self.with_tilde_const(Some(TildeConstReason::Enum { span: item.span }), |this| {
1317 visit::walk_item(this, item)
1318 });
1319 }
1320 ItemKind::Trait(box Trait {
1321 constness,
1322 is_auto,
1323 generics,
1324 ident,
1325 bounds,
1326 items,
1327 ..
1328 }) => {
1329 self.visit_attrs_vis_ident(&item.attrs, &item.vis, ident);
1330 if *is_auto == IsAuto::Yes {
1331 self.deny_const_auto_traits(*constness);
1333 self.deny_generic_params(generics, ident.span);
1335 self.deny_super_traits(bounds, ident.span);
1336 self.deny_where_clause(&generics.where_clause, ident.span);
1337 self.deny_items(items, ident.span);
1338 }
1339
1340 let disallowed = #[allow(non_exhaustive_omitted_patterns)] match constness {
ast::Const::No => true,
_ => false,
}matches!(constness, ast::Const::No)
1343 .then(|| TildeConstReason::Trait { span: item.span });
1344 self.with_tilde_const(disallowed, |this| {
1345 this.visit_generics(generics);
1346 for elem in bounds {
match ::rustc_ast_ir::visit::VisitorResult::branch(this.visit_param_bound(elem,
BoundKind::SuperTraits)) {
core::ops::ControlFlow::Continue(()) =>
(),
#[allow(unreachable_code)]
core::ops::ControlFlow::Break(r) => {
return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
}
};
}walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits)
1347 });
1348 self.with_in_trait(item.span, *constness, |this| {
1349 for elem in items {
match ::rustc_ast_ir::visit::VisitorResult::branch(this.visit_assoc_item(elem,
AssocCtxt::Trait)) {
core::ops::ControlFlow::Continue(()) =>
(),
#[allow(unreachable_code)]
core::ops::ControlFlow::Break(r) => {
return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
}
};
};walk_list!(this, visit_assoc_item, items, AssocCtxt::Trait);
1350 });
1351 }
1352 ItemKind::TraitAlias(box TraitAlias { constness, generics, bounds, .. }) => {
1353 let disallowed = #[allow(non_exhaustive_omitted_patterns)] match constness {
ast::Const::No => true,
_ => false,
}matches!(constness, ast::Const::No)
1354 .then(|| TildeConstReason::Trait { span: item.span });
1355 self.with_tilde_const(disallowed, |this| {
1356 this.visit_generics(generics);
1357 for elem in bounds {
match ::rustc_ast_ir::visit::VisitorResult::branch(this.visit_param_bound(elem,
BoundKind::SuperTraits)) {
core::ops::ControlFlow::Continue(()) =>
(),
#[allow(unreachable_code)]
core::ops::ControlFlow::Break(r) => {
return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
}
};
}walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits)
1358 });
1359 }
1360 ItemKind::Mod(safety, ident, mod_kind) => {
1361 if let &Safety::Unsafe(span) = safety {
1362 self.dcx().emit_err(errors::UnsafeItem { span, kind: "module" });
1363 }
1364 if !#[allow(non_exhaustive_omitted_patterns)] match mod_kind {
ModKind::Loaded(_, Inline::Yes, _) => true,
_ => false,
}matches!(mod_kind, ModKind::Loaded(_, Inline::Yes, _))
1366 && !attr::contains_name(&item.attrs, sym::path)
1367 {
1368 self.check_mod_file_item_asciionly(*ident);
1369 }
1370 visit::walk_item(self, item)
1371 }
1372 ItemKind::Struct(ident, generics, vdata) => {
1373 self.with_tilde_const(Some(TildeConstReason::Struct { span: item.span }), |this| {
1374 let scalable_vector_attr =
1376 item.attrs.iter().find(|attr| attr.has_name(sym::rustc_scalable_vector));
1377 if let Some(attr) = scalable_vector_attr {
1378 if !#[allow(non_exhaustive_omitted_patterns)] match vdata {
VariantData::Tuple(..) => true,
_ => false,
}matches!(vdata, VariantData::Tuple(..)) {
1379 this.dcx()
1380 .emit_err(errors::ScalableVectorNotTupleStruct { span: item.span });
1381 }
1382 if !self.sess.target.arch.supports_scalable_vectors()
1383 && !self.sess.opts.actually_rustdoc
1384 {
1385 this.dcx().emit_err(errors::ScalableVectorBadArch { span: attr.span });
1386 }
1387 }
1388
1389 match vdata {
1390 VariantData::Struct { fields, .. } => {
1391 this.visit_attrs_vis_ident(&item.attrs, &item.vis, ident);
1392 this.visit_generics(generics);
1393 for elem in fields {
match ::rustc_ast_ir::visit::VisitorResult::branch(this.visit_field_def(elem))
{
core::ops::ControlFlow::Continue(()) =>
(),
#[allow(unreachable_code)]
core::ops::ControlFlow::Break(r) => {
return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
}
};
};walk_list!(this, visit_field_def, fields);
1394 }
1395 _ => visit::walk_item(this, item),
1396 }
1397 })
1398 }
1399 ItemKind::Union(ident, generics, vdata) => {
1400 if vdata.fields().is_empty() {
1401 self.dcx().emit_err(errors::FieldlessUnion { span: item.span });
1402 }
1403 self.with_tilde_const(Some(TildeConstReason::Union { span: item.span }), |this| {
1404 match vdata {
1405 VariantData::Struct { fields, .. } => {
1406 this.visit_attrs_vis_ident(&item.attrs, &item.vis, ident);
1407 this.visit_generics(generics);
1408 for elem in fields {
match ::rustc_ast_ir::visit::VisitorResult::branch(this.visit_field_def(elem))
{
core::ops::ControlFlow::Continue(()) =>
(),
#[allow(unreachable_code)]
core::ops::ControlFlow::Break(r) => {
return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
}
};
};walk_list!(this, visit_field_def, fields);
1409 }
1410 _ => visit::walk_item(this, item),
1411 }
1412 });
1413 }
1414 ItemKind::Const(box ConstItem { defaultness, ident, rhs_kind, .. }) => {
1415 self.check_defaultness(item.span, *defaultness, AllowDefault::No, AllowFinal::No);
1416 if !rhs_kind.has_expr() {
1417 self.dcx().emit_err(errors::ConstWithoutBody {
1418 span: item.span,
1419 replace_span: self.ending_semi_or_hi(item.span),
1420 });
1421 }
1422 if ident.name == kw::Underscore
1423 && !#[allow(non_exhaustive_omitted_patterns)] match item.vis.kind {
VisibilityKind::Inherited => true,
_ => false,
}matches!(item.vis.kind, VisibilityKind::Inherited)
1424 && ident.span.eq_ctxt(item.vis.span)
1425 {
1426 self.lint_buffer.buffer_lint(
1427 UNUSED_VISIBILITIES,
1428 item.id,
1429 item.vis.span,
1430 errors::UnusedVisibility { span: item.vis.span },
1431 )
1432 }
1433
1434 visit::walk_item(self, item);
1435 }
1436 ItemKind::Static(box StaticItem { expr, safety, .. }) => {
1437 self.check_item_safety(item.span, *safety);
1438 if #[allow(non_exhaustive_omitted_patterns)] match safety {
Safety::Unsafe(_) => true,
_ => false,
}matches!(safety, Safety::Unsafe(_)) {
1439 self.dcx().emit_err(errors::UnsafeStatic { span: item.span });
1440 }
1441
1442 if expr.is_none() {
1443 self.dcx().emit_err(errors::StaticWithoutBody {
1444 span: item.span,
1445 replace_span: self.ending_semi_or_hi(item.span),
1446 });
1447 }
1448 visit::walk_item(self, item);
1449 }
1450 ItemKind::TyAlias(
1451 ty_alias @ box TyAlias { defaultness, bounds, after_where_clause, ty, .. },
1452 ) => {
1453 self.check_defaultness(item.span, *defaultness, AllowDefault::No, AllowFinal::No);
1454 if ty.is_none() {
1455 self.dcx().emit_err(errors::TyAliasWithoutBody {
1456 span: item.span,
1457 replace_span: self.ending_semi_or_hi(item.span),
1458 });
1459 }
1460 self.check_type_no_bounds(bounds, "this context");
1461
1462 if self.features.lazy_type_alias() {
1463 if let Err(err) = self.check_type_alias_where_clause_location(ty_alias) {
1464 self.dcx().emit_err(err);
1465 }
1466 } else if after_where_clause.has_where_token {
1467 self.dcx().emit_err(errors::WhereClauseAfterTypeAlias {
1468 span: after_where_clause.span,
1469 help: self.sess.is_nightly_build(),
1470 });
1471 }
1472 visit::walk_item(self, item);
1473 }
1474 _ => visit::walk_item(self, item),
1475 }
1476
1477 self.lint_node_id = previous_lint_node_id;
1478 }
1479
1480 fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
1481 match &fi.kind {
1482 ForeignItemKind::Fn(box Fn { defaultness, ident, sig, body, .. }) => {
1483 self.check_defaultness(fi.span, *defaultness, AllowDefault::No, AllowFinal::No);
1484 self.check_foreign_fn_bodyless(*ident, body.as_deref());
1485 self.check_foreign_fn_headerless(sig.header);
1486 self.check_foreign_item_ascii_only(*ident);
1487 self.check_extern_fn_signature(
1488 self.extern_mod_abi.unwrap_or(ExternAbi::FALLBACK),
1489 FnCtxt::Foreign,
1490 ident,
1491 sig,
1492 );
1493
1494 if let Some(attr) = attr::find_by_name(fi.attrs(), sym::track_caller)
1495 && self.extern_mod_abi != Some(ExternAbi::Rust)
1496 {
1497 self.dcx().emit_err(errors::RequiresRustAbi {
1498 track_caller_span: attr.span,
1499 extern_abi_span: self.current_extern_span(),
1500 });
1501 }
1502 }
1503 ForeignItemKind::TyAlias(box TyAlias {
1504 defaultness,
1505 ident,
1506 generics,
1507 after_where_clause,
1508 bounds,
1509 ty,
1510 ..
1511 }) => {
1512 self.check_defaultness(fi.span, *defaultness, AllowDefault::No, AllowFinal::No);
1513 self.check_foreign_kind_bodyless(*ident, "type", ty.as_ref().map(|b| b.span));
1514 self.check_type_no_bounds(bounds, "`extern` blocks");
1515 self.check_foreign_ty_genericless(generics, after_where_clause);
1516 self.check_foreign_item_ascii_only(*ident);
1517 }
1518 ForeignItemKind::Static(box StaticItem { ident, safety, expr, .. }) => {
1519 self.check_item_safety(fi.span, *safety);
1520 self.check_foreign_kind_bodyless(*ident, "static", expr.as_ref().map(|b| b.span));
1521 self.check_foreign_item_ascii_only(*ident);
1522 }
1523 ForeignItemKind::MacCall(..) => {}
1524 }
1525
1526 visit::walk_item(self, fi)
1527 }
1528
1529 fn visit_generic_args(&mut self, generic_args: &'a GenericArgs) {
1531 match generic_args {
1532 GenericArgs::AngleBracketed(data) => {
1533 self.check_generic_args_before_constraints(data);
1534
1535 for arg in &data.args {
1536 match arg {
1537 AngleBracketedArg::Arg(arg) => self.visit_generic_arg(arg),
1538 AngleBracketedArg::Constraint(constraint) => {
1541 self.with_impl_trait(None, |this| {
1542 this.visit_assoc_item_constraint(constraint);
1543 });
1544 }
1545 }
1546 }
1547 }
1548 GenericArgs::Parenthesized(data) => {
1549 for elem in &data.inputs {
match ::rustc_ast_ir::visit::VisitorResult::branch(self.visit_ty(elem)) {
core::ops::ControlFlow::Continue(()) =>
(),
#[allow(unreachable_code)]
core::ops::ControlFlow::Break(r) => {
return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
}
};
};walk_list!(self, visit_ty, &data.inputs);
1550 if let FnRetTy::Ty(ty) = &data.output {
1551 self.with_impl_trait(None, |this| this.visit_ty(ty));
1554 }
1555 }
1556 GenericArgs::ParenthesizedElided(_span) => {}
1557 }
1558 }
1559
1560 fn visit_generics(&mut self, generics: &'a Generics) {
1561 let mut prev_param_default = None;
1562 for param in &generics.params {
1563 match param.kind {
1564 GenericParamKind::Lifetime => (),
1565 GenericParamKind::Type { default: Some(_), .. }
1566 | GenericParamKind::Const { default: Some(_), .. } => {
1567 prev_param_default = Some(param.ident.span);
1568 }
1569 GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {
1570 if let Some(span) = prev_param_default {
1571 self.dcx().emit_err(errors::GenericDefaultTrailing { span });
1572 break;
1573 }
1574 }
1575 }
1576 }
1577
1578 validate_generic_param_order(self.dcx(), &generics.params, generics.span);
1579
1580 for predicate in &generics.where_clause.predicates {
1581 let span = predicate.span;
1582 if let WherePredicateKind::EqPredicate(predicate) = &predicate.kind {
1583 deny_equality_constraints(self, predicate, span, generics);
1584 }
1585 }
1586 for elem in &generics.params {
match ::rustc_ast_ir::visit::VisitorResult::branch(self.visit_generic_param(elem))
{
core::ops::ControlFlow::Continue(()) =>
(),
#[allow(unreachable_code)]
core::ops::ControlFlow::Break(r) => {
return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
}
};
};walk_list!(self, visit_generic_param, &generics.params);
1587 for predicate in &generics.where_clause.predicates {
1588 match &predicate.kind {
1589 WherePredicateKind::BoundPredicate(bound_pred) => {
1590 if !bound_pred.bound_generic_params.is_empty() {
1596 for bound in &bound_pred.bounds {
1597 match bound {
1598 GenericBound::Trait(t) => {
1599 if !t.bound_generic_params.is_empty() {
1600 self.dcx()
1601 .emit_err(errors::NestedLifetimes { span: t.span });
1602 }
1603 }
1604 GenericBound::Outlives(_) => {}
1605 GenericBound::Use(..) => {}
1606 }
1607 }
1608 }
1609 }
1610 _ => {}
1611 }
1612 self.visit_where_predicate(predicate);
1613 }
1614 }
1615
1616 fn visit_param_bound(&mut self, bound: &'a GenericBound, ctxt: BoundKind) {
1617 match bound {
1618 GenericBound::Trait(trait_ref) => {
1619 match (ctxt, trait_ref.modifiers.constness, trait_ref.modifiers.polarity) {
1620 (
1621 BoundKind::TraitObject,
1622 BoundConstness::Always(_),
1623 BoundPolarity::Positive,
1624 ) => {
1625 self.dcx().emit_err(errors::ConstBoundTraitObject { span: trait_ref.span });
1626 }
1627 (_, BoundConstness::Maybe(span), BoundPolarity::Positive)
1628 if let Some(reason) = self.disallow_tilde_const =>
1629 {
1630 self.dcx().emit_err(errors::TildeConstDisallowed { span, reason });
1631 }
1632 _ => {}
1633 }
1634
1635 if let BoundPolarity::Negative(_) = trait_ref.modifiers.polarity
1637 && let Some(segment) = trait_ref.trait_ref.path.segments.last()
1638 {
1639 match segment.args.as_deref() {
1640 Some(ast::GenericArgs::AngleBracketed(args)) => {
1641 for arg in &args.args {
1642 if let ast::AngleBracketedArg::Constraint(constraint) = arg {
1643 self.dcx().emit_err(errors::ConstraintOnNegativeBound {
1644 span: constraint.span,
1645 });
1646 }
1647 }
1648 }
1649 Some(ast::GenericArgs::Parenthesized(args)) => {
1651 self.dcx().emit_err(errors::NegativeBoundWithParentheticalNotation {
1652 span: args.span,
1653 });
1654 }
1655 Some(ast::GenericArgs::ParenthesizedElided(_)) | None => {}
1656 }
1657 }
1658 }
1659 GenericBound::Outlives(_) => {}
1660 GenericBound::Use(_, span) => match ctxt {
1661 BoundKind::Impl => {}
1662 BoundKind::Bound | BoundKind::TraitObject | BoundKind::SuperTraits => {
1663 self.dcx().emit_err(errors::PreciseCapturingNotAllowedHere {
1664 loc: ctxt.descr(),
1665 span: *span,
1666 });
1667 }
1668 },
1669 }
1670
1671 visit::walk_param_bound(self, bound)
1672 }
1673
1674 fn visit_fn(&mut self, fk: FnKind<'a>, attrs: &AttrVec, span: Span, id: NodeId) {
1675 let self_semantic = match fk.ctxt() {
1677 Some(FnCtxt::Assoc(_)) => SelfSemantic::Yes,
1678 _ => SelfSemantic::No,
1679 };
1680 self.check_fn_decl(fk.decl(), self_semantic);
1681
1682 if let Some(&FnHeader { safety, .. }) = fk.header() {
1683 self.check_item_safety(span, safety);
1684 }
1685
1686 if let FnKind::Fn(ctxt, _, fun) = fk {
1687 let ext = match fun.sig.header.ext {
1688 Extern::None => None,
1689 Extern::Implicit(span) => Some((ExternAbi::FALLBACK, span)),
1690 Extern::Explicit(str_lit, span) => {
1691 ExternAbi::from_str(str_lit.symbol.as_str()).ok().map(|abi| (abi, span))
1692 }
1693 };
1694
1695 if let Some((extern_abi, extern_abi_span)) = ext {
1696 self.check_extern_fn_signature(extern_abi, ctxt, &fun.ident, &fun.sig);
1698
1699 if let Some(attr) = attr::find_by_name(attrs, sym::track_caller)
1701 && extern_abi != ExternAbi::Rust
1702 {
1703 self.dcx().emit_err(errors::RequiresRustAbi {
1704 track_caller_span: attr.span,
1705 extern_abi_span,
1706 });
1707 }
1708 }
1709 }
1710
1711 self.check_c_variadic_type(fk, attrs);
1712
1713 if let Some(&FnHeader {
1715 constness: Const::Yes(const_span),
1716 coroutine_kind: Some(coroutine_kind),
1717 ..
1718 }) = fk.header()
1719 {
1720 self.dcx().emit_err(errors::ConstAndCoroutine {
1721 spans: ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[coroutine_kind.span(), const_span]))vec![coroutine_kind.span(), const_span],
1722 const_span,
1723 coroutine_span: coroutine_kind.span(),
1724 coroutine_kind: coroutine_kind.as_str(),
1725 span,
1726 });
1727 }
1728
1729 if let FnKind::Fn(
1730 _,
1731 _,
1732 Fn {
1733 sig: FnSig { header: FnHeader { ext: Extern::Implicit(extern_span), .. }, .. },
1734 ..
1735 },
1736 ) = fk
1737 {
1738 self.handle_missing_abi(*extern_span, id);
1739 }
1740
1741 if let FnKind::Fn(ctxt, _, Fn { body: None, sig, .. }) = fk {
1743 Self::check_decl_no_pat(&sig.decl, |span, ident, mut_ident| {
1744 if mut_ident && #[allow(non_exhaustive_omitted_patterns)] match ctxt {
FnCtxt::Assoc(_) => true,
_ => false,
}matches!(ctxt, FnCtxt::Assoc(_)) {
1745 if let Some(ident) = ident {
1746 let is_foreign = #[allow(non_exhaustive_omitted_patterns)] match ctxt {
FnCtxt::Foreign => true,
_ => false,
}matches!(ctxt, FnCtxt::Foreign);
1747 self.lint_buffer.dyn_buffer_lint(
1748 PATTERNS_IN_FNS_WITHOUT_BODY,
1749 id,
1750 span,
1751 move |dcx, level| {
1752 let sub = errors::PatternsInFnsWithoutBodySub { ident, span };
1753 if is_foreign {
1754 errors::PatternsInFnsWithoutBody::Foreign { sub }
1755 } else {
1756 errors::PatternsInFnsWithoutBody::Bodiless { sub }
1757 }
1758 .into_diag(dcx, level)
1759 },
1760 )
1761 }
1762 } else {
1763 match ctxt {
1764 FnCtxt::Foreign => self.dcx().emit_err(errors::PatternInForeign { span }),
1765 _ => self.dcx().emit_err(errors::PatternInBodiless { span }),
1766 };
1767 }
1768 });
1769 }
1770
1771 let tilde_const_allowed =
1772 #[allow(non_exhaustive_omitted_patterns)] match fk.header() {
Some(FnHeader { constness: ast::Const::Yes(_), .. }) => true,
_ => false,
}matches!(fk.header(), Some(FnHeader { constness: ast::Const::Yes(_), .. }))
1773 || #[allow(non_exhaustive_omitted_patterns)] match fk.ctxt() {
Some(FnCtxt::Assoc(_)) => true,
_ => false,
}matches!(fk.ctxt(), Some(FnCtxt::Assoc(_)))
1774 && self
1775 .outer_trait_or_trait_impl
1776 .as_ref()
1777 .and_then(TraitOrImpl::constness)
1778 .is_some();
1779
1780 let disallowed = (!tilde_const_allowed).then(|| match fk {
1781 FnKind::Fn(_, _, f) => TildeConstReason::Function { ident: f.ident.span },
1782 FnKind::Closure(..) => TildeConstReason::Closure,
1783 });
1784 self.with_tilde_const(disallowed, |this| visit::walk_fn(this, fk));
1785 }
1786
1787 fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
1788 if let Some(ident) = item.kind.ident()
1789 && attr::contains_name(&item.attrs, sym::no_mangle)
1790 {
1791 self.check_nomangle_item_asciionly(ident, item.span);
1792 }
1793
1794 let defaultness = item.kind.defaultness();
1795 self.check_defaultness(
1796 item.span,
1797 defaultness,
1798 AllowDefault::when(#[allow(non_exhaustive_omitted_patterns)] match ctxt {
AssocCtxt::Impl { .. } => true,
_ => false,
}matches!(ctxt, AssocCtxt::Impl { .. })),
1800 AllowFinal::when(
1802 ctxt == AssocCtxt::Trait && #[allow(non_exhaustive_omitted_patterns)] match item.kind {
AssocItemKind::Fn(..) => true,
_ => false,
}matches!(item.kind, AssocItemKind::Fn(..)),
1803 ),
1804 );
1805
1806 self.check_final_has_body(item, defaultness);
1807
1808 if let AssocCtxt::Impl { .. } = ctxt {
1809 match &item.kind {
1810 AssocItemKind::Const(box ConstItem { rhs_kind, .. }) => {
1811 if !rhs_kind.has_expr() {
1812 self.dcx().emit_err(errors::AssocConstWithoutBody {
1813 span: item.span,
1814 replace_span: self.ending_semi_or_hi(item.span),
1815 });
1816 }
1817 }
1818 AssocItemKind::Fn(box Fn { body, .. }) => {
1819 if body.is_none() && !self.is_sdylib_interface {
1820 self.dcx().emit_err(errors::AssocFnWithoutBody {
1821 span: item.span,
1822 replace_span: self.ending_semi_or_hi(item.span),
1823 });
1824 }
1825 }
1826 AssocItemKind::Type(box TyAlias { bounds, ty, .. }) => {
1827 if ty.is_none() {
1828 self.dcx().emit_err(errors::AssocTypeWithoutBody {
1829 span: item.span,
1830 replace_span: self.ending_semi_or_hi(item.span),
1831 });
1832 }
1833 self.check_type_no_bounds(bounds, "`impl`s");
1834 }
1835 _ => {}
1836 }
1837 }
1838
1839 if let AssocItemKind::Type(ty_alias) = &item.kind
1840 && let Err(err) = self.check_type_alias_where_clause_location(ty_alias)
1841 {
1842 let sugg = match err.sugg {
1843 errors::WhereClauseBeforeTypeAliasSugg::Remove { .. } => None,
1844 errors::WhereClauseBeforeTypeAliasSugg::Move { snippet, right, .. } => {
1845 Some((right, snippet))
1846 }
1847 };
1848 let left_sp = self
1849 .sess
1850 .source_map()
1851 .span_extend_prev_while(err.span, char::is_whitespace)
1852 .unwrap_or(err.span);
1853 self.lint_buffer.dyn_buffer_lint(
1854 DEPRECATED_WHERE_CLAUSE_LOCATION,
1855 item.id,
1856 err.span,
1857 move |dcx, level| {
1858 let suggestion = match sugg {
1859 Some((right_sp, sugg)) => {
1860 errors::DeprecatedWhereClauseLocationSugg::MoveToEnd {
1861 left: left_sp,
1862 right: right_sp,
1863 sugg,
1864 }
1865 }
1866 None => errors::DeprecatedWhereClauseLocationSugg::RemoveWhere {
1867 span: err.span,
1868 },
1869 };
1870 errors::DeprecatedWhereClauseLocation { suggestion }.into_diag(dcx, level)
1871 },
1872 );
1873 }
1874
1875 match &self.outer_trait_or_trait_impl {
1876 Some(parent @ (TraitOrImpl::Trait { .. } | TraitOrImpl::TraitImpl { .. })) => {
1877 self.visibility_not_permitted(
1878 &item.vis,
1879 errors::VisibilityNotPermittedNote::TraitImpl,
1880 );
1881 if let AssocItemKind::Fn(box Fn { sig, .. }) = &item.kind {
1882 self.check_trait_fn_not_const(sig.header.constness, parent);
1883 self.check_async_fn_in_const_trait_or_impl(sig, parent);
1884 }
1885 }
1886 Some(parent @ TraitOrImpl::Impl { constness }) => {
1887 if let AssocItemKind::Fn(box Fn { sig, .. }) = &item.kind {
1888 self.check_impl_fn_not_const(sig.header.constness, *constness);
1889 self.check_async_fn_in_const_trait_or_impl(sig, parent);
1890 }
1891 }
1892 None => {}
1893 }
1894
1895 if let AssocItemKind::Const(ci) = &item.kind {
1896 self.check_item_named(ci.ident, "const");
1897 }
1898
1899 let parent_is_const =
1900 self.outer_trait_or_trait_impl.as_ref().and_then(TraitOrImpl::constness).is_some();
1901
1902 match &item.kind {
1903 AssocItemKind::Fn(func)
1904 if parent_is_const
1905 || ctxt == AssocCtxt::Trait
1906 || #[allow(non_exhaustive_omitted_patterns)] match func.sig.header.constness {
Const::Yes(_) => true,
_ => false,
}matches!(func.sig.header.constness, Const::Yes(_)) =>
1907 {
1908 self.visit_attrs_vis_ident(&item.attrs, &item.vis, &func.ident);
1909 let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), &item.vis, &*func);
1910 self.visit_fn(kind, &item.attrs, item.span, item.id);
1911 }
1912 AssocItemKind::Type(_) => {
1913 let disallowed = (!parent_is_const).then(|| match self.outer_trait_or_trait_impl {
1914 Some(TraitOrImpl::Trait { .. }) => {
1915 TildeConstReason::TraitAssocTy { span: item.span }
1916 }
1917 Some(TraitOrImpl::TraitImpl { .. }) => {
1918 TildeConstReason::TraitImplAssocTy { span: item.span }
1919 }
1920 Some(TraitOrImpl::Impl { .. }) | None => {
1921 TildeConstReason::InherentAssocTy { span: item.span }
1922 }
1923 });
1924 self.with_tilde_const(disallowed, |this| {
1925 this.with_in_trait_or_impl(None, |this| {
1926 visit::walk_assoc_item(this, item, ctxt)
1927 })
1928 })
1929 }
1930 _ => self.with_in_trait_or_impl(None, |this| visit::walk_assoc_item(this, item, ctxt)),
1931 }
1932 }
1933
1934 fn visit_anon_const(&mut self, anon_const: &'a AnonConst) {
1935 self.with_tilde_const(
1936 Some(TildeConstReason::AnonConst { span: anon_const.value.span }),
1937 |this| visit::walk_anon_const(this, anon_const),
1938 )
1939 }
1940}
1941
1942fn deny_equality_constraints(
1945 this: &AstValidator<'_>,
1946 predicate: &WhereEqPredicate,
1947 predicate_span: Span,
1948 generics: &Generics,
1949) {
1950 let mut err = errors::EqualityInWhere { span: predicate_span, assoc: None, assoc2: None };
1951
1952 if let TyKind::Path(Some(qself), full_path) = &predicate.lhs_ty.kind
1954 && let TyKind::Path(None, path) = &qself.ty.kind
1955 && let [PathSegment { ident, args: None, .. }] = &path.segments[..]
1956 {
1957 for param in &generics.params {
1958 if param.ident == *ident
1959 && let [PathSegment { ident, args, .. }] = &full_path.segments[qself.position..]
1960 {
1961 let mut assoc_path = full_path.clone();
1963 assoc_path.segments.pop();
1965 let len = assoc_path.segments.len() - 1;
1966 let gen_args = args.as_deref().cloned();
1967 let arg = AngleBracketedArg::Constraint(AssocItemConstraint {
1969 id: rustc_ast::node_id::DUMMY_NODE_ID,
1970 ident: *ident,
1971 gen_args,
1972 kind: AssocItemConstraintKind::Equality {
1973 term: predicate.rhs_ty.clone().into(),
1974 },
1975 span: ident.span,
1976 });
1977 match &mut assoc_path.segments[len].args {
1979 Some(args) => match args.deref_mut() {
1980 GenericArgs::Parenthesized(_) | GenericArgs::ParenthesizedElided(..) => {
1981 continue;
1982 }
1983 GenericArgs::AngleBracketed(args) => {
1984 args.args.push(arg);
1985 }
1986 },
1987 empty_args => {
1988 *empty_args = Some(
1989 AngleBracketedArgs { span: ident.span, args: {
let len = [()].len();
let mut vec = ::thin_vec::ThinVec::with_capacity(len);
vec.push(arg);
vec
}thin_vec![arg] }.into(),
1990 );
1991 }
1992 }
1993 err.assoc = Some(errors::AssociatedSuggestion {
1994 span: predicate_span,
1995 ident: *ident,
1996 param: param.ident,
1997 path: pprust::path_to_string(&assoc_path),
1998 })
1999 }
2000 }
2001 }
2002
2003 let mut suggest =
2004 |poly: &PolyTraitRef, potential_assoc: &PathSegment, predicate: &WhereEqPredicate| {
2005 if let [trait_segment] = &poly.trait_ref.path.segments[..] {
2006 let assoc = pprust::path_to_string(&ast::Path::from_ident(potential_assoc.ident));
2007 let ty = pprust::ty_to_string(&predicate.rhs_ty);
2008 let (args, span) = match &trait_segment.args {
2009 Some(args) => match args.deref() {
2010 ast::GenericArgs::AngleBracketed(args) => {
2011 let Some(arg) = args.args.last() else {
2012 return;
2013 };
2014 (::alloc::__export::must_use({
::alloc::fmt::format(format_args!(", {0} = {1}", assoc, ty))
})format!(", {assoc} = {ty}"), arg.span().shrink_to_hi())
2015 }
2016 _ => return,
2017 },
2018 None => (::alloc::__export::must_use({
::alloc::fmt::format(format_args!("<{0} = {1}>", assoc, ty))
})format!("<{assoc} = {ty}>"), trait_segment.span().shrink_to_hi()),
2019 };
2020 let removal_span = if generics.where_clause.predicates.len() == 1 {
2021 generics.where_clause.span
2023 } else {
2024 let mut span = predicate_span;
2025 let mut prev_span: Option<Span> = None;
2026 let mut preds = generics.where_clause.predicates.iter().peekable();
2027 while let Some(pred) = preds.next() {
2029 if let WherePredicateKind::EqPredicate(_) = pred.kind
2030 && pred.span == predicate_span
2031 {
2032 if let Some(next) = preds.peek() {
2033 span = span.with_hi(next.span.lo());
2035 } else if let Some(prev_span) = prev_span {
2036 span = span.with_lo(prev_span.hi());
2038 }
2039 }
2040 prev_span = Some(pred.span);
2041 }
2042 span
2043 };
2044 err.assoc2 = Some(errors::AssociatedSuggestion2 {
2045 span,
2046 args,
2047 predicate: removal_span,
2048 trait_segment: trait_segment.ident,
2049 potential_assoc: potential_assoc.ident,
2050 });
2051 }
2052 };
2053
2054 if let TyKind::Path(None, full_path) = &predicate.lhs_ty.kind {
2055 for bounds in generics.params.iter().map(|p| &p.bounds).chain(
2057 generics.where_clause.predicates.iter().filter_map(|pred| match &pred.kind {
2058 WherePredicateKind::BoundPredicate(p) => Some(&p.bounds),
2059 _ => None,
2060 }),
2061 ) {
2062 for bound in bounds {
2063 if let GenericBound::Trait(poly) = bound
2064 && poly.modifiers == TraitBoundModifiers::NONE
2065 {
2066 if full_path.segments[..full_path.segments.len() - 1]
2067 .iter()
2068 .map(|segment| segment.ident.name)
2069 .zip(poly.trait_ref.path.segments.iter().map(|segment| segment.ident.name))
2070 .all(|(a, b)| a == b)
2071 && let Some(potential_assoc) = full_path.segments.last()
2072 {
2073 suggest(poly, potential_assoc, predicate);
2074 }
2075 }
2076 }
2077 }
2078 if let [potential_param, potential_assoc] = &full_path.segments[..] {
2080 for (ident, bounds) in generics.params.iter().map(|p| (p.ident, &p.bounds)).chain(
2081 generics.where_clause.predicates.iter().filter_map(|pred| match &pred.kind {
2082 WherePredicateKind::BoundPredicate(p)
2083 if let ast::TyKind::Path(None, path) = &p.bounded_ty.kind
2084 && let [segment] = &path.segments[..] =>
2085 {
2086 Some((segment.ident, &p.bounds))
2087 }
2088 _ => None,
2089 }),
2090 ) {
2091 if ident == potential_param.ident {
2092 for bound in bounds {
2093 if let ast::GenericBound::Trait(poly) = bound
2094 && poly.modifiers == TraitBoundModifiers::NONE
2095 {
2096 suggest(poly, potential_assoc, predicate);
2097 }
2098 }
2099 }
2100 }
2101 }
2102 }
2103 this.dcx().emit_err(err);
2104}
2105
2106pub fn check_crate(
2107 sess: &Session,
2108 features: &Features,
2109 krate: &Crate,
2110 is_sdylib_interface: bool,
2111 lints: &mut LintBuffer,
2112) -> bool {
2113 let mut validator = AstValidator {
2114 sess,
2115 features,
2116 extern_mod_span: None,
2117 outer_trait_or_trait_impl: None,
2118 has_proc_macro_decls: false,
2119 outer_impl_trait_span: None,
2120 disallow_tilde_const: Some(TildeConstReason::Item),
2121 extern_mod_safety: None,
2122 extern_mod_abi: None,
2123 lint_node_id: CRATE_NODE_ID,
2124 is_sdylib_interface,
2125 lint_buffer: lints,
2126 };
2127 visit::walk_crate(&mut validator, krate);
2128
2129 validator.has_proc_macro_decls
2130}