|
7 | 7 | use rustc_hir::HirId;
|
8 | 8 | use rustc_hir::def::{DefKind, Res};
|
9 | 9 | use rustc_hir::def_id::{DefId, LocalDefId};
|
10 |
| -use rustc_middle::bug; |
11 | 10 | use rustc_middle::ty::{self as ty, IsSuggestable, Ty, TyCtxt, Upcast};
|
| 11 | +use rustc_middle::{bug, span_bug}; |
12 | 12 | use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol, kw, sym};
|
13 | 13 | use rustc_trait_selection::traits;
|
14 | 14 | use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor};
|
15 | 15 | use smallvec::SmallVec;
|
16 |
| -use tracing::{debug, instrument}; |
| 16 | +use tracing::{debug, instrument, trace}; |
17 | 17 |
|
18 | 18 | use super::errors::GenericsArgsErrExtend;
|
19 | 19 | use crate::errors;
|
|
22 | 22 | };
|
23 | 23 |
|
24 | 24 | impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
| 25 | + pub(crate) fn lower_where_predicates( |
| 26 | + &self, |
| 27 | + params: &[hir::GenericParam<'tcx>], |
| 28 | + hir_predicates: &[hir::WherePredicate<'tcx>], |
| 29 | + predicates: &mut FxIndexSet<(ty::Clause<'tcx>, Span)>, |
| 30 | + ) { |
| 31 | + let tcx = self.tcx(); |
| 32 | + // Add implicit predicates that should be treated as if the user has written them, |
| 33 | + // including the implicit `T: Sized` for all generic parameters, and `ConstArgHasType` |
| 34 | + // for const params. |
| 35 | + for param in params { |
| 36 | + match param.kind { |
| 37 | + hir::GenericParamKind::Lifetime { .. } => (), |
| 38 | + hir::GenericParamKind::Type { .. } => { |
| 39 | + // TODO: |
| 40 | + let param_ty = |
| 41 | + ty::fold::shift_vars(self.tcx(), self.lower_ty_param(param.hir_id), 1); |
| 42 | + let mut bounds = Vec::new(); |
| 43 | + // Params are implicitly sized unless a `?Sized` bound is found |
| 44 | + self.add_sized_bound( |
| 45 | + &mut bounds, |
| 46 | + param_ty, |
| 47 | + &[], |
| 48 | + Some((param.def_id, hir_predicates)), |
| 49 | + param.span, |
| 50 | + ); |
| 51 | + trace!(?bounds); |
| 52 | + predicates.extend(bounds); |
| 53 | + trace!(?predicates); |
| 54 | + } |
| 55 | + hir::GenericParamKind::Const { .. } => { |
| 56 | + let param_def_id = param.def_id.to_def_id(); |
| 57 | + let ct_ty = tcx.type_of(param_def_id).instantiate_identity(); |
| 58 | + let ct = self.lower_const_param(param_def_id, param.hir_id); |
| 59 | + predicates.insert(( |
| 60 | + ty::ClauseKind::ConstArgHasType(ct, ct_ty).upcast(tcx), |
| 61 | + param.span, |
| 62 | + )); |
| 63 | + } |
| 64 | + } |
| 65 | + } |
| 66 | + |
| 67 | + // Add inline `<T: Foo>` bounds and bounds in the where clause. |
| 68 | + for predicate in hir_predicates { |
| 69 | + match predicate.kind { |
| 70 | + hir::WherePredicateKind::BoundPredicate(bound_pred) => { |
| 71 | + let ty = self.lower_ty_maybe_return_type_notation(bound_pred.bounded_ty); |
| 72 | + |
| 73 | + let mut bound_assumptions = FxIndexSet::default(); |
| 74 | + if self.tcx().features().non_lifetime_binders() { |
| 75 | + self.lower_where_predicates( |
| 76 | + bound_pred.bound_generic_params, |
| 77 | + bound_pred.bound_assumptions, |
| 78 | + &mut bound_assumptions, |
| 79 | + ); |
| 80 | + } |
| 81 | + let bound_assumptions = self.tcx().mk_clauses_from_iter( |
| 82 | + bound_assumptions.into_iter().map(|(clause, _)| clause), |
| 83 | + ); |
| 84 | + |
| 85 | + let bound_vars = tcx.late_bound_vars(predicate.hir_id); |
| 86 | + // Keep the type around in a dummy predicate, in case of no bounds. |
| 87 | + // That way, `where Ty:` is not a complete noop (see #53696) and `Ty` |
| 88 | + // is still checked for WF. |
| 89 | + if bound_pred.bounds.is_empty() { |
| 90 | + if let ty::Param(_) = ty.kind() { |
| 91 | + // This is a `where T:`, which can be in the HIR from the |
| 92 | + // transformation that moves `?Sized` to `T`'s declaration. |
| 93 | + // We can skip the predicate because type parameters are |
| 94 | + // trivially WF, but also we *should*, to avoid exposing |
| 95 | + // users who never wrote `where Type:,` themselves, to |
| 96 | + // compiler/tooling bugs from not handling WF predicates. |
| 97 | + } else { |
| 98 | + let span = bound_pred.bounded_ty.span; |
| 99 | + let predicate = ty::Binder::bind_with_vars( |
| 100 | + ty::ClauseKind::WellFormed(ty.into()), |
| 101 | + bound_vars, |
| 102 | + ); |
| 103 | + predicates.insert((predicate.upcast(tcx), span)); |
| 104 | + } |
| 105 | + } |
| 106 | + |
| 107 | + let mut bounds = Vec::new(); |
| 108 | + self.lower_bounds( |
| 109 | + ty, |
| 110 | + bound_pred.bounds, |
| 111 | + &mut bounds, |
| 112 | + bound_vars, |
| 113 | + bound_assumptions, |
| 114 | + PredicateFilter::All, |
| 115 | + ); |
| 116 | + predicates.extend(bounds); |
| 117 | + } |
| 118 | + |
| 119 | + hir::WherePredicateKind::RegionPredicate(region_pred) => { |
| 120 | + let r1 = self |
| 121 | + .lower_lifetime(region_pred.lifetime, RegionInferReason::RegionPredicate); |
| 122 | + predicates.extend(region_pred.bounds.iter().map(|bound| { |
| 123 | + let (r2, span) = match bound { |
| 124 | + hir::GenericBound::Outlives(lt) => ( |
| 125 | + self.lower_lifetime(lt, RegionInferReason::RegionPredicate), |
| 126 | + lt.ident.span, |
| 127 | + ), |
| 128 | + bound => { |
| 129 | + span_bug!( |
| 130 | + bound.span(), |
| 131 | + "lifetime param bounds must be outlives, but found {bound:?}" |
| 132 | + ) |
| 133 | + } |
| 134 | + }; |
| 135 | + let pred = ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(r1, r2)) |
| 136 | + .upcast(tcx); |
| 137 | + (pred, span) |
| 138 | + })) |
| 139 | + } |
| 140 | + |
| 141 | + hir::WherePredicateKind::EqPredicate(..) => { |
| 142 | + // FIXME(#20041) |
| 143 | + } |
| 144 | + } |
| 145 | + } |
| 146 | + } |
| 147 | + |
25 | 148 | /// Add a `Sized` bound to the `bounds` if appropriate.
|
26 | 149 | ///
|
27 | 150 | /// Doesn't add the bound if the HIR bounds contain any of `Sized`, `?Sized` or `!Sized`.
|
|
30 | 153 | bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
|
31 | 154 | self_ty: Ty<'tcx>,
|
32 | 155 | hir_bounds: &'tcx [hir::GenericBound<'tcx>],
|
33 |
| - self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>, |
| 156 | + self_ty_where_predicates: Option<(LocalDefId, &[hir::WherePredicate<'tcx>])>, |
34 | 157 | span: Span,
|
35 | 158 | ) {
|
36 | 159 | let tcx = self.tcx();
|
|
115 | 238 | } else if let Some(sized_def_id) = sized_def_id {
|
116 | 239 | // There was no `?Sized`, `!Sized` or explicit `Sized` bound;
|
117 | 240 | // add `Sized` if it's available.
|
118 |
| - let trait_ref = ty::TraitRef::new(tcx, sized_def_id, [self_ty]); |
| 241 | + let trait_ref = ty::Binder::bind_with_vars( |
| 242 | + ty::TraitRef::new(tcx, sized_def_id, [self_ty]), |
| 243 | + ty::List::empty(), |
| 244 | + ); |
119 | 245 | // Preferable to put this obligation first, since we report better errors for sized ambiguity.
|
120 | 246 | bounds.insert(0, (trait_ref.upcast(tcx), span));
|
121 | 247 | }
|
|
149 | 275 | hir_bounds: I,
|
150 | 276 | bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
|
151 | 277 | bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
|
| 278 | + bound_assumptions: ty::Clauses<'tcx>, |
152 | 279 | predicate_filter: PredicateFilter,
|
153 | 280 | ) where
|
154 | 281 | 'tcx: 'hir,
|
|
170 | 297 | match hir_bound {
|
171 | 298 | hir::GenericBound::Trait(poly_trait_ref) => {
|
172 | 299 | let hir::TraitBoundModifiers { constness, polarity } = poly_trait_ref.modifiers;
|
| 300 | + |
| 301 | + let mut additional_bound_assumptions = FxIndexSet::default(); |
| 302 | + if self.tcx().features().non_lifetime_binders() { |
| 303 | + self.lower_where_predicates( |
| 304 | + poly_trait_ref.bound_generic_params, |
| 305 | + poly_trait_ref.bound_assumptions, |
| 306 | + &mut additional_bound_assumptions, |
| 307 | + ); |
| 308 | + } |
| 309 | + let bound_assumptions = |
| 310 | + self.tcx().mk_clauses_from_iter(bound_assumptions.into_iter().chain( |
| 311 | + additional_bound_assumptions.into_iter().map(|(clause, _)| clause), |
| 312 | + )); |
| 313 | + |
173 | 314 | let _ = self.lower_poly_trait_ref(
|
174 | 315 | &poly_trait_ref.trait_ref,
|
175 | 316 | poly_trait_ref.span,
|
176 | 317 | constness,
|
177 | 318 | polarity,
|
178 | 319 | param_ty,
|
| 320 | + bound_assumptions, |
179 | 321 | bounds,
|
180 | 322 | predicate_filter,
|
181 | 323 | );
|
|
190 | 332 | }
|
191 | 333 |
|
192 | 334 | let region = self.lower_lifetime(lifetime, RegionInferReason::OutlivesBound);
|
193 |
| - let bound = ty::Binder::bind_with_vars( |
| 335 | + let bound = ty::Binder::bind_with_vars_and_clauses( |
194 | 336 | ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(param_ty, region)),
|
195 | 337 | bound_vars,
|
| 338 | + bound_assumptions, |
196 | 339 | );
|
197 | 340 | bounds.push((bound.upcast(self.tcx()), lifetime.ident.span));
|
198 | 341 | }
|
|
419 | 562 | hir_bounds,
|
420 | 563 | bounds,
|
421 | 564 | projection_ty.bound_vars(),
|
| 565 | + projection_ty.skip_binder_with_clauses().1, |
422 | 566 | predicate_filter,
|
423 | 567 | );
|
424 | 568 | }
|
|
0 commit comments