]>
Commit | Line | Data |
---|---|---|
9ffffee4 | 1 | use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; |
dfeec247 | 2 | use rustc_hir as hir; |
9ffffee4 FG |
3 | use rustc_hir::def::DefKind; |
4 | use rustc_index::bit_set::BitSet; | |
49aad941 | 5 | use rustc_middle::query::Providers; |
9ffffee4 | 6 | use rustc_middle::ty::{ |
353b0b11 FG |
7 | self, Binder, EarlyBinder, ImplTraitInTraitData, Predicate, PredicateKind, ToPredicate, Ty, |
8 | TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, | |
9ffffee4 | 9 | }; |
9c376795 | 10 | use rustc_session::config::TraitSolver; |
353b0b11 FG |
11 | use rustc_span::def_id::{DefId, LocalDefId, CRATE_DEF_ID}; |
12 | use rustc_span::DUMMY_SP; | |
ba9703b0 | 13 | use rustc_trait_selection::traits; |
dfeec247 | 14 | |
74b04a01 XL |
15 | fn sized_constraint_for_ty<'tcx>( |
16 | tcx: TyCtxt<'tcx>, | |
5e7ed085 | 17 | adtdef: ty::AdtDef<'tcx>, |
74b04a01 XL |
18 | ty: Ty<'tcx>, |
19 | ) -> Vec<Ty<'tcx>> { | |
923072b8 | 20 | use rustc_type_ir::sty::TyKind::*; |
dfeec247 | 21 | |
1b1a35ee | 22 | let result = match ty.kind() { |
dfeec247 XL |
23 | Bool | Char | Int(..) | Uint(..) | Float(..) | RawPtr(..) | Ref(..) | FnDef(..) |
24 | | FnPtr(_) | Array(..) | Closure(..) | Generator(..) | Never => vec![], | |
25 | ||
9ffffee4 FG |
26 | Str |
27 | | Dynamic(..) | |
28 | | Slice(_) | |
29 | | Foreign(..) | |
30 | | Error(_) | |
31 | | GeneratorWitness(..) | |
32 | | GeneratorWitnessMIR(..) => { | |
dfeec247 XL |
33 | // these are never sized - return the target type |
34 | vec![ty] | |
35 | } | |
36 | ||
37 | Tuple(ref tys) => match tys.last() { | |
38 | None => vec![], | |
5e7ed085 | 39 | Some(&ty) => sized_constraint_for_ty(tcx, adtdef, ty), |
dfeec247 XL |
40 | }, |
41 | ||
42 | Adt(adt, substs) => { | |
43 | // recursive case | |
44 | let adt_tys = adt.sized_constraint(tcx); | |
45 | debug!("sized_constraint_for_ty({:?}) intermediate = {:?}", ty, adt_tys); | |
46 | adt_tys | |
064997fb | 47 | .0 |
dfeec247 | 48 | .iter() |
064997fb | 49 | .map(|ty| adt_tys.rebind(*ty).subst(tcx, substs)) |
dfeec247 XL |
50 | .flat_map(|ty| sized_constraint_for_ty(tcx, adtdef, ty)) |
51 | .collect() | |
52 | } | |
53 | ||
9c376795 | 54 | Alias(..) => { |
dfeec247 XL |
55 | // must calculate explicitly. |
56 | // FIXME: consider special-casing always-Sized projections | |
57 | vec![ty] | |
58 | } | |
59 | ||
dfeec247 XL |
60 | Param(..) => { |
61 | // perf hack: if there is a `T: Sized` bound, then | |
62 | // we know that `T` is Sized and do not need to check | |
63 | // it on the impl. | |
64 | ||
5e7ed085 | 65 | let Some(sized_trait) = tcx.lang_items().sized_trait() else { return vec![ty] }; |
49aad941 FG |
66 | let sized_predicate = |
67 | ty::TraitRef::new(tcx, sized_trait, [ty]).without_const().to_predicate(tcx); | |
5e7ed085 | 68 | let predicates = tcx.predicates_of(adtdef.did()).predicates; |
dfeec247 XL |
69 | if predicates.iter().any(|(p, _)| *p == sized_predicate) { vec![] } else { vec![ty] } |
70 | } | |
71 | ||
72 | Placeholder(..) | Bound(..) | Infer(..) => { | |
73 | bug!("unexpected type `{:?}` in sized_constraint_for_ty", ty) | |
74 | } | |
75 | }; | |
76 | debug!("sized_constraint_for_ty({:?}) = {:?}", ty, result); | |
77 | result | |
78 | } | |
79 | ||
353b0b11 FG |
80 | fn impl_defaultness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Defaultness { |
81 | match tcx.hir().get_by_def_id(def_id) { | |
064997fb FG |
82 | hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(impl_), .. }) => impl_.defaultness, |
83 | hir::Node::ImplItem(hir::ImplItem { defaultness, .. }) | |
84 | | hir::Node::TraitItem(hir::TraitItem { defaultness, .. }) => *defaultness, | |
85 | node => { | |
86 | bug!("`impl_defaultness` called on {:?}", node); | |
87 | } | |
ba9703b0 XL |
88 | } |
89 | } | |
90 | ||
dfeec247 XL |
91 | /// Calculates the `Sized` constraint. |
92 | /// | |
93 | /// In fact, there are only a few options for the types in the constraint: | |
94 | /// - an obviously-unsized type | |
95 | /// - a type parameter or projection whose Sizedness can't be known | |
96 | /// - a tuple of type parameters or projections, if there are multiple | |
97 | /// such. | |
2b03887a FG |
98 | /// - an Error, if a type is infinitely sized |
99 | fn adt_sized_constraint(tcx: TyCtxt<'_>, def_id: DefId) -> &[Ty<'_>] { | |
100 | if let Some(def_id) = def_id.as_local() { | |
101 | if matches!(tcx.representability(def_id), ty::Representability::Infinite) { | |
9ffffee4 | 102 | return tcx.mk_type_list(&[tcx.ty_error_misc()]); |
2b03887a FG |
103 | } |
104 | } | |
dfeec247 XL |
105 | let def = tcx.adt_def(def_id); |
106 | ||
9ffffee4 | 107 | let result = tcx.mk_type_list_from_iter( |
5e7ed085 | 108 | def.variants() |
dfeec247 | 109 | .iter() |
353b0b11 | 110 | .filter_map(|v| v.fields.raw.last()) |
9ffffee4 | 111 | .flat_map(|f| sized_constraint_for_ty(tcx, def, tcx.type_of(f.did).subst_identity())), |
dfeec247 XL |
112 | ); |
113 | ||
114 | debug!("adt_sized_constraint: {:?} => {:?}", def, result); | |
115 | ||
2b03887a | 116 | result |
dfeec247 XL |
117 | } |
118 | ||
dfeec247 XL |
119 | /// See `ParamEnv` struct definition for details. |
120 | fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> { | |
dfeec247 | 121 | // Compute the bounds on Self and the type parameters. |
1b1a35ee | 122 | let ty::InstantiatedPredicates { mut predicates, .. } = |
dfeec247 XL |
123 | tcx.predicates_of(def_id).instantiate_identity(tcx); |
124 | ||
353b0b11 FG |
125 | // When computing the param_env of an RPITIT, use predicates of the containing function, |
126 | // *except* for the additional assumption that the RPITIT normalizes to the trait method's | |
127 | // default opaque type. This is needed to properly check the item bounds of the assoc | |
128 | // type hold (`check_type_bounds`), since that method already installs a similar projection | |
129 | // bound, so they will conflict. | |
130 | // FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): I don't like this, we should | |
131 | // at least be making sure that the generics in RPITITs and their parent fn don't | |
132 | // get out of alignment, or else we do actually need to substitute these predicates. | |
133 | if let Some(ImplTraitInTraitData::Trait { fn_def_id, .. }) | |
134 | | Some(ImplTraitInTraitData::Impl { fn_def_id, .. }) = tcx.opt_rpitit_info(def_id) | |
135 | { | |
136 | predicates = tcx.predicates_of(fn_def_id).instantiate_identity(tcx).predicates; | |
137 | } | |
138 | ||
dfeec247 XL |
139 | // Finally, we have to normalize the bounds in the environment, in |
140 | // case they contain any associated type projections. This process | |
141 | // can yield errors if the put in illegal associated types, like | |
142 | // `<i32 as Foo>::Bar` where `i32` does not implement `Foo`. We | |
143 | // report these errors right here; this doesn't actually feel | |
144 | // right to me, because constructing the environment feels like a | |
94222f64 | 145 | // kind of an "idempotent" action, but I'm not sure where would be |
dfeec247 XL |
146 | // a better place. In practice, we construct environments for |
147 | // every fn once during type checking, and we'll abort if there | |
5099ac24 | 148 | // are any errors at that point, so outside of type inference you can be |
dfeec247 XL |
149 | // sure that this will succeed without errors anyway. |
150 | ||
9c376795 | 151 | if tcx.sess.opts.unstable_opts.trait_solver == TraitSolver::Chalk { |
1b1a35ee XL |
152 | let environment = well_formed_types_in_env(tcx, def_id); |
153 | predicates.extend(environment); | |
154 | } | |
155 | ||
9ffffee4 FG |
156 | if tcx.def_kind(def_id) == DefKind::AssocFn |
157 | && tcx.associated_item(def_id).container == ty::AssocItemContainer::TraitContainer | |
158 | { | |
159 | let sig = tcx.fn_sig(def_id).subst_identity(); | |
353b0b11 FG |
160 | // We accounted for the binder of the fn sig, so skip the binder. |
161 | sig.skip_binder().visit_with(&mut ImplTraitInTraitFinder { | |
9ffffee4 FG |
162 | tcx, |
163 | fn_def_id: def_id, | |
164 | bound_vars: sig.bound_vars(), | |
165 | predicates: &mut predicates, | |
166 | seen: FxHashSet::default(), | |
353b0b11 | 167 | depth: ty::INNERMOST, |
9ffffee4 FG |
168 | }); |
169 | } | |
170 | ||
a2a8927a | 171 | let local_did = def_id.as_local(); |
353b0b11 FG |
172 | // FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): This isn't correct for |
173 | // RPITITs in const trait fn. | |
174 | let hir_id = local_did.and_then(|def_id| tcx.opt_local_def_id_to_hir_id(def_id)); | |
a2a8927a | 175 | |
2b03887a | 176 | // FIXME(consts): This is not exactly in line with the constness query. |
a2a8927a XL |
177 | let constness = match hir_id { |
178 | Some(hir_id) => match tcx.hir().get(hir_id) { | |
179 | hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Fn(..), .. }) | |
923072b8 | 180 | if tcx.is_const_default_method(def_id) => |
a2a8927a XL |
181 | { |
182 | hir::Constness::Const | |
183 | } | |
184 | ||
185 | hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(..), .. }) | |
186 | | hir::Node::Item(hir::Item { kind: hir::ItemKind::Static(..), .. }) | |
187 | | hir::Node::TraitItem(hir::TraitItem { | |
188 | kind: hir::TraitItemKind::Const(..), .. | |
189 | }) | |
190 | | hir::Node::AnonConst(_) | |
191 | | hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. }) | |
192 | | hir::Node::ImplItem(hir::ImplItem { | |
193 | kind: | |
194 | hir::ImplItemKind::Fn( | |
195 | hir::FnSig { | |
196 | header: hir::FnHeader { constness: hir::Constness::Const, .. }, | |
197 | .. | |
198 | }, | |
199 | .., | |
200 | ), | |
201 | .. | |
202 | }) => hir::Constness::Const, | |
203 | ||
204 | hir::Node::ImplItem(hir::ImplItem { | |
2b03887a | 205 | kind: hir::ImplItemKind::Type(..) | hir::ImplItemKind::Fn(..), |
a2a8927a XL |
206 | .. |
207 | }) => { | |
9c376795 | 208 | let parent_hir_id = tcx.hir().parent_id(hir_id); |
a2a8927a XL |
209 | match tcx.hir().get(parent_hir_id) { |
210 | hir::Node::Item(hir::Item { | |
211 | kind: hir::ItemKind::Impl(hir::Impl { constness, .. }), | |
212 | .. | |
213 | }) => *constness, | |
214 | _ => span_bug!( | |
215 | tcx.def_span(parent_hir_id.owner), | |
216 | "impl item's parent node is not an impl", | |
217 | ), | |
218 | } | |
219 | } | |
220 | ||
221 | hir::Node::Item(hir::Item { | |
222 | kind: | |
223 | hir::ItemKind::Fn(hir::FnSig { header: hir::FnHeader { constness, .. }, .. }, ..), | |
224 | .. | |
225 | }) | |
226 | | hir::Node::TraitItem(hir::TraitItem { | |
227 | kind: | |
228 | hir::TraitItemKind::Fn( | |
229 | hir::FnSig { header: hir::FnHeader { constness, .. }, .. }, | |
230 | .., | |
231 | ), | |
232 | .. | |
233 | }) | |
234 | | hir::Node::Item(hir::Item { | |
235 | kind: hir::ItemKind::Impl(hir::Impl { constness, .. }), | |
236 | .. | |
237 | }) => *constness, | |
238 | ||
239 | _ => hir::Constness::NotConst, | |
240 | }, | |
2b03887a FG |
241 | // FIXME(consts): It's suspicious that a param-env for a foreign item |
242 | // will always have NotConst param-env, though we don't typically use | |
243 | // that param-env for anything meaningful right now, so it's likely | |
244 | // not an issue. | |
a2a8927a XL |
245 | None => hir::Constness::NotConst, |
246 | }; | |
247 | ||
9ffffee4 FG |
248 | let unnormalized_env = |
249 | ty::ParamEnv::new(tcx.mk_predicates(&predicates), traits::Reveal::UserFacing, constness); | |
064997fb | 250 | |
9ffffee4 | 251 | let body_id = local_did.unwrap_or(CRATE_DEF_ID); |
dfeec247 | 252 | let cause = traits::ObligationCause::misc(tcx.def_span(def_id), body_id); |
064997fb | 253 | traits::normalize_param_env_or_error(tcx, unnormalized_env, cause) |
dfeec247 XL |
254 | } |
255 | ||
9ffffee4 FG |
256 | /// Walk through a function type, gathering all RPITITs and installing a |
257 | /// `NormalizesTo(Projection(RPITIT) -> Opaque(RPITIT))` predicate into the | |
258 | /// predicates list. This allows us to observe that an RPITIT projects to | |
259 | /// its corresponding opaque within the body of a default-body trait method. | |
260 | struct ImplTraitInTraitFinder<'a, 'tcx> { | |
261 | tcx: TyCtxt<'tcx>, | |
262 | predicates: &'a mut Vec<Predicate<'tcx>>, | |
263 | fn_def_id: DefId, | |
264 | bound_vars: &'tcx ty::List<ty::BoundVariableKind>, | |
265 | seen: FxHashSet<DefId>, | |
353b0b11 | 266 | depth: ty::DebruijnIndex, |
9ffffee4 FG |
267 | } |
268 | ||
269 | impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> { | |
353b0b11 FG |
270 | fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>( |
271 | &mut self, | |
272 | binder: &ty::Binder<'tcx, T>, | |
273 | ) -> std::ops::ControlFlow<Self::BreakTy> { | |
274 | self.depth.shift_in(1); | |
275 | let binder = binder.super_visit_with(self); | |
276 | self.depth.shift_out(1); | |
277 | binder | |
278 | } | |
279 | ||
9ffffee4 | 280 | fn visit_ty(&mut self, ty: Ty<'tcx>) -> std::ops::ControlFlow<Self::BreakTy> { |
353b0b11 FG |
281 | if let ty::Alias(ty::Projection, unshifted_alias_ty) = *ty.kind() |
282 | && self.tcx.is_impl_trait_in_trait(unshifted_alias_ty.def_id) | |
283 | && self.tcx.impl_trait_in_trait_parent_fn(unshifted_alias_ty.def_id) == self.fn_def_id | |
284 | && self.seen.insert(unshifted_alias_ty.def_id) | |
9ffffee4 | 285 | { |
353b0b11 FG |
286 | // We have entered some binders as we've walked into the |
287 | // bounds of the RPITIT. Shift these binders back out when | |
288 | // constructing the top-level projection predicate. | |
289 | let shifted_alias_ty = self.tcx.fold_regions(unshifted_alias_ty, |re, depth| { | |
290 | if let ty::ReLateBound(index, bv) = re.kind() { | |
291 | if depth != ty::INNERMOST { | |
292 | return self.tcx.mk_re_error_with_message( | |
293 | DUMMY_SP, | |
294 | "we shouldn't walk non-predicate binders with `impl Trait`...", | |
295 | ); | |
296 | } | |
297 | self.tcx.mk_re_late_bound(index.shifted_out_to_binder(self.depth), bv) | |
298 | } else { | |
299 | re | |
300 | } | |
301 | }); | |
302 | ||
303 | // If we're lowering to associated item, install the opaque type which is just | |
304 | // the `type_of` of the trait's associated item. If we're using the old lowering | |
305 | // strategy, then just reinterpret the associated type like an opaque :^) | |
306 | let default_ty = if self.tcx.lower_impl_trait_in_trait_to_assoc_ty() { | |
307 | self.tcx.type_of(shifted_alias_ty.def_id).subst(self.tcx, shifted_alias_ty.substs) | |
308 | } else { | |
309 | self.tcx.mk_alias(ty::Opaque, shifted_alias_ty) | |
310 | }; | |
311 | ||
9ffffee4 FG |
312 | self.predicates.push( |
313 | ty::Binder::bind_with_vars( | |
353b0b11 | 314 | ty::ProjectionPredicate { projection_ty: shifted_alias_ty, term: default_ty.into() }, |
9ffffee4 FG |
315 | self.bound_vars, |
316 | ) | |
317 | .to_predicate(self.tcx), | |
318 | ); | |
319 | ||
353b0b11 FG |
320 | // We walk the *un-shifted* alias ty, because we're tracking the de bruijn |
321 | // binder depth, and if we were to walk `shifted_alias_ty` instead, we'd | |
322 | // have to reset `self.depth` back to `ty::INNERMOST` or something. It's | |
323 | // easier to just do this. | |
324 | for bound in self | |
325 | .tcx | |
326 | .item_bounds(unshifted_alias_ty.def_id) | |
327 | .subst_iter(self.tcx, unshifted_alias_ty.substs) | |
9ffffee4 FG |
328 | { |
329 | bound.visit_with(self); | |
330 | } | |
331 | } | |
332 | ||
333 | ty.super_visit_with(self) | |
334 | } | |
335 | } | |
336 | ||
1b1a35ee XL |
337 | /// Elaborate the environment. |
338 | /// | |
339 | /// Collect a list of `Predicate`'s used for building the `ParamEnv`. Adds `TypeWellFormedFromEnv`'s | |
340 | /// that are assumed to be well-formed (because they come from the environment). | |
341 | /// | |
342 | /// Used only in chalk mode. | |
9c376795 | 343 | fn well_formed_types_in_env(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::List<Predicate<'_>> { |
1b1a35ee XL |
344 | use rustc_hir::{ForeignItemKind, ImplItemKind, ItemKind, Node, TraitItemKind}; |
345 | use rustc_middle::ty::subst::GenericArgKind; | |
346 | ||
347 | debug!("environment(def_id = {:?})", def_id); | |
348 | ||
349 | // The environment of an impl Trait type is its defining function's environment. | |
350 | if let Some(parent) = ty::is_impl_trait_defn(tcx, def_id) { | |
a2a8927a | 351 | return well_formed_types_in_env(tcx, parent.to_def_id()); |
1b1a35ee XL |
352 | } |
353 | ||
354 | // Compute the bounds on `Self` and the type parameters. | |
355 | let ty::InstantiatedPredicates { predicates, .. } = | |
356 | tcx.predicates_of(def_id).instantiate_identity(tcx); | |
357 | ||
358 | let clauses = predicates.into_iter(); | |
359 | ||
360 | if !def_id.is_local() { | |
361 | return ty::List::empty(); | |
362 | } | |
5099ac24 | 363 | let node = tcx.hir().get_by_def_id(def_id.expect_local()); |
1b1a35ee XL |
364 | |
365 | enum NodeKind { | |
366 | TraitImpl, | |
367 | InherentImpl, | |
368 | Fn, | |
369 | Other, | |
fc512014 | 370 | } |
1b1a35ee XL |
371 | |
372 | let node_kind = match node { | |
373 | Node::TraitItem(item) => match item.kind { | |
374 | TraitItemKind::Fn(..) => NodeKind::Fn, | |
375 | _ => NodeKind::Other, | |
376 | }, | |
377 | ||
378 | Node::ImplItem(item) => match item.kind { | |
379 | ImplItemKind::Fn(..) => NodeKind::Fn, | |
380 | _ => NodeKind::Other, | |
381 | }, | |
382 | ||
383 | Node::Item(item) => match item.kind { | |
5869c6ff XL |
384 | ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) => NodeKind::TraitImpl, |
385 | ItemKind::Impl(hir::Impl { of_trait: None, .. }) => NodeKind::InherentImpl, | |
1b1a35ee XL |
386 | ItemKind::Fn(..) => NodeKind::Fn, |
387 | _ => NodeKind::Other, | |
388 | }, | |
389 | ||
390 | Node::ForeignItem(item) => match item.kind { | |
391 | ForeignItemKind::Fn(..) => NodeKind::Fn, | |
392 | _ => NodeKind::Other, | |
393 | }, | |
394 | ||
395 | // FIXME: closures? | |
396 | _ => NodeKind::Other, | |
397 | }; | |
398 | ||
399 | // FIXME(eddyb) isn't the unordered nature of this a hazard? | |
400 | let mut inputs = FxIndexSet::default(); | |
401 | ||
402 | match node_kind { | |
403 | // In a trait impl, we assume that the header trait ref and all its | |
404 | // constituents are well-formed. | |
405 | NodeKind::TraitImpl => { | |
9c376795 | 406 | let trait_ref = tcx.impl_trait_ref(def_id).expect("not an impl").subst_identity(); |
1b1a35ee XL |
407 | |
408 | // FIXME(chalk): this has problems because of late-bound regions | |
409 | //inputs.extend(trait_ref.substs.iter().flat_map(|arg| arg.walk())); | |
410 | inputs.extend(trait_ref.substs.iter()); | |
411 | } | |
412 | ||
413 | // In an inherent impl, we assume that the receiver type and all its | |
414 | // constituents are well-formed. | |
415 | NodeKind::InherentImpl => { | |
9ffffee4 | 416 | let self_ty = tcx.type_of(def_id).subst_identity(); |
5099ac24 | 417 | inputs.extend(self_ty.walk()); |
1b1a35ee XL |
418 | } |
419 | ||
420 | // In an fn, we assume that the arguments and all their constituents are | |
421 | // well-formed. | |
422 | NodeKind::Fn => { | |
9ffffee4 | 423 | let fn_sig = tcx.fn_sig(def_id).subst_identity(); |
fc512014 | 424 | let fn_sig = tcx.liberate_late_bound_regions(def_id, fn_sig); |
1b1a35ee | 425 | |
5099ac24 | 426 | inputs.extend(fn_sig.inputs().iter().flat_map(|ty| ty.walk())); |
1b1a35ee XL |
427 | } |
428 | ||
429 | NodeKind::Other => (), | |
430 | } | |
431 | let input_clauses = inputs.into_iter().filter_map(|arg| { | |
432 | match arg.unpack() { | |
433 | GenericArgKind::Type(ty) => { | |
5869c6ff XL |
434 | let binder = Binder::dummy(PredicateKind::TypeWellFormedFromEnv(ty)); |
435 | Some(tcx.mk_predicate(binder)) | |
1b1a35ee XL |
436 | } |
437 | ||
438 | // FIXME(eddyb) no WF conditions from lifetimes? | |
439 | GenericArgKind::Lifetime(_) => None, | |
440 | ||
441 | // FIXME(eddyb) support const generics in Chalk | |
442 | GenericArgKind::Const(_) => None, | |
443 | } | |
444 | }); | |
445 | ||
9ffffee4 | 446 | tcx.mk_predicates_from_iter(clauses.chain(input_clauses)) |
1b1a35ee XL |
447 | } |
448 | ||
3dfed10e XL |
449 | fn param_env_reveal_all_normalized(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> { |
450 | tcx.param_env(def_id).with_reveal_all_normalized(tcx) | |
451 | } | |
452 | ||
dfeec247 XL |
453 | fn instance_def_size_estimate<'tcx>( |
454 | tcx: TyCtxt<'tcx>, | |
455 | instance_def: ty::InstanceDef<'tcx>, | |
456 | ) -> usize { | |
457 | use ty::InstanceDef; | |
458 | ||
459 | match instance_def { | |
460 | InstanceDef::Item(..) | InstanceDef::DropGlue(..) => { | |
461 | let mir = tcx.instance_mir(instance_def); | |
f2b60f7d | 462 | mir.basic_blocks.iter().map(|bb| bb.statements.len() + 1).sum() |
dfeec247 XL |
463 | } |
464 | // Estimate the size of other compiler-generated shims to be 1. | |
465 | _ => 1, | |
466 | } | |
467 | } | |
468 | ||
469 | /// If `def_id` is an issue 33140 hack impl, returns its self type; otherwise, returns `None`. | |
470 | /// | |
f9f354fc | 471 | /// See [`ty::ImplOverlapKind::Issue33140`] for more details. |
9ffffee4 | 472 | fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option<EarlyBinder<Ty<'_>>> { |
dfeec247 XL |
473 | debug!("issue33140_self_ty({:?})", def_id); |
474 | ||
475 | let trait_ref = tcx | |
476 | .impl_trait_ref(def_id) | |
9c376795 FG |
477 | .unwrap_or_else(|| bug!("issue33140_self_ty called on inherent impl {:?}", def_id)) |
478 | .skip_binder(); | |
dfeec247 XL |
479 | |
480 | debug!("issue33140_self_ty({:?}), trait-ref={:?}", def_id, trait_ref); | |
481 | ||
482 | let is_marker_like = tcx.impl_polarity(def_id) == ty::ImplPolarity::Positive | |
483 | && tcx.associated_item_def_ids(trait_ref.def_id).is_empty(); | |
484 | ||
485 | // Check whether these impls would be ok for a marker trait. | |
486 | if !is_marker_like { | |
487 | debug!("issue33140_self_ty - not marker-like!"); | |
488 | return None; | |
489 | } | |
490 | ||
491 | // impl must be `impl Trait for dyn Marker1 + Marker2 + ...` | |
492 | if trait_ref.substs.len() != 1 { | |
493 | debug!("issue33140_self_ty - impl has substs!"); | |
494 | return None; | |
495 | } | |
496 | ||
497 | let predicates = tcx.predicates_of(def_id); | |
498 | if predicates.parent.is_some() || !predicates.predicates.is_empty() { | |
499 | debug!("issue33140_self_ty - impl has predicates {:?}!", predicates); | |
500 | return None; | |
501 | } | |
502 | ||
503 | let self_ty = trait_ref.self_ty(); | |
1b1a35ee | 504 | let self_ty_matches = match self_ty.kind() { |
f2b60f7d | 505 | ty::Dynamic(ref data, re, _) if re.is_static() => data.principal().is_none(), |
dfeec247 XL |
506 | _ => false, |
507 | }; | |
508 | ||
509 | if self_ty_matches { | |
510 | debug!("issue33140_self_ty - MATCHES!"); | |
9ffffee4 | 511 | Some(EarlyBinder(self_ty)) |
dfeec247 XL |
512 | } else { |
513 | debug!("issue33140_self_ty - non-matching self type"); | |
514 | None | |
515 | } | |
516 | } | |
517 | ||
518 | /// Check if a function is async. | |
353b0b11 FG |
519 | fn asyncness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::IsAsync { |
520 | let node = tcx.hir().get_by_def_id(def_id); | |
487cf647 | 521 | node.fn_sig().map_or(hir::IsAsync::NotAsync, |sig| sig.header.asyncness) |
6a06907d XL |
522 | } |
523 | ||
9ffffee4 FG |
524 | fn unsizing_params_for_adt<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> BitSet<u32> { |
525 | let def = tcx.adt_def(def_id); | |
526 | let num_params = tcx.generics_of(def_id).count(); | |
527 | ||
528 | let maybe_unsizing_param_idx = |arg: ty::GenericArg<'tcx>| match arg.unpack() { | |
529 | ty::GenericArgKind::Type(ty) => match ty.kind() { | |
530 | ty::Param(p) => Some(p.index), | |
531 | _ => None, | |
532 | }, | |
533 | ||
534 | // We can't unsize a lifetime | |
535 | ty::GenericArgKind::Lifetime(_) => None, | |
536 | ||
537 | ty::GenericArgKind::Const(ct) => match ct.kind() { | |
538 | ty::ConstKind::Param(p) => Some(p.index), | |
539 | _ => None, | |
540 | }, | |
541 | }; | |
542 | ||
543 | // The last field of the structure has to exist and contain type/const parameters. | |
544 | let Some((tail_field, prefix_fields)) = | |
353b0b11 | 545 | def.non_enum_variant().fields.raw.split_last() else |
9ffffee4 FG |
546 | { |
547 | return BitSet::new_empty(num_params); | |
548 | }; | |
549 | ||
550 | let mut unsizing_params = BitSet::new_empty(num_params); | |
551 | for arg in tcx.type_of(tail_field.did).subst_identity().walk() { | |
552 | if let Some(i) = maybe_unsizing_param_idx(arg) { | |
553 | unsizing_params.insert(i); | |
554 | } | |
555 | } | |
556 | ||
557 | // Ensure none of the other fields mention the parameters used | |
558 | // in unsizing. | |
559 | for field in prefix_fields { | |
560 | for arg in tcx.type_of(field.did).subst_identity().walk() { | |
561 | if let Some(i) = maybe_unsizing_param_idx(arg) { | |
562 | unsizing_params.remove(i); | |
563 | } | |
564 | } | |
565 | } | |
566 | ||
567 | unsizing_params | |
568 | } | |
569 | ||
49aad941 FG |
570 | pub fn provide(providers: &mut Providers) { |
571 | *providers = Providers { | |
dfeec247 | 572 | asyncness, |
dfeec247 | 573 | adt_sized_constraint, |
dfeec247 | 574 | param_env, |
3dfed10e | 575 | param_env_reveal_all_normalized, |
dfeec247 XL |
576 | instance_def_size_estimate, |
577 | issue33140_self_ty, | |
ba9703b0 | 578 | impl_defaultness, |
9ffffee4 | 579 | unsizing_params_for_adt, |
dfeec247 XL |
580 | ..*providers |
581 | }; | |
582 | } |