]>
Commit | Line | Data |
---|---|---|
9ffffee4 | 1 | use crate::middle::resolve_bound_vars as rbv; |
2b03887a FG |
2 | use hir::{ |
3 | intravisit::{self, Visitor}, | |
4 | GenericParamKind, HirId, Node, | |
5 | }; | |
6 | use rustc_hir as hir; | |
7 | use rustc_hir::def::DefKind; | |
353b0b11 | 8 | use rustc_hir::def_id::LocalDefId; |
2b03887a FG |
9 | use rustc_middle::ty::{self, TyCtxt}; |
10 | use rustc_session::lint; | |
11 | use rustc_span::symbol::{kw, Symbol}; | |
fe692bf9 | 12 | use rustc_span::{sym, Span}; |
2b03887a | 13 | |
353b0b11 | 14 | pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { |
2b03887a FG |
15 | use rustc_hir::*; |
16 | ||
353b0b11 | 17 | let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); |
2b03887a FG |
18 | |
19 | let node = tcx.hir().get(hir_id); | |
20 | let parent_def_id = match node { | |
21 | Node::ImplItem(_) | |
22 | | Node::TraitItem(_) | |
23 | | Node::Variant(_) | |
24 | | Node::Ctor(..) | |
25 | | Node::Field(_) => { | |
26 | let parent_id = tcx.hir().get_parent_item(hir_id); | |
27 | Some(parent_id.to_def_id()) | |
28 | } | |
29 | // FIXME(#43408) always enable this once `lazy_normalization` is | |
30 | // stable enough and does not need a feature gate anymore. | |
31 | Node::AnonConst(_) => { | |
32 | let parent_def_id = tcx.hir().get_parent_item(hir_id); | |
33 | ||
34 | let mut in_param_ty = false; | |
35 | for (_parent, node) in tcx.hir().parent_iter(hir_id) { | |
36 | if let Some(generics) = node.generics() { | |
37 | let mut visitor = AnonConstInParamTyDetector { | |
38 | in_param_ty: false, | |
39 | found_anon_const_in_param_ty: false, | |
40 | ct: hir_id, | |
41 | }; | |
42 | ||
43 | visitor.visit_generics(generics); | |
44 | in_param_ty = visitor.found_anon_const_in_param_ty; | |
45 | break; | |
46 | } | |
47 | } | |
48 | ||
49 | if in_param_ty { | |
50 | // We do not allow generic parameters in anon consts if we are inside | |
51 | // of a const parameter type, e.g. `struct Foo<const N: usize, const M: [u8; N]>` is not allowed. | |
52 | None | |
fe692bf9 | 53 | } else if tcx.features().generic_const_exprs { |
49aad941 FG |
54 | let parent_node = tcx.hir().get_parent(hir_id); |
55 | if let Node::Variant(Variant { disr_expr: Some(constant), .. }) = parent_node | |
56 | && constant.hir_id == hir_id | |
57 | { | |
58 | // enum variant discriminants are not allowed to use any kind of generics | |
59 | None | |
60 | } else if let Some(param_id) = | |
61 | tcx.hir().opt_const_param_default_param_def_id(hir_id) | |
62 | { | |
2b03887a FG |
63 | // If the def_id we are calling generics_of on is an anon ct default i.e: |
64 | // | |
65 | // struct Foo<const N: usize = { .. }>; | |
66 | // ^^^ ^ ^^^^^^ def id of this anon const | |
67 | // ^ ^ param_id | |
68 | // ^ parent_def_id | |
69 | // | |
70 | // then we only want to return generics for params to the left of `N`. If we don't do that we | |
add651ee | 71 | // end up with that const looking like: `ty::ConstKind::Unevaluated(def_id, args: [N#0])`. |
2b03887a | 72 | // |
add651ee FG |
73 | // This causes ICEs (#86580) when building the args for Foo in `fn foo() -> Foo { .. }` as |
74 | // we substitute the defaults with the partially built args when we build the args. Subst'ing | |
75 | // the `N#0` on the unevaluated const indexes into the empty args we're in the process of building. | |
2b03887a FG |
76 | // |
77 | // We fix this by having this function return the parent's generics ourselves and truncating the | |
78 | // generics to only include non-forward declared params (with the exception of the `Self` ty) | |
79 | // | |
add651ee FG |
80 | // For the above code example that means we want `args: []` |
81 | // For the following struct def we want `args: [N#0]` when generics_of is called on | |
2b03887a FG |
82 | // the def id of the `{ N + 1 }` anon const |
83 | // struct Foo<const N: usize, const M: usize = { N + 1 }>; | |
84 | // | |
85 | // This has some implications for how we get the predicates available to the anon const | |
86 | // see `explicit_predicates_of` for more information on this | |
87 | let generics = tcx.generics_of(parent_def_id.to_def_id()); | |
487cf647 | 88 | let param_def_idx = generics.param_def_id_to_index[¶m_id.to_def_id()]; |
2b03887a | 89 | // In the above example this would be .params[..N#0] |
9c376795 | 90 | let params = generics.params_to(param_def_idx as usize, tcx).to_owned(); |
2b03887a FG |
91 | let param_def_id_to_index = |
92 | params.iter().map(|param| (param.def_id, param.index)).collect(); | |
93 | ||
94 | return ty::Generics { | |
95 | // we set the parent of these generics to be our parent's parent so that we | |
add651ee | 96 | // dont end up with args: [N, M, N] for the const default on a struct like this: |
2b03887a FG |
97 | // struct Foo<const N: usize, const M: usize = { ... }>; |
98 | parent: generics.parent, | |
99 | parent_count: generics.parent_count, | |
100 | params, | |
101 | param_def_id_to_index, | |
102 | has_self: generics.has_self, | |
103 | has_late_bound_regions: generics.has_late_bound_regions, | |
fe692bf9 | 104 | host_effect_index: None, |
2b03887a | 105 | }; |
49aad941 FG |
106 | } else { |
107 | // HACK(eddyb) this provides the correct generics when | |
108 | // `feature(generic_const_expressions)` is enabled, so that const expressions | |
109 | // used with const generics, e.g. `Foo<{N+1}>`, can work at all. | |
110 | // | |
111 | // Note that we do not supply the parent generics when using | |
112 | // `min_const_generics`. | |
113 | Some(parent_def_id.to_def_id()) | |
2b03887a | 114 | } |
2b03887a | 115 | } else { |
9c376795 | 116 | let parent_node = tcx.hir().get_parent(hir_id); |
2b03887a FG |
117 | match parent_node { |
118 | // HACK(eddyb) this provides the correct generics for repeat | |
119 | // expressions' count (i.e. `N` in `[x; N]`), and explicit | |
120 | // `enum` discriminants (i.e. `D` in `enum Foo { Bar = D }`), | |
121 | // as they shouldn't be able to cause query cycle errors. | |
9c376795 | 122 | Node::Expr(Expr { kind: ExprKind::Repeat(_, constant), .. }) |
2b03887a FG |
123 | if constant.hir_id() == hir_id => |
124 | { | |
125 | Some(parent_def_id.to_def_id()) | |
126 | } | |
2b03887a FG |
127 | // Exclude `GlobalAsm` here which cannot have generics. |
128 | Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. }) | |
129 | if asm.operands.iter().any(|(op, _op_sp)| match op { | |
130 | hir::InlineAsmOperand::Const { anon_const } | |
131 | | hir::InlineAsmOperand::SymFn { anon_const } => { | |
132 | anon_const.hir_id == hir_id | |
133 | } | |
134 | _ => false, | |
135 | }) => | |
136 | { | |
137 | Some(parent_def_id.to_def_id()) | |
138 | } | |
139 | _ => None, | |
140 | } | |
141 | } | |
142 | } | |
fe692bf9 FG |
143 | Node::ConstBlock(_) |
144 | | Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure { .. }, .. }) => { | |
353b0b11 | 145 | Some(tcx.typeck_root_def_id(def_id.to_def_id())) |
2b03887a FG |
146 | } |
147 | Node::Item(item) => match item.kind { | |
fe692bf9 | 148 | ItemKind::OpaqueTy(&hir::OpaqueTy { |
2b03887a FG |
149 | origin: |
150 | hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id), | |
151 | in_trait, | |
152 | .. | |
153 | }) => { | |
154 | if in_trait { | |
155 | assert!(matches!(tcx.def_kind(fn_def_id), DefKind::AssocFn)) | |
156 | } else { | |
157 | assert!(matches!(tcx.def_kind(fn_def_id), DefKind::AssocFn | DefKind::Fn)) | |
158 | } | |
159 | Some(fn_def_id.to_def_id()) | |
160 | } | |
49aad941 FG |
161 | ItemKind::OpaqueTy(hir::OpaqueTy { |
162 | origin: hir::OpaqueTyOrigin::TyAlias { .. }, | |
163 | .. | |
164 | }) => { | |
2b03887a FG |
165 | let parent_id = tcx.hir().get_parent_item(hir_id); |
166 | assert_ne!(parent_id, hir::CRATE_OWNER_ID); | |
167 | debug!("generics_of: parent of opaque ty {:?} is {:?}", def_id, parent_id); | |
168 | // Opaque types are always nested within another item, and | |
169 | // inherit the generics of the item. | |
170 | Some(parent_id.to_def_id()) | |
171 | } | |
172 | _ => None, | |
173 | }, | |
174 | _ => None, | |
175 | }; | |
176 | ||
177 | enum Defaults { | |
178 | Allowed, | |
179 | // See #36887 | |
180 | FutureCompatDisallowed, | |
181 | Deny, | |
182 | } | |
183 | ||
184 | let no_generics = hir::Generics::empty(); | |
185 | let ast_generics = node.generics().unwrap_or(&no_generics); | |
186 | let (opt_self, allow_defaults) = match node { | |
187 | Node::Item(item) => { | |
188 | match item.kind { | |
189 | ItemKind::Trait(..) | ItemKind::TraitAlias(..) => { | |
190 | // Add in the self type parameter. | |
191 | // | |
192 | // Something of a hack: use the node id for the trait, also as | |
193 | // the node id for the Self type parameter. | |
194 | let opt_self = Some(ty::GenericParamDef { | |
195 | index: 0, | |
196 | name: kw::SelfUpper, | |
353b0b11 | 197 | def_id: def_id.to_def_id(), |
2b03887a FG |
198 | pure_wrt_drop: false, |
199 | kind: ty::GenericParamDefKind::Type { | |
200 | has_default: false, | |
201 | synthetic: false, | |
202 | }, | |
203 | }); | |
204 | ||
205 | (opt_self, Defaults::Allowed) | |
206 | } | |
207 | ItemKind::TyAlias(..) | |
208 | | ItemKind::Enum(..) | |
209 | | ItemKind::Struct(..) | |
210 | | ItemKind::OpaqueTy(..) | |
211 | | ItemKind::Union(..) => (None, Defaults::Allowed), | |
add651ee | 212 | ItemKind::Const(..) => (None, Defaults::Deny), |
2b03887a FG |
213 | _ => (None, Defaults::FutureCompatDisallowed), |
214 | } | |
215 | } | |
216 | ||
217 | // GATs | |
218 | Node::TraitItem(item) if matches!(item.kind, TraitItemKind::Type(..)) => { | |
219 | (None, Defaults::Deny) | |
220 | } | |
221 | Node::ImplItem(item) if matches!(item.kind, ImplItemKind::Type(..)) => { | |
222 | (None, Defaults::Deny) | |
223 | } | |
224 | ||
225 | _ => (None, Defaults::FutureCompatDisallowed), | |
226 | }; | |
227 | ||
228 | let has_self = opt_self.is_some(); | |
229 | let mut parent_has_self = false; | |
230 | let mut own_start = has_self as u32; | |
fe692bf9 | 231 | let mut host_effect_index = None; |
2b03887a FG |
232 | let parent_count = parent_def_id.map_or(0, |def_id| { |
233 | let generics = tcx.generics_of(def_id); | |
234 | assert!(!has_self); | |
235 | parent_has_self = generics.has_self; | |
fe692bf9 | 236 | host_effect_index = generics.host_effect_index; |
2b03887a FG |
237 | own_start = generics.count() as u32; |
238 | generics.parent_count + generics.params.len() | |
239 | }); | |
240 | ||
241 | let mut params: Vec<_> = Vec::with_capacity(ast_generics.params.len() + has_self as usize); | |
242 | ||
243 | if let Some(opt_self) = opt_self { | |
244 | params.push(opt_self); | |
245 | } | |
246 | ||
247 | let early_lifetimes = super::early_bound_lifetimes_from_generics(tcx, ast_generics); | |
248 | params.extend(early_lifetimes.enumerate().map(|(i, param)| ty::GenericParamDef { | |
249 | name: param.name.ident().name, | |
250 | index: own_start + i as u32, | |
487cf647 | 251 | def_id: param.def_id.to_def_id(), |
2b03887a FG |
252 | pure_wrt_drop: param.pure_wrt_drop, |
253 | kind: ty::GenericParamDefKind::Lifetime, | |
254 | })); | |
255 | ||
256 | // Now create the real type and const parameters. | |
257 | let type_start = own_start - has_self as u32 + params.len() as u32; | |
fe692bf9 | 258 | let mut i: u32 = 0; |
2b03887a FG |
259 | let mut next_index = || { |
260 | let prev = i; | |
261 | i += 1; | |
fe692bf9 | 262 | prev + type_start |
2b03887a FG |
263 | }; |
264 | ||
265 | const TYPE_DEFAULT_NOT_ALLOWED: &'static str = "defaults for type parameters are only allowed in \ | |
266 | `struct`, `enum`, `type`, or `trait` definitions"; | |
267 | ||
268 | params.extend(ast_generics.params.iter().filter_map(|param| match param.kind { | |
269 | GenericParamKind::Lifetime { .. } => None, | |
9c376795 | 270 | GenericParamKind::Type { default, synthetic, .. } => { |
2b03887a FG |
271 | if default.is_some() { |
272 | match allow_defaults { | |
273 | Defaults::Allowed => {} | |
274 | Defaults::FutureCompatDisallowed | |
275 | if tcx.features().default_type_parameter_fallback => {} | |
276 | Defaults::FutureCompatDisallowed => { | |
277 | tcx.struct_span_lint_hir( | |
278 | lint::builtin::INVALID_TYPE_PARAM_DEFAULT, | |
279 | param.hir_id, | |
280 | param.span, | |
281 | TYPE_DEFAULT_NOT_ALLOWED, | |
282 | |lint| lint, | |
283 | ); | |
284 | } | |
285 | Defaults::Deny => { | |
286 | tcx.sess.span_err(param.span, TYPE_DEFAULT_NOT_ALLOWED); | |
287 | } | |
288 | } | |
289 | } | |
290 | ||
291 | let kind = ty::GenericParamDefKind::Type { has_default: default.is_some(), synthetic }; | |
292 | ||
293 | Some(ty::GenericParamDef { | |
294 | index: next_index(), | |
295 | name: param.name.ident().name, | |
487cf647 | 296 | def_id: param.def_id.to_def_id(), |
2b03887a FG |
297 | pure_wrt_drop: param.pure_wrt_drop, |
298 | kind, | |
299 | }) | |
300 | } | |
301 | GenericParamKind::Const { default, .. } => { | |
fe692bf9 FG |
302 | let is_host_param = tcx.has_attr(param.def_id, sym::rustc_host); |
303 | ||
304 | if !matches!(allow_defaults, Defaults::Allowed) | |
305 | && default.is_some() | |
306 | // `rustc_host` effect params are allowed to have defaults. | |
307 | && !is_host_param | |
308 | { | |
2b03887a FG |
309 | tcx.sess.span_err( |
310 | param.span, | |
311 | "defaults for const parameters are only allowed in \ | |
312 | `struct`, `enum`, `type`, or `trait` definitions", | |
313 | ); | |
314 | } | |
315 | ||
fe692bf9 FG |
316 | let index = next_index(); |
317 | ||
318 | if is_host_param { | |
319 | if let Some(idx) = host_effect_index { | |
320 | bug!("parent also has host effect param? index: {idx}, def: {def_id:?}"); | |
321 | } | |
322 | ||
add651ee | 323 | host_effect_index = Some(index as usize); |
fe692bf9 FG |
324 | } |
325 | ||
2b03887a | 326 | Some(ty::GenericParamDef { |
fe692bf9 | 327 | index, |
2b03887a | 328 | name: param.name.ident().name, |
487cf647 | 329 | def_id: param.def_id.to_def_id(), |
2b03887a | 330 | pure_wrt_drop: param.pure_wrt_drop, |
781aab86 FG |
331 | kind: ty::GenericParamDefKind::Const { |
332 | has_default: default.is_some(), | |
333 | is_host_effect: is_host_param, | |
334 | }, | |
2b03887a FG |
335 | }) |
336 | } | |
337 | })); | |
338 | ||
339 | // provide junk type parameter defs - the only place that | |
340 | // cares about anything but the length is instantiation, | |
341 | // and we don't do that for closures. | |
342 | if let Node::Expr(&hir::Expr { | |
343 | kind: hir::ExprKind::Closure(hir::Closure { movability: gen, .. }), | |
344 | .. | |
345 | }) = node | |
346 | { | |
347 | let dummy_args = if gen.is_some() { | |
348 | &["<resume_ty>", "<yield_ty>", "<return_ty>", "<witness>", "<upvars>"][..] | |
349 | } else { | |
350 | &["<closure_kind>", "<closure_signature>", "<upvars>"][..] | |
351 | }; | |
352 | ||
353 | params.extend(dummy_args.iter().map(|&arg| ty::GenericParamDef { | |
354 | index: next_index(), | |
355 | name: Symbol::intern(arg), | |
353b0b11 | 356 | def_id: def_id.to_def_id(), |
2b03887a FG |
357 | pure_wrt_drop: false, |
358 | kind: ty::GenericParamDefKind::Type { has_default: false, synthetic: false }, | |
359 | })); | |
360 | } | |
361 | ||
362 | // provide junk type parameter defs for const blocks. | |
fe692bf9 FG |
363 | if let Node::ConstBlock(_) = node { |
364 | params.push(ty::GenericParamDef { | |
365 | index: next_index(), | |
366 | name: Symbol::intern("<const_ty>"), | |
367 | def_id: def_id.to_def_id(), | |
368 | pure_wrt_drop: false, | |
369 | kind: ty::GenericParamDefKind::Type { has_default: false, synthetic: false }, | |
370 | }); | |
2b03887a FG |
371 | } |
372 | ||
373 | let param_def_id_to_index = params.iter().map(|param| (param.def_id, param.index)).collect(); | |
374 | ||
375 | ty::Generics { | |
376 | parent: parent_def_id, | |
377 | parent_count, | |
378 | params, | |
379 | param_def_id_to_index, | |
380 | has_self: has_self || parent_has_self, | |
381 | has_late_bound_regions: has_late_bound_regions(tcx, node), | |
fe692bf9 | 382 | host_effect_index, |
2b03887a FG |
383 | } |
384 | } | |
385 | ||
386 | fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option<Span> { | |
387 | struct LateBoundRegionsDetector<'tcx> { | |
388 | tcx: TyCtxt<'tcx>, | |
389 | outer_index: ty::DebruijnIndex, | |
390 | has_late_bound_regions: Option<Span>, | |
391 | } | |
392 | ||
393 | impl<'tcx> Visitor<'tcx> for LateBoundRegionsDetector<'tcx> { | |
394 | fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) { | |
395 | if self.has_late_bound_regions.is_some() { | |
396 | return; | |
397 | } | |
398 | match ty.kind { | |
399 | hir::TyKind::BareFn(..) => { | |
400 | self.outer_index.shift_in(1); | |
401 | intravisit::walk_ty(self, ty); | |
402 | self.outer_index.shift_out(1); | |
403 | } | |
404 | _ => intravisit::walk_ty(self, ty), | |
405 | } | |
406 | } | |
407 | ||
408 | fn visit_poly_trait_ref(&mut self, tr: &'tcx hir::PolyTraitRef<'tcx>) { | |
409 | if self.has_late_bound_regions.is_some() { | |
410 | return; | |
411 | } | |
412 | self.outer_index.shift_in(1); | |
413 | intravisit::walk_poly_trait_ref(self, tr); | |
414 | self.outer_index.shift_out(1); | |
415 | } | |
416 | ||
417 | fn visit_lifetime(&mut self, lt: &'tcx hir::Lifetime) { | |
418 | if self.has_late_bound_regions.is_some() { | |
419 | return; | |
420 | } | |
421 | ||
9ffffee4 FG |
422 | match self.tcx.named_bound_var(lt.hir_id) { |
423 | Some(rbv::ResolvedArg::StaticLifetime | rbv::ResolvedArg::EarlyBound(..)) => {} | |
424 | Some(rbv::ResolvedArg::LateBound(debruijn, _, _)) | |
425 | if debruijn < self.outer_index => {} | |
426 | Some( | |
427 | rbv::ResolvedArg::LateBound(..) | |
428 | | rbv::ResolvedArg::Free(..) | |
429 | | rbv::ResolvedArg::Error(_), | |
430 | ) | |
431 | | None => { | |
487cf647 | 432 | self.has_late_bound_regions = Some(lt.ident.span); |
2b03887a FG |
433 | } |
434 | } | |
435 | } | |
436 | } | |
437 | ||
438 | fn has_late_bound_regions<'tcx>( | |
439 | tcx: TyCtxt<'tcx>, | |
440 | generics: &'tcx hir::Generics<'tcx>, | |
441 | decl: &'tcx hir::FnDecl<'tcx>, | |
442 | ) -> Option<Span> { | |
443 | let mut visitor = LateBoundRegionsDetector { | |
444 | tcx, | |
445 | outer_index: ty::INNERMOST, | |
446 | has_late_bound_regions: None, | |
447 | }; | |
448 | for param in generics.params { | |
449 | if let GenericParamKind::Lifetime { .. } = param.kind { | |
450 | if tcx.is_late_bound(param.hir_id) { | |
451 | return Some(param.span); | |
452 | } | |
453 | } | |
454 | } | |
455 | visitor.visit_fn_decl(decl); | |
456 | visitor.has_late_bound_regions | |
457 | } | |
458 | ||
459 | match node { | |
9c376795 FG |
460 | Node::TraitItem(item) => match &item.kind { |
461 | hir::TraitItemKind::Fn(sig, _) => has_late_bound_regions(tcx, &item.generics, sig.decl), | |
2b03887a FG |
462 | _ => None, |
463 | }, | |
9c376795 FG |
464 | Node::ImplItem(item) => match &item.kind { |
465 | hir::ImplItemKind::Fn(sig, _) => has_late_bound_regions(tcx, &item.generics, sig.decl), | |
2b03887a FG |
466 | _ => None, |
467 | }, | |
468 | Node::ForeignItem(item) => match item.kind { | |
9c376795 | 469 | hir::ForeignItemKind::Fn(fn_decl, _, generics) => { |
2b03887a FG |
470 | has_late_bound_regions(tcx, generics, fn_decl) |
471 | } | |
472 | _ => None, | |
473 | }, | |
9c376795 FG |
474 | Node::Item(item) => match &item.kind { |
475 | hir::ItemKind::Fn(sig, .., generics, _) => { | |
2b03887a FG |
476 | has_late_bound_regions(tcx, generics, sig.decl) |
477 | } | |
478 | _ => None, | |
479 | }, | |
480 | _ => None, | |
481 | } | |
482 | } | |
483 | ||
484 | struct AnonConstInParamTyDetector { | |
485 | in_param_ty: bool, | |
486 | found_anon_const_in_param_ty: bool, | |
487 | ct: HirId, | |
488 | } | |
489 | ||
490 | impl<'v> Visitor<'v> for AnonConstInParamTyDetector { | |
491 | fn visit_generic_param(&mut self, p: &'v hir::GenericParam<'v>) { | |
492 | if let GenericParamKind::Const { ty, default: _ } = p.kind { | |
493 | let prev = self.in_param_ty; | |
494 | self.in_param_ty = true; | |
495 | self.visit_ty(ty); | |
496 | self.in_param_ty = prev; | |
497 | } | |
498 | } | |
499 | ||
500 | fn visit_anon_const(&mut self, c: &'v hir::AnonConst) { | |
501 | if self.in_param_ty && self.ct == c.hir_id { | |
502 | self.found_anon_const_in_param_ty = true; | |
503 | } else { | |
504 | intravisit::walk_anon_const(self, c) | |
505 | } | |
506 | } | |
507 | } |