]>
Commit | Line | Data |
---|---|---|
2b03887a FG |
1 | use crate::astconv::AstConv; |
2 | use crate::bounds::Bounds; | |
3 | use crate::collect::ItemCtxt; | |
4 | use crate::constrained_generic_params as cgp; | |
5 | use hir::{HirId, Node}; | |
6 | use rustc_data_structures::fx::FxIndexSet; | |
7 | use rustc_hir as hir; | |
8 | use rustc_hir::def::DefKind; | |
9 | use rustc_hir::def_id::{DefId, LocalDefId}; | |
10 | use rustc_hir::intravisit::{self, Visitor}; | |
11 | use rustc_middle::ty::subst::InternalSubsts; | |
12 | use rustc_middle::ty::ToPredicate; | |
13 | use rustc_middle::ty::{self, Ty, TyCtxt}; | |
14 | use rustc_span::symbol::{sym, Ident}; | |
15 | use rustc_span::{Span, DUMMY_SP}; | |
16 | ||
17 | #[derive(Debug)] | |
18 | struct OnlySelfBounds(bool); | |
19 | ||
20 | /// Returns a list of all type predicates (explicit and implicit) for the definition with | |
21 | /// ID `def_id`. This includes all predicates returned by `predicates_defined_on`, plus | |
22 | /// `Self: Trait` predicates for traits. | |
23 | pub(super) fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> { | |
24 | let mut result = tcx.predicates_defined_on(def_id); | |
25 | ||
26 | if tcx.is_trait(def_id) { | |
27 | // For traits, add `Self: Trait` predicate. This is | |
28 | // not part of the predicates that a user writes, but it | |
29 | // is something that one must prove in order to invoke a | |
30 | // method or project an associated type. | |
31 | // | |
32 | // In the chalk setup, this predicate is not part of the | |
33 | // "predicates" for a trait item. But it is useful in | |
34 | // rustc because if you directly (e.g.) invoke a trait | |
35 | // method like `Trait::method(...)`, you must naturally | |
36 | // prove that the trait applies to the types that were | |
37 | // used, and adding the predicate into this list ensures | |
38 | // that this is done. | |
39 | // | |
40 | // We use a DUMMY_SP here as a way to signal trait bounds that come | |
41 | // from the trait itself that *shouldn't* be shown as the source of | |
42 | // an obligation and instead be skipped. Otherwise we'd use | |
43 | // `tcx.def_span(def_id);` | |
44 | ||
45 | let constness = if tcx.has_attr(def_id, sym::const_trait) { | |
46 | ty::BoundConstness::ConstIfConst | |
47 | } else { | |
48 | ty::BoundConstness::NotConst | |
49 | }; | |
50 | ||
51 | let span = rustc_span::DUMMY_SP; | |
52 | result.predicates = | |
53 | tcx.arena.alloc_from_iter(result.predicates.iter().copied().chain(std::iter::once(( | |
54 | ty::TraitRef::identity(tcx, def_id).with_constness(constness).to_predicate(tcx), | |
55 | span, | |
56 | )))); | |
57 | } | |
58 | debug!("predicates_of(def_id={:?}) = {:?}", def_id, result); | |
59 | result | |
60 | } | |
61 | ||
62 | /// Returns a list of user-specified type predicates for the definition with ID `def_id`. | |
63 | /// N.B., this does not include any implied/inferred constraints. | |
64 | #[instrument(level = "trace", skip(tcx), ret)] | |
65 | fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> { | |
66 | use rustc_hir::*; | |
67 | ||
68 | let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); | |
69 | let node = tcx.hir().get(hir_id); | |
70 | ||
71 | let mut is_trait = None; | |
72 | let mut is_default_impl_trait = None; | |
73 | ||
74 | let icx = ItemCtxt::new(tcx, def_id); | |
75 | ||
76 | const NO_GENERICS: &hir::Generics<'_> = hir::Generics::empty(); | |
77 | ||
78 | // We use an `IndexSet` to preserves order of insertion. | |
79 | // Preserving the order of insertion is important here so as not to break UI tests. | |
80 | let mut predicates: FxIndexSet<(ty::Predicate<'_>, Span)> = FxIndexSet::default(); | |
81 | ||
82 | let ast_generics = match node { | |
83 | Node::TraitItem(item) => item.generics, | |
84 | ||
85 | Node::ImplItem(item) => item.generics, | |
86 | ||
487cf647 FG |
87 | Node::Item(item) => match item.kind { |
88 | ItemKind::Impl(ref impl_) => { | |
89 | if impl_.defaultness.is_default() { | |
90 | is_default_impl_trait = tcx.impl_trait_ref(def_id).map(ty::Binder::dummy); | |
2b03887a | 91 | } |
487cf647 | 92 | &impl_.generics |
2b03887a | 93 | } |
487cf647 FG |
94 | ItemKind::Fn(.., ref generics, _) |
95 | | ItemKind::TyAlias(_, ref generics) | |
96 | | ItemKind::Enum(_, ref generics) | |
97 | | ItemKind::Struct(_, ref generics) | |
98 | | ItemKind::Union(_, ref generics) => *generics, | |
99 | ||
100 | ItemKind::Trait(_, _, ref generics, ..) => { | |
101 | is_trait = Some(ty::TraitRef::identity(tcx, def_id)); | |
102 | *generics | |
103 | } | |
104 | ItemKind::TraitAlias(ref generics, _) => { | |
105 | is_trait = Some(ty::TraitRef::identity(tcx, def_id)); | |
106 | *generics | |
107 | } | |
108 | ItemKind::OpaqueTy(OpaqueTy { ref generics, .. }) => generics, | |
109 | _ => NO_GENERICS, | |
110 | }, | |
2b03887a FG |
111 | |
112 | Node::ForeignItem(item) => match item.kind { | |
113 | ForeignItemKind::Static(..) => NO_GENERICS, | |
114 | ForeignItemKind::Fn(_, _, ref generics) => *generics, | |
115 | ForeignItemKind::Type => NO_GENERICS, | |
116 | }, | |
117 | ||
118 | _ => NO_GENERICS, | |
119 | }; | |
120 | ||
121 | let generics = tcx.generics_of(def_id); | |
122 | let parent_count = generics.parent_count as u32; | |
123 | let has_own_self = generics.has_self && parent_count == 0; | |
124 | ||
125 | // Below we'll consider the bounds on the type parameters (including `Self`) | |
126 | // and the explicit where-clauses, but to get the full set of predicates | |
127 | // on a trait we need to add in the supertrait bounds and bounds found on | |
128 | // associated types. | |
129 | if let Some(_trait_ref) = is_trait { | |
130 | predicates.extend(tcx.super_predicates_of(def_id).predicates.iter().cloned()); | |
131 | } | |
132 | ||
133 | // In default impls, we can assume that the self type implements | |
134 | // the trait. So in: | |
135 | // | |
136 | // default impl Foo for Bar { .. } | |
137 | // | |
138 | // we add a default where clause `Foo: Bar`. We do a similar thing for traits | |
139 | // (see below). Recall that a default impl is not itself an impl, but rather a | |
140 | // set of defaults that can be incorporated into another impl. | |
141 | if let Some(trait_ref) = is_default_impl_trait { | |
142 | predicates.insert((trait_ref.without_const().to_predicate(tcx), tcx.def_span(def_id))); | |
143 | } | |
144 | ||
145 | // Collect the region predicates that were declared inline as | |
146 | // well. In the case of parameters declared on a fn or method, we | |
147 | // have to be careful to only iterate over early-bound regions. | |
148 | let mut index = parent_count | |
149 | + has_own_self as u32 | |
150 | + super::early_bound_lifetimes_from_generics(tcx, ast_generics).count() as u32; | |
151 | ||
152 | trace!(?predicates); | |
153 | trace!(?ast_generics); | |
487cf647 | 154 | trace!(?generics); |
2b03887a FG |
155 | |
156 | // Collect the predicates that were written inline by the user on each | |
157 | // type parameter (e.g., `<T: Foo>`). | |
158 | for param in ast_generics.params { | |
159 | match param.kind { | |
160 | // We already dealt with early bound lifetimes above. | |
161 | GenericParamKind::Lifetime { .. } => (), | |
162 | GenericParamKind::Type { .. } => { | |
163 | let name = param.name.ident().name; | |
164 | let param_ty = ty::ParamTy::new(index, name).to_ty(tcx); | |
165 | index += 1; | |
166 | ||
167 | let mut bounds = Bounds::default(); | |
168 | // Params are implicitly sized unless a `?Sized` bound is found | |
169 | <dyn AstConv<'_>>::add_implicitly_sized( | |
170 | &icx, | |
171 | &mut bounds, | |
172 | &[], | |
487cf647 | 173 | Some((param.def_id, ast_generics.predicates)), |
2b03887a FG |
174 | param.span, |
175 | ); | |
176 | trace!(?bounds); | |
177 | predicates.extend(bounds.predicates(tcx, param_ty)); | |
178 | trace!(?predicates); | |
179 | } | |
180 | GenericParamKind::Const { .. } => { | |
181 | // Bounds on const parameters are currently not possible. | |
182 | index += 1; | |
183 | } | |
184 | } | |
185 | } | |
186 | ||
187 | trace!(?predicates); | |
188 | // Add in the bounds that appear in the where-clause. | |
189 | for predicate in ast_generics.predicates { | |
190 | match predicate { | |
191 | hir::WherePredicate::BoundPredicate(bound_pred) => { | |
192 | let ty = icx.to_ty(bound_pred.bounded_ty); | |
193 | let bound_vars = icx.tcx.late_bound_vars(bound_pred.hir_id); | |
194 | ||
195 | // Keep the type around in a dummy predicate, in case of no bounds. | |
196 | // That way, `where Ty:` is not a complete noop (see #53696) and `Ty` | |
197 | // is still checked for WF. | |
198 | if bound_pred.bounds.is_empty() { | |
199 | if let ty::Param(_) = ty.kind() { | |
200 | // This is a `where T:`, which can be in the HIR from the | |
201 | // transformation that moves `?Sized` to `T`'s declaration. | |
202 | // We can skip the predicate because type parameters are | |
203 | // trivially WF, but also we *should*, to avoid exposing | |
204 | // users who never wrote `where Type:,` themselves, to | |
205 | // compiler/tooling bugs from not handling WF predicates. | |
206 | } else { | |
207 | let span = bound_pred.bounded_ty.span; | |
208 | let predicate = ty::Binder::bind_with_vars( | |
209 | ty::PredicateKind::WellFormed(ty.into()), | |
210 | bound_vars, | |
211 | ); | |
212 | predicates.insert((predicate.to_predicate(tcx), span)); | |
213 | } | |
214 | } | |
215 | ||
216 | let mut bounds = Bounds::default(); | |
217 | <dyn AstConv<'_>>::add_bounds( | |
218 | &icx, | |
219 | ty, | |
220 | bound_pred.bounds.iter(), | |
221 | &mut bounds, | |
222 | bound_vars, | |
223 | ); | |
224 | predicates.extend(bounds.predicates(tcx, ty)); | |
225 | } | |
226 | ||
227 | hir::WherePredicate::RegionPredicate(region_pred) => { | |
228 | let r1 = <dyn AstConv<'_>>::ast_region_to_region(&icx, ®ion_pred.lifetime, None); | |
229 | predicates.extend(region_pred.bounds.iter().map(|bound| { | |
230 | let (r2, span) = match bound { | |
231 | hir::GenericBound::Outlives(lt) => { | |
487cf647 | 232 | (<dyn AstConv<'_>>::ast_region_to_region(&icx, lt, None), lt.ident.span) |
2b03887a FG |
233 | } |
234 | _ => bug!(), | |
235 | }; | |
487cf647 FG |
236 | let pred = ty::Binder::dummy(ty::PredicateKind::Clause( |
237 | ty::Clause::RegionOutlives(ty::OutlivesPredicate(r1, r2)), | |
2b03887a FG |
238 | )) |
239 | .to_predicate(icx.tcx); | |
240 | ||
241 | (pred, span) | |
242 | })) | |
243 | } | |
244 | ||
245 | hir::WherePredicate::EqPredicate(..) => { | |
246 | // FIXME(#20041) | |
247 | } | |
248 | } | |
249 | } | |
250 | ||
251 | if tcx.features().generic_const_exprs { | |
252 | predicates.extend(const_evaluatable_predicates_of(tcx, def_id.expect_local())); | |
253 | } | |
254 | ||
255 | let mut predicates: Vec<_> = predicates.into_iter().collect(); | |
256 | ||
257 | // Subtle: before we store the predicates into the tcx, we | |
258 | // sort them so that predicates like `T: Foo<Item=U>` come | |
259 | // before uses of `U`. This avoids false ambiguity errors | |
260 | // in trait checking. See `setup_constraining_predicates` | |
261 | // for details. | |
262 | if let Node::Item(&Item { kind: ItemKind::Impl { .. }, .. }) = node { | |
263 | let self_ty = tcx.type_of(def_id); | |
264 | let trait_ref = tcx.impl_trait_ref(def_id); | |
265 | cgp::setup_constraining_predicates( | |
266 | tcx, | |
267 | &mut predicates, | |
268 | trait_ref, | |
269 | &mut cgp::parameters_for_impl(self_ty, trait_ref), | |
270 | ); | |
271 | } | |
272 | ||
487cf647 FG |
273 | // Opaque types duplicate some of their generic parameters. |
274 | // We create bi-directional Outlives predicates between the original | |
275 | // and the duplicated parameter, to ensure that they do not get out of sync. | |
276 | if let Node::Item(&Item { kind: ItemKind::OpaqueTy(..), .. }) = node { | |
277 | let opaque_ty_id = tcx.hir().get_parent_node(hir_id); | |
278 | let opaque_ty_node = tcx.hir().get(opaque_ty_id); | |
279 | let Node::Ty(&Ty { kind: TyKind::OpaqueDef(_, lifetimes, _), .. }) = opaque_ty_node else { | |
280 | bug!("unexpected {opaque_ty_node:?}") | |
281 | }; | |
282 | debug!(?lifetimes); | |
283 | for (arg, duplicate) in std::iter::zip(lifetimes, ast_generics.params) { | |
284 | let hir::GenericArg::Lifetime(arg) = arg else { bug!() }; | |
285 | let orig_region = <dyn AstConv<'_>>::ast_region_to_region(&icx, &arg, None); | |
286 | if !matches!(orig_region.kind(), ty::ReEarlyBound(..)) { | |
287 | // Only early-bound regions can point to the original generic parameter. | |
288 | continue; | |
289 | } | |
290 | ||
291 | let hir::GenericParamKind::Lifetime { .. } = duplicate.kind else { continue }; | |
292 | let dup_def = tcx.hir().local_def_id(duplicate.hir_id).to_def_id(); | |
293 | ||
294 | let Some(dup_index) = generics.param_def_id_to_index(tcx, dup_def) else { bug!() }; | |
295 | ||
296 | let dup_region = tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion { | |
297 | def_id: dup_def, | |
298 | index: dup_index, | |
299 | name: duplicate.name.ident().name, | |
300 | })); | |
301 | predicates.push(( | |
302 | ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::RegionOutlives( | |
303 | ty::OutlivesPredicate(orig_region, dup_region), | |
304 | ))) | |
305 | .to_predicate(icx.tcx), | |
306 | duplicate.span, | |
307 | )); | |
308 | predicates.push(( | |
309 | ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::RegionOutlives( | |
310 | ty::OutlivesPredicate(dup_region, orig_region), | |
311 | ))) | |
312 | .to_predicate(icx.tcx), | |
313 | duplicate.span, | |
314 | )); | |
315 | } | |
316 | debug!(?predicates); | |
317 | } | |
318 | ||
2b03887a FG |
319 | ty::GenericPredicates { |
320 | parent: generics.parent, | |
321 | predicates: tcx.arena.alloc_from_iter(predicates), | |
322 | } | |
323 | } | |
324 | ||
325 | fn const_evaluatable_predicates_of<'tcx>( | |
326 | tcx: TyCtxt<'tcx>, | |
327 | def_id: LocalDefId, | |
328 | ) -> FxIndexSet<(ty::Predicate<'tcx>, Span)> { | |
329 | struct ConstCollector<'tcx> { | |
330 | tcx: TyCtxt<'tcx>, | |
331 | preds: FxIndexSet<(ty::Predicate<'tcx>, Span)>, | |
332 | } | |
333 | ||
334 | impl<'tcx> intravisit::Visitor<'tcx> for ConstCollector<'tcx> { | |
335 | fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) { | |
487cf647 | 336 | let ct = ty::Const::from_anon_const(self.tcx, c.def_id); |
2b03887a | 337 | if let ty::ConstKind::Unevaluated(_) = ct.kind() { |
487cf647 | 338 | let span = self.tcx.def_span(c.def_id); |
2b03887a FG |
339 | self.preds.insert(( |
340 | ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(ct)) | |
341 | .to_predicate(self.tcx), | |
342 | span, | |
343 | )); | |
344 | } | |
345 | } | |
346 | ||
347 | fn visit_const_param_default(&mut self, _param: HirId, _ct: &'tcx hir::AnonConst) { | |
348 | // Do not look into const param defaults, | |
349 | // these get checked when they are actually instantiated. | |
350 | // | |
351 | // We do not want the following to error: | |
352 | // | |
353 | // struct Foo<const N: usize, const M: usize = { N + 1 }>; | |
354 | // struct Bar<const N: usize>(Foo<N, 3>); | |
355 | } | |
356 | } | |
357 | ||
358 | let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); | |
359 | let node = tcx.hir().get(hir_id); | |
360 | ||
361 | let mut collector = ConstCollector { tcx, preds: FxIndexSet::default() }; | |
362 | if let hir::Node::Item(item) = node && let hir::ItemKind::Impl(ref impl_) = item.kind { | |
363 | if let Some(of_trait) = &impl_.of_trait { | |
364 | debug!("const_evaluatable_predicates_of({:?}): visit impl trait_ref", def_id); | |
365 | collector.visit_trait_ref(of_trait); | |
366 | } | |
367 | ||
368 | debug!("const_evaluatable_predicates_of({:?}): visit_self_ty", def_id); | |
369 | collector.visit_ty(impl_.self_ty); | |
370 | } | |
371 | ||
372 | if let Some(generics) = node.generics() { | |
373 | debug!("const_evaluatable_predicates_of({:?}): visit_generics", def_id); | |
374 | collector.visit_generics(generics); | |
375 | } | |
376 | ||
377 | if let Some(fn_sig) = tcx.hir().fn_sig_by_hir_id(hir_id) { | |
378 | debug!("const_evaluatable_predicates_of({:?}): visit_fn_decl", def_id); | |
379 | collector.visit_fn_decl(fn_sig.decl); | |
380 | } | |
381 | debug!("const_evaluatable_predicates_of({:?}) = {:?}", def_id, collector.preds); | |
382 | ||
383 | collector.preds | |
384 | } | |
385 | ||
386 | pub(super) fn trait_explicit_predicates_and_bounds( | |
387 | tcx: TyCtxt<'_>, | |
388 | def_id: LocalDefId, | |
389 | ) -> ty::GenericPredicates<'_> { | |
390 | assert_eq!(tcx.def_kind(def_id), DefKind::Trait); | |
391 | gather_explicit_predicates_of(tcx, def_id.to_def_id()) | |
392 | } | |
393 | ||
394 | pub(super) fn explicit_predicates_of<'tcx>( | |
395 | tcx: TyCtxt<'tcx>, | |
396 | def_id: DefId, | |
397 | ) -> ty::GenericPredicates<'tcx> { | |
398 | let def_kind = tcx.def_kind(def_id); | |
399 | if let DefKind::Trait = def_kind { | |
400 | // Remove bounds on associated types from the predicates, they will be | |
401 | // returned by `explicit_item_bounds`. | |
402 | let predicates_and_bounds = tcx.trait_explicit_predicates_and_bounds(def_id.expect_local()); | |
403 | let trait_identity_substs = InternalSubsts::identity_for_item(tcx, def_id); | |
404 | ||
405 | let is_assoc_item_ty = |ty: Ty<'tcx>| { | |
406 | // For a predicate from a where clause to become a bound on an | |
407 | // associated type: | |
408 | // * It must use the identity substs of the item. | |
409 | // * Since any generic parameters on the item are not in scope, | |
410 | // this means that the item is not a GAT, and its identity | |
411 | // substs are the same as the trait's. | |
412 | // * It must be an associated type for this trait (*not* a | |
413 | // supertrait). | |
414 | if let ty::Projection(projection) = ty.kind() { | |
415 | projection.substs == trait_identity_substs | |
416 | && tcx.associated_item(projection.item_def_id).container_id(tcx) == def_id | |
417 | } else { | |
418 | false | |
419 | } | |
420 | }; | |
421 | ||
422 | let predicates: Vec<_> = predicates_and_bounds | |
423 | .predicates | |
424 | .iter() | |
425 | .copied() | |
426 | .filter(|(pred, _)| match pred.kind().skip_binder() { | |
487cf647 FG |
427 | ty::PredicateKind::Clause(ty::Clause::Trait(tr)) => !is_assoc_item_ty(tr.self_ty()), |
428 | ty::PredicateKind::Clause(ty::Clause::Projection(proj)) => { | |
2b03887a FG |
429 | !is_assoc_item_ty(proj.projection_ty.self_ty()) |
430 | } | |
487cf647 FG |
431 | ty::PredicateKind::Clause(ty::Clause::TypeOutlives(outlives)) => { |
432 | !is_assoc_item_ty(outlives.0) | |
433 | } | |
2b03887a FG |
434 | _ => true, |
435 | }) | |
436 | .collect(); | |
437 | if predicates.len() == predicates_and_bounds.predicates.len() { | |
438 | predicates_and_bounds | |
439 | } else { | |
440 | ty::GenericPredicates { | |
441 | parent: predicates_and_bounds.parent, | |
442 | predicates: tcx.arena.alloc_slice(&predicates), | |
443 | } | |
444 | } | |
445 | } else { | |
446 | if matches!(def_kind, DefKind::AnonConst) && tcx.lazy_normalization() { | |
447 | let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); | |
487cf647 FG |
448 | let parent_def_id = tcx.hir().get_parent_item(hir_id); |
449 | ||
450 | if tcx.hir().opt_const_param_default_param_def_id(hir_id).is_some() { | |
2b03887a FG |
451 | // In `generics_of` we set the generics' parent to be our parent's parent which means that |
452 | // we lose out on the predicates of our actual parent if we dont return those predicates here. | |
453 | // (See comment in `generics_of` for more information on why the parent shenanigans is necessary) | |
454 | // | |
455 | // struct Foo<T, const N: usize = { <T as Trait>::ASSOC }>(T) where T: Trait; | |
456 | // ^^^ ^^^^^^^^^^^^^^^^^^^^^^^ the def id we are calling | |
457 | // ^^^ explicit_predicates_of on | |
458 | // parent item we dont have set as the | |
459 | // parent of generics returned by `generics_of` | |
460 | // | |
461 | // In the above code we want the anon const to have predicates in its param env for `T: Trait` | |
487cf647 FG |
462 | // and we would be calling `explicit_predicates_of(Foo)` here |
463 | return tcx.explicit_predicates_of(parent_def_id); | |
464 | } | |
465 | ||
466 | let parent_def_kind = tcx.def_kind(parent_def_id); | |
467 | if matches!(parent_def_kind, DefKind::OpaqueTy) { | |
468 | // In `instantiate_identity` we inherit the predicates of our parent. | |
469 | // However, opaque types do not have a parent (see `gather_explicit_predicates_of`), which means | |
470 | // that we lose out on the predicates of our actual parent if we dont return those predicates here. | |
471 | // | |
472 | // | |
473 | // fn foo<T: Trait>() -> impl Iterator<Output = Another<{ <T as Trait>::ASSOC }> > { todo!() } | |
474 | // ^^^^^^^^^^^^^^^^^^^ the def id we are calling | |
475 | // explicit_predicates_of on | |
476 | // | |
477 | // In the above code we want the anon const to have predicates in its param env for `T: Trait`. | |
478 | // However, the anon const cannot inherit predicates from its parent since it's opaque. | |
479 | // | |
480 | // To fix this, we call `explicit_predicates_of` directly on `foo`, the parent's parent. | |
481 | ||
482 | // In the above example this is `foo::{opaque#0}` or `impl Iterator` | |
483 | let parent_hir_id = tcx.hir().local_def_id_to_hir_id(parent_def_id.def_id); | |
484 | ||
485 | // In the above example this is the function `foo` | |
486 | let item_def_id = tcx.hir().get_parent_item(parent_hir_id); | |
487 | ||
488 | // In the above code example we would be calling `explicit_predicates_of(foo)` here | |
2b03887a FG |
489 | return tcx.explicit_predicates_of(item_def_id); |
490 | } | |
491 | } | |
492 | gather_explicit_predicates_of(tcx, def_id) | |
493 | } | |
494 | } | |
495 | ||
496 | /// Ensures that the super-predicates of the trait with a `DefId` | |
497 | /// of `trait_def_id` are converted and stored. This also ensures that | |
498 | /// the transitive super-predicates are converted. | |
499 | pub(super) fn super_predicates_of( | |
500 | tcx: TyCtxt<'_>, | |
501 | trait_def_id: DefId, | |
502 | ) -> ty::GenericPredicates<'_> { | |
503 | tcx.super_predicates_that_define_assoc_type((trait_def_id, None)) | |
504 | } | |
505 | ||
506 | /// Ensures that the super-predicates of the trait with a `DefId` | |
507 | /// of `trait_def_id` are converted and stored. This also ensures that | |
508 | /// the transitive super-predicates are converted. | |
509 | pub(super) fn super_predicates_that_define_assoc_type( | |
510 | tcx: TyCtxt<'_>, | |
511 | (trait_def_id, assoc_name): (DefId, Option<Ident>), | |
512 | ) -> ty::GenericPredicates<'_> { | |
513 | if trait_def_id.is_local() { | |
514 | debug!("local trait"); | |
515 | let trait_hir_id = tcx.hir().local_def_id_to_hir_id(trait_def_id.expect_local()); | |
516 | ||
517 | let Node::Item(item) = tcx.hir().get(trait_hir_id) else { | |
518 | bug!("trait_node_id {} is not an item", trait_hir_id); | |
519 | }; | |
520 | ||
521 | let (generics, bounds) = match item.kind { | |
522 | hir::ItemKind::Trait(.., ref generics, ref supertraits, _) => (generics, supertraits), | |
523 | hir::ItemKind::TraitAlias(ref generics, ref supertraits) => (generics, supertraits), | |
524 | _ => span_bug!(item.span, "super_predicates invoked on non-trait"), | |
525 | }; | |
526 | ||
527 | let icx = ItemCtxt::new(tcx, trait_def_id); | |
528 | ||
529 | // Convert the bounds that follow the colon, e.g., `Bar + Zed` in `trait Foo: Bar + Zed`. | |
530 | let self_param_ty = tcx.types.self_param; | |
531 | let superbounds1 = if let Some(assoc_name) = assoc_name { | |
532 | <dyn AstConv<'_>>::compute_bounds_that_match_assoc_type( | |
533 | &icx, | |
534 | self_param_ty, | |
535 | bounds, | |
536 | assoc_name, | |
537 | ) | |
538 | } else { | |
539 | <dyn AstConv<'_>>::compute_bounds(&icx, self_param_ty, bounds) | |
540 | }; | |
541 | ||
542 | let superbounds1 = superbounds1.predicates(tcx, self_param_ty); | |
543 | ||
544 | // Convert any explicit superbounds in the where-clause, | |
545 | // e.g., `trait Foo where Self: Bar`. | |
546 | // In the case of trait aliases, however, we include all bounds in the where-clause, | |
547 | // so e.g., `trait Foo = where u32: PartialEq<Self>` would include `u32: PartialEq<Self>` | |
548 | // as one of its "superpredicates". | |
549 | let is_trait_alias = tcx.is_trait_alias(trait_def_id); | |
550 | let superbounds2 = icx.type_parameter_bounds_in_generics( | |
551 | generics, | |
487cf647 | 552 | item.owner_id.def_id, |
2b03887a FG |
553 | self_param_ty, |
554 | OnlySelfBounds(!is_trait_alias), | |
555 | assoc_name, | |
556 | ); | |
557 | ||
558 | // Combine the two lists to form the complete set of superbounds: | |
559 | let superbounds = &*tcx.arena.alloc_from_iter(superbounds1.into_iter().chain(superbounds2)); | |
560 | debug!(?superbounds); | |
561 | ||
562 | // Now require that immediate supertraits are converted, | |
563 | // which will, in turn, reach indirect supertraits. | |
564 | if assoc_name.is_none() { | |
565 | // Now require that immediate supertraits are converted, | |
566 | // which will, in turn, reach indirect supertraits. | |
567 | for &(pred, span) in superbounds { | |
568 | debug!("superbound: {:?}", pred); | |
487cf647 FG |
569 | if let ty::PredicateKind::Clause(ty::Clause::Trait(bound)) = |
570 | pred.kind().skip_binder() | |
571 | { | |
2b03887a FG |
572 | tcx.at(span).super_predicates_of(bound.def_id()); |
573 | } | |
574 | } | |
575 | } | |
576 | ||
577 | ty::GenericPredicates { parent: None, predicates: superbounds } | |
578 | } else { | |
579 | // if `assoc_name` is None, then the query should've been redirected to an | |
580 | // external provider | |
581 | assert!(assoc_name.is_some()); | |
582 | tcx.super_predicates_of(trait_def_id) | |
583 | } | |
584 | } | |
585 | ||
586 | /// Returns the predicates defined on `item_def_id` of the form | |
587 | /// `X: Foo` where `X` is the type parameter `def_id`. | |
588 | #[instrument(level = "trace", skip(tcx))] | |
589 | pub(super) fn type_param_predicates( | |
590 | tcx: TyCtxt<'_>, | |
591 | (item_def_id, def_id, assoc_name): (DefId, LocalDefId, Ident), | |
592 | ) -> ty::GenericPredicates<'_> { | |
593 | use rustc_hir::*; | |
594 | ||
595 | // In the AST, bounds can derive from two places. Either | |
596 | // written inline like `<T: Foo>` or in a where-clause like | |
597 | // `where T: Foo`. | |
598 | ||
599 | let param_id = tcx.hir().local_def_id_to_hir_id(def_id); | |
600 | let param_owner = tcx.hir().ty_param_owner(def_id); | |
601 | let generics = tcx.generics_of(param_owner); | |
602 | let index = generics.param_def_id_to_index[&def_id.to_def_id()]; | |
603 | let ty = tcx.mk_ty_param(index, tcx.hir().ty_param_name(def_id)); | |
604 | ||
605 | // Don't look for bounds where the type parameter isn't in scope. | |
606 | let parent = if item_def_id == param_owner.to_def_id() { | |
607 | None | |
608 | } else { | |
609 | tcx.generics_of(item_def_id).parent | |
610 | }; | |
611 | ||
612 | let mut result = parent | |
613 | .map(|parent| { | |
614 | let icx = ItemCtxt::new(tcx, parent); | |
615 | icx.get_type_parameter_bounds(DUMMY_SP, def_id.to_def_id(), assoc_name) | |
616 | }) | |
617 | .unwrap_or_default(); | |
618 | let mut extend = None; | |
619 | ||
620 | let item_hir_id = tcx.hir().local_def_id_to_hir_id(item_def_id.expect_local()); | |
621 | let ast_generics = match tcx.hir().get(item_hir_id) { | |
622 | Node::TraitItem(item) => &item.generics, | |
623 | ||
624 | Node::ImplItem(item) => &item.generics, | |
625 | ||
626 | Node::Item(item) => { | |
627 | match item.kind { | |
628 | ItemKind::Fn(.., ref generics, _) | |
629 | | ItemKind::Impl(hir::Impl { ref generics, .. }) | |
630 | | ItemKind::TyAlias(_, ref generics) | |
631 | | ItemKind::OpaqueTy(OpaqueTy { | |
632 | ref generics, | |
633 | origin: hir::OpaqueTyOrigin::TyAlias, | |
634 | .. | |
635 | }) | |
636 | | ItemKind::Enum(_, ref generics) | |
637 | | ItemKind::Struct(_, ref generics) | |
638 | | ItemKind::Union(_, ref generics) => generics, | |
639 | ItemKind::Trait(_, _, ref generics, ..) => { | |
640 | // Implied `Self: Trait` and supertrait bounds. | |
641 | if param_id == item_hir_id { | |
642 | let identity_trait_ref = ty::TraitRef::identity(tcx, item_def_id); | |
643 | extend = | |
644 | Some((identity_trait_ref.without_const().to_predicate(tcx), item.span)); | |
645 | } | |
646 | generics | |
647 | } | |
648 | _ => return result, | |
649 | } | |
650 | } | |
651 | ||
652 | Node::ForeignItem(item) => match item.kind { | |
653 | ForeignItemKind::Fn(_, _, ref generics) => generics, | |
654 | _ => return result, | |
655 | }, | |
656 | ||
657 | _ => return result, | |
658 | }; | |
659 | ||
660 | let icx = ItemCtxt::new(tcx, item_def_id); | |
661 | let extra_predicates = extend.into_iter().chain( | |
662 | icx.type_parameter_bounds_in_generics( | |
663 | ast_generics, | |
487cf647 | 664 | def_id, |
2b03887a FG |
665 | ty, |
666 | OnlySelfBounds(true), | |
667 | Some(assoc_name), | |
668 | ) | |
669 | .into_iter() | |
670 | .filter(|(predicate, _)| match predicate.kind().skip_binder() { | |
487cf647 | 671 | ty::PredicateKind::Clause(ty::Clause::Trait(data)) => data.self_ty().is_param(index), |
2b03887a FG |
672 | _ => false, |
673 | }), | |
674 | ); | |
675 | result.predicates = | |
676 | tcx.arena.alloc_from_iter(result.predicates.iter().copied().chain(extra_predicates)); | |
677 | result | |
678 | } | |
679 | ||
680 | impl<'tcx> ItemCtxt<'tcx> { | |
681 | /// Finds bounds from `hir::Generics`. This requires scanning through the | |
682 | /// AST. We do this to avoid having to convert *all* the bounds, which | |
683 | /// would create artificial cycles. Instead, we can only convert the | |
684 | /// bounds for a type parameter `X` if `X::Foo` is used. | |
685 | #[instrument(level = "trace", skip(self, ast_generics))] | |
686 | fn type_parameter_bounds_in_generics( | |
687 | &self, | |
688 | ast_generics: &'tcx hir::Generics<'tcx>, | |
487cf647 | 689 | param_def_id: LocalDefId, |
2b03887a FG |
690 | ty: Ty<'tcx>, |
691 | only_self_bounds: OnlySelfBounds, | |
692 | assoc_name: Option<Ident>, | |
693 | ) -> Vec<(ty::Predicate<'tcx>, Span)> { | |
2b03887a FG |
694 | ast_generics |
695 | .predicates | |
696 | .iter() | |
697 | .filter_map(|wp| match *wp { | |
698 | hir::WherePredicate::BoundPredicate(ref bp) => Some(bp), | |
699 | _ => None, | |
700 | }) | |
701 | .flat_map(|bp| { | |
487cf647 | 702 | let bt = if bp.is_param_bound(param_def_id.to_def_id()) { |
2b03887a FG |
703 | Some(ty) |
704 | } else if !only_self_bounds.0 { | |
705 | Some(self.to_ty(bp.bounded_ty)) | |
706 | } else { | |
707 | None | |
708 | }; | |
709 | let bvars = self.tcx.late_bound_vars(bp.hir_id); | |
710 | ||
711 | bp.bounds.iter().filter_map(move |b| bt.map(|bt| (bt, b, bvars))).filter( | |
712 | |(_, b, _)| match assoc_name { | |
713 | Some(assoc_name) => self.bound_defines_assoc_item(b, assoc_name), | |
714 | None => true, | |
715 | }, | |
716 | ) | |
717 | }) | |
718 | .flat_map(|(bt, b, bvars)| predicates_from_bound(self, bt, b, bvars)) | |
719 | .collect() | |
720 | } | |
721 | ||
722 | #[instrument(level = "trace", skip(self))] | |
723 | fn bound_defines_assoc_item(&self, b: &hir::GenericBound<'_>, assoc_name: Ident) -> bool { | |
724 | match b { | |
725 | hir::GenericBound::Trait(poly_trait_ref, _) => { | |
726 | let trait_ref = &poly_trait_ref.trait_ref; | |
727 | if let Some(trait_did) = trait_ref.trait_def_id() { | |
728 | self.tcx.trait_may_define_assoc_type(trait_did, assoc_name) | |
729 | } else { | |
730 | false | |
731 | } | |
732 | } | |
733 | _ => false, | |
734 | } | |
735 | } | |
736 | } | |
737 | ||
738 | /// Converts a specific `GenericBound` from the AST into a set of | |
739 | /// predicates that apply to the self type. A vector is returned | |
740 | /// because this can be anywhere from zero predicates (`T: ?Sized` adds no | |
741 | /// predicates) to one (`T: Foo`) to many (`T: Bar<X = i32>` adds `T: Bar` | |
742 | /// and `<T as Bar>::X == i32`). | |
743 | fn predicates_from_bound<'tcx>( | |
744 | astconv: &dyn AstConv<'tcx>, | |
745 | param_ty: Ty<'tcx>, | |
746 | bound: &'tcx hir::GenericBound<'tcx>, | |
747 | bound_vars: &'tcx ty::List<ty::BoundVariableKind>, | |
748 | ) -> Vec<(ty::Predicate<'tcx>, Span)> { | |
749 | let mut bounds = Bounds::default(); | |
750 | astconv.add_bounds(param_ty, [bound].into_iter(), &mut bounds, bound_vars); | |
751 | bounds.predicates(astconv.tcx(), param_ty).collect() | |
752 | } |