]>
Commit | Line | Data |
---|---|---|
5e7ed085 | 1 | use rustc_errors::{Applicability, StashKey}; |
74b04a01 | 2 | use rustc_hir as hir; |
f9f354fc | 3 | use rustc_hir::def_id::{DefId, LocalDefId}; |
74b04a01 XL |
4 | use rustc_hir::intravisit; |
5 | use rustc_hir::intravisit::Visitor; | |
5869c6ff | 6 | use rustc_hir::{HirId, Node}; |
5099ac24 | 7 | use rustc_middle::hir::nested_filter; |
9c376795 | 8 | use rustc_middle::ty::print::with_forced_trimmed_paths; |
5099ac24 | 9 | use rustc_middle::ty::subst::InternalSubsts; |
ba9703b0 | 10 | use rustc_middle::ty::util::IntTypeExt; |
353b0b11 | 11 | use rustc_middle::ty::{self, ImplTraitInTraitData, IsSuggestable, Ty, TyCtxt, TypeVisitableExt}; |
f035d41b | 12 | use rustc_span::symbol::Ident; |
74b04a01 XL |
13 | use rustc_span::{Span, DUMMY_SP}; |
14 | ||
15 | use super::ItemCtxt; | |
a2a8927a | 16 | use super::{bad_placeholder, is_suggestable_infer_ty}; |
04454e1e | 17 | use crate::errors::UnconstrainedOpaqueType; |
74b04a01 | 18 | |
3dfed10e XL |
19 | /// Computes the relevant generic parameter for a potential generic const argument. |
20 | /// | |
21 | /// This should be called using the query `tcx.opt_const_param_of`. | |
22 | pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<DefId> { | |
23 | use hir::*; | |
3dfed10e XL |
24 | let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); |
25 | ||
5099ac24 FG |
26 | match tcx.hir().get(hir_id) { |
27 | Node::AnonConst(_) => (), | |
28 | _ => return None, | |
29 | }; | |
6a06907d | 30 | |
9c376795 | 31 | let parent_node_id = tcx.hir().parent_id(hir_id); |
5099ac24 | 32 | let parent_node = tcx.hir().get(parent_node_id); |
6a06907d | 33 | |
5099ac24 FG |
34 | let (generics, arg_idx) = match parent_node { |
35 | // This match arm is for when the def_id appears in a GAT whose | |
36 | // path can't be resolved without typechecking e.g. | |
37 | // | |
38 | // trait Foo { | |
39 | // type Assoc<const N: usize>; | |
40 | // fn foo() -> Self::Assoc<3>; | |
41 | // } | |
42 | // | |
43 | // In the above code we would call this query with the def_id of 3 and | |
44 | // the parent_node we match on would be the hir node for Self::Assoc<3> | |
45 | // | |
5e7ed085 | 46 | // `Self::Assoc<3>` cant be resolved without typechecking here as we |
5099ac24 FG |
47 | // didnt write <Self as Foo>::Assoc<3>. If we did then another match |
48 | // arm would handle this. | |
49 | // | |
50 | // I believe this match arm is only needed for GAT but I am not 100% sure - BoxyUwU | |
51 | Node::Ty(hir_ty @ Ty { kind: TyKind::Path(QPath::TypeRelative(_, segment)), .. }) => { | |
52 | // Find the Item containing the associated type so we can create an ItemCtxt. | |
53 | // Using the ItemCtxt convert the HIR for the unresolved assoc type into a | |
54 | // ty which is a fully resolved projection. | |
55 | // For the code example above, this would mean converting Self::Assoc<3> | |
9c376795 | 56 | // into a ty::Alias(ty::Projection, <Self as Foo>::Assoc<3>) |
9ffffee4 | 57 | let item_def_id = tcx |
5099ac24 | 58 | .hir() |
9ffffee4 FG |
59 | .parent_owner_iter(hir_id) |
60 | .find(|(_, node)| matches!(node, OwnerNode::Item(_))) | |
61 | .unwrap() | |
62 | .0 | |
353b0b11 | 63 | .def_id; |
9ffffee4 | 64 | let item_ctxt = &ItemCtxt::new(tcx, item_def_id) as &dyn crate::astconv::AstConv<'_>; |
5099ac24 FG |
65 | let ty = item_ctxt.ast_ty_to_ty(hir_ty); |
66 | ||
67 | // Iterate through the generics of the projection to find the one that corresponds to | |
f2b60f7d FG |
68 | // the def_id that this query was called with. We filter to only type and const args here |
69 | // as a precaution for if it's ever allowed to elide lifetimes in GAT's. It currently isn't | |
5099ac24 | 70 | // but it can't hurt to be safe ^^ |
9c376795 FG |
71 | if let ty::Alias(ty::Projection, projection) = ty.kind() { |
72 | let generics = tcx.generics_of(projection.def_id); | |
5099ac24 FG |
73 | |
74 | let arg_index = segment | |
3dfed10e XL |
75 | .args |
76 | .and_then(|args| { | |
77 | args.args | |
78 | .iter() | |
5099ac24 | 79 | .filter(|arg| arg.is_ty_or_const()) |
f2b60f7d | 80 | .position(|arg| arg.hir_id() == hir_id) |
3dfed10e XL |
81 | }) |
82 | .unwrap_or_else(|| { | |
83 | bug!("no arg matching AnonConst in segment"); | |
84 | }); | |
85 | ||
5099ac24 FG |
86 | (generics, arg_index) |
87 | } else { | |
88 | // I dont think it's possible to reach this but I'm not 100% sure - BoxyUwU | |
89 | tcx.sess.delay_span_bug( | |
90 | tcx.def_span(def_id), | |
91 | "unexpected non-GAT usage of an anon const", | |
92 | ); | |
93 | return None; | |
3dfed10e | 94 | } |
5099ac24 FG |
95 | } |
96 | Node::Expr(&Expr { | |
97 | kind: | |
98 | ExprKind::MethodCall(segment, ..) | ExprKind::Path(QPath::TypeRelative(_, segment)), | |
99 | .. | |
100 | }) => { | |
064997fb | 101 | let body_owner = tcx.hir().enclosing_body_owner(hir_id); |
5099ac24 FG |
102 | let tables = tcx.typeck(body_owner); |
103 | // This may fail in case the method/path does not actually exist. | |
104 | // As there is no relevant param for `def_id`, we simply return | |
105 | // `None` here. | |
106 | let type_dependent_def = tables.type_dependent_def_id(parent_node_id)?; | |
107 | let idx = segment | |
108 | .args | |
109 | .and_then(|args| { | |
110 | args.args | |
111 | .iter() | |
112 | .filter(|arg| arg.is_ty_or_const()) | |
f2b60f7d | 113 | .position(|arg| arg.hir_id() == hir_id) |
5099ac24 FG |
114 | }) |
115 | .unwrap_or_else(|| { | |
116 | bug!("no arg matching AnonConst in segment"); | |
117 | }); | |
3dfed10e | 118 | |
5099ac24 FG |
119 | (tcx.generics_of(type_dependent_def), idx) |
120 | } | |
121 | ||
122 | Node::Ty(&Ty { kind: TyKind::Path(_), .. }) | |
123 | | Node::Expr(&Expr { kind: ExprKind::Path(_) | ExprKind::Struct(..), .. }) | |
124 | | Node::TraitRef(..) | |
125 | | Node::Pat(_) => { | |
126 | let path = match parent_node { | |
127 | Node::Ty(&Ty { kind: TyKind::Path(QPath::Resolved(_, path)), .. }) | |
128 | | Node::TraitRef(&TraitRef { path, .. }) => &*path, | |
129 | Node::Expr(&Expr { | |
130 | kind: | |
131 | ExprKind::Path(QPath::Resolved(_, path)) | |
132 | | ExprKind::Struct(&QPath::Resolved(_, path), ..), | |
133 | .. | |
134 | }) => { | |
064997fb | 135 | let body_owner = tcx.hir().enclosing_body_owner(hir_id); |
5099ac24 FG |
136 | let _tables = tcx.typeck(body_owner); |
137 | &*path | |
138 | } | |
139 | Node::Pat(pat) => { | |
140 | if let Some(path) = get_path_containing_arg_in_pat(pat, hir_id) { | |
141 | path | |
142 | } else { | |
1b1a35ee XL |
143 | tcx.sess.delay_span_bug( |
144 | tcx.def_span(def_id), | |
5099ac24 | 145 | &format!("unable to find const parent for {} in pat {:?}", hir_id, pat), |
1b1a35ee XL |
146 | ); |
147 | return None; | |
148 | } | |
5099ac24 FG |
149 | } |
150 | _ => { | |
151 | tcx.sess.delay_span_bug( | |
152 | tcx.def_span(def_id), | |
153 | &format!("unexpected const parent path {:?}", parent_node), | |
154 | ); | |
155 | return None; | |
156 | } | |
157 | }; | |
3dfed10e | 158 | |
5099ac24 FG |
159 | // We've encountered an `AnonConst` in some path, so we need to |
160 | // figure out which generic parameter it corresponds to and return | |
161 | // the relevant type. | |
923072b8 FG |
162 | let Some((arg_index, segment)) = path.segments.iter().find_map(|seg| { |
163 | let args = seg.args?; | |
164 | args.args | |
165 | .iter() | |
166 | .filter(|arg| arg.is_ty_or_const()) | |
f2b60f7d | 167 | .position(|arg| arg.hir_id() == hir_id) |
923072b8 | 168 | .map(|index| (index, seg)).or_else(|| args.bindings |
3dfed10e | 169 | .iter() |
923072b8 FG |
170 | .filter_map(TypeBinding::opt_const) |
171 | .position(|ct| ct.hir_id == hir_id) | |
172 | .map(|idx| (idx, seg))) | |
173 | }) else { | |
174 | tcx.sess.delay_span_bug( | |
175 | tcx.def_span(def_id), | |
176 | "no arg matching AnonConst in path", | |
177 | ); | |
178 | return None; | |
5099ac24 FG |
179 | }; |
180 | ||
f2b60f7d | 181 | let generics = match tcx.res_generics_def_id(segment.res) { |
5099ac24 FG |
182 | Some(def_id) => tcx.generics_of(def_id), |
183 | None => { | |
184 | tcx.sess.delay_span_bug( | |
185 | tcx.def_span(def_id), | |
f2b60f7d | 186 | &format!("unexpected anon const res {:?} in path: {:?}", segment.res, path), |
5099ac24 FG |
187 | ); |
188 | return None; | |
189 | } | |
190 | }; | |
3dfed10e | 191 | |
5099ac24 FG |
192 | (generics, arg_index) |
193 | } | |
194 | _ => return None, | |
195 | }; | |
196 | ||
197 | debug!(?parent_node); | |
198 | debug!(?generics, ?arg_idx); | |
199 | generics | |
200 | .params | |
201 | .iter() | |
202 | .filter(|param| param.kind.is_ty_or_const()) | |
203 | .nth(match generics.has_self && generics.parent.is_none() { | |
204 | true => arg_idx + 1, | |
205 | false => arg_idx, | |
206 | }) | |
207 | .and_then(|param| match param.kind { | |
208 | ty::GenericParamDefKind::Const { .. } => { | |
209 | debug!(?param); | |
210 | Some(param.def_id) | |
3dfed10e XL |
211 | } |
212 | _ => None, | |
5099ac24 | 213 | }) |
3dfed10e XL |
214 | } |
215 | ||
5869c6ff XL |
216 | fn get_path_containing_arg_in_pat<'hir>( |
217 | pat: &'hir hir::Pat<'hir>, | |
218 | arg_id: HirId, | |
219 | ) -> Option<&'hir hir::Path<'hir>> { | |
220 | use hir::*; | |
221 | ||
222 | let is_arg_in_path = |p: &hir::Path<'_>| { | |
223 | p.segments | |
224 | .iter() | |
225 | .filter_map(|seg| seg.args) | |
226 | .flat_map(|args| args.args) | |
f2b60f7d | 227 | .any(|arg| arg.hir_id() == arg_id) |
5869c6ff XL |
228 | }; |
229 | let mut arg_path = None; | |
230 | pat.walk(|pat| match pat.kind { | |
231 | PatKind::Struct(QPath::Resolved(_, path), _, _) | |
232 | | PatKind::TupleStruct(QPath::Resolved(_, path), _, _) | |
233 | | PatKind::Path(QPath::Resolved(_, path)) | |
234 | if is_arg_in_path(path) => | |
235 | { | |
236 | arg_path = Some(path); | |
237 | false | |
238 | } | |
239 | _ => true, | |
240 | }); | |
241 | arg_path | |
242 | } | |
243 | ||
353b0b11 FG |
244 | pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty<'_>> { |
245 | // If we are computing `type_of` the synthesized associated type for an RPITIT in the impl | |
246 | // side, use `collect_return_position_impl_trait_in_trait_tys` to infer the value of the | |
247 | // associated type in the impl. | |
248 | if let Some(ImplTraitInTraitData::Impl { fn_def_id, .. }) = | |
249 | tcx.opt_rpitit_info(def_id.to_def_id()) | |
250 | { | |
251 | match tcx.collect_return_position_impl_trait_in_trait_tys(fn_def_id) { | |
252 | Ok(map) => { | |
253 | let assoc_item = tcx.associated_item(def_id); | |
254 | return ty::EarlyBinder(map[&assoc_item.trait_item_def_id.unwrap()]); | |
255 | } | |
256 | Err(_) => { | |
257 | return ty::EarlyBinder(tcx.ty_error_with_message( | |
258 | DUMMY_SP, | |
259 | "Could not collect return position impl trait in trait tys", | |
260 | )); | |
261 | } | |
262 | } | |
263 | } | |
264 | ||
74b04a01 XL |
265 | use rustc_hir::*; |
266 | ||
3dfed10e | 267 | let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); |
74b04a01 | 268 | |
353b0b11 | 269 | let icx = ItemCtxt::new(tcx, def_id); |
74b04a01 | 270 | |
9ffffee4 | 271 | let output = match tcx.hir().get(hir_id) { |
74b04a01 | 272 | Node::TraitItem(item) => match item.kind { |
ba9703b0 | 273 | TraitItemKind::Fn(..) => { |
353b0b11 | 274 | let substs = InternalSubsts::identity_for_item(tcx, def_id); |
3dfed10e | 275 | tcx.mk_fn_def(def_id.to_def_id(), substs) |
74b04a01 | 276 | } |
c295e0f8 | 277 | TraitItemKind::Const(ty, body_id) => body_id |
74b04a01 | 278 | .and_then(|body_id| { |
353b0b11 FG |
279 | is_suggestable_infer_ty(ty).then(|| { |
280 | infer_placeholder_type( | |
281 | tcx, def_id, body_id, ty.span, item.ident, "constant", | |
282 | ) | |
283 | }) | |
74b04a01 XL |
284 | }) |
285 | .unwrap_or_else(|| icx.to_ty(ty)), | |
c295e0f8 | 286 | TraitItemKind::Type(_, Some(ty)) => icx.to_ty(ty), |
74b04a01 XL |
287 | TraitItemKind::Type(_, None) => { |
288 | span_bug!(item.span, "associated type missing default"); | |
289 | } | |
290 | }, | |
291 | ||
292 | Node::ImplItem(item) => match item.kind { | |
ba9703b0 | 293 | ImplItemKind::Fn(..) => { |
353b0b11 | 294 | let substs = InternalSubsts::identity_for_item(tcx, def_id); |
3dfed10e | 295 | tcx.mk_fn_def(def_id.to_def_id(), substs) |
74b04a01 | 296 | } |
c295e0f8 | 297 | ImplItemKind::Const(ty, body_id) => { |
74b04a01 | 298 | if is_suggestable_infer_ty(ty) { |
136023e0 | 299 | infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident, "constant") |
74b04a01 XL |
300 | } else { |
301 | icx.to_ty(ty) | |
302 | } | |
303 | } | |
2b03887a | 304 | ImplItemKind::Type(ty) => { |
5099ac24 | 305 | if tcx.impl_trait_ref(tcx.hir().get_parent_item(hir_id)).is_none() { |
6a06907d | 306 | check_feature_inherent_assoc_ty(tcx, item.span); |
74b04a01 XL |
307 | } |
308 | ||
309 | icx.to_ty(ty) | |
310 | } | |
311 | }, | |
312 | ||
313 | Node::Item(item) => { | |
314 | match item.kind { | |
c295e0f8 | 315 | ItemKind::Static(ty, .., body_id) => { |
74b04a01 | 316 | if is_suggestable_infer_ty(ty) { |
136023e0 XL |
317 | infer_placeholder_type( |
318 | tcx, | |
319 | def_id, | |
320 | body_id, | |
321 | ty.span, | |
322 | item.ident, | |
323 | "static variable", | |
324 | ) | |
325 | } else { | |
326 | icx.to_ty(ty) | |
327 | } | |
328 | } | |
c295e0f8 | 329 | ItemKind::Const(ty, body_id) => { |
136023e0 XL |
330 | if is_suggestable_infer_ty(ty) { |
331 | infer_placeholder_type( | |
332 | tcx, def_id, body_id, ty.span, item.ident, "constant", | |
333 | ) | |
74b04a01 XL |
334 | } else { |
335 | icx.to_ty(ty) | |
336 | } | |
337 | } | |
04454e1e | 338 | ItemKind::TyAlias(self_ty, _) => icx.to_ty(self_ty), |
353b0b11 FG |
339 | ItemKind::Impl(hir::Impl { self_ty, .. }) => match self_ty.find_self_aliases() { |
340 | spans if spans.len() > 0 => { | |
341 | let guar = tcx.sess.emit_err(crate::errors::SelfInImplSelf { | |
342 | span: spans.into(), | |
343 | note: (), | |
344 | }); | |
345 | tcx.ty_error(guar) | |
2b03887a | 346 | } |
353b0b11 | 347 | _ => icx.to_ty(*self_ty), |
2b03887a | 348 | }, |
74b04a01 | 349 | ItemKind::Fn(..) => { |
353b0b11 | 350 | let substs = InternalSubsts::identity_for_item(tcx, def_id); |
3dfed10e | 351 | tcx.mk_fn_def(def_id.to_def_id(), substs) |
74b04a01 XL |
352 | } |
353 | ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) => { | |
354 | let def = tcx.adt_def(def_id); | |
353b0b11 | 355 | let substs = InternalSubsts::identity_for_item(tcx, def_id); |
74b04a01 XL |
356 | tcx.mk_adt(def, substs) |
357 | } | |
a2a8927a | 358 | ItemKind::OpaqueTy(OpaqueTy { origin: hir::OpaqueTyOrigin::TyAlias, .. }) => { |
064997fb | 359 | find_opaque_ty_constraints_for_tait(tcx, def_id) |
74b04a01 XL |
360 | } |
361 | // Opaque types desugared from `impl Trait`. | |
f2b60f7d FG |
362 | ItemKind::OpaqueTy(OpaqueTy { |
363 | origin: | |
364 | hir::OpaqueTyOrigin::FnReturn(owner) | hir::OpaqueTyOrigin::AsyncFn(owner), | |
365 | in_trait, | |
366 | .. | |
367 | }) => { | |
353b0b11 FG |
368 | if in_trait && !tcx.impl_defaultness(owner).has_value() { |
369 | span_bug!( | |
370 | tcx.def_span(def_id), | |
371 | "tried to get type of this RPITIT with no definition" | |
372 | ); | |
f2b60f7d | 373 | } |
2b03887a | 374 | find_opaque_ty_constraints_for_rpit(tcx, def_id, owner) |
74b04a01 XL |
375 | } |
376 | ItemKind::Trait(..) | |
377 | | ItemKind::TraitAlias(..) | |
94222f64 | 378 | | ItemKind::Macro(..) |
74b04a01 | 379 | | ItemKind::Mod(..) |
fc512014 | 380 | | ItemKind::ForeignMod { .. } |
74b04a01 XL |
381 | | ItemKind::GlobalAsm(..) |
382 | | ItemKind::ExternCrate(..) | |
383 | | ItemKind::Use(..) => { | |
384 | span_bug!( | |
385 | item.span, | |
386 | "compute_type_of_item: unexpected item type: {:?}", | |
387 | item.kind | |
388 | ); | |
389 | } | |
390 | } | |
391 | } | |
392 | ||
393 | Node::ForeignItem(foreign_item) => match foreign_item.kind { | |
394 | ForeignItemKind::Fn(..) => { | |
353b0b11 | 395 | let substs = InternalSubsts::identity_for_item(tcx, def_id); |
3dfed10e | 396 | tcx.mk_fn_def(def_id.to_def_id(), substs) |
74b04a01 | 397 | } |
c295e0f8 | 398 | ForeignItemKind::Static(t, _) => icx.to_ty(t), |
3dfed10e | 399 | ForeignItemKind::Type => tcx.mk_foreign(def_id.to_def_id()), |
74b04a01 XL |
400 | }, |
401 | ||
9c376795 | 402 | Node::Ctor(def) | Node::Variant(Variant { data: def, .. }) => match def { |
74b04a01 | 403 | VariantData::Unit(..) | VariantData::Struct(..) => { |
9ffffee4 | 404 | tcx.type_of(tcx.hir().get_parent_item(hir_id)).subst_identity() |
74b04a01 XL |
405 | } |
406 | VariantData::Tuple(..) => { | |
353b0b11 | 407 | let substs = InternalSubsts::identity_for_item(tcx, def_id); |
3dfed10e | 408 | tcx.mk_fn_def(def_id.to_def_id(), substs) |
74b04a01 XL |
409 | } |
410 | }, | |
411 | ||
c295e0f8 | 412 | Node::Field(field) => icx.to_ty(field.ty), |
74b04a01 | 413 | |
f2b60f7d FG |
414 | Node::Expr(&Expr { kind: ExprKind::Closure { .. }, .. }) => { |
415 | tcx.typeck(def_id).node_type(hir_id) | |
416 | } | |
74b04a01 | 417 | |
94222f64 XL |
418 | Node::AnonConst(_) if let Some(param) = tcx.opt_const_param_of(def_id) => { |
419 | // We defer to `type_of` of the corresponding parameter | |
420 | // for generic arguments. | |
9ffffee4 | 421 | tcx.type_of(param).subst_identity() |
94222f64 | 422 | } |
3dfed10e | 423 | |
94222f64 | 424 | Node::AnonConst(_) => { |
9c376795 | 425 | let parent_node = tcx.hir().get_parent(hir_id); |
74b04a01 | 426 | match parent_node { |
9c376795 FG |
427 | Node::Ty(Ty { kind: TyKind::Array(_, constant), .. }) |
428 | | Node::Expr(Expr { kind: ExprKind::Repeat(_, constant), .. }) | |
a2a8927a | 429 | if constant.hir_id() == hir_id => |
74b04a01 XL |
430 | { |
431 | tcx.types.usize | |
432 | } | |
9c376795 | 433 | Node::Ty(Ty { kind: TyKind::Typeof(e), .. }) if e.hir_id == hir_id => { |
cdc7bbd5 XL |
434 | tcx.typeck(def_id).node_type(e.hir_id) |
435 | } | |
74b04a01 | 436 | |
9c376795 | 437 | Node::Expr(Expr { kind: ExprKind::ConstBlock(anon_const), .. }) |
29967ef6 XL |
438 | if anon_const.hir_id == hir_id => |
439 | { | |
353b0b11 | 440 | let substs = InternalSubsts::identity_for_item(tcx, def_id); |
3c0e092e | 441 | substs.as_inline_const().ty() |
29967ef6 XL |
442 | } |
443 | ||
17df50a5 XL |
444 | Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. }) |
445 | | Node::Item(&Item { kind: ItemKind::GlobalAsm(asm), .. }) | |
446 | if asm.operands.iter().any(|(op, _op_sp)| match op { | |
04454e1e | 447 | hir::InlineAsmOperand::Const { anon_const } |
f2b60f7d FG |
448 | | hir::InlineAsmOperand::SymFn { anon_const } => { |
449 | anon_const.hir_id == hir_id | |
450 | } | |
cdc7bbd5 XL |
451 | _ => false, |
452 | }) => | |
453 | { | |
454 | tcx.typeck(def_id).node_type(hir_id) | |
455 | } | |
456 | ||
9c376795 | 457 | Node::Variant(Variant { disr_expr: Some(e), .. }) if e.hir_id == hir_id => { |
f2b60f7d FG |
458 | tcx.adt_def(tcx.hir().get_parent_item(hir_id)).repr().discr_type().to_ty(tcx) |
459 | } | |
460 | ||
353b0b11 FG |
461 | Node::TypeBinding(TypeBinding { |
462 | hir_id: binding_id, | |
463 | kind: TypeBindingKind::Equality { term: Term::Const(e) }, | |
464 | ident, | |
465 | .. | |
466 | }) if let Node::TraitRef(trait_ref) = tcx.hir().get_parent(*binding_id) | |
f2b60f7d FG |
467 | && e.hir_id == hir_id => |
468 | { | |
469 | let Some(trait_def_id) = trait_ref.trait_def_id() else { | |
9ffffee4 | 470 | return ty::EarlyBinder(tcx.ty_error_with_message(DUMMY_SP, "Could not find trait")); |
f2b60f7d FG |
471 | }; |
472 | let assoc_items = tcx.associated_items(trait_def_id); | |
473 | let assoc_item = assoc_items.find_by_name_and_kind( | |
474 | tcx, | |
9c376795 | 475 | *ident, |
f2b60f7d FG |
476 | ty::AssocKind::Const, |
477 | def_id.to_def_id(), | |
478 | ); | |
479 | if let Some(assoc_item) = assoc_item { | |
353b0b11 FG |
480 | tcx.type_of(assoc_item.def_id) |
481 | .no_bound_vars() | |
482 | .expect("const parameter types cannot be generic") | |
f2b60f7d FG |
483 | } else { |
484 | // FIXME(associated_const_equality): add a useful error message here. | |
485 | tcx.ty_error_with_message( | |
486 | DUMMY_SP, | |
487 | "Could not find associated const on trait", | |
488 | ) | |
489 | } | |
490 | } | |
74b04a01 | 491 | |
353b0b11 FG |
492 | Node::TypeBinding(TypeBinding { |
493 | hir_id: binding_id, | |
494 | gen_args, | |
495 | kind, | |
496 | ident, | |
497 | .. | |
498 | }) if let Node::TraitRef(trait_ref) = tcx.hir().get_parent(*binding_id) | |
f2b60f7d FG |
499 | && let Some((idx, _)) = |
500 | gen_args.args.iter().enumerate().find(|(_, arg)| { | |
501 | if let GenericArg::Const(ct) = arg { | |
502 | ct.value.hir_id == hir_id | |
503 | } else { | |
504 | false | |
505 | } | |
506 | }) => | |
5099ac24 | 507 | { |
f2b60f7d | 508 | let Some(trait_def_id) = trait_ref.trait_def_id() else { |
9ffffee4 | 509 | return ty::EarlyBinder(tcx.ty_error_with_message(DUMMY_SP, "Could not find trait")); |
f2b60f7d FG |
510 | }; |
511 | let assoc_items = tcx.associated_items(trait_def_id); | |
512 | let assoc_item = assoc_items.find_by_name_and_kind( | |
513 | tcx, | |
9c376795 | 514 | *ident, |
f2b60f7d FG |
515 | match kind { |
516 | // I think `<A: T>` type bindings requires that `A` is a type | |
517 | TypeBindingKind::Constraint { .. } | |
518 | | TypeBindingKind::Equality { term: Term::Ty(..) } => { | |
519 | ty::AssocKind::Type | |
520 | } | |
521 | TypeBindingKind::Equality { term: Term::Const(..) } => { | |
522 | ty::AssocKind::Const | |
523 | } | |
524 | }, | |
525 | def_id.to_def_id(), | |
526 | ); | |
353b0b11 FG |
527 | if let Some(assoc_item) = assoc_item |
528 | && let param = &tcx.generics_of(assoc_item.def_id).params[idx] | |
529 | && matches!(param.kind, ty::GenericParamDefKind::Const { .. }) | |
2b03887a | 530 | { |
353b0b11 FG |
531 | tcx.type_of(param.def_id) |
532 | .no_bound_vars() | |
533 | .expect("const parameter types cannot be generic") | |
f2b60f7d FG |
534 | } else { |
535 | // FIXME(associated_const_equality): add a useful error message here. | |
536 | tcx.ty_error_with_message( | |
537 | DUMMY_SP, | |
353b0b11 | 538 | "Could not find const param on associated item", |
f2b60f7d FG |
539 | ) |
540 | } | |
5099ac24 FG |
541 | } |
542 | ||
cdc7bbd5 | 543 | Node::GenericParam(&GenericParam { |
487cf647 | 544 | def_id: param_def_id, |
cdc7bbd5 XL |
545 | kind: GenericParamKind::Const { default: Some(ct), .. }, |
546 | .. | |
9ffffee4 | 547 | }) if ct.hir_id == hir_id => tcx.type_of(param_def_id).subst_identity(), |
cdc7bbd5 | 548 | |
f2b60f7d | 549 | x => tcx.ty_error_with_message( |
f035d41b | 550 | DUMMY_SP, |
5099ac24 | 551 | &format!("unexpected const parent in type_of(): {x:?}"), |
f035d41b | 552 | ), |
74b04a01 XL |
553 | } |
554 | } | |
555 | ||
556 | Node::GenericParam(param) => match ¶m.kind { | |
3dfed10e XL |
557 | GenericParamKind::Type { default: Some(ty), .. } |
558 | | GenericParamKind::Const { ty, .. } => icx.to_ty(ty), | |
74b04a01 XL |
559 | x => bug!("unexpected non-type Node::GenericParam: {:?}", x), |
560 | }, | |
561 | ||
562 | x => { | |
136023e0 | 563 | bug!("unexpected sort of node in type_of(): {:?}", x); |
74b04a01 | 564 | } |
9ffffee4 FG |
565 | }; |
566 | ty::EarlyBinder(output) | |
74b04a01 XL |
567 | } |
568 | ||
136023e0 | 569 | #[instrument(skip(tcx), level = "debug")] |
c295e0f8 XL |
570 | /// Checks "defining uses" of opaque `impl Trait` types to ensure that they meet the restrictions |
571 | /// laid for "higher-order pattern unification". | |
572 | /// This ensures that inference is tractable. | |
573 | /// In particular, definitions of opaque types can only use other generics as arguments, | |
574 | /// and they cannot repeat an argument. Example: | |
575 | /// | |
04454e1e | 576 | /// ```ignore (illustrative) |
c295e0f8 XL |
577 | /// type Foo<A, B> = impl Bar<A, B>; |
578 | /// | |
579 | /// // Okay -- `Foo` is applied to two distinct, generic types. | |
580 | /// fn a<T, U>() -> Foo<T, U> { .. } | |
581 | /// | |
582 | /// // Not okay -- `Foo` is applied to `T` twice. | |
583 | /// fn b<T>() -> Foo<T, T> { .. } | |
584 | /// | |
585 | /// // Not okay -- `Foo` is applied to a non-generic type. | |
586 | /// fn b<T>() -> Foo<T, u32> { .. } | |
587 | /// ``` | |
588 | /// | |
064997fb | 589 | fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> { |
74b04a01 XL |
590 | use rustc_hir::{Expr, ImplItem, Item, TraitItem}; |
591 | ||
74b04a01 XL |
592 | struct ConstraintLocator<'tcx> { |
593 | tcx: TyCtxt<'tcx>, | |
136023e0 XL |
594 | |
595 | /// def_id of the opaque type whose defining uses are being checked | |
064997fb | 596 | def_id: LocalDefId, |
136023e0 XL |
597 | |
598 | /// as we walk the defining uses, we are checking that all of them | |
599 | /// define the same hidden type. This variable is set to `Some` | |
600 | /// with the first type that we find, and then later types are | |
601 | /// checked against it (we also carry the span of that first | |
602 | /// type). | |
5e7ed085 | 603 | found: Option<ty::OpaqueHiddenType<'tcx>>, |
2b03887a FG |
604 | |
605 | /// In the presence of dead code, typeck may figure out a hidden type | |
353b0b11 | 606 | /// while borrowck will not. We collect these cases here and check at |
2b03887a FG |
607 | /// the end that we actually found a type that matches (modulo regions). |
608 | typeck_types: Vec<ty::OpaqueHiddenType<'tcx>>, | |
74b04a01 XL |
609 | } |
610 | ||
611 | impl ConstraintLocator<'_> { | |
136023e0 | 612 | #[instrument(skip(self), level = "debug")] |
064997fb | 613 | fn check(&mut self, item_def_id: LocalDefId) { |
74b04a01 | 614 | // Don't try to check items that cannot possibly constrain the type. |
064997fb | 615 | if !self.tcx.has_typeck_results(item_def_id) { |
136023e0 | 616 | debug!("no constraint: no typeck results"); |
74b04a01 XL |
617 | return; |
618 | } | |
619 | // Calling `mir_borrowck` can lead to cycle errors through | |
620 | // const-checking, avoid calling it if we don't have to. | |
5e7ed085 FG |
621 | // ```rust |
622 | // type Foo = impl Fn() -> usize; // when computing type for this | |
623 | // const fn bar() -> Foo { | |
624 | // || 0usize | |
625 | // } | |
626 | // const BAZR: Foo = bar(); // we would mir-borrowck this, causing cycles | |
627 | // // because we again need to reveal `Foo` so we can check whether the | |
628 | // // constant does not contain interior mutability. | |
629 | // ``` | |
064997fb | 630 | let tables = self.tcx.typeck(item_def_id); |
9ffffee4 FG |
631 | if let Some(guar) = tables.tainted_by_errors { |
632 | self.found = | |
633 | Some(ty::OpaqueHiddenType { span: DUMMY_SP, ty: self.tcx.ty_error(guar) }); | |
5e7ed085 FG |
634 | return; |
635 | } | |
2b03887a | 636 | let Some(&typeck_hidden_ty) = tables.concrete_opaque_types.get(&self.def_id) else { |
136023e0 | 637 | debug!("no constraints in typeck results"); |
74b04a01 | 638 | return; |
2b03887a FG |
639 | }; |
640 | if self.typeck_types.iter().all(|prev| prev.ty != typeck_hidden_ty.ty) { | |
641 | self.typeck_types.push(typeck_hidden_ty); | |
74b04a01 | 642 | } |
2b03887a | 643 | |
74b04a01 | 644 | // Use borrowck to get the type with unerased regions. |
064997fb | 645 | let concrete_opaque_types = &self.tcx.mir_borrowck(item_def_id).concrete_opaque_types; |
136023e0 | 646 | debug!(?concrete_opaque_types); |
064997fb | 647 | if let Some(&concrete_type) = concrete_opaque_types.get(&self.def_id) { |
04454e1e | 648 | debug!(?concrete_type, "found constraint"); |
2b03887a FG |
649 | if let Some(prev) = &mut self.found { |
650 | if concrete_type.ty != prev.ty && !(concrete_type, prev.ty).references_error() { | |
9ffffee4 FG |
651 | let guar = prev.report_mismatch(&concrete_type, self.tcx); |
652 | prev.ty = self.tcx.ty_error(guar); | |
74b04a01 XL |
653 | } |
654 | } else { | |
5e7ed085 | 655 | self.found = Some(concrete_type); |
74b04a01 | 656 | } |
74b04a01 XL |
657 | } |
658 | } | |
659 | } | |
660 | ||
661 | impl<'tcx> intravisit::Visitor<'tcx> for ConstraintLocator<'tcx> { | |
5099ac24 | 662 | type NestedFilter = nested_filter::All; |
74b04a01 | 663 | |
5099ac24 FG |
664 | fn nested_visit_map(&mut self) -> Self::Map { |
665 | self.tcx.hir() | |
74b04a01 XL |
666 | } |
667 | fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) { | |
487cf647 FG |
668 | if let hir::ExprKind::Closure(closure) = ex.kind { |
669 | self.check(closure.def_id); | |
74b04a01 XL |
670 | } |
671 | intravisit::walk_expr(self, ex); | |
672 | } | |
673 | fn visit_item(&mut self, it: &'tcx Item<'tcx>) { | |
2b03887a | 674 | trace!(?it.owner_id); |
74b04a01 | 675 | // The opaque type itself or its children are not within its reveal scope. |
2b03887a FG |
676 | if it.owner_id.def_id != self.def_id { |
677 | self.check(it.owner_id.def_id); | |
74b04a01 XL |
678 | intravisit::walk_item(self, it); |
679 | } | |
680 | } | |
681 | fn visit_impl_item(&mut self, it: &'tcx ImplItem<'tcx>) { | |
2b03887a | 682 | trace!(?it.owner_id); |
74b04a01 | 683 | // The opaque type itself or its children are not within its reveal scope. |
2b03887a FG |
684 | if it.owner_id.def_id != self.def_id { |
685 | self.check(it.owner_id.def_id); | |
74b04a01 XL |
686 | intravisit::walk_impl_item(self, it); |
687 | } | |
688 | } | |
689 | fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) { | |
2b03887a FG |
690 | trace!(?it.owner_id); |
691 | self.check(it.owner_id.def_id); | |
74b04a01 XL |
692 | intravisit::walk_trait_item(self, it); |
693 | } | |
694 | } | |
695 | ||
3dfed10e | 696 | let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); |
74b04a01 | 697 | let scope = tcx.hir().get_defining_scope(hir_id); |
9c376795 | 698 | let mut locator = ConstraintLocator { def_id, tcx, found: None, typeck_types: vec![] }; |
74b04a01 | 699 | |
5e7ed085 | 700 | debug!(?scope); |
74b04a01 XL |
701 | |
702 | if scope == hir::CRATE_HIR_ID { | |
c295e0f8 | 703 | tcx.hir().walk_toplevel_module(&mut locator); |
74b04a01 | 704 | } else { |
5e7ed085 | 705 | trace!("scope={:#?}", tcx.hir().get(scope)); |
74b04a01 XL |
706 | match tcx.hir().get(scope) { |
707 | // We explicitly call `visit_*` methods, instead of using `intravisit::walk_*` methods | |
708 | // This allows our visitor to process the defining item itself, causing | |
709 | // it to pick up any 'sibling' defining uses. | |
710 | // | |
711 | // For example, this code: | |
712 | // ``` | |
713 | // fn foo() { | |
714 | // type Blah = impl Debug; | |
715 | // let my_closure = || -> Blah { true }; | |
716 | // } | |
717 | // ``` | |
718 | // | |
719 | // requires us to explicitly process `foo()` in order | |
720 | // to notice the defining usage of `Blah`. | |
c295e0f8 XL |
721 | Node::Item(it) => locator.visit_item(it), |
722 | Node::ImplItem(it) => locator.visit_impl_item(it), | |
723 | Node::TraitItem(it) => locator.visit_trait_item(it), | |
74b04a01 XL |
724 | other => bug!("{:?} is not a valid scope for an opaque type item", other), |
725 | } | |
726 | } | |
727 | ||
2b03887a | 728 | let Some(hidden) = locator.found else { |
487cf647 | 729 | let reported = tcx.sess.emit_err(UnconstrainedOpaqueType { |
2b03887a FG |
730 | span: tcx.def_span(def_id), |
731 | name: tcx.item_name(tcx.local_parent(def_id).to_def_id()), | |
732 | what: match tcx.hir().get(scope) { | |
733 | _ if scope == hir::CRATE_HIR_ID => "module", | |
734 | Node::Item(hir::Item { kind: hir::ItemKind::Mod(_), .. }) => "module", | |
735 | Node::Item(hir::Item { kind: hir::ItemKind::Impl(_), .. }) => "impl", | |
736 | _ => "item", | |
737 | }, | |
738 | }); | |
9ffffee4 | 739 | return tcx.ty_error(reported); |
2b03887a FG |
740 | }; |
741 | ||
742 | // Only check against typeck if we didn't already error | |
743 | if !hidden.ty.references_error() { | |
744 | for concrete_type in locator.typeck_types { | |
745 | if tcx.erase_regions(concrete_type.ty) != tcx.erase_regions(hidden.ty) | |
746 | && !(concrete_type, hidden).references_error() | |
747 | { | |
748 | hidden.report_mismatch(&concrete_type, tcx); | |
749 | } | |
74b04a01 XL |
750 | } |
751 | } | |
2b03887a FG |
752 | |
753 | hidden.ty | |
74b04a01 XL |
754 | } |
755 | ||
064997fb FG |
756 | fn find_opaque_ty_constraints_for_rpit( |
757 | tcx: TyCtxt<'_>, | |
758 | def_id: LocalDefId, | |
759 | owner_def_id: LocalDefId, | |
760 | ) -> Ty<'_> { | |
761 | use rustc_hir::{Expr, ImplItem, Item, TraitItem}; | |
762 | ||
763 | struct ConstraintChecker<'tcx> { | |
764 | tcx: TyCtxt<'tcx>, | |
765 | ||
766 | /// def_id of the opaque type whose defining uses are being checked | |
767 | def_id: LocalDefId, | |
768 | ||
769 | found: ty::OpaqueHiddenType<'tcx>, | |
770 | } | |
771 | ||
772 | impl ConstraintChecker<'_> { | |
773 | #[instrument(skip(self), level = "debug")] | |
774 | fn check(&self, def_id: LocalDefId) { | |
775 | // Use borrowck to get the type with unerased regions. | |
776 | let concrete_opaque_types = &self.tcx.mir_borrowck(def_id).concrete_opaque_types; | |
777 | debug!(?concrete_opaque_types); | |
353b0b11 | 778 | for (&def_id, &concrete_type) in concrete_opaque_types { |
064997fb FG |
779 | if def_id != self.def_id { |
780 | // Ignore constraints for other opaque types. | |
781 | continue; | |
782 | } | |
783 | ||
784 | debug!(?concrete_type, "found constraint"); | |
785 | ||
786 | if concrete_type.ty != self.found.ty | |
787 | && !(concrete_type, self.found).references_error() | |
788 | { | |
789 | self.found.report_mismatch(&concrete_type, self.tcx); | |
790 | } | |
791 | } | |
792 | } | |
793 | } | |
794 | ||
795 | impl<'tcx> intravisit::Visitor<'tcx> for ConstraintChecker<'tcx> { | |
796 | type NestedFilter = nested_filter::OnlyBodies; | |
797 | ||
798 | fn nested_visit_map(&mut self) -> Self::Map { | |
799 | self.tcx.hir() | |
800 | } | |
801 | fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) { | |
487cf647 FG |
802 | if let hir::ExprKind::Closure(closure) = ex.kind { |
803 | self.check(closure.def_id); | |
064997fb FG |
804 | } |
805 | intravisit::walk_expr(self, ex); | |
806 | } | |
807 | fn visit_item(&mut self, it: &'tcx Item<'tcx>) { | |
2b03887a | 808 | trace!(?it.owner_id); |
064997fb | 809 | // The opaque type itself or its children are not within its reveal scope. |
2b03887a FG |
810 | if it.owner_id.def_id != self.def_id { |
811 | self.check(it.owner_id.def_id); | |
064997fb FG |
812 | intravisit::walk_item(self, it); |
813 | } | |
814 | } | |
815 | fn visit_impl_item(&mut self, it: &'tcx ImplItem<'tcx>) { | |
2b03887a | 816 | trace!(?it.owner_id); |
064997fb | 817 | // The opaque type itself or its children are not within its reveal scope. |
2b03887a FG |
818 | if it.owner_id.def_id != self.def_id { |
819 | self.check(it.owner_id.def_id); | |
064997fb FG |
820 | intravisit::walk_impl_item(self, it); |
821 | } | |
822 | } | |
823 | fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) { | |
2b03887a FG |
824 | trace!(?it.owner_id); |
825 | self.check(it.owner_id.def_id); | |
064997fb FG |
826 | intravisit::walk_trait_item(self, it); |
827 | } | |
828 | } | |
829 | ||
830 | let concrete = tcx.mir_borrowck(owner_def_id).concrete_opaque_types.get(&def_id).copied(); | |
831 | ||
832 | if let Some(concrete) = concrete { | |
833 | let scope = tcx.hir().local_def_id_to_hir_id(owner_def_id); | |
834 | debug!(?scope); | |
9c376795 | 835 | let mut locator = ConstraintChecker { def_id, tcx, found: concrete }; |
064997fb FG |
836 | |
837 | match tcx.hir().get(scope) { | |
838 | Node::Item(it) => intravisit::walk_item(&mut locator, it), | |
839 | Node::ImplItem(it) => intravisit::walk_impl_item(&mut locator, it), | |
840 | Node::TraitItem(it) => intravisit::walk_trait_item(&mut locator, it), | |
841 | other => bug!("{:?} is not a valid scope for an opaque type item", other), | |
842 | } | |
843 | } | |
844 | ||
845 | concrete.map(|concrete| concrete.ty).unwrap_or_else(|| { | |
846 | let table = tcx.typeck(owner_def_id); | |
9ffffee4 | 847 | if let Some(guar) = table.tainted_by_errors { |
064997fb FG |
848 | // Some error in the |
849 | // owner fn prevented us from populating | |
850 | // the `concrete_opaque_types` table. | |
9ffffee4 | 851 | tcx.ty_error(guar) |
064997fb | 852 | } else { |
2b03887a FG |
853 | table.concrete_opaque_types.get(&def_id).map(|ty| ty.ty).unwrap_or_else(|| { |
854 | // We failed to resolve the opaque type or it | |
855 | // resolves to itself. We interpret this as the | |
856 | // no values of the hidden type ever being constructed, | |
857 | // so we can just make the hidden type be `!`. | |
858 | // For backwards compatibility reasons, we fall back to | |
859 | // `()` until we the diverging default is changed. | |
860 | tcx.mk_diverging_default() | |
861 | }) | |
064997fb FG |
862 | } |
863 | }) | |
864 | } | |
865 | ||
136023e0 XL |
866 | fn infer_placeholder_type<'a>( |
867 | tcx: TyCtxt<'a>, | |
f9f354fc | 868 | def_id: LocalDefId, |
74b04a01 XL |
869 | body_id: hir::BodyId, |
870 | span: Span, | |
871 | item_ident: Ident, | |
136023e0 XL |
872 | kind: &'static str, |
873 | ) -> Ty<'a> { | |
3dfed10e | 874 | let ty = tcx.diagnostic_only_typeck(def_id).node_type(body_id.hir_id); |
74b04a01 XL |
875 | |
876 | // If this came from a free `const` or `static mut?` item, | |
877 | // then the user may have written e.g. `const A = 42;`. | |
878 | // In this case, the parser has stashed a diagnostic for | |
879 | // us to improve in typeck so we do that now. | |
880 | match tcx.sess.diagnostic().steal_diagnostic(span, StashKey::ItemNoType) { | |
881 | Some(mut err) => { | |
dc3f5686 | 882 | if !ty.references_error() { |
f2b60f7d FG |
883 | // Only suggest adding `:` if it was missing (and suggested by parsing diagnostic) |
884 | let colon = if span == item_ident.span.shrink_to_hi() { ":" } else { "" }; | |
885 | ||
dc3f5686 XL |
886 | // The parser provided a sub-optimal `HasPlaceholders` suggestion for the type. |
887 | // We are typeck and have the real type, so remove that and suggest the actual type. | |
5099ac24 FG |
888 | // FIXME(eddyb) this looks like it should be functionality on `Diagnostic`. |
889 | if let Ok(suggestions) = &mut err.suggestions { | |
890 | suggestions.clear(); | |
891 | } | |
dc3f5686 | 892 | |
9ffffee4 | 893 | if let Some(ty) = ty.make_suggestable(tcx, false) { |
dc3f5686 XL |
894 | err.span_suggestion( |
895 | span, | |
896 | &format!("provide a type for the {item}", item = kind), | |
9ffffee4 | 897 | format!("{colon} {ty}"), |
dc3f5686 XL |
898 | Applicability::MachineApplicable, |
899 | ); | |
900 | } else { | |
9c376795 | 901 | with_forced_trimmed_paths!(err.span_note( |
dc3f5686 | 902 | tcx.hir().body(body_id).value.span, |
9c376795 FG |
903 | &format!("however, the inferred type `{ty}` cannot be named"), |
904 | )); | |
dc3f5686 | 905 | } |
136023e0 XL |
906 | } |
907 | ||
dc3f5686 | 908 | err.emit(); |
74b04a01 XL |
909 | } |
910 | None => { | |
5099ac24 | 911 | let mut diag = bad_placeholder(tcx, vec![span], kind); |
6a06907d XL |
912 | |
913 | if !ty.references_error() { | |
9ffffee4 | 914 | if let Some(ty) = ty.make_suggestable(tcx, false) { |
136023e0 XL |
915 | diag.span_suggestion( |
916 | span, | |
917 | "replace with the correct type", | |
9ffffee4 FG |
918 | ty, |
919 | Applicability::MachineApplicable, | |
136023e0 XL |
920 | ); |
921 | } else { | |
9c376795 | 922 | with_forced_trimmed_paths!(diag.span_note( |
136023e0 | 923 | tcx.hir().body(body_id).value.span, |
9c376795 FG |
924 | &format!("however, the inferred type `{ty}` cannot be named"), |
925 | )); | |
136023e0 | 926 | } |
74b04a01 | 927 | } |
6a06907d | 928 | |
74b04a01 XL |
929 | diag.emit(); |
930 | } | |
931 | } | |
932 | ||
ba9703b0 | 933 | // Typeck doesn't expect erased regions to be returned from `type_of`. |
064997fb | 934 | tcx.fold_regions(ty, |r, _| match *r { |
ba9703b0 XL |
935 | ty::ReErased => tcx.lifetimes.re_static, |
936 | _ => r, | |
937 | }) | |
74b04a01 XL |
938 | } |
939 | ||
6a06907d XL |
940 | fn check_feature_inherent_assoc_ty(tcx: TyCtxt<'_>, span: Span) { |
941 | if !tcx.features().inherent_associated_types { | |
942 | use rustc_session::parse::feature_err; | |
943 | use rustc_span::symbol::sym; | |
944 | feature_err( | |
945 | &tcx.sess.parse_sess, | |
946 | sym::inherent_associated_types, | |
947 | span, | |
948 | "inherent associated types are unstable", | |
949 | ) | |
950 | .emit(); | |
951 | } | |
74b04a01 | 952 | } |