]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_middle/src/ty/diagnostics.rs
New upstream version 1.69.0+dfsg1
[rustc.git] / compiler / rustc_middle / src / ty / diagnostics.rs
CommitLineData
5099ac24 1//! Diagnostics related methods for `Ty`.
60c5eb7d 2
923072b8
FG
3use std::ops::ControlFlow;
4
a2a8927a 5use crate::ty::{
9ffffee4
FG
6 AliasTy, Const, ConstKind, DefIdTree, FallibleTypeFolder, InferConst, InferTy, Opaque,
7 PolyTraitPredicate, Projection, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable,
8 TypeSuperVisitable, TypeVisitable, TypeVisitor,
a2a8927a
XL
9};
10
5e7ed085 11use rustc_data_structures::fx::FxHashMap;
04454e1e 12use rustc_errors::{Applicability, Diagnostic, DiagnosticArgValue, IntoDiagnosticArg};
f9f354fc 13use rustc_hir as hir;
9c376795 14use rustc_hir::def::DefKind;
f9f354fc 15use rustc_hir::def_id::DefId;
04454e1e 16use rustc_hir::WherePredicate;
a2a8927a 17use rustc_span::Span;
923072b8 18use rustc_type_ir::sty::TyKind::*;
60c5eb7d 19
04454e1e
FG
20impl<'tcx> IntoDiagnosticArg for Ty<'tcx> {
21 fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
9c376795 22 self.to_string().into_diagnostic_arg()
04454e1e
FG
23 }
24}
25
5099ac24
FG
26impl<'tcx> Ty<'tcx> {
27 /// Similar to `Ty::is_primitive`, but also considers inferred numeric values to be primitive.
28 pub fn is_primitive_ty(self) -> bool {
29967ef6
XL
29 matches!(
30 self.kind(),
5869c6ff
XL
31 Bool | Char
32 | Str
33 | Int(_)
34 | Uint(_)
35 | Float(_)
36 | Infer(
37 InferTy::IntVar(_)
38 | InferTy::FloatVar(_)
39 | InferTy::FreshIntTy(_)
40 | InferTy::FreshFloatTy(_)
41 )
29967ef6 42 )
60c5eb7d
XL
43 }
44
45 /// Whether the type is succinctly representable as a type instead of just referred to with a
46 /// description in error messages. This is used in the main error message.
5099ac24 47 pub fn is_simple_ty(self) -> bool {
1b1a35ee 48 match self.kind() {
dfeec247
XL
49 Bool
50 | Char
51 | Str
52 | Int(_)
53 | Uint(_)
54 | Float(_)
ba9703b0
XL
55 | Infer(
56 InferTy::IntVar(_)
57 | InferTy::FloatVar(_)
58 | InferTy::FreshIntTy(_)
59 | InferTy::FreshFloatTy(_),
60 ) => true,
60c5eb7d
XL
61 Ref(_, x, _) | Array(x, _) | Slice(x) => x.peel_refs().is_simple_ty(),
62 Tuple(tys) if tys.is_empty() => true,
63 _ => false,
64 }
65 }
66
67 /// Whether the type is succinctly representable as a type instead of just referred to with a
68 /// description in error messages. This is used in the primary span label. Beyond what
69 /// `is_simple_ty` includes, it also accepts ADTs with no type arguments and references to
70 /// ADTs with no type arguments.
5099ac24 71 pub fn is_simple_text(self) -> bool {
1b1a35ee 72 match self.kind() {
17df50a5 73 Adt(_, substs) => substs.non_erasable_generics().next().is_none(),
60c5eb7d
XL
74 Ref(_, ty, _) => ty.is_simple_text(),
75 _ => self.is_simple_ty(),
76 }
77 }
923072b8 78}
60c5eb7d 79
9ffffee4 80pub trait IsSuggestable<'tcx>: Sized {
923072b8
FG
81 /// Whether this makes sense to suggest in a diagnostic.
82 ///
83 /// We filter out certain types and constants since they don't provide
84 /// meaningful rendered suggestions when pretty-printed. We leave some
85 /// nonsense, such as region vars, since those render as `'_` and are
86 /// usually okay to reinterpret as elided lifetimes.
064997fb
FG
87 ///
88 /// Only if `infer_suggestable` is true, we consider type and const
89 /// inference variables to be suggestable.
90 fn is_suggestable(self, tcx: TyCtxt<'tcx>, infer_suggestable: bool) -> bool;
9ffffee4
FG
91
92 fn make_suggestable(self, tcx: TyCtxt<'tcx>, infer_suggestable: bool) -> Option<Self>;
923072b8 93}
a2a8927a 94
923072b8
FG
95impl<'tcx, T> IsSuggestable<'tcx> for T
96where
9ffffee4 97 T: TypeVisitable<TyCtxt<'tcx>> + TypeFoldable<TyCtxt<'tcx>>,
923072b8 98{
064997fb
FG
99 fn is_suggestable(self, tcx: TyCtxt<'tcx>, infer_suggestable: bool) -> bool {
100 self.visit_with(&mut IsSuggestableVisitor { tcx, infer_suggestable }).is_continue()
60c5eb7d 101 }
9ffffee4
FG
102
103 fn make_suggestable(self, tcx: TyCtxt<'tcx>, infer_suggestable: bool) -> Option<T> {
104 self.try_fold_with(&mut MakeSuggestableFolder { tcx, infer_suggestable }).ok()
105 }
60c5eb7d 106}
f9f354fc 107
923072b8
FG
108pub fn suggest_arbitrary_trait_bound<'tcx>(
109 tcx: TyCtxt<'tcx>,
6a06907d 110 generics: &hir::Generics<'_>,
5e7ed085 111 err: &mut Diagnostic,
923072b8 112 trait_pred: PolyTraitPredicate<'tcx>,
f2b60f7d 113 associated_ty: Option<(&'static str, Ty<'tcx>)>,
6a06907d 114) -> bool {
064997fb 115 if !trait_pred.is_suggestable(tcx, false) {
923072b8
FG
116 return false;
117 }
118
119 let param_name = trait_pred.skip_binder().self_ty().to_string();
f2b60f7d
FG
120 let mut constraint = trait_pred.print_modifiers_and_trait_path().to_string();
121
122 if let Some((name, term)) = associated_ty {
123 // FIXME: this case overlaps with code in TyCtxt::note_and_explain_type_err.
124 // That should be extracted into a helper function.
125 if constraint.ends_with('>') {
126 constraint = format!("{}, {} = {}>", &constraint[..constraint.len() - 1], name, term);
127 } else {
128 constraint.push_str(&format!("<{} = {}>", name, term));
129 }
130 }
131
6a06907d 132 let param = generics.params.iter().find(|p| p.name.ident().as_str() == param_name);
923072b8
FG
133
134 // Skip, there is a param named Self
135 if param.is_some() && param_name == "Self" {
136 return false;
6a06907d 137 }
923072b8 138
5e7ed085 139 // Suggest a where clause bound for a non-type parameter.
6a06907d 140 err.span_suggestion_verbose(
04454e1e 141 generics.tail_span_for_predicate_suggestion(),
6a06907d 142 &format!(
923072b8 143 "consider {} `where` clause, but there might be an alternative better way to express \
6a06907d 144 this requirement",
923072b8 145 if generics.where_clause_span.is_empty() { "introducing a" } else { "extending the" },
6a06907d 146 ),
923072b8 147 format!("{} {}: {}", generics.add_where_or_trailing_comma(), param_name, constraint),
6a06907d
XL
148 Applicability::MaybeIncorrect,
149 );
150 true
151}
152
5e7ed085
FG
153#[derive(Debug)]
154enum SuggestChangingConstraintsMessage<'a> {
155 RestrictBoundFurther,
156 RestrictType { ty: &'a str },
157 RestrictTypeFurther { ty: &'a str },
158 RemovingQSized,
159}
160
94222f64
XL
161fn suggest_removing_unsized_bound(
162 generics: &hir::Generics<'_>,
5e7ed085 163 suggestions: &mut Vec<(Span, String, SuggestChangingConstraintsMessage<'_>)>,
94222f64
XL
164 param: &hir::GenericParam<'_>,
165 def_id: Option<DefId>,
166) {
167 // See if there's a `?Sized` bound that can be removed to suggest that.
c295e0f8
XL
168 // First look at the `where` clause because we can have `where T: ?Sized`,
169 // then look at params.
04454e1e
FG
170 for (where_pos, predicate) in generics.predicates.iter().enumerate() {
171 let WherePredicate::BoundPredicate(predicate) = predicate else {
172 continue;
173 };
487cf647 174 if !predicate.is_param_bound(param.def_id.to_def_id()) {
04454e1e
FG
175 continue;
176 };
5e7ed085 177
04454e1e 178 for (pos, bound) in predicate.bounds.iter().enumerate() {
487cf647 179 let hir::GenericBound::Trait(poly, hir::TraitBoundModifier::Maybe) = bound else {
04454e1e
FG
180 continue;
181 };
182 if poly.trait_ref.trait_def_id() != def_id {
183 continue;
94222f64 184 }
04454e1e
FG
185 let sp = generics.span_for_bound_removal(where_pos, pos);
186 suggestions.push((
187 sp,
188 String::new(),
189 SuggestChangingConstraintsMessage::RemovingQSized,
190 ));
94222f64
XL
191 }
192 }
193}
194
f9f354fc 195/// Suggest restricting a type param with a new bound.
9ffffee4
FG
196///
197/// If `span_to_replace` is provided, then that span will be replaced with the
198/// `constraint`. If one wasn't provided, then the full bound will be suggested.
f9f354fc
XL
199pub fn suggest_constraining_type_param(
200 tcx: TyCtxt<'_>,
201 generics: &hir::Generics<'_>,
5e7ed085 202 err: &mut Diagnostic,
f9f354fc
XL
203 param_name: &str,
204 constraint: &str,
205 def_id: Option<DefId>,
9ffffee4 206 span_to_replace: Option<Span>,
f9f354fc 207) -> bool {
5e7ed085
FG
208 suggest_constraining_type_params(
209 tcx,
210 generics,
211 err,
212 [(param_name, constraint, def_id)].into_iter(),
9ffffee4 213 span_to_replace,
5e7ed085
FG
214 )
215}
f9f354fc 216
5e7ed085
FG
217/// Suggest restricting a type param with a new bound.
218pub fn suggest_constraining_type_params<'a>(
219 tcx: TyCtxt<'_>,
220 generics: &hir::Generics<'_>,
221 err: &mut Diagnostic,
222 param_names_and_constraints: impl Iterator<Item = (&'a str, &'a str, Option<DefId>)>,
9ffffee4 223 span_to_replace: Option<Span>,
5e7ed085
FG
224) -> bool {
225 let mut grouped = FxHashMap::default();
226 param_names_and_constraints.for_each(|(param_name, constraint, def_id)| {
227 grouped.entry(param_name).or_insert(Vec::new()).push((constraint, def_id))
228 });
f9f354fc 229
5e7ed085
FG
230 let mut applicability = Applicability::MachineApplicable;
231 let mut suggestions = Vec::new();
f9f354fc 232
5e7ed085
FG
233 for (param_name, mut constraints) in grouped {
234 let param = generics.params.iter().find(|p| p.name.ident().as_str() == param_name);
235 let Some(param) = param else { return false };
f9f354fc 236
5e7ed085
FG
237 {
238 let mut sized_constraints =
239 constraints.drain_filter(|(_, def_id)| *def_id == tcx.lang_items().sized_trait());
240 if let Some((constraint, def_id)) = sized_constraints.next() {
241 applicability = Applicability::MaybeIncorrect;
f9f354fc 242
5e7ed085
FG
243 err.span_label(
244 param.span,
245 &format!("this type parameter needs to be `{}`", constraint),
246 );
487cf647 247 suggest_removing_unsized_bound(generics, &mut suggestions, param, def_id);
5e7ed085
FG
248 }
249 }
250
251 if constraints.is_empty() {
252 continue;
253 }
254
923072b8
FG
255 let mut constraint = constraints.iter().map(|&(c, _)| c).collect::<Vec<_>>();
256 constraint.sort();
257 constraint.dedup();
258 let constraint = constraint.join(" + ");
04454e1e 259 let mut suggest_restrict = |span, bound_list_non_empty| {
5e7ed085
FG
260 suggestions.push((
261 span,
9ffffee4
FG
262 if span_to_replace.is_some() {
263 constraint.clone()
264 } else if bound_list_non_empty {
04454e1e
FG
265 format!(" + {}", constraint)
266 } else {
267 format!(" {}", constraint)
268 },
5e7ed085
FG
269 SuggestChangingConstraintsMessage::RestrictBoundFurther,
270 ))
271 };
272
9ffffee4
FG
273 if let Some(span) = span_to_replace {
274 suggest_restrict(span, true);
275 continue;
276 }
277
04454e1e
FG
278 // When the type parameter has been provided bounds
279 //
280 // Message:
281 // fn foo<T>(t: T) where T: Foo { ... }
282 // ^^^^^^
283 // |
284 // help: consider further restricting this bound with `+ Bar`
285 //
286 // Suggestion:
287 // fn foo<T>(t: T) where T: Foo { ... }
288 // ^
289 // |
290 // replace with: ` + Bar`
291 //
292 // Or, if user has provided some bounds, suggest restricting them:
293 //
294 // fn foo<T: Foo>(t: T) { ... }
295 // ---
296 // |
297 // help: consider further restricting this bound with `+ Bar`
298 //
299 // Suggestion for tools in this case is:
300 //
301 // fn foo<T: Foo>(t: T) { ... }
302 // --
303 // |
304 // replace with: `T: Bar +`
487cf647 305 if let Some(span) = generics.bounds_span_for_suggestions(param.def_id) {
04454e1e 306 suggest_restrict(span, true);
5e7ed085 307 continue;
f9f354fc
XL
308 }
309
923072b8 310 if generics.has_where_clause_predicates {
5e7ed085
FG
311 // This part is a bit tricky, because using the `where` clause user can
312 // provide zero, one or many bounds for the same type parameter, so we
313 // have following cases to consider:
314 //
04454e1e 315 // When the type parameter has been provided zero bounds
5e7ed085
FG
316 //
317 // Message:
318 // fn foo<X, Y>(x: X, y: Y) where Y: Foo { ... }
319 // - help: consider restricting this type parameter with `where X: Bar`
320 //
321 // Suggestion:
322 // fn foo<X, Y>(x: X, y: Y) where Y: Foo { ... }
323 // - insert: `, X: Bar`
04454e1e
FG
324 suggestions.push((
325 generics.tail_span_for_predicate_suggestion(),
326 constraints
327 .iter()
328 .map(|&(constraint, _)| format!(", {}: {}", param_name, constraint))
329 .collect::<String>(),
330 SuggestChangingConstraintsMessage::RestrictTypeFurther { ty: param_name },
331 ));
332 continue;
333 }
5e7ed085 334
04454e1e
FG
335 // Additionally, there may be no `where` clause but the generic parameter has a default:
336 //
337 // Message:
338 // trait Foo<T=()> {... }
339 // - help: consider further restricting this type parameter with `where T: Zar`
340 //
341 // Suggestion:
342 // trait Foo<T=()> {... }
343 // - insert: `where T: Zar`
344 if matches!(param.kind, hir::GenericParamKind::Type { default: Some(_), .. }) {
345 // Suggest a bound, but there is no existing `where` clause *and* the type param has a
346 // default (`<T=Foo>`), so we suggest adding `where T: Bar`.
347 suggestions.push((
348 generics.tail_span_for_predicate_suggestion(),
349 format!(" where {}: {}", param_name, constraint),
350 SuggestChangingConstraintsMessage::RestrictTypeFurther { ty: param_name },
351 ));
352 continue;
353 }
f9f354fc 354
04454e1e
FG
355 // If user has provided a colon, don't suggest adding another:
356 //
357 // fn foo<T:>(t: T) { ... }
358 // - insert: consider restricting this type parameter with `T: Foo`
359 if let Some(colon_span) = param.colon_span {
360 suggestions.push((
361 colon_span.shrink_to_hi(),
362 format!(" {}", constraint),
363 SuggestChangingConstraintsMessage::RestrictType { ty: param_name },
364 ));
365 continue;
f9f354fc 366 }
04454e1e
FG
367
368 // If user hasn't provided any bounds, suggest adding a new one:
369 //
370 // fn foo<T>(t: T) { ... }
371 // - help: consider restricting this type parameter with `T: Foo`
372 suggestions.push((
373 param.span.shrink_to_hi(),
374 format!(": {}", constraint),
375 SuggestChangingConstraintsMessage::RestrictType { ty: param_name },
376 ));
5e7ed085
FG
377 }
378
487cf647
FG
379 // FIXME: remove the suggestions that are from derive, as the span is not correct
380 suggestions = suggestions
381 .into_iter()
382 .filter(|(span, _, _)| !span.in_derive_expansion())
383 .collect::<Vec<_>>();
384
5e7ed085
FG
385 if suggestions.len() == 1 {
386 let (span, suggestion, msg) = suggestions.pop().unwrap();
f9f354fc 387
5e7ed085
FG
388 let s;
389 let msg = match msg {
390 SuggestChangingConstraintsMessage::RestrictBoundFurther => {
391 "consider further restricting this bound"
392 }
393 SuggestChangingConstraintsMessage::RestrictType { ty } => {
394 s = format!("consider restricting type parameter `{}`", ty);
395 &s
396 }
397 SuggestChangingConstraintsMessage::RestrictTypeFurther { ty } => {
398 s = format!("consider further restricting type parameter `{}`", ty);
399 &s
400 }
401 SuggestChangingConstraintsMessage::RemovingQSized => {
402 "consider removing the `?Sized` bound to make the type parameter `Sized`"
403 }
404 };
405
406 err.span_suggestion_verbose(span, msg, suggestion, applicability);
407 } else if suggestions.len() > 1 {
408 err.multipart_suggestion_verbose(
409 "consider restricting type parameters",
410 suggestions.into_iter().map(|(span, suggestion, _)| (span, suggestion)).collect(),
411 applicability,
412 );
f9f354fc 413 }
5e7ed085
FG
414
415 true
f9f354fc
XL
416}
417
f035d41b
XL
418/// Collect al types that have an implicit `'static` obligation that we could suggest `'_` for.
419pub struct TraitObjectVisitor<'tcx>(pub Vec<&'tcx hir::Ty<'tcx>>, pub crate::hir::map::Map<'tcx>);
420
421impl<'v> hir::intravisit::Visitor<'v> for TraitObjectVisitor<'v> {
f035d41b
XL
422 fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) {
423 match ty.kind {
424 hir::TyKind::TraitObject(
425 _,
426 hir::Lifetime {
487cf647 427 res:
f035d41b
XL
428 hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Static,
429 ..
430 },
6a06907d 431 _,
f035d41b
XL
432 ) => {
433 self.0.push(ty);
434 }
f2b60f7d 435 hir::TyKind::OpaqueDef(item_id, _, _) => {
f035d41b 436 self.0.push(ty);
6a06907d 437 let item = self.1.item(item_id);
f035d41b
XL
438 hir::intravisit::walk_item(self, item);
439 }
440 _ => {}
f9f354fc 441 }
f035d41b 442 hir::intravisit::walk_ty(self, ty);
f9f354fc
XL
443 }
444}
a2a8927a
XL
445
446/// Collect al types that have an implicit `'static` obligation that we could suggest `'_` for.
447pub struct StaticLifetimeVisitor<'tcx>(pub Vec<Span>, pub crate::hir::map::Map<'tcx>);
448
449impl<'v> hir::intravisit::Visitor<'v> for StaticLifetimeVisitor<'v> {
a2a8927a 450 fn visit_lifetime(&mut self, lt: &'v hir::Lifetime) {
487cf647 451 if let hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Static = lt.res
a2a8927a 452 {
487cf647 453 self.0.push(lt.ident.span);
a2a8927a
XL
454 }
455 }
456}
923072b8
FG
457
458pub struct IsSuggestableVisitor<'tcx> {
459 tcx: TyCtxt<'tcx>,
064997fb 460 infer_suggestable: bool,
923072b8
FG
461}
462
9ffffee4 463impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for IsSuggestableVisitor<'tcx> {
923072b8
FG
464 type BreakTy = ();
465
466 fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
9c376795 467 match *t.kind() {
064997fb
FG
468 Infer(InferTy::TyVar(_)) if self.infer_suggestable => {}
469
923072b8
FG
470 FnDef(..)
471 | Closure(..)
472 | Infer(..)
473 | Generator(..)
474 | GeneratorWitness(..)
475 | Bound(_, _)
476 | Placeholder(_)
477 | Error(_) => {
478 return ControlFlow::Break(());
479 }
480
9c376795
FG
481 Alias(Opaque, AliasTy { def_id, .. }) => {
482 let parent = self.tcx.parent(def_id);
9ffffee4 483 let parent_ty = self.tcx.type_of(parent).subst_identity();
9c376795 484 if let DefKind::TyAlias | DefKind::AssocTy = self.tcx.def_kind(parent)
9ffffee4 485 && let Alias(Opaque, AliasTy { def_id: parent_opaque_def_id, .. }) = *parent_ty.kind()
9c376795 486 && parent_opaque_def_id == def_id
923072b8
FG
487 {
488 // Okay
489 } else {
490 return ControlFlow::Break(());
491 }
492 }
493
9c376795
FG
494 Alias(Projection, AliasTy { def_id, .. }) => {
495 if self.tcx.def_kind(def_id) != DefKind::AssocTy {
496 return ControlFlow::Break(());
923072b8
FG
497 }
498 }
499
500 Param(param) => {
501 // FIXME: It would be nice to make this not use string manipulation,
502 // but it's pretty hard to do this, since `ty::ParamTy` is missing
503 // sufficient info to determine if it is synthetic, and we don't
504 // always have a convenient way of getting `ty::Generics` at the call
505 // sites we invoke `IsSuggestable::is_suggestable`.
506 if param.name.as_str().starts_with("impl ") {
507 return ControlFlow::Break(());
508 }
509 }
510
511 _ => {}
512 }
513
514 t.super_visit_with(self)
515 }
516
517 fn visit_const(&mut self, c: Const<'tcx>) -> ControlFlow<Self::BreakTy> {
518 match c.kind() {
064997fb
FG
519 ConstKind::Infer(InferConst::Var(_)) if self.infer_suggestable => {}
520
923072b8
FG
521 ConstKind::Infer(..)
522 | ConstKind::Bound(..)
523 | ConstKind::Placeholder(..)
524 | ConstKind::Error(..) => {
525 return ControlFlow::Break(());
526 }
527 _ => {}
528 }
529
530 c.super_visit_with(self)
531 }
532}
9ffffee4
FG
533
534pub struct MakeSuggestableFolder<'tcx> {
535 tcx: TyCtxt<'tcx>,
536 infer_suggestable: bool,
537}
538
539impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for MakeSuggestableFolder<'tcx> {
540 type Error = ();
541
542 fn interner(&self) -> TyCtxt<'tcx> {
543 self.tcx
544 }
545
546 fn try_fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
547 let t = match *t.kind() {
548 Infer(InferTy::TyVar(_)) if self.infer_suggestable => t,
549
550 FnDef(def_id, substs) => {
551 self.tcx.mk_fn_ptr(self.tcx.fn_sig(def_id).subst(self.tcx, substs))
552 }
553
554 // FIXME(compiler-errors): We could replace these with infer, I guess.
555 Closure(..)
556 | Infer(..)
557 | Generator(..)
558 | GeneratorWitness(..)
559 | Bound(_, _)
560 | Placeholder(_)
561 | Error(_) => {
562 return Err(());
563 }
564
565 Alias(Opaque, AliasTy { def_id, .. }) => {
566 let parent = self.tcx.parent(def_id);
567 let parent_ty = self.tcx.type_of(parent).subst_identity();
568 if let hir::def::DefKind::TyAlias | hir::def::DefKind::AssocTy = self.tcx.def_kind(parent)
569 && let Alias(Opaque, AliasTy { def_id: parent_opaque_def_id, .. }) = *parent_ty.kind()
570 && parent_opaque_def_id == def_id
571 {
572 t
573 } else {
574 return Err(());
575 }
576 }
577
578 Param(param) => {
579 // FIXME: It would be nice to make this not use string manipulation,
580 // but it's pretty hard to do this, since `ty::ParamTy` is missing
581 // sufficient info to determine if it is synthetic, and we don't
582 // always have a convenient way of getting `ty::Generics` at the call
583 // sites we invoke `IsSuggestable::is_suggestable`.
584 if param.name.as_str().starts_with("impl ") {
585 return Err(());
586 }
587
588 t
589 }
590
591 _ => t,
592 };
593
594 t.try_super_fold_with(self)
595 }
596
597 fn try_fold_const(&mut self, c: Const<'tcx>) -> Result<Const<'tcx>, ()> {
598 let c = match c.kind() {
599 ConstKind::Infer(InferConst::Var(_)) if self.infer_suggestable => c,
600
601 ConstKind::Infer(..)
602 | ConstKind::Bound(..)
603 | ConstKind::Placeholder(..)
604 | ConstKind::Error(..) => {
605 return Err(());
606 }
607
608 _ => c,
609 };
610
611 c.try_super_fold_with(self)
612 }
613}
614
615#[derive(Diagnostic)]
616#[diag(middle_const_not_used_in_type_alias)]
617pub(super) struct ConstNotUsedTraitAlias {
618 pub ct: String,
619 #[primary_span]
620 pub span: Span,
621}