1 use rustc_data_structures
::fx
::FxIndexSet
;
3 use rustc_hir
::def_id
::DefId
;
4 use rustc_middle
::ty
::subst
::Subst
;
5 use rustc_middle
::ty
::{
6 self, Binder
, EarlyBinder
, Predicate
, PredicateKind
, ToPredicate
, Ty
, TyCtxt
,
8 use rustc_span
::{sym, Span}
;
9 use rustc_trait_selection
::traits
;
11 fn sized_constraint_for_ty
<'tcx
>(
13 adtdef
: ty
::AdtDef
<'tcx
>,
18 let result
= match ty
.kind() {
19 Bool
| Char
| Int(..) | Uint(..) | Float(..) | RawPtr(..) | Ref(..) | FnDef(..)
20 | FnPtr(_
) | Array(..) | Closure(..) | Generator(..) | Never
=> vec
![],
22 Str
| Dynamic(..) | Slice(_
) | Foreign(..) | Error(_
) | GeneratorWitness(..) => {
23 // these are never sized - return the target type
27 Tuple(ref tys
) => match tys
.last() {
29 Some(&ty
) => sized_constraint_for_ty(tcx
, adtdef
, ty
),
34 let adt_tys
= adt
.sized_constraint(tcx
);
35 debug
!("sized_constraint_for_ty({:?}) intermediate = {:?}", ty
, adt_tys
);
38 .map(|ty
| EarlyBinder(*ty
).subst(tcx
, substs
))
39 .flat_map(|ty
| sized_constraint_for_ty(tcx
, adtdef
, ty
))
43 Projection(..) | Opaque(..) => {
44 // must calculate explicitly.
45 // FIXME: consider special-casing always-Sized projections
50 // perf hack: if there is a `T: Sized` bound, then
51 // we know that `T` is Sized and do not need to check
54 let Some(sized_trait
) = tcx
.lang_items().sized_trait() else { return vec![ty] }
;
55 let sized_predicate
= ty
::Binder
::dummy(ty
::TraitRef
{
57 substs
: tcx
.mk_substs_trait(ty
, &[]),
61 let predicates
= tcx
.predicates_of(adtdef
.did()).predicates
;
62 if predicates
.iter().any(|(p
, _
)| *p
== sized_predicate
) { vec![] }
else { vec![ty] }
65 Placeholder(..) | Bound(..) | Infer(..) => {
66 bug
!("unexpected type `{:?}` in sized_constraint_for_ty", ty
)
69 debug
!("sized_constraint_for_ty({:?}) = {:?}", ty
, result
);
73 fn impl_defaultness(tcx
: TyCtxt
<'_
>, def_id
: DefId
) -> hir
::Defaultness
{
74 let item
= tcx
.hir().expect_item(def_id
.expect_local());
75 if let hir
::ItemKind
::Impl(impl_
) = &item
.kind
{
78 bug
!("`impl_defaultness` called on {:?}", item
);
82 /// Calculates the `Sized` constraint.
84 /// In fact, there are only a few options for the types in the constraint:
85 /// - an obviously-unsized type
86 /// - a type parameter or projection whose Sizedness can't be known
87 /// - a tuple of type parameters or projections, if there are multiple
89 /// - an Error, if a type contained itself. The representability
90 /// check should catch this case.
91 fn adt_sized_constraint(tcx
: TyCtxt
<'_
>, def_id
: DefId
) -> ty
::AdtSizedConstraint
<'_
> {
92 let def
= tcx
.adt_def(def_id
);
94 let result
= tcx
.mk_type_list(
97 .flat_map(|v
| v
.fields
.last())
98 .flat_map(|f
| sized_constraint_for_ty(tcx
, def
, tcx
.type_of(f
.did
))),
101 debug
!("adt_sized_constraint: {:?} => {:?}", def
, result
);
103 ty
::AdtSizedConstraint(result
)
106 fn def_ident_span(tcx
: TyCtxt
<'_
>, def_id
: DefId
) -> Option
<Span
> {
108 .get_if_local(def_id
)
109 .and_then(|node
| match node
{
110 // A `Ctor` doesn't have an identifier itself, but its parent
111 // struct/variant does. Compare with `hir::Map::opt_span`.
112 hir
::Node
::Ctor(ctor
) => ctor
114 .and_then(|ctor_id
| tcx
.hir().find(tcx
.hir().get_parent_node(ctor_id
)))
115 .and_then(|parent
| parent
.ident()),
118 .map(|ident
| ident
.span
)
121 /// See `ParamEnv` struct definition for details.
122 #[instrument(level = "debug", skip(tcx))]
123 fn param_env(tcx
: TyCtxt
<'_
>, def_id
: DefId
) -> ty
::ParamEnv
<'_
> {
124 // The param_env of an impl Trait type is its defining function's param_env
125 if let Some(parent
) = ty
::is_impl_trait_defn(tcx
, def_id
) {
126 return param_env(tcx
, parent
.to_def_id());
128 // Compute the bounds on Self and the type parameters.
130 let ty
::InstantiatedPredicates { mut predicates, .. }
=
131 tcx
.predicates_of(def_id
).instantiate_identity(tcx
);
133 // Finally, we have to normalize the bounds in the environment, in
134 // case they contain any associated type projections. This process
135 // can yield errors if the put in illegal associated types, like
136 // `<i32 as Foo>::Bar` where `i32` does not implement `Foo`. We
137 // report these errors right here; this doesn't actually feel
138 // right to me, because constructing the environment feels like a
139 // kind of an "idempotent" action, but I'm not sure where would be
140 // a better place. In practice, we construct environments for
141 // every fn once during type checking, and we'll abort if there
142 // are any errors at that point, so outside of type inference you can be
143 // sure that this will succeed without errors anyway.
145 if tcx
.sess
.opts
.debugging_opts
.chalk
{
146 let environment
= well_formed_types_in_env(tcx
, def_id
);
147 predicates
.extend(environment
);
150 let local_did
= def_id
.as_local();
151 let hir_id
= local_did
.map(|def_id
| tcx
.hir().local_def_id_to_hir_id(def_id
));
153 let constness
= match hir_id
{
154 Some(hir_id
) => match tcx
.hir().get(hir_id
) {
155 hir
::Node
::TraitItem(hir
::TraitItem { kind: hir::TraitItemKind::Fn(..), .. }
)
156 if tcx
.has_attr(def_id
, sym
::default_method_body_is_const
) =>
158 hir
::Constness
::Const
161 hir
::Node
::Item(hir
::Item { kind: hir::ItemKind::Const(..), .. }
)
162 | hir
::Node
::Item(hir
::Item { kind: hir::ItemKind::Static(..), .. }
)
163 | hir
::Node
::TraitItem(hir
::TraitItem
{
164 kind
: hir
::TraitItemKind
::Const(..), ..
166 | hir
::Node
::AnonConst(_
)
167 | hir
::Node
::ImplItem(hir
::ImplItem { kind: hir::ImplItemKind::Const(..), .. }
)
168 | hir
::Node
::ImplItem(hir
::ImplItem
{
170 hir
::ImplItemKind
::Fn(
172 header
: hir
::FnHeader { constness: hir::Constness::Const, .. }
,
178 }) => hir
::Constness
::Const
,
180 hir
::Node
::ImplItem(hir
::ImplItem
{
181 kind
: hir
::ImplItemKind
::TyAlias(..) | hir
::ImplItemKind
::Fn(..),
184 let parent_hir_id
= tcx
.hir().get_parent_node(hir_id
);
185 match tcx
.hir().get(parent_hir_id
) {
186 hir
::Node
::Item(hir
::Item
{
187 kind
: hir
::ItemKind
::Impl(hir
::Impl { constness, .. }
),
191 tcx
.def_span(parent_hir_id
.owner
),
192 "impl item's parent node is not an impl",
197 hir
::Node
::Item(hir
::Item
{
199 hir
::ItemKind
::Fn(hir
::FnSig { header: hir::FnHeader { constness, .. }
, .. }, ..),
202 | hir
::Node
::TraitItem(hir
::TraitItem
{
204 hir
::TraitItemKind
::Fn(
205 hir
::FnSig { header: hir::FnHeader { constness, .. }
, .. },
210 | hir
::Node
::Item(hir
::Item
{
211 kind
: hir
::ItemKind
::Impl(hir
::Impl { constness, .. }
),
215 _
=> hir
::Constness
::NotConst
,
217 None
=> hir
::Constness
::NotConst
,
220 let unnormalized_env
= ty
::ParamEnv
::new(
221 tcx
.intern_predicates(&predicates
),
222 traits
::Reveal
::UserFacing
,
226 let body_id
= hir_id
.map_or(hir
::CRATE_HIR_ID
, |id
| {
227 tcx
.hir().maybe_body_owned_by(id
).map_or(id
, |body
| body
.hir_id
)
229 let cause
= traits
::ObligationCause
::misc(tcx
.def_span(def_id
), body_id
);
230 traits
::normalize_param_env_or_error(tcx
, def_id
, unnormalized_env
, cause
)
233 /// Elaborate the environment.
235 /// Collect a list of `Predicate`'s used for building the `ParamEnv`. Adds `TypeWellFormedFromEnv`'s
236 /// that are assumed to be well-formed (because they come from the environment).
238 /// Used only in chalk mode.
239 fn well_formed_types_in_env
<'tcx
>(
242 ) -> &'tcx ty
::List
<Predicate
<'tcx
>> {
243 use rustc_hir
::{ForeignItemKind, ImplItemKind, ItemKind, Node, TraitItemKind}
;
244 use rustc_middle
::ty
::subst
::GenericArgKind
;
246 debug
!("environment(def_id = {:?})", def_id
);
248 // The environment of an impl Trait type is its defining function's environment.
249 if let Some(parent
) = ty
::is_impl_trait_defn(tcx
, def_id
) {
250 return well_formed_types_in_env(tcx
, parent
.to_def_id());
253 // Compute the bounds on `Self` and the type parameters.
254 let ty
::InstantiatedPredicates { predicates, .. }
=
255 tcx
.predicates_of(def_id
).instantiate_identity(tcx
);
257 let clauses
= predicates
.into_iter();
259 if !def_id
.is_local() {
260 return ty
::List
::empty();
262 let node
= tcx
.hir().get_by_def_id(def_id
.expect_local());
271 let node_kind
= match node
{
272 Node
::TraitItem(item
) => match item
.kind
{
273 TraitItemKind
::Fn(..) => NodeKind
::Fn
,
274 _
=> NodeKind
::Other
,
277 Node
::ImplItem(item
) => match item
.kind
{
278 ImplItemKind
::Fn(..) => NodeKind
::Fn
,
279 _
=> NodeKind
::Other
,
282 Node
::Item(item
) => match item
.kind
{
283 ItemKind
::Impl(hir
::Impl { of_trait: Some(_), .. }
) => NodeKind
::TraitImpl
,
284 ItemKind
::Impl(hir
::Impl { of_trait: None, .. }
) => NodeKind
::InherentImpl
,
285 ItemKind
::Fn(..) => NodeKind
::Fn
,
286 _
=> NodeKind
::Other
,
289 Node
::ForeignItem(item
) => match item
.kind
{
290 ForeignItemKind
::Fn(..) => NodeKind
::Fn
,
291 _
=> NodeKind
::Other
,
295 _
=> NodeKind
::Other
,
298 // FIXME(eddyb) isn't the unordered nature of this a hazard?
299 let mut inputs
= FxIndexSet
::default();
302 // In a trait impl, we assume that the header trait ref and all its
303 // constituents are well-formed.
304 NodeKind
::TraitImpl
=> {
305 let trait_ref
= tcx
.impl_trait_ref(def_id
).expect("not an impl");
307 // FIXME(chalk): this has problems because of late-bound regions
308 //inputs.extend(trait_ref.substs.iter().flat_map(|arg| arg.walk()));
309 inputs
.extend(trait_ref
.substs
.iter());
312 // In an inherent impl, we assume that the receiver type and all its
313 // constituents are well-formed.
314 NodeKind
::InherentImpl
=> {
315 let self_ty
= tcx
.type_of(def_id
);
316 inputs
.extend(self_ty
.walk());
319 // In an fn, we assume that the arguments and all their constituents are
322 let fn_sig
= tcx
.fn_sig(def_id
);
323 let fn_sig
= tcx
.liberate_late_bound_regions(def_id
, fn_sig
);
325 inputs
.extend(fn_sig
.inputs().iter().flat_map(|ty
| ty
.walk()));
328 NodeKind
::Other
=> (),
330 let input_clauses
= inputs
.into_iter().filter_map(|arg
| {
332 GenericArgKind
::Type(ty
) => {
333 let binder
= Binder
::dummy(PredicateKind
::TypeWellFormedFromEnv(ty
));
334 Some(tcx
.mk_predicate(binder
))
337 // FIXME(eddyb) no WF conditions from lifetimes?
338 GenericArgKind
::Lifetime(_
) => None
,
340 // FIXME(eddyb) support const generics in Chalk
341 GenericArgKind
::Const(_
) => None
,
345 tcx
.mk_predicates(clauses
.chain(input_clauses
))
348 fn param_env_reveal_all_normalized(tcx
: TyCtxt
<'_
>, def_id
: DefId
) -> ty
::ParamEnv
<'_
> {
349 tcx
.param_env(def_id
).with_reveal_all_normalized(tcx
)
352 fn instance_def_size_estimate
<'tcx
>(
354 instance_def
: ty
::InstanceDef
<'tcx
>,
359 InstanceDef
::Item(..) | InstanceDef
::DropGlue(..) => {
360 let mir
= tcx
.instance_mir(instance_def
);
361 mir
.basic_blocks().iter().map(|bb
| bb
.statements
.len() + 1).sum()
363 // Estimate the size of other compiler-generated shims to be 1.
368 /// If `def_id` is an issue 33140 hack impl, returns its self type; otherwise, returns `None`.
370 /// See [`ty::ImplOverlapKind::Issue33140`] for more details.
371 fn issue33140_self_ty(tcx
: TyCtxt
<'_
>, def_id
: DefId
) -> Option
<Ty
<'_
>> {
372 debug
!("issue33140_self_ty({:?})", def_id
);
375 .impl_trait_ref(def_id
)
376 .unwrap_or_else(|| bug
!("issue33140_self_ty called on inherent impl {:?}", def_id
));
378 debug
!("issue33140_self_ty({:?}), trait-ref={:?}", def_id
, trait_ref
);
380 let is_marker_like
= tcx
.impl_polarity(def_id
) == ty
::ImplPolarity
::Positive
381 && tcx
.associated_item_def_ids(trait_ref
.def_id
).is_empty();
383 // Check whether these impls would be ok for a marker trait.
385 debug
!("issue33140_self_ty - not marker-like!");
389 // impl must be `impl Trait for dyn Marker1 + Marker2 + ...`
390 if trait_ref
.substs
.len() != 1 {
391 debug
!("issue33140_self_ty - impl has substs!");
395 let predicates
= tcx
.predicates_of(def_id
);
396 if predicates
.parent
.is_some() || !predicates
.predicates
.is_empty() {
397 debug
!("issue33140_self_ty - impl has predicates {:?}!", predicates
);
401 let self_ty
= trait_ref
.self_ty();
402 let self_ty_matches
= match self_ty
.kind() {
403 ty
::Dynamic(ref data
, re
) if re
.is_static() => data
.principal().is_none(),
408 debug
!("issue33140_self_ty - MATCHES!");
411 debug
!("issue33140_self_ty - non-matching self type");
416 /// Check if a function is async.
417 fn asyncness(tcx
: TyCtxt
<'_
>, def_id
: DefId
) -> hir
::IsAsync
{
418 let node
= tcx
.hir().get_by_def_id(def_id
.expect_local());
419 if let Some(fn_kind
) = node
.fn_kind() { fn_kind.asyncness() }
else { hir::IsAsync::NotAsync }
422 /// Don't call this directly: use ``tcx.conservative_is_privately_uninhabited`` instead.
423 #[instrument(level = "debug", skip(tcx))]
424 pub fn conservative_is_privately_uninhabited_raw
<'tcx
>(
426 param_env_and
: ty
::ParamEnvAnd
<'tcx
, Ty
<'tcx
>>,
428 let (param_env
, ty
) = param_env_and
.into_parts();
431 debug
!("ty::Never =>");
434 ty
::Adt(def
, _
) if def
.is_union() => {
435 debug
!("ty::Adt(def, _) if def.is_union() =>");
436 // For now, `union`s are never considered uninhabited.
439 ty
::Adt(def
, substs
) => {
440 debug
!("ty::Adt(def, _) if def.is_not_union() =>");
441 // Any ADT is uninhabited if either:
442 // (a) It has no variants (i.e. an empty `enum`);
443 // (b) Each of its variants (a single one in the case of a `struct`) has at least
444 // one uninhabited field.
445 def
.variants().iter().all(|var
| {
446 var
.fields
.iter().any(|field
| {
447 let ty
= tcx
.bound_type_of(field
.did
).subst(tcx
, substs
);
448 tcx
.conservative_is_privately_uninhabited(param_env
.and(ty
))
452 ty
::Tuple(fields
) => {
453 debug
!("ty::Tuple(..) =>");
454 fields
.iter().any(|ty
| tcx
.conservative_is_privately_uninhabited(param_env
.and(ty
)))
456 ty
::Array(ty
, len
) => {
457 debug
!("ty::Array(ty, len) =>");
458 match len
.try_eval_usize(tcx
, param_env
) {
459 Some(0) | None
=> false,
460 // If the array is definitely non-empty, it's uninhabited if
461 // the type of its elements is uninhabited.
462 Some(1..) => tcx
.conservative_is_privately_uninhabited(param_env
.and(*ty
)),
466 debug
!("ty::Ref(..) =>");
467 // References to uninitialised memory is valid for any type, including
468 // uninhabited types, in unsafe code, so we treat all references as
479 pub fn provide(providers
: &mut ty
::query
::Providers
) {
480 *providers
= ty
::query
::Providers
{
482 adt_sized_constraint
,
485 param_env_reveal_all_normalized
,
486 instance_def_size_estimate
,
489 conservative_is_privately_uninhabited
: conservative_is_privately_uninhabited_raw
,