1 use rustc_errors::{Applicability, ErrorReported, StashKey};
3 use rustc_hir::def::CtorOf;
4 use rustc_hir::def::{DefKind, Res};
5 use rustc_hir::def_id::{DefId, LocalDefId};
6 use rustc_hir::intravisit;
7 use rustc_hir::intravisit::Visitor;
8 use rustc_hir::{HirId, Node};
9 use rustc_middle::hir::nested_filter;
10 use rustc_middle::ty::subst::InternalSubsts;
11 use rustc_middle::ty::util::IntTypeExt;
12 use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable, TypeFolder};
13 use rustc_span::symbol::Ident;
14 use rustc_span::{Span, DUMMY_SP};
17 use super::{bad_placeholder, is_suggestable_infer_ty};
19 /// Computes the relevant generic parameter for a potential generic const argument.
21 /// This should be called using the query `tcx.opt_const_param_of`.
22 #[instrument(level = "debug", skip(tcx))]
23 pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<DefId> {
25 let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
27 match tcx.hir().get(hir_id) {
28 Node::AnonConst(_) => (),
32 let parent_node_id = tcx.hir().get_parent_node(hir_id);
33 let parent_node = tcx.hir().get(parent_node_id);
35 let (generics, arg_idx) = match parent_node {
36 // This match arm is for when the def_id appears in a GAT whose
37 // path can't be resolved without typechecking e.g.
40 // type Assoc<const N: usize>;
41 // fn foo() -> Self::Assoc<3>;
44 // In the above code we would call this query with the def_id of 3 and
45 // the parent_node we match on would be the hir node for Self::Assoc<3>
47 // `Self::Assoc<3>` cant be resolved without typchecking here as we
48 // didnt write <Self as Foo>::Assoc<3>. If we did then another match
49 // arm would handle this.
51 // I believe this match arm is only needed for GAT but I am not 100% sure - BoxyUwU
52 Node::Ty(hir_ty @ Ty { kind: TyKind::Path(QPath::TypeRelative(_, segment)), .. }) => {
53 // Find the Item containing the associated type so we can create an ItemCtxt.
54 // Using the ItemCtxt convert the HIR for the unresolved assoc type into a
55 // ty which is a fully resolved projection.
56 // For the code example above, this would mean converting Self::Assoc<3>
57 // into a ty::Projection(<Self as Foo>::Assoc<3>)
61 .filter(|(_, node)| matches!(node, Node::Item(_)))
65 let item_did = tcx.hir().local_def_id(item_hir_id).to_def_id();
66 let item_ctxt = &ItemCtxt::new(tcx, item_did) as &dyn crate::astconv::AstConv<'_>;
67 let ty = item_ctxt.ast_ty_to_ty(hir_ty);
69 // Iterate through the generics of the projection to find the one that corresponds to
70 // the def_id that this query was called with. We filter to only const args here as a
71 // precaution for if it's ever allowed to elide lifetimes in GAT's. It currently isn't
72 // but it can't hurt to be safe ^^
73 if let ty::Projection(projection) = ty.kind() {
74 let generics = tcx.generics_of(projection.item_def_id);
76 let arg_index = segment
81 .filter(|arg| arg.is_ty_or_const())
82 .position(|arg| arg.id() == hir_id)
85 bug!("no arg matching AnonConst in segment");
90 // I dont think it's possible to reach this but I'm not 100% sure - BoxyUwU
91 tcx.sess.delay_span_bug(
93 "unexpected non-GAT usage of an anon const",
100 ExprKind::MethodCall(segment, ..) | ExprKind::Path(QPath::TypeRelative(_, segment)),
103 let body_owner = tcx.hir().local_def_id(tcx.hir().enclosing_body_owner(hir_id));
104 let tables = tcx.typeck(body_owner);
105 // This may fail in case the method/path does not actually exist.
106 // As there is no relevant param for `def_id`, we simply return
108 let type_dependent_def = tables.type_dependent_def_id(parent_node_id)?;
114 .filter(|arg| arg.is_ty_or_const())
115 .position(|arg| arg.id() == hir_id)
118 bug!("no arg matching AnonConst in segment");
121 (tcx.generics_of(type_dependent_def), idx)
124 Node::Ty(&Ty { kind: TyKind::Path(_), .. })
125 | Node::Expr(&Expr { kind: ExprKind::Path(_) | ExprKind::Struct(..), .. })
128 let path = match parent_node {
129 Node::Ty(&Ty { kind: TyKind::Path(QPath::Resolved(_, path)), .. })
130 | Node::TraitRef(&TraitRef { path, .. }) => &*path,
133 ExprKind::Path(QPath::Resolved(_, path))
134 | ExprKind::Struct(&QPath::Resolved(_, path), ..),
137 let body_owner = tcx.hir().local_def_id(tcx.hir().enclosing_body_owner(hir_id));
138 let _tables = tcx.typeck(body_owner);
142 if let Some(path) = get_path_containing_arg_in_pat(pat, hir_id) {
145 tcx.sess.delay_span_bug(
146 tcx.def_span(def_id),
147 &format!("unable to find const parent for {} in pat {:?}", hir_id, pat),
153 tcx.sess.delay_span_bug(
154 tcx.def_span(def_id),
155 &format!("unexpected const parent path {:?}", parent_node),
161 // We've encountered an `AnonConst` in some path, so we need to
162 // figure out which generic parameter it corresponds to and return
163 // the relevant type.
164 let filtered = path.segments.iter().find_map(|seg| {
168 .filter(|arg| arg.is_ty_or_const())
169 .position(|arg| arg.id() == hir_id)
170 .map(|index| (index, seg))
173 // FIXME(associated_const_generics): can we blend this with iteration above?
174 let (arg_index, segment) = match filtered {
176 let binding_filtered = path.segments.iter().find_map(|seg| {
180 .filter_map(TypeBinding::opt_const)
181 .position(|ct| ct.hir_id == hir_id)
182 .map(|idx| (idx, seg))
184 match binding_filtered {
185 Some(inner) => inner,
187 tcx.sess.delay_span_bug(
188 tcx.def_span(def_id),
189 "no arg matching AnonConst in path",
195 Some(inner) => inner,
198 // Try to use the segment resolution if it is valid, otherwise we
199 // default to the path resolution.
200 let res = segment.res.filter(|&r| r != Res::Err).unwrap_or(path.res);
201 let generics = match res {
202 Res::Def(DefKind::Ctor(CtorOf::Variant, _), def_id) => tcx
203 .generics_of(tcx.parent(def_id).and_then(|def_id| tcx.parent(def_id)).unwrap()),
204 Res::Def(DefKind::Variant | DefKind::Ctor(CtorOf::Struct, _), def_id) => {
205 tcx.generics_of(tcx.parent(def_id).unwrap())
207 // Other `DefKind`s don't have generics and would ICE when calling
217 | DefKind::TraitAlias
221 | DefKind::AssocConst
224 ) => tcx.generics_of(def_id),
226 tcx.sess.delay_span_bug(tcx.def_span(def_id), "anon const with Res::Err");
230 // If the user tries to specify generics on a type that does not take them,
231 // e.g. `usize<T>`, we may hit this branch, in which case we treat it as if
232 // no arguments have been passed. An error should already have been emitted.
233 tcx.sess.delay_span_bug(
234 tcx.def_span(def_id),
235 &format!("unexpected anon const res {:?} in path: {:?}", res, path),
241 (generics, arg_index)
246 debug!(?parent_node);
247 debug!(?generics, ?arg_idx);
251 .filter(|param| param.kind.is_ty_or_const())
252 .nth(match generics.has_self && generics.parent.is_none() {
256 .and_then(|param| match param.kind {
257 ty::GenericParamDefKind::Const { .. } => {
265 fn get_path_containing_arg_in_pat<'hir>(
266 pat: &'hir hir::Pat<'hir>,
268 ) -> Option<&'hir hir::Path<'hir>> {
271 let is_arg_in_path = |p: &hir::Path<'_>| {
274 .filter_map(|seg| seg.args)
275 .flat_map(|args| args.args)
276 .any(|arg| arg.id() == arg_id)
278 let mut arg_path = None;
279 pat.walk(|pat| match pat.kind {
280 PatKind::Struct(QPath::Resolved(_, path), _, _)
281 | PatKind::TupleStruct(QPath::Resolved(_, path), _, _)
282 | PatKind::Path(QPath::Resolved(_, path))
283 if is_arg_in_path(path) =>
285 arg_path = Some(path);
293 pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
294 let def_id = def_id.expect_local();
297 let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
299 let icx = ItemCtxt::new(tcx, def_id.to_def_id());
301 match tcx.hir().get(hir_id) {
302 Node::TraitItem(item) => match item.kind {
303 TraitItemKind::Fn(..) => {
304 let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
305 tcx.mk_fn_def(def_id.to_def_id(), substs)
307 TraitItemKind::Const(ty, body_id) => body_id
308 .and_then(|body_id| {
309 if is_suggestable_infer_ty(ty) {
310 Some(infer_placeholder_type(
311 tcx, def_id, body_id, ty.span, item.ident, "constant",
317 .unwrap_or_else(|| icx.to_ty(ty)),
318 TraitItemKind::Type(_, Some(ty)) => icx.to_ty(ty),
319 TraitItemKind::Type(_, None) => {
320 span_bug!(item.span, "associated type missing default");
324 Node::ImplItem(item) => match item.kind {
325 ImplItemKind::Fn(..) => {
326 let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
327 tcx.mk_fn_def(def_id.to_def_id(), substs)
329 ImplItemKind::Const(ty, body_id) => {
330 if is_suggestable_infer_ty(ty) {
331 infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident, "constant")
336 ImplItemKind::TyAlias(ty) => {
337 if tcx.impl_trait_ref(tcx.hir().get_parent_item(hir_id)).is_none() {
338 check_feature_inherent_assoc_ty(tcx, item.span);
345 Node::Item(item) => {
347 ItemKind::Static(ty, .., body_id) => {
348 if is_suggestable_infer_ty(ty) {
349 infer_placeholder_type(
361 ItemKind::Const(ty, body_id) => {
362 if is_suggestable_infer_ty(ty) {
363 infer_placeholder_type(
364 tcx, def_id, body_id, ty.span, item.ident, "constant",
370 ItemKind::TyAlias(self_ty, _)
371 | ItemKind::Impl(hir::Impl { self_ty, .. }) => icx.to_ty(self_ty),
372 ItemKind::Fn(..) => {
373 let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
374 tcx.mk_fn_def(def_id.to_def_id(), substs)
376 ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) => {
377 let def = tcx.adt_def(def_id);
378 let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
379 tcx.mk_adt(def, substs)
381 ItemKind::OpaqueTy(OpaqueTy { origin: hir::OpaqueTyOrigin::TyAlias, .. }) => {
382 find_opaque_ty_constraints(tcx, def_id)
384 // Opaque types desugared from `impl Trait`.
385 ItemKind::OpaqueTy(OpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn(owner) | hir::OpaqueTyOrigin::AsyncFn(owner), .. }) => {
386 let concrete_ty = tcx
388 .concrete_opaque_types
389 .get_value_matching(|(key, _)| key.def_id == def_id.to_def_id())
392 tcx.sess.delay_span_bug(
395 "owner {:?} has no opaque type for {:?} in its typeck results",
399 if let Some(ErrorReported) =
400 tcx.typeck(owner).tainted_by_errors
403 // owner fn prevented us from populating
404 // the `concrete_opaque_types` table.
407 // We failed to resolve the opaque type or it
408 // resolves to itself. Return the non-revealed
409 // type, which should result in E0720.
412 InternalSubsts::identity_for_item(tcx, def_id.to_def_id()),
416 debug!("concrete_ty = {:?}", concrete_ty);
420 | ItemKind::TraitAlias(..)
421 | ItemKind::Macro(..)
423 | ItemKind::ForeignMod { .. }
424 | ItemKind::GlobalAsm(..)
425 | ItemKind::ExternCrate(..)
426 | ItemKind::Use(..) => {
429 "compute_type_of_item: unexpected item type: {:?}",
436 Node::ForeignItem(foreign_item) => match foreign_item.kind {
437 ForeignItemKind::Fn(..) => {
438 let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
439 tcx.mk_fn_def(def_id.to_def_id(), substs)
441 ForeignItemKind::Static(t, _) => icx.to_ty(t),
442 ForeignItemKind::Type => tcx.mk_foreign(def_id.to_def_id()),
445 Node::Ctor(&ref def) | Node::Variant(Variant { data: ref def, .. }) => match *def {
446 VariantData::Unit(..) | VariantData::Struct(..) => {
447 tcx.type_of(tcx.hir().get_parent_item(hir_id))
449 VariantData::Tuple(..) => {
450 let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
451 tcx.mk_fn_def(def_id.to_def_id(), substs)
455 Node::Field(field) => icx.to_ty(field.ty),
457 Node::Expr(&Expr { kind: ExprKind::Closure(..), .. }) => tcx.typeck(def_id).node_type(hir_id),
459 Node::AnonConst(_) if let Some(param) = tcx.opt_const_param_of(def_id) => {
460 // We defer to `type_of` of the corresponding parameter
461 // for generic arguments.
465 Node::AnonConst(_) => {
466 let parent_node = tcx.hir().get(tcx.hir().get_parent_node(hir_id));
468 Node::Ty(&Ty { kind: TyKind::Array(_, ref constant), .. })
469 | Node::Expr(&Expr { kind: ExprKind::Repeat(_, ref constant), .. })
470 if constant.hir_id() == hir_id =>
474 Node::Ty(&Ty { kind: TyKind::Typeof(ref e), .. }) if e.hir_id == hir_id => {
475 tcx.typeck(def_id).node_type(e.hir_id)
478 Node::Expr(&Expr { kind: ExprKind::ConstBlock(ref anon_const), .. })
479 if anon_const.hir_id == hir_id =>
481 let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
482 substs.as_inline_const().ty()
485 Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. })
486 | Node::Item(&Item { kind: ItemKind::GlobalAsm(asm), .. })
487 if asm.operands.iter().any(|(op, _op_sp)| match op {
488 hir::InlineAsmOperand::Const { anon_const } => anon_const.hir_id == hir_id,
492 tcx.typeck(def_id).node_type(hir_id)
495 Node::Variant(Variant { disr_expr: Some(ref e), .. }) if e.hir_id == hir_id => tcx
496 .adt_def(tcx.hir().get_parent_item(hir_id))
501 Node::TraitRef(trait_ref @ &TraitRef {
503 }) if let Some((binding, seg)) =
510 .find_map(|binding| if binding.opt_const()?.hir_id == hir_id {
517 let Some(trait_def_id) = trait_ref.trait_def_id() else {
518 return tcx.ty_error_with_message(DUMMY_SP, "Could not find trait");
520 let assoc_items = tcx.associated_items(trait_def_id);
521 let assoc_item = assoc_items.find_by_name_and_kind(
522 tcx, binding.ident, ty::AssocKind::Const, def_id.to_def_id(),
524 if let Some(assoc_item) = assoc_item {
525 tcx.type_of(assoc_item.def_id)
527 // FIXME(associated_const_equality): add a useful error message here.
528 tcx.ty_error_with_message(
530 &format!("Could not find associated const on trait"),
535 Node::GenericParam(&GenericParam {
536 hir_id: param_hir_id,
537 kind: GenericParamKind::Const { default: Some(ct), .. },
539 }) if ct.hir_id == hir_id => tcx.type_of(tcx.hir().local_def_id(param_hir_id)),
542 tcx.ty_error_with_message(
544 &format!("unexpected const parent in type_of(): {x:?}"),
549 Node::GenericParam(param) => match ¶m.kind {
550 GenericParamKind::Type { default: Some(ty), .. }
551 | GenericParamKind::Const { ty, .. } => icx.to_ty(ty),
552 x => bug!("unexpected non-type Node::GenericParam: {:?}", x),
556 bug!("unexpected sort of node in type_of(): {:?}", x);
561 #[instrument(skip(tcx), level = "debug")]
562 /// Checks "defining uses" of opaque `impl Trait` types to ensure that they meet the restrictions
563 /// laid for "higher-order pattern unification".
564 /// This ensures that inference is tractable.
565 /// In particular, definitions of opaque types can only use other generics as arguments,
566 /// and they cannot repeat an argument. Example:
569 /// type Foo<A, B> = impl Bar<A, B>;
571 /// // Okay -- `Foo` is applied to two distinct, generic types.
572 /// fn a<T, U>() -> Foo<T, U> { .. }
574 /// // Not okay -- `Foo` is applied to `T` twice.
575 /// fn b<T>() -> Foo<T, T> { .. }
577 /// // Not okay -- `Foo` is applied to a non-generic type.
578 /// fn b<T>() -> Foo<T, u32> { .. }
581 fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
582 use rustc_hir::{Expr, ImplItem, Item, TraitItem};
584 struct ConstraintLocator<'tcx> {
587 /// def_id of the opaque type whose defining uses are being checked
590 /// as we walk the defining uses, we are checking that all of them
591 /// define the same hidden type. This variable is set to `Some`
592 /// with the first type that we find, and then later types are
593 /// checked against it (we also carry the span of that first
595 found: Option<(Span, Ty<'tcx>)>,
598 impl ConstraintLocator<'_> {
599 #[instrument(skip(self), level = "debug")]
600 fn check(&mut self, def_id: LocalDefId) {
601 // Don't try to check items that cannot possibly constrain the type.
602 if !self.tcx.has_typeck_results(def_id) {
603 debug!("no constraint: no typeck results");
606 // Calling `mir_borrowck` can lead to cycle errors through
607 // const-checking, avoid calling it if we don't have to.
608 if !self.tcx.typeck(def_id).concrete_opaque_types.contains(&self.def_id) {
609 debug!("no constraints in typeck results");
612 // Use borrowck to get the type with unerased regions.
613 let concrete_opaque_types = &self.tcx.mir_borrowck(def_id).concrete_opaque_types;
614 debug!(?concrete_opaque_types);
615 for (opaque_type_key, concrete_type) in concrete_opaque_types {
616 if opaque_type_key.def_id != self.def_id {
617 // Ignore constraints for other opaque types.
621 debug!(?concrete_type, ?opaque_type_key.substs, "found constraint");
623 // FIXME(oli-obk): trace the actual span from inference to improve errors.
624 let span = self.tcx.def_span(def_id);
626 if let Some((prev_span, prev_ty)) = self.found {
627 if *concrete_type != prev_ty && !(*concrete_type, prev_ty).references_error() {
629 // Found different concrete types for the opaque type.
630 let mut err = self.tcx.sess.struct_span_err(
632 "concrete type differs from previous defining opaque type use",
636 format!("expected `{}`, got `{}`", prev_ty, concrete_type),
638 err.span_note(prev_span, "previous use here");
642 self.found = Some((span, concrete_type));
648 impl<'tcx> intravisit::Visitor<'tcx> for ConstraintLocator<'tcx> {
649 type NestedFilter = nested_filter::All;
651 fn nested_visit_map(&mut self) -> Self::Map {
654 fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) {
655 if let hir::ExprKind::Closure(..) = ex.kind {
656 let def_id = self.tcx.hir().local_def_id(ex.hir_id);
659 intravisit::walk_expr(self, ex);
661 fn visit_item(&mut self, it: &'tcx Item<'tcx>) {
662 debug!("find_existential_constraints: visiting {:?}", it);
663 // The opaque type itself or its children are not within its reveal scope.
664 if it.def_id.to_def_id() != self.def_id {
665 self.check(it.def_id);
666 intravisit::walk_item(self, it);
669 fn visit_impl_item(&mut self, it: &'tcx ImplItem<'tcx>) {
670 debug!("find_existential_constraints: visiting {:?}", it);
671 // The opaque type itself or its children are not within its reveal scope.
672 if it.def_id.to_def_id() != self.def_id {
673 self.check(it.def_id);
674 intravisit::walk_impl_item(self, it);
677 fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) {
678 debug!("find_existential_constraints: visiting {:?}", it);
679 self.check(it.def_id);
680 intravisit::walk_trait_item(self, it);
684 let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
685 let scope = tcx.hir().get_defining_scope(hir_id);
686 let mut locator = ConstraintLocator { def_id: def_id.to_def_id(), tcx, found: None };
688 debug!("find_opaque_ty_constraints: scope={:?}", scope);
690 if scope == hir::CRATE_HIR_ID {
691 tcx.hir().walk_toplevel_module(&mut locator);
693 debug!("find_opaque_ty_constraints: scope={:?}", tcx.hir().get(scope));
694 match tcx.hir().get(scope) {
695 // We explicitly call `visit_*` methods, instead of using `intravisit::walk_*` methods
696 // This allows our visitor to process the defining item itself, causing
697 // it to pick up any 'sibling' defining uses.
699 // For example, this code:
702 // type Blah = impl Debug;
703 // let my_closure = || -> Blah { true };
707 // requires us to explicitly process `foo()` in order
708 // to notice the defining usage of `Blah`.
709 Node::Item(it) => locator.visit_item(it),
710 Node::ImplItem(it) => locator.visit_impl_item(it),
711 Node::TraitItem(it) => locator.visit_trait_item(it),
712 other => bug!("{:?} is not a valid scope for an opaque type item", other),
716 match locator.found {
719 let span = tcx.def_span(def_id);
720 tcx.sess.span_err(span, "could not find defining uses");
726 fn infer_placeholder_type<'a>(
729 body_id: hir::BodyId,
734 // Attempts to make the type nameable by turning FnDefs into FnPtrs.
735 struct MakeNameable<'tcx> {
740 impl<'tcx> MakeNameable<'tcx> {
741 fn new(tcx: TyCtxt<'tcx>) -> Self {
742 MakeNameable { success: true, tcx }
746 impl<'tcx> TypeFolder<'tcx> for MakeNameable<'tcx> {
747 fn tcx(&self) -> TyCtxt<'tcx> {
751 fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
757 ty::FnDef(def_id, _) => self.tcx.mk_fn_ptr(self.tcx.fn_sig(*def_id)),
758 // FIXME: non-capturing closures should also suggest a function pointer
759 ty::Closure(..) | ty::Generator(..) => {
760 self.success = false;
763 _ => ty.super_fold_with(self),
768 let ty = tcx.diagnostic_only_typeck(def_id).node_type(body_id.hir_id);
770 // If this came from a free `const` or `static mut?` item,
771 // then the user may have written e.g. `const A = 42;`.
772 // In this case, the parser has stashed a diagnostic for
773 // us to improve in typeck so we do that now.
774 match tcx.sess.diagnostic().steal_diagnostic(span, StashKey::ItemNoType) {
776 if !ty.references_error() {
777 // The parser provided a sub-optimal `HasPlaceholders` suggestion for the type.
778 // We are typeck and have the real type, so remove that and suggest the actual type.
779 // FIXME(eddyb) this looks like it should be functionality on `Diagnostic`.
780 if let Ok(suggestions) = &mut err.suggestions {
784 // Suggesting unnameable types won't help.
785 let mut mk_nameable = MakeNameable::new(tcx);
786 let ty = mk_nameable.fold_ty(ty);
787 let sugg_ty = if mk_nameable.success { Some(ty) } else { None };
788 if let Some(sugg_ty) = sugg_ty {
791 &format!("provide a type for the {item}", item = kind),
792 format!("{}: {}", item_ident, sugg_ty),
793 Applicability::MachineApplicable,
797 tcx.hir().body(body_id).value.span,
798 &format!("however, the inferred type `{}` cannot be named", ty),
806 let mut diag = bad_placeholder(tcx, vec![span], kind);
808 if !ty.references_error() {
809 let mut mk_nameable = MakeNameable::new(tcx);
810 let ty = mk_nameable.fold_ty(ty);
811 let sugg_ty = if mk_nameable.success { Some(ty) } else { None };
812 if let Some(sugg_ty) = sugg_ty {
813 diag.span_suggestion(
815 "replace with the correct type",
817 Applicability::MaybeIncorrect,
821 tcx.hir().body(body_id).value.span,
822 &format!("however, the inferred type `{}` cannot be named", ty),
831 // Typeck doesn't expect erased regions to be returned from `type_of`.
832 tcx.fold_regions(ty, &mut false, |r, _| match r {
833 ty::ReErased => tcx.lifetimes.re_static,
838 fn check_feature_inherent_assoc_ty(tcx: TyCtxt<'_>, span: Span) {
839 if !tcx.features().inherent_associated_types {
840 use rustc_session::parse::feature_err;
841 use rustc_span::symbol::sym;
843 &tcx.sess.parse_sess,
844 sym::inherent_associated_types,
846 "inherent associated types are unstable",