1 use rustc_data_structures
::fx
::FxIndexSet
;
2 use rustc_data_structures
::svh
::Svh
;
4 use rustc_hir
::def_id
::{CrateNum, DefId, LocalDefId, LOCAL_CRATE}
;
5 use rustc_middle
::hir
::map
as hir_map
;
6 use rustc_middle
::ty
::subst
::Subst
;
7 use rustc_middle
::ty
::{
8 self, Binder
, Predicate
, PredicateAtom
, PredicateKind
, ToPredicate
, Ty
, TyCtxt
, WithConstness
,
10 use rustc_session
::CrateDisambiguator
;
11 use rustc_span
::symbol
::Symbol
;
13 use rustc_trait_selection
::traits
;
15 fn sized_constraint_for_ty
<'tcx
>(
22 let result
= match ty
.kind() {
23 Bool
| Char
| Int(..) | Uint(..) | Float(..) | RawPtr(..) | Ref(..) | FnDef(..)
24 | FnPtr(_
) | Array(..) | Closure(..) | Generator(..) | Never
=> vec
![],
26 Str
| Dynamic(..) | Slice(_
) | Foreign(..) | Error(_
) | GeneratorWitness(..) => {
27 // these are never sized - return the target type
31 Tuple(ref tys
) => match tys
.last() {
33 Some(ty
) => sized_constraint_for_ty(tcx
, adtdef
, ty
.expect_ty()),
38 let adt_tys
= adt
.sized_constraint(tcx
);
39 debug
!("sized_constraint_for_ty({:?}) intermediate = {:?}", ty
, adt_tys
);
42 .map(|ty
| ty
.subst(tcx
, substs
))
43 .flat_map(|ty
| sized_constraint_for_ty(tcx
, adtdef
, ty
))
47 Projection(..) | Opaque(..) => {
48 // must calculate explicitly.
49 // FIXME: consider special-casing always-Sized projections
54 // perf hack: if there is a `T: Sized` bound, then
55 // we know that `T` is Sized and do not need to check
58 let sized_trait
= match tcx
.lang_items().sized_trait() {
62 let sized_predicate
= ty
::Binder
::dummy(ty
::TraitRef
{
64 substs
: tcx
.mk_substs_trait(ty
, &[]),
68 let predicates
= tcx
.predicates_of(adtdef
.did
).predicates
;
69 if predicates
.iter().any(|(p
, _
)| *p
== sized_predicate
) { vec![] }
else { vec![ty] }
72 Placeholder(..) | Bound(..) | Infer(..) => {
73 bug
!("unexpected type `{:?}` in sized_constraint_for_ty", ty
)
76 debug
!("sized_constraint_for_ty({:?}) = {:?}", ty
, result
);
80 fn associated_item_from_trait_item_ref(
82 parent_def_id
: LocalDefId
,
83 trait_item_ref
: &hir
::TraitItemRef
,
85 let def_id
= tcx
.hir().local_def_id(trait_item_ref
.id
.hir_id
);
86 let (kind
, has_self
) = match trait_item_ref
.kind
{
87 hir
::AssocItemKind
::Const
=> (ty
::AssocKind
::Const
, false),
88 hir
::AssocItemKind
::Fn { has_self }
=> (ty
::AssocKind
::Fn
, has_self
),
89 hir
::AssocItemKind
::Type
=> (ty
::AssocKind
::Type
, false),
93 ident
: trait_item_ref
.ident
,
95 vis
: tcx
.visibility(def_id
),
96 defaultness
: trait_item_ref
.defaultness
,
97 def_id
: def_id
.to_def_id(),
98 container
: ty
::TraitContainer(parent_def_id
.to_def_id()),
99 fn_has_self_parameter
: has_self
,
103 fn associated_item_from_impl_item_ref(
105 parent_def_id
: LocalDefId
,
106 impl_item_ref
: &hir
::ImplItemRef
<'_
>,
108 let def_id
= tcx
.hir().local_def_id(impl_item_ref
.id
.hir_id
);
109 let (kind
, has_self
) = match impl_item_ref
.kind
{
110 hir
::AssocItemKind
::Const
=> (ty
::AssocKind
::Const
, false),
111 hir
::AssocItemKind
::Fn { has_self }
=> (ty
::AssocKind
::Fn
, has_self
),
112 hir
::AssocItemKind
::Type
=> (ty
::AssocKind
::Type
, false),
116 ident
: impl_item_ref
.ident
,
118 vis
: tcx
.visibility(def_id
),
119 defaultness
: impl_item_ref
.defaultness
,
120 def_id
: def_id
.to_def_id(),
121 container
: ty
::ImplContainer(parent_def_id
.to_def_id()),
122 fn_has_self_parameter
: has_self
,
126 fn associated_item(tcx
: TyCtxt
<'_
>, def_id
: DefId
) -> ty
::AssocItem
{
127 let id
= tcx
.hir().local_def_id_to_hir_id(def_id
.expect_local());
128 let parent_id
= tcx
.hir().get_parent_item(id
);
129 let parent_def_id
= tcx
.hir().local_def_id(parent_id
);
130 let parent_item
= tcx
.hir().expect_item(parent_id
);
131 match parent_item
.kind
{
132 hir
::ItemKind
::Impl { ref items, .. }
=> {
133 if let Some(impl_item_ref
) = items
.iter().find(|i
| i
.id
.hir_id
== id
) {
135 associated_item_from_impl_item_ref(tcx
, parent_def_id
, impl_item_ref
);
136 debug_assert_eq
!(assoc_item
.def_id
, def_id
);
141 hir
::ItemKind
::Trait(.., ref trait_item_refs
) => {
142 if let Some(trait_item_ref
) = trait_item_refs
.iter().find(|i
| i
.id
.hir_id
== id
) {
144 associated_item_from_trait_item_ref(tcx
, parent_def_id
, trait_item_ref
);
145 debug_assert_eq
!(assoc_item
.def_id
, def_id
);
155 "unexpected parent of trait or impl item or item not found: {:?}",
160 fn impl_defaultness(tcx
: TyCtxt
<'_
>, def_id
: DefId
) -> hir
::Defaultness
{
161 let hir_id
= tcx
.hir().local_def_id_to_hir_id(def_id
.expect_local());
162 let item
= tcx
.hir().expect_item(hir_id
);
163 if let hir
::ItemKind
::Impl { defaultness, .. }
= item
.kind
{
166 bug
!("`impl_defaultness` called on {:?}", item
);
170 /// Calculates the `Sized` constraint.
172 /// In fact, there are only a few options for the types in the constraint:
173 /// - an obviously-unsized type
174 /// - a type parameter or projection whose Sizedness can't be known
175 /// - a tuple of type parameters or projections, if there are multiple
177 /// - a Error, if a type contained itself. The representability
178 /// check should catch this case.
179 fn adt_sized_constraint(tcx
: TyCtxt
<'_
>, def_id
: DefId
) -> ty
::AdtSizedConstraint
<'_
> {
180 let def
= tcx
.adt_def(def_id
);
182 let result
= tcx
.mk_type_list(
185 .flat_map(|v
| v
.fields
.last())
186 .flat_map(|f
| sized_constraint_for_ty(tcx
, def
, tcx
.type_of(f
.did
))),
189 debug
!("adt_sized_constraint: {:?} => {:?}", def
, result
);
191 ty
::AdtSizedConstraint(result
)
194 fn associated_item_def_ids(tcx
: TyCtxt
<'_
>, def_id
: DefId
) -> &[DefId
] {
195 let id
= tcx
.hir().local_def_id_to_hir_id(def_id
.expect_local());
196 let item
= tcx
.hir().expect_item(id
);
198 hir
::ItemKind
::Trait(.., ref trait_item_refs
) => tcx
.arena
.alloc_from_iter(
201 .map(|trait_item_ref
| trait_item_ref
.id
)
202 .map(|id
| tcx
.hir().local_def_id(id
.hir_id
).to_def_id()),
204 hir
::ItemKind
::Impl { ref items, .. }
=> tcx
.arena
.alloc_from_iter(
207 .map(|impl_item_ref
| impl_item_ref
.id
)
208 .map(|id
| tcx
.hir().local_def_id(id
.hir_id
).to_def_id()),
210 hir
::ItemKind
::TraitAlias(..) => &[],
211 _
=> span_bug
!(item
.span
, "associated_item_def_ids: not impl or trait"),
215 fn associated_items(tcx
: TyCtxt
<'_
>, def_id
: DefId
) -> ty
::AssociatedItems
<'_
> {
216 let items
= tcx
.associated_item_def_ids(def_id
).iter().map(|did
| tcx
.associated_item(*did
));
217 ty
::AssociatedItems
::new(items
)
220 fn def_span(tcx
: TyCtxt
<'_
>, def_id
: DefId
) -> Span
{
221 tcx
.hir().span_if_local(def_id
).unwrap()
224 /// If the given `DefId` describes an item belonging to a trait,
225 /// returns the `DefId` of the trait that the trait item belongs to;
226 /// otherwise, returns `None`.
227 fn trait_of_item(tcx
: TyCtxt
<'_
>, def_id
: DefId
) -> Option
<DefId
> {
228 tcx
.opt_associated_item(def_id
).and_then(|associated_item
| match associated_item
.container
{
229 ty
::TraitContainer(def_id
) => Some(def_id
),
230 ty
::ImplContainer(_
) => None
,
234 /// See `ParamEnv` struct definition for details.
235 fn param_env(tcx
: TyCtxt
<'_
>, def_id
: DefId
) -> ty
::ParamEnv
<'_
> {
236 // The param_env of an impl Trait type is its defining function's param_env
237 if let Some(parent
) = ty
::is_impl_trait_defn(tcx
, def_id
) {
238 return param_env(tcx
, parent
);
240 // Compute the bounds on Self and the type parameters.
242 let ty
::InstantiatedPredicates { mut predicates, .. }
=
243 tcx
.predicates_of(def_id
).instantiate_identity(tcx
);
245 // Finally, we have to normalize the bounds in the environment, in
246 // case they contain any associated type projections. This process
247 // can yield errors if the put in illegal associated types, like
248 // `<i32 as Foo>::Bar` where `i32` does not implement `Foo`. We
249 // report these errors right here; this doesn't actually feel
250 // right to me, because constructing the environment feels like a
251 // kind of a "idempotent" action, but I'm not sure where would be
252 // a better place. In practice, we construct environments for
253 // every fn once during type checking, and we'll abort if there
254 // are any errors at that point, so after type checking you can be
255 // sure that this will succeed without errors anyway.
257 if tcx
.sess
.opts
.debugging_opts
.chalk
{
258 let environment
= well_formed_types_in_env(tcx
, def_id
);
259 predicates
.extend(environment
);
262 let unnormalized_env
=
263 ty
::ParamEnv
::new(tcx
.intern_predicates(&predicates
), traits
::Reveal
::UserFacing
);
267 .map(|def_id
| tcx
.hir().local_def_id_to_hir_id(def_id
))
268 .map_or(hir
::CRATE_HIR_ID
, |id
| {
269 tcx
.hir().maybe_body_owned_by(id
).map_or(id
, |body
| body
.hir_id
)
271 let cause
= traits
::ObligationCause
::misc(tcx
.def_span(def_id
), body_id
);
272 traits
::normalize_param_env_or_error(tcx
, def_id
, unnormalized_env
, cause
)
275 /// Elaborate the environment.
277 /// Collect a list of `Predicate`'s used for building the `ParamEnv`. Adds `TypeWellFormedFromEnv`'s
278 /// that are assumed to be well-formed (because they come from the environment).
280 /// Used only in chalk mode.
281 fn well_formed_types_in_env
<'tcx
>(
284 ) -> &'tcx ty
::List
<Predicate
<'tcx
>> {
285 use rustc_hir
::{ForeignItemKind, ImplItemKind, ItemKind, Node, TraitItemKind}
;
286 use rustc_middle
::ty
::subst
::GenericArgKind
;
288 debug
!("environment(def_id = {:?})", def_id
);
290 // The environment of an impl Trait type is its defining function's environment.
291 if let Some(parent
) = ty
::is_impl_trait_defn(tcx
, def_id
) {
292 return well_formed_types_in_env(tcx
, parent
);
295 // Compute the bounds on `Self` and the type parameters.
296 let ty
::InstantiatedPredicates { predicates, .. }
=
297 tcx
.predicates_of(def_id
).instantiate_identity(tcx
);
299 let clauses
= predicates
.into_iter();
301 if !def_id
.is_local() {
302 return ty
::List
::empty();
304 let hir_id
= tcx
.hir().local_def_id_to_hir_id(def_id
.expect_local());
305 let node
= tcx
.hir().get(hir_id
);
314 let node_kind
= match node
{
315 Node
::TraitItem(item
) => match item
.kind
{
316 TraitItemKind
::Fn(..) => NodeKind
::Fn
,
317 _
=> NodeKind
::Other
,
320 Node
::ImplItem(item
) => match item
.kind
{
321 ImplItemKind
::Fn(..) => NodeKind
::Fn
,
322 _
=> NodeKind
::Other
,
325 Node
::Item(item
) => match item
.kind
{
326 ItemKind
::Impl { of_trait: Some(_), .. }
=> NodeKind
::TraitImpl
,
327 ItemKind
::Impl { of_trait: None, .. }
=> NodeKind
::InherentImpl
,
328 ItemKind
::Fn(..) => NodeKind
::Fn
,
329 _
=> NodeKind
::Other
,
332 Node
::ForeignItem(item
) => match item
.kind
{
333 ForeignItemKind
::Fn(..) => NodeKind
::Fn
,
334 _
=> NodeKind
::Other
,
338 _
=> NodeKind
::Other
,
341 // FIXME(eddyb) isn't the unordered nature of this a hazard?
342 let mut inputs
= FxIndexSet
::default();
345 // In a trait impl, we assume that the header trait ref and all its
346 // constituents are well-formed.
347 NodeKind
::TraitImpl
=> {
348 let trait_ref
= tcx
.impl_trait_ref(def_id
).expect("not an impl");
350 // FIXME(chalk): this has problems because of late-bound regions
351 //inputs.extend(trait_ref.substs.iter().flat_map(|arg| arg.walk()));
352 inputs
.extend(trait_ref
.substs
.iter());
355 // In an inherent impl, we assume that the receiver type and all its
356 // constituents are well-formed.
357 NodeKind
::InherentImpl
=> {
358 let self_ty
= tcx
.type_of(def_id
);
359 inputs
.extend(self_ty
.walk());
362 // In an fn, we assume that the arguments and all their constituents are
365 let fn_sig
= tcx
.fn_sig(def_id
);
366 let fn_sig
= tcx
.liberate_late_bound_regions(def_id
, &fn_sig
);
368 inputs
.extend(fn_sig
.inputs().iter().flat_map(|ty
| ty
.walk()));
371 NodeKind
::Other
=> (),
373 let input_clauses
= inputs
.into_iter().filter_map(|arg
| {
375 GenericArgKind
::Type(ty
) => {
376 let binder
= Binder
::dummy(PredicateAtom
::TypeWellFormedFromEnv(ty
));
377 Some(tcx
.mk_predicate(PredicateKind
::ForAll(binder
)))
380 // FIXME(eddyb) no WF conditions from lifetimes?
381 GenericArgKind
::Lifetime(_
) => None
,
383 // FIXME(eddyb) support const generics in Chalk
384 GenericArgKind
::Const(_
) => None
,
388 tcx
.mk_predicates(clauses
.chain(input_clauses
))
391 fn param_env_reveal_all_normalized(tcx
: TyCtxt
<'_
>, def_id
: DefId
) -> ty
::ParamEnv
<'_
> {
392 tcx
.param_env(def_id
).with_reveal_all_normalized(tcx
)
395 fn crate_disambiguator(tcx
: TyCtxt
<'_
>, crate_num
: CrateNum
) -> CrateDisambiguator
{
396 assert_eq
!(crate_num
, LOCAL_CRATE
);
397 tcx
.sess
.local_crate_disambiguator()
400 fn original_crate_name(tcx
: TyCtxt
<'_
>, crate_num
: CrateNum
) -> Symbol
{
401 assert_eq
!(crate_num
, LOCAL_CRATE
);
405 fn crate_hash(tcx
: TyCtxt
<'_
>, crate_num
: CrateNum
) -> Svh
{
406 tcx
.index_hir(crate_num
).crate_hash
409 fn instance_def_size_estimate
<'tcx
>(
411 instance_def
: ty
::InstanceDef
<'tcx
>,
416 InstanceDef
::Item(..) | InstanceDef
::DropGlue(..) => {
417 let mir
= tcx
.instance_mir(instance_def
);
418 mir
.basic_blocks().iter().map(|bb
| bb
.statements
.len()).sum()
420 // Estimate the size of other compiler-generated shims to be 1.
425 /// If `def_id` is an issue 33140 hack impl, returns its self type; otherwise, returns `None`.
427 /// See [`ty::ImplOverlapKind::Issue33140`] for more details.
428 fn issue33140_self_ty(tcx
: TyCtxt
<'_
>, def_id
: DefId
) -> Option
<Ty
<'_
>> {
429 debug
!("issue33140_self_ty({:?})", def_id
);
432 .impl_trait_ref(def_id
)
433 .unwrap_or_else(|| bug
!("issue33140_self_ty called on inherent impl {:?}", def_id
));
435 debug
!("issue33140_self_ty({:?}), trait-ref={:?}", def_id
, trait_ref
);
437 let is_marker_like
= tcx
.impl_polarity(def_id
) == ty
::ImplPolarity
::Positive
438 && tcx
.associated_item_def_ids(trait_ref
.def_id
).is_empty();
440 // Check whether these impls would be ok for a marker trait.
442 debug
!("issue33140_self_ty - not marker-like!");
446 // impl must be `impl Trait for dyn Marker1 + Marker2 + ...`
447 if trait_ref
.substs
.len() != 1 {
448 debug
!("issue33140_self_ty - impl has substs!");
452 let predicates
= tcx
.predicates_of(def_id
);
453 if predicates
.parent
.is_some() || !predicates
.predicates
.is_empty() {
454 debug
!("issue33140_self_ty - impl has predicates {:?}!", predicates
);
458 let self_ty
= trait_ref
.self_ty();
459 let self_ty_matches
= match self_ty
.kind() {
460 ty
::Dynamic(ref data
, ty
::ReStatic
) => data
.principal().is_none(),
465 debug
!("issue33140_self_ty - MATCHES!");
468 debug
!("issue33140_self_ty - non-matching self type");
473 /// Check if a function is async.
474 fn asyncness(tcx
: TyCtxt
<'_
>, def_id
: DefId
) -> hir
::IsAsync
{
475 let hir_id
= tcx
.hir().local_def_id_to_hir_id(def_id
.expect_local());
477 let node
= tcx
.hir().get(hir_id
);
479 let fn_like
= hir_map
::blocks
::FnLikeNode
::from_node(node
).unwrap_or_else(|| {
480 bug
!("asyncness: expected fn-like node but got `{:?}`", def_id
);
486 pub fn provide(providers
: &mut ty
::query
::Providers
) {
487 *providers
= ty
::query
::Providers
{
490 associated_item_def_ids
,
492 adt_sized_constraint
,
495 param_env_reveal_all_normalized
,
500 instance_def_size_estimate
,