2019-02-08 14:53:55 +01:00
|
|
|
//! Type context book-keeping.
|
2015-09-06 21:51:58 +03:00
|
|
|
|
2022-11-25 16:55:25 +00:00
|
|
|
#![allow(rustc::usage_of_ty_tykind)]
|
|
|
|
|
2022-12-31 11:00:41 +01:00
|
|
|
pub mod tls;
|
|
|
|
|
2019-03-29 17:49:11 +01:00
|
|
|
use crate::arena::Arena;
|
2022-09-11 23:18:08 -05:00
|
|
|
use crate::dep_graph::{DepGraph, DepKindStruct};
|
2023-02-17 14:24:13 +11:00
|
|
|
use crate::infer::canonical::CanonicalVarInfo;
|
2022-09-24 16:11:18 +02:00
|
|
|
use crate::lint::struct_lint_level;
|
2022-05-09 17:47:02 +02:00
|
|
|
use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
|
2023-02-06 18:38:52 +00:00
|
|
|
use crate::middle::resolve_bound_vars;
|
2019-02-05 11:20:45 -06:00
|
|
|
use crate::middle::stability;
|
2022-02-16 10:56:01 +01:00
|
|
|
use crate::mir::interpret::{self, Allocation, ConstAllocation};
|
2022-02-06 12:16:49 -08:00
|
|
|
use crate::mir::{
|
|
|
|
Body, BorrowCheckResult, Field, Local, Place, PlaceElem, ProjectionKind, Promoted,
|
|
|
|
};
|
2021-04-04 18:42:17 +02:00
|
|
|
use crate::thir::Thir;
|
2019-02-05 11:20:45 -06:00
|
|
|
use crate::traits;
|
2023-02-24 02:35:15 +00:00
|
|
|
use crate::traits::solve;
|
2023-02-03 02:29:52 +00:00
|
|
|
use crate::traits::solve::{ExternalConstraints, ExternalConstraintsData};
|
2021-06-28 21:12:01 +02:00
|
|
|
use crate::ty::query::{self, TyCtxtAt};
|
2020-05-26 13:13:19 -07:00
|
|
|
use crate::ty::{
|
2023-02-22 19:51:17 +04:00
|
|
|
self, AdtDef, AdtDefData, AdtKind, Binder, Const, ConstData, FloatTy, FloatVar, FloatVid,
|
|
|
|
GenericParamDefKind, ImplPolarity, InferTy, IntTy, IntVar, IntVid, List, ParamConst, ParamTy,
|
|
|
|
PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, Region, RegionKind, ReprOptions,
|
|
|
|
TraitObjectVisitor, Ty, TyKind, TyVar, TyVid, TypeAndMut, TypeckResults, UintTy, Visibility,
|
2020-05-26 13:13:19 -07:00
|
|
|
};
|
2022-12-15 20:40:16 +01:00
|
|
|
use crate::ty::{GenericArg, InternalSubsts, SubstsRef};
|
2020-04-27 23:26:11 +05:30
|
|
|
use rustc_ast as ast;
|
2022-02-23 18:02:06 +00:00
|
|
|
use rustc_data_structures::fingerprint::Fingerprint;
|
2019-12-24 05:02:53 +01:00
|
|
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
2022-11-25 16:38:16 +00:00
|
|
|
use rustc_data_structures::intern::Interned;
|
2021-03-16 21:39:03 +01:00
|
|
|
use rustc_data_structures::memmap::Mmap;
|
2019-11-11 17:15:36 -05:00
|
|
|
use rustc_data_structures::profiling::SelfProfilerRef;
|
2020-01-02 00:44:34 +01:00
|
|
|
use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap};
|
2021-05-11 10:38:54 +02:00
|
|
|
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
2020-11-14 01:29:30 +01:00
|
|
|
use rustc_data_structures::steal::Steal;
|
2022-12-08 10:53:20 +00:00
|
|
|
use rustc_data_structures::sync::{self, Lock, Lrc, MappedReadGuard, ReadGuard, WorkerLocal};
|
2023-02-21 15:18:10 +01:00
|
|
|
use rustc_data_structures::unord::UnordSet;
|
2022-09-16 11:01:02 +04:00
|
|
|
use rustc_errors::{
|
|
|
|
DecorateLint, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed, MultiSpan,
|
|
|
|
};
|
2020-01-11 15:03:15 +01:00
|
|
|
use rustc_hir as hir;
|
2022-12-15 20:40:16 +01:00
|
|
|
use rustc_hir::def::DefKind;
|
|
|
|
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
|
2021-07-12 22:19:25 +02:00
|
|
|
use rustc_hir::definitions::Definitions;
|
2020-06-09 13:57:33 -07:00
|
|
|
use rustc_hir::intravisit::Visitor;
|
2020-08-18 11:47:27 +01:00
|
|
|
use rustc_hir::lang_items::LangItem;
|
2020-11-22 02:13:53 +01:00
|
|
|
use rustc_hir::{
|
2022-12-15 20:40:16 +01:00
|
|
|
Constness, ExprKind, HirId, ImplItemKind, ItemKind, Node, TraitCandidate, TraitItemKind,
|
2020-11-22 02:13:53 +01:00
|
|
|
};
|
2022-12-15 20:40:16 +01:00
|
|
|
use rustc_index::vec::IndexVec;
|
2019-12-24 17:38:22 -05:00
|
|
|
use rustc_macros::HashStable;
|
2022-11-26 13:54:45 +00:00
|
|
|
use rustc_query_system::dep_graph::DepNodeIndex;
|
2022-04-04 22:19:25 +02:00
|
|
|
use rustc_query_system::ich::StableHashingContext;
|
2020-12-06 17:30:55 -08:00
|
|
|
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
|
2022-12-05 17:00:26 +00:00
|
|
|
use rustc_session::config::CrateType;
|
2022-12-07 14:31:50 +00:00
|
|
|
use rustc_session::cstore::{CrateStoreDyn, Untracked};
|
2022-09-24 16:11:18 +02:00
|
|
|
use rustc_session::lint::Lint;
|
2021-07-04 13:02:51 -05:00
|
|
|
use rustc_session::Limit;
|
2020-01-11 15:03:15 +01:00
|
|
|
use rustc_session::Session;
|
2021-06-28 21:12:01 +02:00
|
|
|
use rustc_span::def_id::{DefPathHash, StableCrateId};
|
2022-03-24 02:03:04 +00:00
|
|
|
use rustc_span::source_map::SourceMap;
|
2020-12-03 20:10:55 -03:00
|
|
|
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
2020-05-05 23:02:09 -05:00
|
|
|
use rustc_span::{Span, DUMMY_SP};
|
2022-03-04 13:46:56 +11:00
|
|
|
use rustc_target::abi::{Layout, LayoutS, TargetDataLayout, VariantIdx};
|
2019-12-24 17:38:22 -05:00
|
|
|
use rustc_target::spec::abi;
|
2021-01-31 10:32:34 +01:00
|
|
|
use rustc_type_ir::sty::TyKind::*;
|
2022-11-25 16:38:16 +00:00
|
|
|
use rustc_type_ir::WithCachedTypeInfo;
|
Clarify iterator interners.
There are two traits, `InternAs` and `InternIteratorElement`. I found
them confusing to use, particularly this:
```
pub fn mk_tup<I: InternAs<Ty<'tcx>, Ty<'tcx>>>(self, iter: I) -> I::Output {
iter.intern_with(|ts| self.intern_tup(ts))
}
```
where I thought there might have been two levels of interning going on
(there isn't) due to the `intern_with`/`InternAs` + `intern_tup` naming.
And then I found the actual traits and impls themselves *very*
confusing.
- `InternAs` has a single impl, for iterators, with four type variables.
- `InternAs` is only implemented for iterators because it wouldn't
really make sense to implement for any other type. And you can't
really understand the trait without seeing that single impl, which is
suspicious.
- `InternAs` is basically just a wrapper for `InternIteratorElement`
which does all the actual work.
- Neither trait actually does any interning. They just have `Intern` in
their name because they are used *by* interning code.
- There are no comments.
So this commit improves things.
- It removes `InternAs` completely. This makes the `mk_*` function
signatures slightly more verbose -- two trait bounds instead of one --
but much easier to read, because you only need to understand one trait
instead of two.
- It renames `InternIteratorElement` as `CollectAndApply`. Likewise, it
renames its method `intern_with` as `collect_and_apply`. These names
describe better what's going on: we collect the iterator elements into
a slice and then apply a function to the slice.
- It adds comments, making clear that all this is all there just to
provide an optimized version of `f(&iter.collect::<Vec<_>>())`.
It took me a couple of attempts to come up with this commit. My initial
attempt kept `InternAs` around, but renamed things and added comments,
and I wasn't happy with it. I think this version is much better. The
resulting code is shorter, despite the addition of the comments.
2023-02-16 12:06:36 +11:00
|
|
|
use rustc_type_ir::{CollectAndApply, DynKind, Interner, TypeFlags};
|
2020-01-11 15:03:15 +01:00
|
|
|
|
2017-09-07 13:21:46 -07:00
|
|
|
use std::any::Any;
|
2023-03-14 22:56:20 +00:00
|
|
|
use std::assert_matches::debug_assert_matches;
|
2015-09-06 21:51:58 +03:00
|
|
|
use std::borrow::Borrow;
|
2017-04-27 13:04:57 -04:00
|
|
|
use std::cmp::Ordering;
|
2018-06-27 06:01:19 -04:00
|
|
|
use std::fmt;
|
2019-12-24 17:38:22 -05:00
|
|
|
use std::hash::{Hash, Hasher};
|
2016-10-24 18:23:29 -06:00
|
|
|
use std::iter;
|
2019-12-24 17:38:22 -05:00
|
|
|
use std::mem;
|
|
|
|
use std::ops::{Bound, Deref};
|
2015-09-06 21:51:58 +03:00
|
|
|
|
2022-12-29 23:14:29 +00:00
|
|
|
const TINY_CONST_EVAL_LIMIT: Limit = Limit(20);
|
|
|
|
|
2021-06-28 21:33:47 +02:00
|
|
|
pub trait OnDiskCache<'tcx>: rustc_data_structures::sync::Sync {
|
2021-06-28 21:12:01 +02:00
|
|
|
/// Creates a new `OnDiskCache` instance from the serialized data in `data`.
|
2021-03-16 21:39:03 +01:00
|
|
|
fn new(sess: &'tcx Session, data: Mmap, start_pos: usize) -> Self
|
2021-06-28 21:12:01 +02:00
|
|
|
where
|
|
|
|
Self: Sized;
|
|
|
|
|
|
|
|
fn new_empty(source_map: &'tcx SourceMap) -> Self
|
|
|
|
where
|
|
|
|
Self: Sized;
|
|
|
|
|
2021-03-17 22:49:16 +01:00
|
|
|
fn drop_serialized_data(&self, tcx: TyCtxt<'tcx>);
|
|
|
|
|
Use delayed error handling for `Encodable` and `Encoder` infallible.
There are two impls of the `Encoder` trait: `opaque::Encoder` and
`opaque::FileEncoder`. The former encodes into memory and is infallible, the
latter writes to file and is fallible.
Currently, standard `Result`/`?`/`unwrap` error handling is used, but this is a
bit verbose and has non-trivial cost, which is annoying given how rare failures
are (especially in the infallible `opaque::Encoder` case).
This commit changes how `Encoder` fallibility is handled. All the `emit_*`
methods are now infallible. `opaque::Encoder` requires no great changes for
this. `opaque::FileEncoder` now implements a delayed error handling strategy.
If a failure occurs, it records this via the `res` field, and all subsequent
encoding operations are skipped if `res` indicates an error has occurred. Once
encoding is complete, the new `finish` method is called, which returns a
`Result`. In other words, there is now a single `Result`-producing method
instead of many of them.
This has very little effect on how any file errors are reported if
`opaque::FileEncoder` has any failures.
Much of this commit is boring mechanical changes, removing `Result` return
values and `?` or `unwrap` from expressions. The more interesting parts are as
follows.
- serialize.rs: The `Encoder` trait gains an `Ok` associated type. The
`into_inner` method is changed into `finish`, which returns
`Result<Vec<u8>, !>`.
- opaque.rs: The `FileEncoder` adopts the delayed error handling
strategy. Its `Ok` type is a `usize`, returning the number of bytes
written, replacing previous uses of `FileEncoder::position`.
- Various methods that take an encoder now consume it, rather than being
passed a mutable reference, e.g. `serialize_query_result_cache`.
2022-06-07 13:30:45 +10:00
|
|
|
fn serialize(&self, tcx: TyCtxt<'tcx>, encoder: FileEncoder) -> FileEncodeResult;
|
2021-06-28 21:12:01 +02:00
|
|
|
}
|
|
|
|
|
2021-01-31 10:32:34 +01:00
|
|
|
#[allow(rustc::usage_of_ty_tykind)]
|
2022-05-27 20:03:57 -07:00
|
|
|
impl<'tcx> Interner for TyCtxt<'tcx> {
|
2021-01-31 10:32:34 +01:00
|
|
|
type AdtDef = ty::AdtDef<'tcx>;
|
|
|
|
type SubstsRef = ty::SubstsRef<'tcx>;
|
|
|
|
type DefId = DefId;
|
2023-02-09 19:16:07 +00:00
|
|
|
type Binder<T> = Binder<'tcx, T>;
|
2021-01-31 10:32:34 +01:00
|
|
|
type Ty = Ty<'tcx>;
|
|
|
|
type Const = ty::Const<'tcx>;
|
|
|
|
type Region = Region<'tcx>;
|
2023-02-09 19:16:07 +00:00
|
|
|
type Predicate = Predicate<'tcx>;
|
2021-01-31 10:32:34 +01:00
|
|
|
type TypeAndMut = TypeAndMut<'tcx>;
|
|
|
|
type Mutability = hir::Mutability;
|
|
|
|
type Movability = hir::Movability;
|
|
|
|
type PolyFnSig = PolyFnSig<'tcx>;
|
2022-11-19 03:28:56 +00:00
|
|
|
type ListBinderExistentialPredicate = &'tcx List<PolyExistentialPredicate<'tcx>>;
|
2021-01-31 10:32:34 +01:00
|
|
|
type BinderListTy = Binder<'tcx, &'tcx List<Ty<'tcx>>>;
|
|
|
|
type ListTy = &'tcx List<Ty<'tcx>>;
|
2022-11-26 21:51:55 +00:00
|
|
|
type AliasTy = ty::AliasTy<'tcx>;
|
2021-01-31 10:32:34 +01:00
|
|
|
type ParamTy = ParamTy;
|
|
|
|
type BoundTy = ty::BoundTy;
|
|
|
|
type PlaceholderType = ty::PlaceholderType;
|
|
|
|
type InferTy = InferTy;
|
2022-11-02 23:15:49 +08:00
|
|
|
type ErrorGuaranteed = ErrorGuaranteed;
|
2021-01-31 10:32:34 +01:00
|
|
|
type PredicateKind = ty::PredicateKind<'tcx>;
|
|
|
|
type AllocId = crate::mir::interpret::AllocId;
|
2022-06-19 00:20:27 -04:00
|
|
|
|
|
|
|
type EarlyBoundRegion = ty::EarlyBoundRegion;
|
|
|
|
type BoundRegion = ty::BoundRegion;
|
|
|
|
type FreeRegion = ty::FreeRegion;
|
|
|
|
type RegionVid = ty::RegionVid;
|
|
|
|
type PlaceholderRegion = ty::PlaceholderRegion;
|
2021-01-31 10:32:34 +01:00
|
|
|
}
|
|
|
|
|
2022-02-04 14:27:17 +11:00
|
|
|
type InternedSet<'tcx, T> = ShardedHashMap<InternedInSet<'tcx, T>, ()>;
|
2018-04-09 16:38:00 +09:00
|
|
|
|
2016-05-11 04:14:41 +03:00
|
|
|
pub struct CtxtInterners<'tcx> {
|
2019-09-06 03:57:44 +01:00
|
|
|
/// The arena that types, regions, etc. are allocated from.
|
2020-01-02 01:26:18 +01:00
|
|
|
arena: &'tcx WorkerLocal<Arena<'tcx>>,
|
2016-04-28 03:13:17 +03:00
|
|
|
|
2021-08-26 19:47:07 +03:00
|
|
|
// Specifically use a speedy hash algorithm for these hash sets, since
|
|
|
|
// they're accessed quite often.
|
2022-11-25 16:55:25 +00:00
|
|
|
type_: InternedSet<'tcx, WithCachedTypeInfo<TyKind<'tcx>>>,
|
2022-11-23 09:25:01 +00:00
|
|
|
const_lists: InternedSet<'tcx, List<ty::Const<'tcx>>>,
|
2019-02-26 09:30:34 +08:00
|
|
|
substs: InternedSet<'tcx, InternalSubsts<'tcx>>,
|
2020-10-28 01:11:03 +00:00
|
|
|
canonical_var_infos: InternedSet<'tcx, List<CanonicalVarInfo<'tcx>>>,
|
2022-06-19 00:20:27 -04:00
|
|
|
region: InternedSet<'tcx, RegionKind<'tcx>>,
|
2022-11-19 03:28:56 +00:00
|
|
|
poly_existential_predicates: InternedSet<'tcx, List<PolyExistentialPredicate<'tcx>>>,
|
2022-11-30 14:47:40 +00:00
|
|
|
predicate: InternedSet<'tcx, WithCachedTypeInfo<ty::Binder<'tcx, PredicateKind<'tcx>>>>,
|
2018-08-22 00:35:01 +01:00
|
|
|
predicates: InternedSet<'tcx, List<Predicate<'tcx>>>,
|
2019-03-28 18:00:17 -07:00
|
|
|
projs: InternedSet<'tcx, List<ProjectionKind>>,
|
2019-10-11 16:19:59 -03:00
|
|
|
place_elems: InternedSet<'tcx, List<PlaceElem<'tcx>>>,
|
2022-11-25 15:33:51 +00:00
|
|
|
const_: InternedSet<'tcx, ConstData<'tcx>>,
|
2021-08-26 19:47:07 +03:00
|
|
|
const_allocation: InternedSet<'tcx, Allocation>,
|
2020-10-05 20:41:46 -04:00
|
|
|
bound_variable_kinds: InternedSet<'tcx, List<ty::BoundVariableKind>>,
|
2023-01-20 20:56:16 -08:00
|
|
|
layout: InternedSet<'tcx, LayoutS>,
|
2022-03-05 07:28:41 +11:00
|
|
|
adt_def: InternedSet<'tcx, AdtDefData>,
|
2023-02-03 02:29:52 +00:00
|
|
|
external_constraints: InternedSet<'tcx, ExternalConstraintsData<'tcx>>,
|
2016-04-28 03:13:17 +03:00
|
|
|
}
|
|
|
|
|
2019-06-14 00:48:52 +03:00
|
|
|
impl<'tcx> CtxtInterners<'tcx> {
|
2020-01-02 01:26:18 +01:00
|
|
|
fn new(arena: &'tcx WorkerLocal<Arena<'tcx>>) -> CtxtInterners<'tcx> {
|
2016-04-28 03:13:17 +03:00
|
|
|
CtxtInterners {
|
2018-04-09 16:38:00 +09:00
|
|
|
arena,
|
|
|
|
type_: Default::default(),
|
2022-11-23 09:25:01 +00:00
|
|
|
const_lists: Default::default(),
|
2018-04-09 16:38:00 +09:00
|
|
|
substs: Default::default(),
|
|
|
|
region: Default::default(),
|
2020-12-11 15:02:46 -05:00
|
|
|
poly_existential_predicates: Default::default(),
|
2018-04-09 16:38:00 +09:00
|
|
|
canonical_var_infos: Default::default(),
|
2020-06-10 09:30:39 +01:00
|
|
|
predicate: Default::default(),
|
2018-04-09 16:38:00 +09:00
|
|
|
predicates: Default::default(),
|
2018-10-26 11:28:40 +02:00
|
|
|
projs: Default::default(),
|
2019-10-11 16:19:59 -03:00
|
|
|
place_elems: Default::default(),
|
2019-03-14 10:19:31 +01:00
|
|
|
const_: Default::default(),
|
2021-08-26 19:47:07 +03:00
|
|
|
const_allocation: Default::default(),
|
2020-10-05 20:41:46 -04:00
|
|
|
bound_variable_kinds: Default::default(),
|
2021-08-26 19:47:07 +03:00
|
|
|
layout: Default::default(),
|
2021-12-14 12:37:04 -05:00
|
|
|
adt_def: Default::default(),
|
2023-02-03 02:29:52 +00:00
|
|
|
external_constraints: Default::default(),
|
2016-04-28 03:13:17 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-17 14:33:08 +11:00
|
|
|
/// Interns a type. (Use `mk_*` functions instead, where possible.)
|
2019-08-11 12:55:14 -04:00
|
|
|
#[allow(rustc::usage_of_ty_tykind)]
|
2018-11-29 21:13:04 +01:00
|
|
|
#[inline(never)]
|
2022-12-08 08:52:07 +00:00
|
|
|
fn intern_ty(&self, kind: TyKind<'tcx>, sess: &Session, untracked: &Untracked) -> Ty<'tcx> {
|
Overhaul `TyS` and `Ty`.
Specifically, change `Ty` from this:
```
pub type Ty<'tcx> = &'tcx TyS<'tcx>;
```
to this
```
pub struct Ty<'tcx>(Interned<'tcx, TyS<'tcx>>);
```
There are two benefits to this.
- It's now a first class type, so we can define methods on it. This
means we can move a lot of methods away from `TyS`, leaving `TyS` as a
barely-used type, which is appropriate given that it's not meant to
be used directly.
- The uniqueness requirement is now explicit, via the `Interned` type.
E.g. the pointer-based `Eq` and `Hash` comes from `Interned`, rather
than via `TyS`, which wasn't obvious at all.
Much of this commit is boring churn. The interesting changes are in
these files:
- compiler/rustc_middle/src/arena.rs
- compiler/rustc_middle/src/mir/visit.rs
- compiler/rustc_middle/src/ty/context.rs
- compiler/rustc_middle/src/ty/mod.rs
Specifically:
- Most mentions of `TyS` are removed. It's very much a dumb struct now;
`Ty` has all the smarts.
- `TyS` now has `crate` visibility instead of `pub`.
- `TyS::make_for_test` is removed in favour of the static `BOOL_TY`,
which just works better with the new structure.
- The `Eq`/`Ord`/`Hash` impls are removed from `TyS`. `Interned`s impls
of `Eq`/`Hash` now suffice. `Ord` is now partly on `Interned`
(pointer-based, for the `Equal` case) and partly on `TyS`
(contents-based, for the other cases).
- There are many tedious sigil adjustments, i.e. adding or removing `*`
or `&`. They seem to be unavoidable.
2022-01-25 14:13:38 +11:00
|
|
|
Ty(Interned::new_unchecked(
|
|
|
|
self.type_
|
|
|
|
.intern(kind, |kind| {
|
|
|
|
let flags = super::flags::FlagComputation::for_kind(&kind);
|
2022-12-08 08:52:07 +00:00
|
|
|
let stable_hash = self.stable_hash(&flags, sess, untracked, &kind);
|
2022-02-23 18:02:06 +00:00
|
|
|
|
2022-11-25 16:55:25 +00:00
|
|
|
InternedInSet(self.arena.alloc(WithCachedTypeInfo {
|
|
|
|
internee: kind,
|
|
|
|
stable_hash,
|
Overhaul `TyS` and `Ty`.
Specifically, change `Ty` from this:
```
pub type Ty<'tcx> = &'tcx TyS<'tcx>;
```
to this
```
pub struct Ty<'tcx>(Interned<'tcx, TyS<'tcx>>);
```
There are two benefits to this.
- It's now a first class type, so we can define methods on it. This
means we can move a lot of methods away from `TyS`, leaving `TyS` as a
barely-used type, which is appropriate given that it's not meant to
be used directly.
- The uniqueness requirement is now explicit, via the `Interned` type.
E.g. the pointer-based `Eq` and `Hash` comes from `Interned`, rather
than via `TyS`, which wasn't obvious at all.
Much of this commit is boring churn. The interesting changes are in
these files:
- compiler/rustc_middle/src/arena.rs
- compiler/rustc_middle/src/mir/visit.rs
- compiler/rustc_middle/src/ty/context.rs
- compiler/rustc_middle/src/ty/mod.rs
Specifically:
- Most mentions of `TyS` are removed. It's very much a dumb struct now;
`Ty` has all the smarts.
- `TyS` now has `crate` visibility instead of `pub`.
- `TyS::make_for_test` is removed in favour of the static `BOOL_TY`,
which just works better with the new structure.
- The `Eq`/`Ord`/`Hash` impls are removed from `TyS`. `Interned`s impls
of `Eq`/`Hash` now suffice. `Ord` is now partly on `Interned`
(pointer-based, for the `Equal` case) and partly on `TyS`
(contents-based, for the other cases).
- There are many tedious sigil adjustments, i.e. adding or removing `*`
or `&`. They seem to be unavoidable.
2022-01-25 14:13:38 +11:00
|
|
|
flags: flags.flags,
|
|
|
|
outer_exclusive_binder: flags.outer_exclusive_binder,
|
2022-11-25 16:55:25 +00:00
|
|
|
}))
|
Overhaul `TyS` and `Ty`.
Specifically, change `Ty` from this:
```
pub type Ty<'tcx> = &'tcx TyS<'tcx>;
```
to this
```
pub struct Ty<'tcx>(Interned<'tcx, TyS<'tcx>>);
```
There are two benefits to this.
- It's now a first class type, so we can define methods on it. This
means we can move a lot of methods away from `TyS`, leaving `TyS` as a
barely-used type, which is appropriate given that it's not meant to
be used directly.
- The uniqueness requirement is now explicit, via the `Interned` type.
E.g. the pointer-based `Eq` and `Hash` comes from `Interned`, rather
than via `TyS`, which wasn't obvious at all.
Much of this commit is boring churn. The interesting changes are in
these files:
- compiler/rustc_middle/src/arena.rs
- compiler/rustc_middle/src/mir/visit.rs
- compiler/rustc_middle/src/ty/context.rs
- compiler/rustc_middle/src/ty/mod.rs
Specifically:
- Most mentions of `TyS` are removed. It's very much a dumb struct now;
`Ty` has all the smarts.
- `TyS` now has `crate` visibility instead of `pub`.
- `TyS::make_for_test` is removed in favour of the static `BOOL_TY`,
which just works better with the new structure.
- The `Eq`/`Ord`/`Hash` impls are removed from `TyS`. `Interned`s impls
of `Eq`/`Hash` now suffice. `Ord` is now partly on `Interned`
(pointer-based, for the `Equal` case) and partly on `TyS`
(contents-based, for the other cases).
- There are many tedious sigil adjustments, i.e. adding or removing `*`
or `&`. They seem to be unavoidable.
2022-01-25 14:13:38 +11:00
|
|
|
})
|
|
|
|
.0,
|
|
|
|
))
|
2018-04-30 08:59:23 +02:00
|
|
|
}
|
2020-06-10 09:30:39 +01:00
|
|
|
|
2022-03-14 16:54:31 +00:00
|
|
|
fn stable_hash<'a, T: HashStable<StableHashingContext<'a>>>(
|
|
|
|
&self,
|
|
|
|
flags: &ty::flags::FlagComputation,
|
|
|
|
sess: &'a Session,
|
2022-12-07 14:31:50 +00:00
|
|
|
untracked: &'a Untracked,
|
2022-03-14 16:54:31 +00:00
|
|
|
val: &T,
|
|
|
|
) -> Fingerprint {
|
|
|
|
// It's impossible to hash inference variables (and will ICE), so we don't need to try to cache them.
|
|
|
|
// Without incremental, we rarely stable-hash types, so let's not do it proactively.
|
|
|
|
if flags.flags.intersects(TypeFlags::NEEDS_INFER) || sess.opts.incremental.is_none() {
|
|
|
|
Fingerprint::ZERO
|
|
|
|
} else {
|
|
|
|
let mut hasher = StableHasher::new();
|
2022-12-08 08:52:07 +00:00
|
|
|
let mut hcx = StableHashingContext::new(sess, untracked);
|
2022-03-14 16:54:31 +00:00
|
|
|
val.hash_stable(&mut hcx, &mut hasher);
|
|
|
|
hasher.finish()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-17 14:33:08 +11:00
|
|
|
/// Interns a predicate. (Use `mk_predicate` instead, where possible.)
|
2020-06-10 09:30:39 +01:00
|
|
|
#[inline(never)]
|
2022-03-14 16:54:31 +00:00
|
|
|
fn intern_predicate(
|
|
|
|
&self,
|
|
|
|
kind: Binder<'tcx, PredicateKind<'tcx>>,
|
|
|
|
sess: &Session,
|
2022-12-07 14:31:50 +00:00
|
|
|
untracked: &Untracked,
|
2022-03-14 16:54:31 +00:00
|
|
|
) -> Predicate<'tcx> {
|
2022-01-27 17:00:16 +11:00
|
|
|
Predicate(Interned::new_unchecked(
|
|
|
|
self.predicate
|
|
|
|
.intern(kind, |kind| {
|
|
|
|
let flags = super::flags::FlagComputation::for_predicate(kind);
|
2020-06-10 09:30:39 +01:00
|
|
|
|
2022-12-08 08:52:07 +00:00
|
|
|
let stable_hash = self.stable_hash(&flags, sess, untracked, &kind);
|
2022-03-14 16:54:31 +00:00
|
|
|
|
2022-11-30 14:47:40 +00:00
|
|
|
InternedInSet(self.arena.alloc(WithCachedTypeInfo {
|
|
|
|
internee: kind,
|
|
|
|
stable_hash,
|
2022-01-27 17:00:16 +11:00
|
|
|
flags: flags.flags,
|
|
|
|
outer_exclusive_binder: flags.outer_exclusive_binder,
|
2022-11-30 14:47:40 +00:00
|
|
|
}))
|
2022-01-27 17:00:16 +11:00
|
|
|
})
|
|
|
|
.0,
|
|
|
|
))
|
2020-06-10 09:30:39 +01:00
|
|
|
}
|
2016-04-28 03:13:17 +03:00
|
|
|
}
|
|
|
|
|
2023-02-13 15:37:44 +11:00
|
|
|
// For these preinterned values, an alternative would be to have
|
|
|
|
// variable-length vectors that grow as needed. But that turned out to be
|
|
|
|
// slightly more complex and no faster.
|
|
|
|
|
2023-02-08 11:52:19 +11:00
|
|
|
const NUM_PREINTERNED_TY_VARS: u32 = 100;
|
|
|
|
const NUM_PREINTERNED_FRESH_TYS: u32 = 20;
|
|
|
|
const NUM_PREINTERNED_FRESH_INT_TYS: u32 = 3;
|
|
|
|
const NUM_PREINTERNED_FRESH_FLOAT_TYS: u32 = 3;
|
|
|
|
|
2023-02-13 15:37:44 +11:00
|
|
|
// This number may seem high, but it is reached in all but the smallest crates.
|
|
|
|
const NUM_PREINTERNED_RE_VARS: u32 = 500;
|
|
|
|
const NUM_PREINTERNED_RE_LATE_BOUNDS_I: u32 = 2;
|
|
|
|
const NUM_PREINTERNED_RE_LATE_BOUNDS_V: u32 = 20;
|
|
|
|
|
2015-09-06 21:51:58 +03:00
|
|
|
pub struct CommonTypes<'tcx> {
|
2018-11-29 21:13:04 +01:00
|
|
|
pub unit: Ty<'tcx>,
|
2015-09-06 21:51:58 +03:00
|
|
|
pub bool: Ty<'tcx>,
|
|
|
|
pub char: Ty<'tcx>,
|
|
|
|
pub isize: Ty<'tcx>,
|
|
|
|
pub i8: Ty<'tcx>,
|
|
|
|
pub i16: Ty<'tcx>,
|
|
|
|
pub i32: Ty<'tcx>,
|
|
|
|
pub i64: Ty<'tcx>,
|
2016-08-23 03:56:52 +03:00
|
|
|
pub i128: Ty<'tcx>,
|
2015-09-06 21:51:58 +03:00
|
|
|
pub usize: Ty<'tcx>,
|
|
|
|
pub u8: Ty<'tcx>,
|
|
|
|
pub u16: Ty<'tcx>,
|
|
|
|
pub u32: Ty<'tcx>,
|
|
|
|
pub u64: Ty<'tcx>,
|
2016-08-23 03:56:52 +03:00
|
|
|
pub u128: Ty<'tcx>,
|
2015-09-06 21:51:58 +03:00
|
|
|
pub f32: Ty<'tcx>,
|
|
|
|
pub f64: Ty<'tcx>,
|
2020-05-28 13:02:02 +02:00
|
|
|
pub str_: Ty<'tcx>,
|
2016-08-02 15:56:20 +08:00
|
|
|
pub never: Ty<'tcx>,
|
2019-08-12 22:15:12 +01:00
|
|
|
pub self_param: Ty<'tcx>,
|
2017-04-20 01:58:12 +03:00
|
|
|
|
2019-04-03 11:46:40 +02:00
|
|
|
/// Dummy type used for the `Self` of a `TraitRef` created for converting
|
|
|
|
/// a trait object, and which gets removed in `ExistentialTraitRef`.
|
|
|
|
/// This type must not appear anywhere in other converted types.
|
2023-02-08 11:52:19 +11:00
|
|
|
/// `Infer(ty::FreshTy(0))` does the job.
|
2019-04-03 11:46:40 +02:00
|
|
|
pub trait_object_dummy_self: Ty<'tcx>,
|
2023-02-08 11:52:19 +11:00
|
|
|
|
|
|
|
/// Pre-interned `Infer(ty::TyVar(n))` for small values of `n`.
|
|
|
|
pub ty_vars: Vec<Ty<'tcx>>,
|
|
|
|
|
|
|
|
/// Pre-interned `Infer(ty::FreshTy(n))` for small values of `n`.
|
|
|
|
pub fresh_tys: Vec<Ty<'tcx>>,
|
|
|
|
|
|
|
|
/// Pre-interned `Infer(ty::FreshIntTy(n))` for small values of `n`.
|
|
|
|
pub fresh_int_tys: Vec<Ty<'tcx>>,
|
|
|
|
|
|
|
|
/// Pre-interned `Infer(ty::FreshFloatTy(n))` for small values of `n`.
|
|
|
|
pub fresh_float_tys: Vec<Ty<'tcx>>,
|
2019-04-25 22:04:51 +01:00
|
|
|
}
|
2019-04-03 11:46:40 +02:00
|
|
|
|
2019-04-25 22:04:51 +01:00
|
|
|
pub struct CommonLifetimes<'tcx> {
|
2020-01-18 05:47:28 -05:00
|
|
|
/// `ReStatic`
|
2017-04-20 04:45:53 -04:00
|
|
|
pub re_static: Region<'tcx>,
|
2019-10-08 19:26:57 -04:00
|
|
|
|
2021-10-25 15:43:07 -05:00
|
|
|
/// Erased region, used outside of type inference.
|
2017-04-20 04:45:53 -04:00
|
|
|
pub re_erased: Region<'tcx>,
|
2023-02-13 15:37:44 +11:00
|
|
|
|
|
|
|
/// Pre-interned `ReVar(ty::RegionVar(n))` for small values of `n`.
|
|
|
|
pub re_vars: Vec<Region<'tcx>>,
|
|
|
|
|
|
|
|
/// Pre-interned values of the form:
|
2023-03-03 04:10:46 +01:00
|
|
|
/// `ReLateBound(DebruijnIndex(i), BoundRegion { var: v, kind: BrAnon(v, None) })`
|
2023-02-13 15:37:44 +11:00
|
|
|
/// for small values of `i` and `v`.
|
|
|
|
pub re_late_bounds: Vec<Vec<Region<'tcx>>>,
|
2019-05-01 23:09:53 +01:00
|
|
|
}
|
2019-03-08 01:15:37 +00:00
|
|
|
|
2019-05-01 23:09:53 +01:00
|
|
|
pub struct CommonConsts<'tcx> {
|
2022-02-02 14:24:45 +11:00
|
|
|
pub unit: Const<'tcx>,
|
2015-09-06 21:51:58 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<'tcx> CommonTypes<'tcx> {
|
2022-02-23 18:02:06 +00:00
|
|
|
fn new(
|
|
|
|
interners: &CtxtInterners<'tcx>,
|
|
|
|
sess: &Session,
|
2022-12-07 14:31:50 +00:00
|
|
|
untracked: &Untracked,
|
2022-02-23 18:02:06 +00:00
|
|
|
) -> CommonTypes<'tcx> {
|
2022-12-08 08:52:07 +00:00
|
|
|
let mk = |ty| interners.intern_ty(ty, sess, untracked);
|
2018-11-29 21:13:04 +01:00
|
|
|
|
2023-02-08 11:52:19 +11:00
|
|
|
let ty_vars =
|
|
|
|
(0..NUM_PREINTERNED_TY_VARS).map(|n| mk(Infer(ty::TyVar(TyVid::from(n))))).collect();
|
|
|
|
let fresh_tys: Vec<_> =
|
|
|
|
(0..NUM_PREINTERNED_FRESH_TYS).map(|n| mk(Infer(ty::FreshTy(n)))).collect();
|
|
|
|
let fresh_int_tys: Vec<_> =
|
|
|
|
(0..NUM_PREINTERNED_FRESH_INT_TYS).map(|n| mk(Infer(ty::FreshIntTy(n)))).collect();
|
|
|
|
let fresh_float_tys: Vec<_> =
|
|
|
|
(0..NUM_PREINTERNED_FRESH_FLOAT_TYS).map(|n| mk(Infer(ty::FreshFloatTy(n)))).collect();
|
|
|
|
|
2015-09-06 21:51:58 +03:00
|
|
|
CommonTypes {
|
2018-11-29 21:13:04 +01:00
|
|
|
unit: mk(Tuple(List::empty())),
|
2018-08-22 01:35:55 +01:00
|
|
|
bool: mk(Bool),
|
|
|
|
char: mk(Char),
|
2018-08-22 01:35:02 +01:00
|
|
|
never: mk(Never),
|
2020-12-12 15:28:49 +01:00
|
|
|
isize: mk(Int(ty::IntTy::Isize)),
|
|
|
|
i8: mk(Int(ty::IntTy::I8)),
|
|
|
|
i16: mk(Int(ty::IntTy::I16)),
|
|
|
|
i32: mk(Int(ty::IntTy::I32)),
|
|
|
|
i64: mk(Int(ty::IntTy::I64)),
|
|
|
|
i128: mk(Int(ty::IntTy::I128)),
|
|
|
|
usize: mk(Uint(ty::UintTy::Usize)),
|
|
|
|
u8: mk(Uint(ty::UintTy::U8)),
|
|
|
|
u16: mk(Uint(ty::UintTy::U16)),
|
|
|
|
u32: mk(Uint(ty::UintTy::U32)),
|
|
|
|
u64: mk(Uint(ty::UintTy::U64)),
|
|
|
|
u128: mk(Uint(ty::UintTy::U128)),
|
|
|
|
f32: mk(Float(ty::FloatTy::F32)),
|
|
|
|
f64: mk(Float(ty::FloatTy::F64)),
|
2020-05-28 13:02:02 +02:00
|
|
|
str_: mk(Str),
|
2019-12-24 17:38:22 -05:00
|
|
|
self_param: mk(ty::Param(ty::ParamTy { index: 0, name: kw::SelfUpper })),
|
2017-04-20 01:58:12 +03:00
|
|
|
|
2023-02-08 11:52:19 +11:00
|
|
|
trait_object_dummy_self: fresh_tys[0],
|
|
|
|
|
|
|
|
ty_vars,
|
|
|
|
fresh_tys,
|
|
|
|
fresh_int_tys,
|
|
|
|
fresh_float_tys,
|
2019-04-25 22:04:51 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-04-03 11:46:40 +02:00
|
|
|
|
2019-04-25 22:04:51 +01:00
|
|
|
impl<'tcx> CommonLifetimes<'tcx> {
|
|
|
|
fn new(interners: &CtxtInterners<'tcx>) -> CommonLifetimes<'tcx> {
|
2022-01-28 11:25:15 +11:00
|
|
|
let mk = |r| {
|
|
|
|
Region(Interned::new_unchecked(
|
|
|
|
interners.region.intern(r, |r| InternedInSet(interners.arena.alloc(r))).0,
|
|
|
|
))
|
|
|
|
};
|
2019-04-25 22:04:51 +01:00
|
|
|
|
2023-02-13 15:37:44 +11:00
|
|
|
let re_vars =
|
|
|
|
(0..NUM_PREINTERNED_RE_VARS).map(|n| mk(ty::ReVar(ty::RegionVid::from(n)))).collect();
|
|
|
|
|
|
|
|
let re_late_bounds = (0..NUM_PREINTERNED_RE_LATE_BOUNDS_I)
|
|
|
|
.map(|i| {
|
|
|
|
(0..NUM_PREINTERNED_RE_LATE_BOUNDS_V)
|
|
|
|
.map(|v| {
|
|
|
|
mk(ty::ReLateBound(
|
|
|
|
ty::DebruijnIndex::from(i),
|
|
|
|
ty::BoundRegion {
|
|
|
|
var: ty::BoundVar::from(v),
|
|
|
|
kind: ty::BrAnon(v, None),
|
|
|
|
},
|
|
|
|
))
|
|
|
|
})
|
|
|
|
.collect()
|
|
|
|
})
|
|
|
|
.collect();
|
|
|
|
|
|
|
|
CommonLifetimes {
|
|
|
|
re_static: mk(ty::ReStatic),
|
|
|
|
re_erased: mk(ty::ReErased),
|
|
|
|
re_vars,
|
|
|
|
re_late_bounds,
|
|
|
|
}
|
2015-09-06 21:51:58 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-01 23:09:53 +01:00
|
|
|
impl<'tcx> CommonConsts<'tcx> {
|
|
|
|
fn new(interners: &CtxtInterners<'tcx>, types: &CommonTypes<'tcx>) -> CommonConsts<'tcx> {
|
2022-02-02 14:24:45 +11:00
|
|
|
let mk_const = |c| {
|
|
|
|
Const(Interned::new_unchecked(
|
|
|
|
interners.const_.intern(c, |c| InternedInSet(interners.arena.alloc(c))).0,
|
|
|
|
))
|
|
|
|
};
|
2019-05-01 23:09:53 +01:00
|
|
|
|
|
|
|
CommonConsts {
|
2022-11-25 15:33:51 +00:00
|
|
|
unit: mk_const(ty::ConstData {
|
2022-02-16 10:56:01 +01:00
|
|
|
kind: ty::ConstKind::Value(ty::ValTree::zst()),
|
2020-04-16 13:47:47 +03:00
|
|
|
ty: types.unit,
|
2019-04-03 15:29:31 +02:00
|
|
|
}),
|
2019-05-01 23:09:53 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-27 11:15:06 +00:00
|
|
|
/// This struct contains information regarding the `ReFree(FreeRegion)` corresponding to a lifetime
|
|
|
|
/// conflict.
|
2018-09-02 00:42:51 +02:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct FreeRegionInfo {
|
2022-11-27 11:15:06 +00:00
|
|
|
/// `LocalDefId` corresponding to FreeRegion
|
2020-06-27 13:38:00 +02:00
|
|
|
pub def_id: LocalDefId,
|
2022-11-27 11:15:06 +00:00
|
|
|
/// the bound region corresponding to FreeRegion
|
2020-12-18 13:24:55 -05:00
|
|
|
pub boundregion: ty::BoundRegionKind,
|
2022-11-27 11:15:06 +00:00
|
|
|
/// checks if bound region is in Impl Item
|
2018-09-02 00:42:51 +02:00
|
|
|
pub is_impl_item: bool,
|
|
|
|
}
|
|
|
|
|
2022-11-29 18:49:37 +00:00
|
|
|
/// This struct should only be created by `create_def`.
|
2022-11-26 13:54:45 +00:00
|
|
|
#[derive(Copy, Clone)]
|
2022-12-03 13:36:39 +00:00
|
|
|
pub struct TyCtxtFeed<'tcx, KEY: Copy> {
|
2022-11-26 13:54:45 +00:00
|
|
|
pub tcx: TyCtxt<'tcx>,
|
2022-11-29 18:49:37 +00:00
|
|
|
// Do not allow direct access, as downstream code must not mutate this field.
|
2022-12-03 13:36:39 +00:00
|
|
|
key: KEY,
|
2022-11-29 18:49:37 +00:00
|
|
|
}
|
|
|
|
|
2022-12-03 18:06:39 +00:00
|
|
|
impl<'tcx> TyCtxt<'tcx> {
|
|
|
|
pub fn feed_unit_query(self) -> TyCtxtFeed<'tcx, ()> {
|
|
|
|
TyCtxtFeed { tcx: self, key: () }
|
|
|
|
}
|
2022-12-05 16:37:44 +00:00
|
|
|
pub fn feed_local_crate(self) -> TyCtxtFeed<'tcx, CrateNum> {
|
|
|
|
TyCtxtFeed { tcx: self, key: LOCAL_CRATE }
|
|
|
|
}
|
2022-12-03 18:06:39 +00:00
|
|
|
}
|
|
|
|
|
2022-12-03 13:36:39 +00:00
|
|
|
impl<'tcx, KEY: Copy> TyCtxtFeed<'tcx, KEY> {
|
|
|
|
#[inline(always)]
|
|
|
|
pub fn key(&self) -> KEY {
|
|
|
|
self.key
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'tcx> TyCtxtFeed<'tcx, LocalDefId> {
|
2022-11-29 18:49:37 +00:00
|
|
|
#[inline(always)]
|
|
|
|
pub fn def_id(&self) -> LocalDefId {
|
2022-12-03 13:36:39 +00:00
|
|
|
self.key
|
2022-11-29 18:49:37 +00:00
|
|
|
}
|
2022-11-26 13:54:45 +00:00
|
|
|
}
|
|
|
|
|
2017-09-15 16:19:44 -04:00
|
|
|
/// The central data structure of the compiler. It stores references
|
|
|
|
/// to the various **arenas** and also houses the results of the
|
2017-12-31 17:08:04 +01:00
|
|
|
/// various **compiler queries** that have been performed. See the
|
2020-03-05 18:07:42 -03:00
|
|
|
/// [rustc dev guide] for more details.
|
2017-12-31 17:08:04 +01:00
|
|
|
///
|
2020-03-09 18:33:04 -03:00
|
|
|
/// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/ty.html
|
2016-05-03 04:56:42 +03:00
|
|
|
#[derive(Copy, Clone)]
|
2019-09-25 08:42:46 -04:00
|
|
|
#[rustc_diagnostic_item = "TyCtxt"]
|
2022-02-23 08:06:22 -05:00
|
|
|
#[rustc_pass_by_value]
|
2019-06-14 00:48:52 +03:00
|
|
|
pub struct TyCtxt<'tcx> {
|
|
|
|
gcx: &'tcx GlobalCtxt<'tcx>,
|
2016-05-03 04:56:42 +03:00
|
|
|
}
|
|
|
|
|
2019-06-14 00:48:52 +03:00
|
|
|
impl<'tcx> Deref for TyCtxt<'tcx> {
|
|
|
|
type Target = &'tcx GlobalCtxt<'tcx>;
|
2018-11-29 21:13:04 +01:00
|
|
|
#[inline(always)]
|
2016-05-03 05:23:22 +03:00
|
|
|
fn deref(&self) -> &Self::Target {
|
2016-05-03 04:56:42 +03:00
|
|
|
&self.gcx
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct GlobalCtxt<'tcx> {
|
2019-11-26 23:16:48 +01:00
|
|
|
pub arena: &'tcx WorkerLocal<Arena<'tcx>>,
|
2021-07-13 18:45:20 +02:00
|
|
|
pub hir_arena: &'tcx WorkerLocal<hir::Arena<'tcx>>,
|
2019-05-31 09:25:34 +02:00
|
|
|
|
2019-05-31 10:23:22 +02:00
|
|
|
interners: CtxtInterners<'tcx>,
|
2015-09-06 21:51:58 +03:00
|
|
|
|
2016-09-29 02:30:53 +03:00
|
|
|
pub sess: &'tcx Session,
|
|
|
|
|
2020-01-09 03:45:42 +01:00
|
|
|
/// This only ever stores a `LintStore` but we don't want a dependency on that type here.
|
|
|
|
///
|
|
|
|
/// FIXME(Centril): consider `dyn LintStoreMarker` once
|
|
|
|
/// we can upcast to `Any` for some additional type safety.
|
2020-01-09 09:40:55 +01:00
|
|
|
pub lint_store: Lrc<dyn Any + sync::Sync + sync::Send>,
|
2019-10-09 09:53:13 -04:00
|
|
|
|
2016-01-05 13:07:45 -05:00
|
|
|
pub dep_graph: DepGraph,
|
|
|
|
|
2019-09-27 14:03:09 +02:00
|
|
|
pub prof: SelfProfilerRef,
|
|
|
|
|
2015-09-06 21:51:58 +03:00
|
|
|
/// Common types, pre-interned for your convenience.
|
|
|
|
pub types: CommonTypes<'tcx>,
|
|
|
|
|
2019-04-25 22:04:51 +01:00
|
|
|
/// Common lifetimes, pre-interned for your convenience.
|
|
|
|
pub lifetimes: CommonLifetimes<'tcx>,
|
|
|
|
|
2019-05-01 23:09:53 +01:00
|
|
|
/// Common consts, pre-interned for your convenience.
|
|
|
|
pub consts: CommonConsts<'tcx>,
|
|
|
|
|
2022-12-07 14:31:50 +00:00
|
|
|
untracked: Untracked,
|
2022-12-05 16:19:14 +00:00
|
|
|
|
2021-01-04 23:38:20 +01:00
|
|
|
/// This provides access to the incremental compilation on-disk cache for query results.
|
|
|
|
/// Do not access this directly. It is only meant to be used by
|
|
|
|
/// `DepGraph::try_mark_green()` and the query infrastructure.
|
|
|
|
/// This is `None` if we are not incremental compilation mode
|
2021-06-28 21:12:01 +02:00
|
|
|
pub on_disk_cache: Option<&'tcx dyn OnDiskCache<'tcx>>,
|
2021-01-04 23:38:20 +01:00
|
|
|
|
2021-01-18 22:32:20 +01:00
|
|
|
pub queries: &'tcx dyn query::QueryEngine<'tcx>,
|
2023-02-08 19:53:48 +01:00
|
|
|
pub query_system: query::QuerySystem<'tcx>,
|
2022-09-11 23:18:08 -05:00
|
|
|
pub(crate) query_kinds: &'tcx [DepKindStruct<'tcx>],
|
2016-10-28 13:55:49 +03:00
|
|
|
|
2020-06-10 09:26:54 +01:00
|
|
|
// Internal caches for metadata decoding. No need to track deps on this.
|
|
|
|
pub ty_rcache: Lock<FxHashMap<ty::CReaderCacheKey, Ty<'tcx>>>,
|
|
|
|
pub pred_rcache: Lock<FxHashMap<ty::CReaderCacheKey, Predicate<'tcx>>>,
|
2015-12-22 16:39:33 -05:00
|
|
|
|
2015-09-06 21:51:58 +03:00
|
|
|
/// Caches the results of trait selection. This cache is used
|
|
|
|
/// for things that do not have to do with the parameters in scope.
|
|
|
|
pub selection_cache: traits::SelectionCache<'tcx>,
|
|
|
|
|
2015-10-21 14:50:38 +03:00
|
|
|
/// Caches the results of trait evaluation. This cache is used
|
|
|
|
/// for things that do not have to do with the parameters in scope.
|
|
|
|
/// Merge this with `selection_cache`?
|
|
|
|
pub evaluation_cache: traits::EvaluationCache<'tcx>,
|
|
|
|
|
2023-02-24 02:35:15 +00:00
|
|
|
/// Caches the results of goal evaluation in the new solver.
|
|
|
|
pub new_solver_evaluation_cache: solve::EvaluationCache<'tcx>,
|
|
|
|
|
2016-04-18 16:03:16 +03:00
|
|
|
/// Data layout specification for the current target.
|
|
|
|
pub data_layout: TargetDataLayout,
|
2016-04-19 09:11:46 +03:00
|
|
|
|
2020-03-21 19:19:10 +01:00
|
|
|
/// Stores memory for globals (statics/consts).
|
2020-04-24 12:53:18 +02:00
|
|
|
pub(crate) alloc_map: Lock<interpret::AllocMap<'tcx>>,
|
2015-09-06 21:51:58 +03:00
|
|
|
}
|
|
|
|
|
2023-02-07 16:59:50 +11:00
|
|
|
impl<'tcx> GlobalCtxt<'tcx> {
|
|
|
|
/// Installs `self` in a `TyCtxt` and `ImplicitCtxt` for the duration of
|
|
|
|
/// `f`.
|
|
|
|
pub fn enter<'a: 'tcx, F, R>(&'a self, f: F) -> R
|
|
|
|
where
|
|
|
|
F: FnOnce(TyCtxt<'tcx>) -> R,
|
|
|
|
{
|
|
|
|
let icx = tls::ImplicitCtxt::new(self);
|
|
|
|
tls::enter_context(&icx, || f(icx.tcx))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-14 00:48:52 +03:00
|
|
|
impl<'tcx> TyCtxt<'tcx> {
|
2022-05-09 17:47:02 +02:00
|
|
|
/// Expects a body and returns its codegen attributes.
|
|
|
|
///
|
|
|
|
/// Unlike `codegen_fn_attrs`, this returns `CodegenFnAttrs::EMPTY` for
|
|
|
|
/// constants.
|
|
|
|
pub fn body_codegen_attrs(self, def_id: DefId) -> &'tcx CodegenFnAttrs {
|
|
|
|
let def_kind = self.def_kind(def_id);
|
|
|
|
if def_kind.has_codegen_attrs() {
|
|
|
|
self.codegen_fn_attrs(def_id)
|
|
|
|
} else if matches!(
|
|
|
|
def_kind,
|
|
|
|
DefKind::AnonConst | DefKind::AssocConst | DefKind::Const | DefKind::InlineConst
|
|
|
|
) {
|
|
|
|
CodegenFnAttrs::EMPTY
|
|
|
|
} else {
|
|
|
|
bug!(
|
|
|
|
"body_codegen_fn_attrs called on unexpected definition: {:?} {:?}",
|
|
|
|
def_id,
|
|
|
|
def_kind
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-17 08:47:04 +00:00
|
|
|
pub fn typeck_opt_const_arg(
|
2020-07-07 10:40:36 +02:00
|
|
|
self,
|
2020-07-15 10:50:54 +02:00
|
|
|
def: ty::WithOptConstParam<LocalDefId>,
|
2020-07-17 08:47:04 +00:00
|
|
|
) -> &'tcx TypeckResults<'tcx> {
|
2020-07-15 10:50:54 +02:00
|
|
|
if let Some(param_did) = def.const_param_did {
|
2020-07-17 08:47:04 +00:00
|
|
|
self.typeck_const_arg((def.did, param_did))
|
2020-07-07 10:40:36 +02:00
|
|
|
} else {
|
2020-07-17 08:47:04 +00:00
|
|
|
self.typeck(def.did)
|
2020-07-07 10:40:36 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-06 12:16:49 -08:00
|
|
|
pub fn mir_borrowck_opt_const_arg(
|
|
|
|
self,
|
|
|
|
def: ty::WithOptConstParam<LocalDefId>,
|
|
|
|
) -> &'tcx BorrowCheckResult<'tcx> {
|
|
|
|
if let Some(param_did) = def.const_param_did {
|
|
|
|
self.mir_borrowck_const_arg((def.did, param_did))
|
|
|
|
} else {
|
|
|
|
self.mir_borrowck(def.did)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-04 18:42:17 +02:00
|
|
|
pub fn alloc_steal_thir(self, thir: Thir<'tcx>) -> &'tcx Steal<Thir<'tcx>> {
|
|
|
|
self.arena.alloc(Steal::new(thir))
|
|
|
|
}
|
|
|
|
|
2020-07-03 22:15:27 +02:00
|
|
|
pub fn alloc_steal_mir(self, mir: Body<'tcx>) -> &'tcx Steal<Body<'tcx>> {
|
|
|
|
self.arena.alloc(Steal::new(mir))
|
2015-09-06 21:51:58 +03:00
|
|
|
}
|
|
|
|
|
2019-12-24 17:38:22 -05:00
|
|
|
pub fn alloc_steal_promoted(
|
|
|
|
self,
|
2020-04-12 10:31:00 -07:00
|
|
|
promoted: IndexVec<Promoted, Body<'tcx>>,
|
2020-07-03 22:15:27 +02:00
|
|
|
) -> &'tcx Steal<IndexVec<Promoted, Body<'tcx>>> {
|
|
|
|
self.arena.alloc(Steal::new(promoted))
|
2019-08-04 16:20:21 -04:00
|
|
|
}
|
|
|
|
|
2023-02-17 14:33:08 +11:00
|
|
|
pub fn mk_adt_def(
|
2019-06-14 01:32:15 +03:00
|
|
|
self,
|
|
|
|
did: DefId,
|
|
|
|
kind: AdtKind,
|
|
|
|
variants: IndexVec<VariantIdx, ty::VariantDef>,
|
|
|
|
repr: ReprOptions,
|
2022-03-05 07:28:41 +11:00
|
|
|
) -> ty::AdtDef<'tcx> {
|
2023-02-17 14:33:08 +11:00
|
|
|
self.mk_adt_def_from_data(ty::AdtDefData::new(self, did, kind, variants, repr))
|
2015-09-06 21:51:58 +03:00
|
|
|
}
|
|
|
|
|
2019-09-06 03:57:44 +01:00
|
|
|
/// Allocates a read-only byte or string literal for `mir::interpret`.
|
2018-05-01 12:18:53 +02:00
|
|
|
pub fn allocate_bytes(self, bytes: &[u8]) -> interpret::AllocId {
|
2019-09-06 03:57:44 +01:00
|
|
|
// Create an allocation that just contains these bytes.
|
2021-05-23 12:03:39 +02:00
|
|
|
let alloc = interpret::Allocation::from_bytes_byte_aligned_immutable(bytes);
|
2023-02-17 14:33:08 +11:00
|
|
|
let alloc = self.mk_const_alloc(alloc);
|
2020-04-24 12:53:18 +02:00
|
|
|
self.create_memory_alloc(alloc)
|
2017-12-06 09:25:29 +01:00
|
|
|
}
|
|
|
|
|
2018-09-10 13:40:34 +02:00
|
|
|
/// Returns a range of the start/end indices specified with the
|
|
|
|
/// `rustc_layout_scalar_valid_range` attribute.
|
2021-08-26 19:47:07 +03:00
|
|
|
// FIXME(eddyb) this is an awkward spot for this method, maybe move it?
|
2018-09-10 13:40:34 +02:00
|
|
|
pub fn layout_scalar_valid_range(self, def_id: DefId) -> (Bound<u128>, Bound<u128>) {
|
|
|
|
let get = |name| {
|
2022-05-02 09:31:56 +02:00
|
|
|
let Some(attr) = self.get_attr(def_id, name) else {
|
2022-02-19 00:48:49 +01:00
|
|
|
return Bound::Unbounded;
|
2018-09-10 13:40:34 +02:00
|
|
|
};
|
2020-06-20 20:59:04 -04:00
|
|
|
debug!("layout_scalar_valid_range: attr={:?}", attr);
|
2021-03-16 00:00:00 +00:00
|
|
|
if let Some(
|
2022-06-14 17:34:37 +02:00
|
|
|
&[
|
2022-11-24 15:00:09 +11:00
|
|
|
ast::NestedMetaItem::Lit(ast::MetaItemLit {
|
2022-11-23 15:39:42 +11:00
|
|
|
kind: ast::LitKind::Int(a, _),
|
|
|
|
..
|
2022-06-14 17:34:37 +02:00
|
|
|
}),
|
|
|
|
],
|
2021-03-16 00:00:00 +00:00
|
|
|
) = attr.meta_item_list().as_deref()
|
|
|
|
{
|
|
|
|
Bound::Included(a)
|
|
|
|
} else {
|
|
|
|
self.sess
|
|
|
|
.delay_span_bug(attr.span, "invalid rustc_layout_scalar_valid_range attribute");
|
|
|
|
Bound::Unbounded
|
2018-09-07 13:41:59 +02:00
|
|
|
}
|
|
|
|
};
|
2019-12-24 17:38:22 -05:00
|
|
|
(
|
|
|
|
get(sym::rustc_layout_scalar_valid_range_start),
|
|
|
|
get(sym::rustc_layout_scalar_valid_range_end),
|
|
|
|
)
|
2018-09-07 13:41:59 +02:00
|
|
|
}
|
|
|
|
|
2020-10-16 21:59:49 +02:00
|
|
|
pub fn lift<T: Lift<'tcx>>(self, value: T) -> Option<T::Lifted> {
|
2015-09-06 21:51:58 +03:00
|
|
|
value.lift_to_tcx(self)
|
|
|
|
}
|
|
|
|
|
2019-02-08 14:53:55 +01:00
|
|
|
/// Creates a type context and call the closure with a `TyCtxt` reference
|
2015-09-06 21:51:58 +03:00
|
|
|
/// to the context. The closure enforces that the type context and any interned
|
|
|
|
/// value (types, substs, etc.) can only be used while `ty::tls` has a valid
|
|
|
|
/// reference to the context, to allow formatting values that need it.
|
2018-12-08 20:30:23 +01:00
|
|
|
pub fn create_global_ctxt(
|
|
|
|
s: &'tcx Session,
|
2020-01-09 09:40:55 +01:00
|
|
|
lint_store: Lrc<dyn Any + sync::Send + sync::Sync>,
|
2019-11-27 13:24:19 +01:00
|
|
|
arena: &'tcx WorkerLocal<Arena<'tcx>>,
|
2021-07-13 18:45:20 +02:00
|
|
|
hir_arena: &'tcx WorkerLocal<hir::Arena<'tcx>>,
|
2022-12-07 14:31:50 +00:00
|
|
|
untracked: Untracked,
|
2020-02-08 05:18:34 +01:00
|
|
|
dep_graph: DepGraph,
|
2021-06-28 21:12:01 +02:00
|
|
|
on_disk_cache: Option<&'tcx dyn OnDiskCache<'tcx>>,
|
2021-01-18 22:32:20 +01:00
|
|
|
queries: &'tcx dyn query::QueryEngine<'tcx>,
|
2022-08-29 10:20:14 -05:00
|
|
|
query_kinds: &'tcx [DepKindStruct<'tcx>],
|
2018-12-08 20:30:23 +01:00
|
|
|
) -> GlobalCtxt<'tcx> {
|
2022-11-07 00:36:11 +03:30
|
|
|
let data_layout = s.target.parse_data_layout().unwrap_or_else(|err| {
|
2022-10-04 20:56:05 -04:00
|
|
|
s.emit_fatal(err);
|
2017-12-18 16:18:36 +02:00
|
|
|
});
|
2020-01-02 01:26:18 +01:00
|
|
|
let interners = CtxtInterners::new(arena);
|
2022-12-08 08:52:07 +00:00
|
|
|
let common_types = CommonTypes::new(&interners, s, &untracked);
|
2019-04-25 22:04:51 +01:00
|
|
|
let common_lifetimes = CommonLifetimes::new(&interners);
|
2019-05-01 23:09:53 +01:00
|
|
|
let common_consts = CommonConsts::new(&interners, &common_types);
|
2021-06-01 09:05:22 +02:00
|
|
|
|
2018-12-08 20:30:23 +01:00
|
|
|
GlobalCtxt {
|
2016-09-29 02:30:53 +03:00
|
|
|
sess: s,
|
2019-10-09 09:53:13 -04:00
|
|
|
lint_store,
|
2019-11-27 13:24:19 +01:00
|
|
|
arena,
|
2021-07-13 18:45:20 +02:00
|
|
|
hir_arena,
|
2019-05-31 10:23:22 +02:00
|
|
|
interners,
|
2018-10-26 03:11:11 +09:00
|
|
|
dep_graph,
|
2019-09-27 14:03:09 +02:00
|
|
|
prof: s.prof.clone(),
|
2015-09-06 21:51:58 +03:00
|
|
|
types: common_types,
|
2019-04-25 22:04:51 +01:00
|
|
|
lifetimes: common_lifetimes,
|
2019-05-01 23:09:53 +01:00
|
|
|
consts: common_consts,
|
2022-12-07 14:31:50 +00:00
|
|
|
untracked,
|
2021-01-04 23:38:20 +01:00
|
|
|
on_disk_cache,
|
2020-10-11 10:34:13 +02:00
|
|
|
queries,
|
2023-02-14 14:17:04 +01:00
|
|
|
query_system: Default::default(),
|
2021-10-16 20:10:23 +02:00
|
|
|
query_kinds,
|
2020-06-10 09:26:54 +01:00
|
|
|
ty_rcache: Default::default(),
|
|
|
|
pred_rcache: Default::default(),
|
2018-10-16 16:57:53 +02:00
|
|
|
selection_cache: Default::default(),
|
|
|
|
evaluation_cache: Default::default(),
|
2023-02-24 02:35:15 +00:00
|
|
|
new_solver_evaluation_cache: Default::default(),
|
2017-07-03 11:19:51 -07:00
|
|
|
data_layout,
|
2018-05-02 06:03:06 +02:00
|
|
|
alloc_map: Lock::new(interpret::AllocMap::new()),
|
2018-12-08 20:30:23 +01:00
|
|
|
}
|
2015-09-06 21:51:58 +03:00
|
|
|
}
|
2017-03-08 16:28:47 -05:00
|
|
|
|
2022-11-03 14:15:17 +08:00
|
|
|
/// Constructs a `TyKind::Error` type with current `ErrorGuaranteed`
|
|
|
|
#[track_caller]
|
2023-02-22 22:23:10 +00:00
|
|
|
pub fn ty_error(self, reported: ErrorGuaranteed) -> Ty<'tcx> {
|
2023-02-20 10:19:09 +11:00
|
|
|
self.mk_ty_from_kind(Error(reported))
|
2022-11-03 14:15:17 +08:00
|
|
|
}
|
|
|
|
|
2020-05-05 23:02:09 -05:00
|
|
|
/// Constructs a `TyKind::Error` type and registers a `delay_span_bug` to ensure it gets used.
|
|
|
|
#[track_caller]
|
2023-02-22 22:23:10 +00:00
|
|
|
pub fn ty_error_misc(self) -> Ty<'tcx> {
|
2020-05-26 12:49:11 -05:00
|
|
|
self.ty_error_with_message(DUMMY_SP, "TyKind::Error constructed but no error reported")
|
2020-05-05 23:02:09 -05:00
|
|
|
}
|
|
|
|
|
2020-07-01 09:33:21 +09:00
|
|
|
/// Constructs a `TyKind::Error` type and registers a `delay_span_bug` with the given `msg` to
|
2020-05-05 23:02:09 -05:00
|
|
|
/// ensure it gets used.
|
|
|
|
#[track_caller]
|
|
|
|
pub fn ty_error_with_message<S: Into<MultiSpan>>(self, span: S, msg: &str) -> Ty<'tcx> {
|
2022-01-22 18:49:12 -06:00
|
|
|
let reported = self.sess.delay_span_bug(span, msg);
|
2023-02-20 10:19:09 +11:00
|
|
|
self.mk_ty_from_kind(Error(reported))
|
2020-05-05 23:02:09 -05:00
|
|
|
}
|
|
|
|
|
2023-02-09 10:38:45 +00:00
|
|
|
/// Constructs a `RegionKind::ReError` lifetime.
|
|
|
|
#[track_caller]
|
2023-02-13 13:03:45 +11:00
|
|
|
pub fn mk_re_error(self, reported: ErrorGuaranteed) -> Region<'tcx> {
|
|
|
|
self.intern_region(ty::ReError(reported))
|
2023-02-09 10:38:45 +00:00
|
|
|
}
|
|
|
|
|
2023-02-07 14:55:16 +00:00
|
|
|
/// Constructs a `RegionKind::ReError` lifetime and registers a `delay_span_bug` to ensure it
|
|
|
|
/// gets used.
|
|
|
|
#[track_caller]
|
2023-02-13 13:03:45 +11:00
|
|
|
pub fn mk_re_error_misc(self) -> Region<'tcx> {
|
|
|
|
self.mk_re_error_with_message(
|
2023-02-07 14:55:16 +00:00
|
|
|
DUMMY_SP,
|
|
|
|
"RegionKind::ReError constructed but no error reported",
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Constructs a `RegionKind::ReError` lifetime and registers a `delay_span_bug` with the given
|
|
|
|
/// `msg` to ensure it gets used.
|
|
|
|
#[track_caller]
|
2023-02-13 13:03:45 +11:00
|
|
|
pub fn mk_re_error_with_message<S: Into<MultiSpan>>(self, span: S, msg: &str) -> Region<'tcx> {
|
2023-02-07 14:55:16 +00:00
|
|
|
let reported = self.sess.delay_span_bug(span, msg);
|
2023-02-13 13:03:45 +11:00
|
|
|
self.mk_re_error(reported)
|
2023-02-07 14:55:16 +00:00
|
|
|
}
|
|
|
|
|
2022-11-03 14:15:17 +08:00
|
|
|
/// Like [TyCtxt::ty_error] but for constants, with current `ErrorGuaranteed`
|
|
|
|
#[track_caller]
|
|
|
|
pub fn const_error_with_guaranteed(
|
|
|
|
self,
|
|
|
|
ty: Ty<'tcx>,
|
|
|
|
reported: ErrorGuaranteed,
|
|
|
|
) -> Const<'tcx> {
|
2022-11-04 16:10:32 +08:00
|
|
|
self.mk_const(ty::ConstKind::Error(reported), ty)
|
2022-11-03 14:15:17 +08:00
|
|
|
}
|
|
|
|
|
2022-01-17 07:54:56 +01:00
|
|
|
/// Like [TyCtxt::ty_error] but for constants.
|
2020-05-05 23:02:09 -05:00
|
|
|
#[track_caller]
|
2022-02-02 14:24:45 +11:00
|
|
|
pub fn const_error(self, ty: Ty<'tcx>) -> Const<'tcx> {
|
2022-01-05 11:42:08 +01:00
|
|
|
self.const_error_with_message(
|
|
|
|
ty,
|
|
|
|
DUMMY_SP,
|
|
|
|
"ty::ConstKind::Error constructed but no error reported",
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2022-01-17 07:54:56 +01:00
|
|
|
/// Like [TyCtxt::ty_error_with_message] but for constants.
|
2022-01-05 11:42:08 +01:00
|
|
|
#[track_caller]
|
|
|
|
pub fn const_error_with_message<S: Into<MultiSpan>>(
|
|
|
|
self,
|
|
|
|
ty: Ty<'tcx>,
|
|
|
|
span: S,
|
|
|
|
msg: &str,
|
2022-02-02 14:24:45 +11:00
|
|
|
) -> Const<'tcx> {
|
2022-01-22 18:49:12 -06:00
|
|
|
let reported = self.sess.delay_span_bug(span, msg);
|
2022-11-04 20:33:32 +00:00
|
|
|
self.mk_const(ty::ConstKind::Error(reported), ty)
|
2020-05-05 23:02:09 -05:00
|
|
|
}
|
|
|
|
|
2020-09-19 12:38:24 +02:00
|
|
|
pub fn consider_optimizing<T: Fn() -> String>(self, msg: T) -> bool {
|
2023-02-23 18:51:31 +00:00
|
|
|
self.sess.consider_optimizing(|| self.crate_name(LOCAL_CRATE), msg)
|
2017-03-08 16:28:47 -05:00
|
|
|
}
|
2017-08-31 08:57:41 -07:00
|
|
|
|
2019-05-19 20:16:04 +02:00
|
|
|
/// Obtain all lang items of this crate and all dependencies (recursively)
|
2020-03-31 21:38:14 +02:00
|
|
|
pub fn lang_items(self) -> &'tcx rustc_hir::lang_items::LanguageItems {
|
2021-05-11 13:50:41 +02:00
|
|
|
self.get_lang_items(())
|
2017-08-31 08:57:41 -07:00
|
|
|
}
|
2017-08-31 15:08:34 -07:00
|
|
|
|
2019-05-19 20:16:04 +02:00
|
|
|
/// Obtain the given diagnostic item's `DefId`. Use `is_diagnostic_item` if you just want to
|
|
|
|
/// compare against another `DefId`, since `is_diagnostic_item` is cheaper.
|
|
|
|
pub fn get_diagnostic_item(self, name: Symbol) -> Option<DefId> {
|
2021-10-04 15:57:39 -05:00
|
|
|
self.all_diagnostic_items(()).name_to_id.get(&name).copied()
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Obtain the diagnostic item's name
|
|
|
|
pub fn get_diagnostic_name(self, id: DefId) -> Option<Symbol> {
|
|
|
|
self.diagnostic_items(id.krate).id_to_name.get(&id).copied()
|
2019-05-19 20:16:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Check whether the diagnostic item with the given `name` has the given `DefId`.
|
|
|
|
pub fn is_diagnostic_item(self, name: Symbol, did: DefId) -> bool {
|
2021-10-04 15:57:39 -05:00
|
|
|
self.diagnostic_items(did.krate).name_to_id.get(&name) == Some(&did)
|
2019-05-19 20:16:04 +02:00
|
|
|
}
|
|
|
|
|
2022-11-26 21:33:12 +01:00
|
|
|
/// Returns `true` if the node pointed to by `def_id` is a generator for an async construct.
|
|
|
|
pub fn generator_is_async(self, def_id: DefId) -> bool {
|
|
|
|
matches!(self.generator_kind(def_id), Some(hir::GeneratorKind::Async(_)))
|
|
|
|
}
|
|
|
|
|
2022-02-19 15:36:11 +01:00
|
|
|
pub fn stability(self) -> &'tcx stability::Index {
|
2021-05-11 13:50:41 +02:00
|
|
|
self.stability_index(())
|
2017-08-31 15:08:34 -07:00
|
|
|
}
|
2017-09-07 08:13:41 -07:00
|
|
|
|
2019-11-30 00:23:38 +01:00
|
|
|
pub fn features(self) -> &'tcx rustc_feature::Features {
|
2021-05-11 13:50:41 +02:00
|
|
|
self.features_query(())
|
2018-02-14 16:11:02 +01:00
|
|
|
}
|
|
|
|
|
2020-03-24 09:09:42 +01:00
|
|
|
pub fn def_key(self, id: DefId) -> rustc_hir::definitions::DefKey {
|
2021-05-20 20:17:45 +02:00
|
|
|
// Accessing the DefKey is ok, since it is part of DefPathHash.
|
2021-04-04 14:40:35 +02:00
|
|
|
if let Some(id) = id.as_local() {
|
2021-07-12 22:19:25 +02:00
|
|
|
self.definitions_untracked().def_key(id)
|
2021-04-04 14:40:35 +02:00
|
|
|
} else {
|
2022-12-08 10:53:20 +00:00
|
|
|
self.cstore_untracked().def_key(id)
|
2021-04-04 14:40:35 +02:00
|
|
|
}
|
2017-09-07 13:21:46 -07:00
|
|
|
}
|
|
|
|
|
2019-02-08 14:53:55 +01:00
|
|
|
/// Converts a `DefId` into its fully expanded `DefPath` (every
|
2019-09-06 03:57:44 +01:00
|
|
|
/// `DefId` is really just an interned `DefPath`).
|
2017-09-07 13:21:46 -07:00
|
|
|
///
|
|
|
|
/// Note that if `id` is not local to this crate, the result will
|
|
|
|
/// be a non-local `DefPath`.
|
2020-03-24 09:09:42 +01:00
|
|
|
pub fn def_path(self, id: DefId) -> rustc_hir::definitions::DefPath {
|
2021-05-20 20:17:45 +02:00
|
|
|
// Accessing the DefPath is ok, since it is part of DefPathHash.
|
2019-11-03 20:48:08 +02:00
|
|
|
if let Some(id) = id.as_local() {
|
2021-07-12 22:19:25 +02:00
|
|
|
self.definitions_untracked().def_path(id)
|
2019-11-03 20:48:08 +02:00
|
|
|
} else {
|
2022-12-08 10:53:20 +00:00
|
|
|
self.cstore_untracked().def_path(id)
|
2019-11-03 20:48:08 +02:00
|
|
|
}
|
2017-09-07 13:21:46 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2020-03-24 09:09:42 +01:00
|
|
|
pub fn def_path_hash(self, def_id: DefId) -> rustc_hir::definitions::DefPathHash {
|
2021-05-20 20:17:45 +02:00
|
|
|
// Accessing the DefPathHash is ok, it is incr. comp. stable.
|
2019-11-03 20:48:08 +02:00
|
|
|
if let Some(def_id) = def_id.as_local() {
|
2021-07-12 22:19:25 +02:00
|
|
|
self.definitions_untracked().def_path_hash(def_id)
|
2017-09-07 13:21:46 -07:00
|
|
|
} else {
|
2022-12-08 10:53:20 +00:00
|
|
|
self.cstore_untracked().def_path_hash(def_id)
|
2017-09-07 13:21:46 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-30 22:32:45 +02:00
|
|
|
#[inline]
|
2021-06-30 18:39:28 +02:00
|
|
|
pub fn stable_crate_id(self, crate_num: CrateNum) -> StableCrateId {
|
|
|
|
if crate_num == LOCAL_CRATE {
|
|
|
|
self.sess.local_stable_crate_id()
|
|
|
|
} else {
|
2022-12-08 10:53:20 +00:00
|
|
|
self.cstore_untracked().stable_crate_id(crate_num)
|
2021-06-30 18:39:28 +02:00
|
|
|
}
|
2021-05-30 22:32:45 +02:00
|
|
|
}
|
|
|
|
|
2021-07-20 13:59:12 +02:00
|
|
|
/// Maps a StableCrateId to the corresponding CrateNum. This method assumes
|
|
|
|
/// that the crate in question has already been loaded by the CrateStore.
|
|
|
|
#[inline]
|
|
|
|
pub fn stable_crate_id_to_crate_num(self, stable_crate_id: StableCrateId) -> CrateNum {
|
|
|
|
if stable_crate_id == self.sess.local_stable_crate_id() {
|
|
|
|
LOCAL_CRATE
|
|
|
|
} else {
|
2022-12-08 10:53:20 +00:00
|
|
|
self.cstore_untracked().stable_crate_id_to_crate_num(stable_crate_id)
|
2021-07-20 13:59:12 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-16 17:13:02 +02:00
|
|
|
/// Converts a `DefPathHash` to its corresponding `DefId` in the current compilation
|
|
|
|
/// session, if it still exists. This is used during incremental compilation to
|
|
|
|
/// turn a deserialized `DefPathHash` into its current `DefId`.
|
2022-01-19 17:36:44 -05:00
|
|
|
pub fn def_path_hash_to_def_id(self, hash: DefPathHash, err: &mut dyn FnMut() -> !) -> DefId {
|
2021-10-16 17:13:02 +02:00
|
|
|
debug!("def_path_hash_to_def_id({:?})", hash);
|
|
|
|
|
|
|
|
let stable_crate_id = hash.stable_crate_id();
|
|
|
|
|
|
|
|
// If this is a DefPathHash from the local crate, we can look up the
|
|
|
|
// DefId in the tcx's `Definitions`.
|
|
|
|
if stable_crate_id == self.sess.local_stable_crate_id() {
|
2022-12-08 08:52:07 +00:00
|
|
|
self.untracked.definitions.read().local_def_path_hash_to_def_id(hash, err).to_def_id()
|
2021-10-16 17:13:02 +02:00
|
|
|
} else {
|
|
|
|
// If this is a DefPathHash from an upstream crate, let the CrateStore map
|
|
|
|
// it to a DefId.
|
2022-12-08 10:53:20 +00:00
|
|
|
let cstore = &*self.cstore_untracked();
|
2022-10-25 14:45:02 +04:00
|
|
|
let cnum = cstore.stable_crate_id_to_crate_num(stable_crate_id);
|
|
|
|
cstore.def_path_hash_to_def_id(cnum, hash)
|
2021-10-16 17:13:02 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-04 14:57:14 +02:00
|
|
|
pub fn def_path_debug_str(self, def_id: DefId) -> String {
|
|
|
|
// We are explicitly not going through queries here in order to get
|
2021-06-08 18:36:30 +02:00
|
|
|
// crate name and stable crate id since this code is called from debug!()
|
2017-10-04 14:57:14 +02:00
|
|
|
// statements within the query system and we'd run into endless
|
|
|
|
// recursion otherwise.
|
2021-06-08 18:36:30 +02:00
|
|
|
let (crate_name, stable_crate_id) = if def_id.is_local() {
|
2022-12-05 16:37:44 +00:00
|
|
|
(self.crate_name(LOCAL_CRATE), self.sess.local_stable_crate_id())
|
2017-10-04 14:57:14 +02:00
|
|
|
} else {
|
2022-12-08 10:53:20 +00:00
|
|
|
let cstore = &*self.cstore_untracked();
|
2021-07-12 21:20:16 +02:00
|
|
|
(cstore.crate_name(def_id.krate), cstore.stable_crate_id(def_id.krate))
|
2017-10-04 14:57:14 +02:00
|
|
|
};
|
|
|
|
|
2019-12-24 17:38:22 -05:00
|
|
|
format!(
|
2022-07-16 21:30:17 +03:00
|
|
|
"{}[{:04x}]{}",
|
2019-12-24 17:38:22 -05:00
|
|
|
crate_name,
|
2021-06-08 18:36:30 +02:00
|
|
|
// Don't print the whole stable crate id. That's just
|
2019-12-24 17:38:22 -05:00
|
|
|
// annoying in debug output.
|
2022-07-16 21:30:17 +03:00
|
|
|
stable_crate_id.to_u64() >> 8 * 6,
|
2020-09-23 23:38:38 +01:00
|
|
|
self.def_path(def_id).to_string_no_crate_verbose()
|
2019-12-24 17:38:22 -05:00
|
|
|
)
|
2017-10-04 14:57:14 +02:00
|
|
|
}
|
2022-12-01 10:33:28 +00:00
|
|
|
}
|
2019-09-06 03:57:44 +01:00
|
|
|
|
2022-12-01 10:33:28 +00:00
|
|
|
impl<'tcx> TyCtxtAt<'tcx> {
|
2021-07-12 22:19:25 +02:00
|
|
|
/// Create a new definition within the incr. comp. engine.
|
2022-11-26 13:54:45 +00:00
|
|
|
pub fn create_def(
|
|
|
|
self,
|
|
|
|
parent: LocalDefId,
|
|
|
|
data: hir::definitions::DefPathData,
|
2022-12-03 13:36:39 +00:00
|
|
|
) -> TyCtxtFeed<'tcx, LocalDefId> {
|
2022-05-03 22:14:07 +02:00
|
|
|
// This function modifies `self.definitions` using a side-effect.
|
2021-07-12 22:19:25 +02:00
|
|
|
// We need to ensure that these side effects are re-run by the incr. comp. engine.
|
2022-05-03 22:14:07 +02:00
|
|
|
// Depending on the forever-red node will tell the graph that the calling query
|
|
|
|
// needs to be re-evaluated.
|
2022-04-27 19:18:26 +02:00
|
|
|
self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE);
|
2021-07-12 22:19:25 +02:00
|
|
|
|
2022-05-03 22:14:07 +02:00
|
|
|
// The following call has the side effect of modifying the tables inside `definitions`.
|
|
|
|
// These very tables are relied on by the incr. comp. engine to decode DepNodes and to
|
|
|
|
// decode the on-disk cache.
|
|
|
|
//
|
2021-07-12 22:19:25 +02:00
|
|
|
// Any LocalDefId which is used within queries, either as key or result, either:
|
|
|
|
// - has been created before the construction of the TyCtxt;
|
2022-04-27 19:18:26 +02:00
|
|
|
// - has been created by this call to `create_def`.
|
2021-07-12 22:19:25 +02:00
|
|
|
// As a consequence, this LocalDefId is always re-created before it is needed by the incr.
|
|
|
|
// comp. engine itself.
|
2022-05-03 22:14:07 +02:00
|
|
|
//
|
|
|
|
// This call also writes to the value of `source_span` and `expn_that_defined` queries.
|
|
|
|
// This is fine because:
|
|
|
|
// - those queries are `eval_always` so we won't miss their result changing;
|
|
|
|
// - this write will have happened before these queries are called.
|
2022-12-08 08:52:07 +00:00
|
|
|
let key = self.untracked.definitions.write().create_def(parent, data);
|
2022-11-26 13:54:45 +00:00
|
|
|
|
2022-12-03 13:36:39 +00:00
|
|
|
let feed = TyCtxtFeed { tcx: self.tcx, key };
|
2022-12-01 10:33:28 +00:00
|
|
|
feed.def_span(self.span);
|
|
|
|
feed
|
2021-07-12 22:19:25 +02:00
|
|
|
}
|
2022-12-01 10:33:28 +00:00
|
|
|
}
|
2021-07-12 22:19:25 +02:00
|
|
|
|
2022-12-01 10:33:28 +00:00
|
|
|
impl<'tcx> TyCtxt<'tcx> {
|
2021-07-12 22:19:25 +02:00
|
|
|
pub fn iter_local_def_id(self) -> impl Iterator<Item = LocalDefId> + 'tcx {
|
2022-11-26 13:54:45 +00:00
|
|
|
// Create a dependency to the red node to be sure we re-execute this when the amount of
|
2021-07-12 22:19:25 +02:00
|
|
|
// definitions change.
|
2022-11-26 13:54:45 +00:00
|
|
|
self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE);
|
|
|
|
|
2022-12-08 08:52:07 +00:00
|
|
|
let definitions = &self.untracked.definitions;
|
2022-11-26 13:54:45 +00:00
|
|
|
std::iter::from_generator(|| {
|
|
|
|
let mut i = 0;
|
|
|
|
|
|
|
|
// Recompute the number of definitions each time, because our caller may be creating
|
|
|
|
// new ones.
|
|
|
|
while i < { definitions.read().num_definitions() } {
|
|
|
|
let local_def_index = rustc_span::def_id::DefIndex::from_usize(i);
|
|
|
|
yield LocalDefId { local_def_index };
|
|
|
|
i += 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Leak a read lock once we finish iterating on definitions, to prevent adding new ones.
|
|
|
|
definitions.leak();
|
|
|
|
})
|
2021-07-12 22:19:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn def_path_table(self) -> &'tcx rustc_hir::definitions::DefPathTable {
|
2022-08-18 10:13:37 +08:00
|
|
|
// Create a dependency to the crate to be sure we re-execute this when the amount of
|
2021-07-12 22:19:25 +02:00
|
|
|
// definitions change.
|
2022-11-26 13:54:45 +00:00
|
|
|
self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE);
|
|
|
|
|
2022-08-18 10:13:37 +08:00
|
|
|
// Leak a read lock once we start iterating on definitions, to prevent adding new ones
|
2022-11-16 20:34:16 +00:00
|
|
|
// while iterating. If some query needs to add definitions, it should be `ensure`d above.
|
2022-12-08 08:52:07 +00:00
|
|
|
let definitions = self.untracked.definitions.leak();
|
2021-07-12 22:19:25 +02:00
|
|
|
definitions.def_path_table()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn def_path_hash_to_def_index_map(
|
|
|
|
self,
|
|
|
|
) -> &'tcx rustc_hir::def_path_hash_map::DefPathHashMap {
|
2022-08-18 10:13:37 +08:00
|
|
|
// Create a dependency to the crate to be sure we re-execute this when the amount of
|
2021-07-12 22:19:25 +02:00
|
|
|
// definitions change.
|
|
|
|
self.ensure().hir_crate(());
|
2022-08-18 10:13:37 +08:00
|
|
|
// Leak a read lock once we start iterating on definitions, to prevent adding new ones
|
2022-11-16 20:34:16 +00:00
|
|
|
// while iterating. If some query needs to add definitions, it should be `ensure`d above.
|
2022-12-08 08:52:07 +00:00
|
|
|
let definitions = self.untracked.definitions.leak();
|
2021-07-12 22:19:25 +02:00
|
|
|
definitions.def_path_hash_to_def_index_map()
|
|
|
|
}
|
|
|
|
|
2021-06-28 21:12:01 +02:00
|
|
|
/// Note that this is *untracked* and should only be used within the query
|
|
|
|
/// system if the result is otherwise tracked through queries
|
2023-02-23 01:14:48 +01:00
|
|
|
#[inline]
|
2022-12-08 10:53:20 +00:00
|
|
|
pub fn cstore_untracked(self) -> MappedReadGuard<'tcx, CrateStoreDyn> {
|
|
|
|
ReadGuard::map(self.untracked.cstore.read(), |c| &**c)
|
2021-06-28 21:12:01 +02:00
|
|
|
}
|
|
|
|
|
2023-02-15 17:19:38 +00:00
|
|
|
/// Give out access to the untracked data without any sanity checks.
|
|
|
|
pub fn untracked(self) -> &'tcx Untracked {
|
|
|
|
&self.untracked
|
|
|
|
}
|
2021-06-28 21:12:01 +02:00
|
|
|
/// Note that this is *untracked* and should only be used within the query
|
|
|
|
/// system if the result is otherwise tracked through queries
|
2021-07-12 22:19:25 +02:00
|
|
|
#[inline]
|
|
|
|
pub fn definitions_untracked(self) -> ReadGuard<'tcx, Definitions> {
|
2022-12-08 08:52:07 +00:00
|
|
|
self.untracked.definitions.read()
|
2017-09-07 13:21:46 -07:00
|
|
|
}
|
2017-09-14 15:10:24 +02:00
|
|
|
|
2022-05-30 18:49:17 +02:00
|
|
|
/// Note that this is *untracked* and should only be used within the query
|
|
|
|
/// system if the result is otherwise tracked through queries
|
|
|
|
#[inline]
|
|
|
|
pub fn source_span_untracked(self, def_id: LocalDefId) -> Span {
|
2023-02-21 08:37:10 +00:00
|
|
|
self.untracked.source_span.get(def_id).unwrap_or(DUMMY_SP)
|
2017-09-07 13:21:46 -07:00
|
|
|
}
|
2017-09-14 15:10:24 +02:00
|
|
|
|
2018-12-04 16:26:34 +01:00
|
|
|
#[inline(always)]
|
2021-07-12 22:19:25 +02:00
|
|
|
pub fn with_stable_hashing_context<R>(
|
|
|
|
self,
|
|
|
|
f: impl FnOnce(StableHashingContext<'_>) -> R,
|
|
|
|
) -> R {
|
2022-12-08 08:52:07 +00:00
|
|
|
f(StableHashingContext::new(self.sess, &self.untracked))
|
2017-09-14 15:10:24 +02:00
|
|
|
}
|
2017-09-14 17:43:03 +02:00
|
|
|
|
Use delayed error handling for `Encodable` and `Encoder` infallible.
There are two impls of the `Encoder` trait: `opaque::Encoder` and
`opaque::FileEncoder`. The former encodes into memory and is infallible, the
latter writes to file and is fallible.
Currently, standard `Result`/`?`/`unwrap` error handling is used, but this is a
bit verbose and has non-trivial cost, which is annoying given how rare failures
are (especially in the infallible `opaque::Encoder` case).
This commit changes how `Encoder` fallibility is handled. All the `emit_*`
methods are now infallible. `opaque::Encoder` requires no great changes for
this. `opaque::FileEncoder` now implements a delayed error handling strategy.
If a failure occurs, it records this via the `res` field, and all subsequent
encoding operations are skipped if `res` indicates an error has occurred. Once
encoding is complete, the new `finish` method is called, which returns a
`Result`. In other words, there is now a single `Result`-producing method
instead of many of them.
This has very little effect on how any file errors are reported if
`opaque::FileEncoder` has any failures.
Much of this commit is boring mechanical changes, removing `Result` return
values and `?` or `unwrap` from expressions. The more interesting parts are as
follows.
- serialize.rs: The `Encoder` trait gains an `Ok` associated type. The
`into_inner` method is changed into `finish`, which returns
`Result<Vec<u8>, !>`.
- opaque.rs: The `FileEncoder` adopts the delayed error handling
strategy. Its `Ok` type is a `usize`, returning the number of bytes
written, replacing previous uses of `FileEncoder::position`.
- Various methods that take an encoder now consume it, rather than being
passed a mutable reference, e.g. `serialize_query_result_cache`.
2022-06-07 13:30:45 +10:00
|
|
|
pub fn serialize_query_result_cache(self, encoder: FileEncoder) -> FileEncodeResult {
|
|
|
|
self.on_disk_cache.as_ref().map_or(Ok(0), |c| c.serialize(self, encoder))
|
2017-10-19 14:32:39 +02:00
|
|
|
}
|
|
|
|
|
2020-05-17 10:36:56 +02:00
|
|
|
/// If `true`, we should use lazy normalization for constants, otherwise
|
|
|
|
/// we still evaluate them eagerly.
|
|
|
|
#[inline]
|
|
|
|
pub fn lazy_normalization(self) -> bool {
|
2020-08-05 18:27:54 +02:00
|
|
|
let features = self.features();
|
2021-08-27 18:04:57 +02:00
|
|
|
// Note: We only use lazy normalization for generic const expressions.
|
|
|
|
features.generic_const_exprs
|
2020-05-17 10:36:56 +02:00
|
|
|
}
|
|
|
|
|
2018-03-06 14:44:14 +01:00
|
|
|
#[inline]
|
|
|
|
pub fn local_crate_exports_generics(self) -> bool {
|
2018-07-26 13:20:47 -06:00
|
|
|
debug_assert!(self.sess.opts.share_generics());
|
2018-03-21 12:23:57 +01:00
|
|
|
|
2020-05-15 21:44:28 -07:00
|
|
|
self.sess.crate_types().iter().any(|crate_type| {
|
2018-03-06 14:44:14 +01:00
|
|
|
match crate_type {
|
2019-12-24 17:38:22 -05:00
|
|
|
CrateType::Executable
|
|
|
|
| CrateType::Staticlib
|
|
|
|
| CrateType::ProcMacro
|
|
|
|
| CrateType::Cdylib => false,
|
2019-11-01 13:46:05 +01:00
|
|
|
|
|
|
|
// FIXME rust-lang/rust#64319, rust-lang/rust#64872:
|
|
|
|
// We want to block export of generics from dylibs,
|
|
|
|
// but we must fix rust-lang/rust#65890 before we can
|
|
|
|
// do that robustly.
|
2019-12-24 17:38:22 -05:00
|
|
|
CrateType::Dylib => true,
|
2019-11-01 13:46:05 +01:00
|
|
|
|
2019-12-24 17:38:22 -05:00
|
|
|
CrateType::Rlib => true,
|
2018-03-06 14:44:14 +01:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
2018-09-02 00:42:51 +02:00
|
|
|
|
2022-07-21 11:51:06 +01:00
|
|
|
/// Returns the `DefId` and the `BoundRegionKind` corresponding to the given region.
|
2020-09-18 20:49:25 +02:00
|
|
|
pub fn is_suitable_region(self, region: Region<'tcx>) -> Option<FreeRegionInfo> {
|
2018-09-02 00:42:51 +02:00
|
|
|
let (suitable_region_binding_scope, bound_region) = match *region {
|
2020-06-27 13:38:00 +02:00
|
|
|
ty::ReFree(ref free_region) => {
|
|
|
|
(free_region.scope.expect_local(), free_region.bound_region)
|
2019-12-24 17:38:22 -05:00
|
|
|
}
|
2020-06-27 13:38:00 +02:00
|
|
|
ty::ReEarlyBound(ref ebr) => (
|
2022-04-25 22:08:45 +03:00
|
|
|
self.local_parent(ebr.def_id.expect_local()),
|
2020-12-18 13:24:55 -05:00
|
|
|
ty::BoundRegionKind::BrNamed(ebr.def_id, ebr.name),
|
2020-06-27 13:38:00 +02:00
|
|
|
),
|
2018-09-02 00:42:51 +02:00
|
|
|
_ => return None, // not a free region
|
|
|
|
};
|
|
|
|
|
2021-10-20 20:59:15 +02:00
|
|
|
let is_impl_item = match self.hir().find_by_def_id(suitable_region_binding_scope) {
|
2020-04-16 17:38:52 -07:00
|
|
|
Some(Node::Item(..) | Node::TraitItem(..)) => false,
|
2018-09-02 00:42:51 +02:00
|
|
|
Some(Node::ImplItem(..)) => {
|
|
|
|
self.is_bound_region_in_impl_item(suitable_region_binding_scope)
|
|
|
|
}
|
|
|
|
_ => return None,
|
|
|
|
};
|
|
|
|
|
2020-03-20 15:03:11 +01:00
|
|
|
Some(FreeRegionInfo {
|
2018-09-02 00:42:51 +02:00
|
|
|
def_id: suitable_region_binding_scope,
|
|
|
|
boundregion: bound_region,
|
2019-10-24 01:28:27 +08:00
|
|
|
is_impl_item,
|
2020-03-20 15:03:11 +01:00
|
|
|
})
|
2018-09-02 00:42:51 +02:00
|
|
|
}
|
|
|
|
|
2020-06-22 16:05:31 -07:00
|
|
|
/// Given a `DefId` for an `fn`, return all the `dyn` and `impl` traits in its return type.
|
2020-06-27 13:15:12 +02:00
|
|
|
pub fn return_type_impl_or_dyn_traits(
|
2020-09-18 20:49:25 +02:00
|
|
|
self,
|
2020-06-27 13:15:12 +02:00
|
|
|
scope_def_id: LocalDefId,
|
|
|
|
) -> Vec<&'tcx hir::Ty<'tcx>> {
|
2020-08-12 12:22:56 +02:00
|
|
|
let hir_id = self.hir().local_def_id_to_hir_id(scope_def_id);
|
2022-02-19 00:48:49 +01:00
|
|
|
let Some(hir::FnDecl { output: hir::FnRetTy::Return(hir_output), .. }) = self.hir().fn_decl_by_hir_id(hir_id) else {
|
|
|
|
return vec![];
|
2020-05-26 13:13:19 -07:00
|
|
|
};
|
|
|
|
|
2020-06-09 13:57:33 -07:00
|
|
|
let mut v = TraitObjectVisitor(vec![], self.hir());
|
|
|
|
v.visit_ty(hir_output);
|
|
|
|
v.0
|
2020-05-26 13:13:19 -07:00
|
|
|
}
|
|
|
|
|
2022-12-05 16:51:49 -08:00
|
|
|
/// Given a `DefId` for an `fn`, return all the `dyn` and `impl` traits in its return type and associated alias span when type alias is used
|
|
|
|
pub fn return_type_impl_or_dyn_traits_with_type_alias(
|
|
|
|
self,
|
|
|
|
scope_def_id: LocalDefId,
|
|
|
|
) -> Option<(Vec<&'tcx hir::Ty<'tcx>>, Span)> {
|
|
|
|
let hir_id = self.hir().local_def_id_to_hir_id(scope_def_id);
|
|
|
|
let mut v = TraitObjectVisitor(vec![], self.hir());
|
|
|
|
// when the return type is a type alias
|
|
|
|
if let Some(hir::FnDecl { output: hir::FnRetTy::Return(hir_output), .. }) = self.hir().fn_decl_by_hir_id(hir_id)
|
|
|
|
&& let hir::TyKind::Path(hir::QPath::Resolved(
|
|
|
|
None,
|
|
|
|
hir::Path { res: hir::def::Res::Def(DefKind::TyAlias, def_id), .. }, )) = hir_output.kind
|
|
|
|
&& let Some(local_id) = def_id.as_local()
|
|
|
|
&& let Some(alias_ty) = self.hir().get_by_def_id(local_id).alias_ty() // it is type alias
|
|
|
|
&& let Some(alias_generics) = self.hir().get_by_def_id(local_id).generics()
|
|
|
|
{
|
|
|
|
v.visit_ty(alias_ty);
|
|
|
|
if !v.0.is_empty() {
|
|
|
|
return Some((v.0, alias_generics.span));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
|
2020-09-18 20:49:25 +02:00
|
|
|
pub fn return_type_impl_trait(self, scope_def_id: LocalDefId) -> Option<(Ty<'tcx>, Span)> {
|
2021-06-24 14:59:43 +09:00
|
|
|
// `type_of()` will fail on these (#55796, #86483), so only allow `fn`s or closures.
|
2021-10-20 20:59:15 +02:00
|
|
|
match self.hir().get_by_def_id(scope_def_id) {
|
2021-06-24 14:59:43 +09:00
|
|
|
Node::Item(&hir::Item { kind: ItemKind::Fn(..), .. }) => {}
|
|
|
|
Node::TraitItem(&hir::TraitItem { kind: TraitItemKind::Fn(..), .. }) => {}
|
|
|
|
Node::ImplItem(&hir::ImplItem { kind: ImplItemKind::Fn(..), .. }) => {}
|
2022-06-11 21:25:25 +02:00
|
|
|
Node::Expr(&hir::Expr { kind: ExprKind::Closure { .. }, .. }) => {}
|
2021-06-24 14:59:43 +09:00
|
|
|
_ => return None,
|
2018-11-08 15:18:55 -08:00
|
|
|
}
|
|
|
|
|
2023-02-07 01:29:48 -07:00
|
|
|
let ret_ty = self.type_of(scope_def_id).subst_identity();
|
2020-08-03 00:49:11 +02:00
|
|
|
match ret_ty.kind() {
|
2018-09-02 00:42:51 +02:00
|
|
|
ty::FnDef(_, _) => {
|
2020-09-18 20:49:25 +02:00
|
|
|
let sig = ret_ty.fn_sig(self);
|
2020-10-24 02:21:18 +02:00
|
|
|
let output = self.erase_late_bound_regions(sig.output());
|
2023-02-15 11:43:41 +00:00
|
|
|
output.is_impl_trait().then(|| {
|
2021-10-20 20:59:15 +02:00
|
|
|
let hir_id = self.hir().local_def_id_to_hir_id(scope_def_id);
|
2019-10-24 01:28:55 +08:00
|
|
|
let fn_decl = self.hir().fn_decl_by_hir_id(hir_id).unwrap();
|
2023-02-15 11:43:41 +00:00
|
|
|
(output, fn_decl.output.span())
|
|
|
|
})
|
2018-09-02 00:42:51 +02:00
|
|
|
}
|
2019-12-24 17:38:22 -05:00
|
|
|
_ => None,
|
2018-09-02 00:42:51 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-27 11:15:06 +00:00
|
|
|
/// Checks if the bound region is in Impl Item.
|
2020-09-18 20:49:25 +02:00
|
|
|
pub fn is_bound_region_in_impl_item(self, suitable_region_binding_scope: LocalDefId) -> bool {
|
2022-03-13 00:52:25 +01:00
|
|
|
let container_id = self.parent(suitable_region_binding_scope.to_def_id());
|
2018-09-02 00:42:51 +02:00
|
|
|
if self.impl_trait_ref(container_id).is_some() {
|
|
|
|
// For now, we do not try to target impls of traits. This is
|
|
|
|
// because this message is going to suggest that the user
|
|
|
|
// change the fn signature, but they may not be free to do so,
|
|
|
|
// since the signature must match the trait.
|
|
|
|
//
|
|
|
|
// FIXME(#42706) -- in some cases, we could do better here.
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
false
|
|
|
|
}
|
2019-01-19 21:59:34 +01:00
|
|
|
|
2019-09-06 03:57:44 +01:00
|
|
|
/// Determines whether identifiers in the assembly have strict naming rules.
|
2019-01-19 21:59:34 +01:00
|
|
|
/// Currently, only NVPTX* targets need it.
|
2020-09-18 20:49:25 +02:00
|
|
|
pub fn has_strict_asm_symbol_naming(self) -> bool {
|
2020-10-15 11:44:00 +02:00
|
|
|
self.sess.target.arch.contains("nvptx")
|
2017-09-07 13:21:46 -07:00
|
|
|
}
|
2019-10-28 20:02:41 -07:00
|
|
|
|
|
|
|
/// Returns `&'static core::panic::Location<'static>`.
|
2020-09-18 20:49:25 +02:00
|
|
|
pub fn caller_location_ty(self) -> Ty<'tcx> {
|
2019-10-28 20:02:41 -07:00
|
|
|
self.mk_imm_ref(
|
|
|
|
self.lifetimes.re_static,
|
2023-02-07 01:29:48 -07:00
|
|
|
self.type_of(self.require_lang_item(LangItem::PanicLocation, None))
|
2023-02-17 14:33:08 +11:00
|
|
|
.subst(self, self.mk_substs(&[self.lifetimes.re_static.into()])),
|
2019-10-28 20:02:41 -07:00
|
|
|
)
|
|
|
|
}
|
2019-12-30 19:46:30 -06:00
|
|
|
|
2020-01-25 19:09:23 -06:00
|
|
|
/// Returns a displayable description and article for the given `def_id` (e.g. `("a", "struct")`).
|
2020-09-18 20:49:25 +02:00
|
|
|
pub fn article_and_description(self, def_id: DefId) -> (&'static str, &'static str) {
|
2023-02-21 14:05:32 -07:00
|
|
|
let kind = self.def_kind(def_id);
|
|
|
|
(self.def_kind_descr_article(kind, def_id), self.def_kind_descr(kind, def_id))
|
2019-12-30 19:46:30 -06:00
|
|
|
}
|
2021-07-04 13:02:51 -05:00
|
|
|
|
|
|
|
pub fn type_length_limit(self) -> Limit {
|
|
|
|
self.limits(()).type_length_limit
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn recursion_limit(self) -> Limit {
|
|
|
|
self.limits(()).recursion_limit
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn move_size_limit(self) -> Limit {
|
|
|
|
self.limits(()).move_size_limit
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn const_eval_limit(self) -> Limit {
|
2022-12-29 23:14:29 +00:00
|
|
|
if self.sess.opts.unstable_opts.tiny_const_eval_limit {
|
|
|
|
TINY_CONST_EVAL_LIMIT
|
|
|
|
} else {
|
|
|
|
self.limits(()).const_eval_limit
|
|
|
|
}
|
2021-07-04 13:02:51 -05:00
|
|
|
}
|
2021-12-24 11:09:32 +08:00
|
|
|
|
|
|
|
pub fn all_traits(self) -> impl Iterator<Item = DefId> + 'tcx {
|
|
|
|
iter::once(LOCAL_CRATE)
|
|
|
|
.chain(self.crates(()).iter().copied())
|
|
|
|
.flat_map(move |cnum| self.traits_in_crate(cnum).iter().copied())
|
|
|
|
}
|
2022-08-28 00:10:06 +03:00
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn local_visibility(self, def_id: LocalDefId) -> Visibility {
|
2022-09-20 14:11:23 +09:00
|
|
|
self.visibility(def_id).expect_local()
|
2022-08-28 00:10:06 +03:00
|
|
|
}
|
2015-09-06 21:51:58 +03:00
|
|
|
}
|
|
|
|
|
2019-02-28 22:43:53 +00:00
|
|
|
/// A trait implemented for all `X<'a>` types that can be safely and
|
|
|
|
/// efficiently converted to `X<'tcx>` as long as they are part of the
|
|
|
|
/// provided `TyCtxt<'tcx>`.
|
|
|
|
/// This can be done, for example, for `Ty<'tcx>` or `SubstsRef<'tcx>`
|
2015-09-06 21:51:58 +03:00
|
|
|
/// by looking them up in their respective interners.
|
2016-05-11 04:14:41 +03:00
|
|
|
///
|
|
|
|
/// However, this is still not the best implementation as it does
|
|
|
|
/// need to compare the components, even for interned values.
|
2019-02-28 22:43:53 +00:00
|
|
|
/// It would be more efficient if `TypedArena` provided a way to
|
2016-05-11 04:14:41 +03:00
|
|
|
/// determine whether the address is in the allocated range.
|
|
|
|
///
|
2019-09-06 03:57:44 +01:00
|
|
|
/// `None` is returned if the value or one of the components is not part
|
2015-09-06 21:51:58 +03:00
|
|
|
/// of the provided context.
|
2019-02-28 22:43:53 +00:00
|
|
|
/// For `Ty`, `None` can be returned if either the type interner doesn't
|
|
|
|
/// contain the `TyKind` key or if the address of the interned
|
2015-09-06 21:51:58 +03:00
|
|
|
/// pointer differs. The latter case is possible if a primitive type,
|
2018-11-27 02:59:49 +00:00
|
|
|
/// e.g., `()` or `u8`, was interned in a different context.
|
2018-06-27 06:01:19 -04:00
|
|
|
pub trait Lift<'tcx>: fmt::Debug {
|
|
|
|
type Lifted: fmt::Debug + 'tcx;
|
2020-10-16 21:59:49 +02:00
|
|
|
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted>;
|
2015-09-06 21:51:58 +03:00
|
|
|
}
|
|
|
|
|
Overhaul `TyS` and `Ty`.
Specifically, change `Ty` from this:
```
pub type Ty<'tcx> = &'tcx TyS<'tcx>;
```
to this
```
pub struct Ty<'tcx>(Interned<'tcx, TyS<'tcx>>);
```
There are two benefits to this.
- It's now a first class type, so we can define methods on it. This
means we can move a lot of methods away from `TyS`, leaving `TyS` as a
barely-used type, which is appropriate given that it's not meant to
be used directly.
- The uniqueness requirement is now explicit, via the `Interned` type.
E.g. the pointer-based `Eq` and `Hash` comes from `Interned`, rather
than via `TyS`, which wasn't obvious at all.
Much of this commit is boring churn. The interesting changes are in
these files:
- compiler/rustc_middle/src/arena.rs
- compiler/rustc_middle/src/mir/visit.rs
- compiler/rustc_middle/src/ty/context.rs
- compiler/rustc_middle/src/ty/mod.rs
Specifically:
- Most mentions of `TyS` are removed. It's very much a dumb struct now;
`Ty` has all the smarts.
- `TyS` now has `crate` visibility instead of `pub`.
- `TyS::make_for_test` is removed in favour of the static `BOOL_TY`,
which just works better with the new structure.
- The `Eq`/`Ord`/`Hash` impls are removed from `TyS`. `Interned`s impls
of `Eq`/`Hash` now suffice. `Ord` is now partly on `Interned`
(pointer-based, for the `Equal` case) and partly on `TyS`
(contents-based, for the other cases).
- There are many tedious sigil adjustments, i.e. adding or removing `*`
or `&`. They seem to be unavoidable.
2022-01-25 14:13:38 +11:00
|
|
|
macro_rules! nop_lift {
|
|
|
|
($set:ident; $ty:ty => $lifted:ty) => {
|
|
|
|
impl<'a, 'tcx> Lift<'tcx> for $ty {
|
|
|
|
type Lifted = $lifted;
|
|
|
|
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
|
2023-02-15 11:43:41 +00:00
|
|
|
tcx.interners
|
|
|
|
.$set
|
|
|
|
.contains_pointer_to(&InternedInSet(&*self.0.0))
|
2022-02-11 13:20:38 +01:00
|
|
|
// SAFETY: `self` is interned and therefore valid
|
|
|
|
// for the entire lifetime of the `TyCtxt`.
|
2023-02-15 11:43:41 +00:00
|
|
|
.then(|| unsafe { mem::transmute(self) })
|
Overhaul `TyS` and `Ty`.
Specifically, change `Ty` from this:
```
pub type Ty<'tcx> = &'tcx TyS<'tcx>;
```
to this
```
pub struct Ty<'tcx>(Interned<'tcx, TyS<'tcx>>);
```
There are two benefits to this.
- It's now a first class type, so we can define methods on it. This
means we can move a lot of methods away from `TyS`, leaving `TyS` as a
barely-used type, which is appropriate given that it's not meant to
be used directly.
- The uniqueness requirement is now explicit, via the `Interned` type.
E.g. the pointer-based `Eq` and `Hash` comes from `Interned`, rather
than via `TyS`, which wasn't obvious at all.
Much of this commit is boring churn. The interesting changes are in
these files:
- compiler/rustc_middle/src/arena.rs
- compiler/rustc_middle/src/mir/visit.rs
- compiler/rustc_middle/src/ty/context.rs
- compiler/rustc_middle/src/ty/mod.rs
Specifically:
- Most mentions of `TyS` are removed. It's very much a dumb struct now;
`Ty` has all the smarts.
- `TyS` now has `crate` visibility instead of `pub`.
- `TyS::make_for_test` is removed in favour of the static `BOOL_TY`,
which just works better with the new structure.
- The `Eq`/`Ord`/`Hash` impls are removed from `TyS`. `Interned`s impls
of `Eq`/`Hash` now suffice. `Ord` is now partly on `Interned`
(pointer-based, for the `Equal` case) and partly on `TyS`
(contents-based, for the other cases).
- There are many tedious sigil adjustments, i.e. adding or removing `*`
or `&`. They seem to be unavoidable.
2022-01-25 14:13:38 +11:00
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2022-02-07 16:05:17 +01:00
|
|
|
// Can't use the macros as we have reuse the `substs` here.
|
|
|
|
//
|
2023-02-17 14:33:08 +11:00
|
|
|
// See `mk_type_list` for more info.
|
2022-02-07 16:05:17 +01:00
|
|
|
impl<'a, 'tcx> Lift<'tcx> for &'a List<Ty<'a>> {
|
|
|
|
type Lifted = &'tcx List<Ty<'tcx>>;
|
|
|
|
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
|
|
|
|
if self.is_empty() {
|
|
|
|
return Some(List::empty());
|
|
|
|
}
|
2023-02-15 11:43:41 +00:00
|
|
|
|
|
|
|
tcx.interners
|
|
|
|
.substs
|
|
|
|
.contains_pointer_to(&InternedInSet(self.as_substs()))
|
2022-02-11 13:20:38 +01:00
|
|
|
// SAFETY: `self` is interned and therefore valid
|
|
|
|
// for the entire lifetime of the `TyCtxt`.
|
2023-02-15 11:43:41 +00:00
|
|
|
.then(|| unsafe { mem::transmute::<&'a List<Ty<'a>>, &'tcx List<Ty<'tcx>>>(self) })
|
2022-02-07 16:05:17 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-28 20:30:06 +01:00
|
|
|
macro_rules! nop_list_lift {
|
2020-01-02 00:44:34 +01:00
|
|
|
($set:ident; $ty:ty => $lifted:ty) => {
|
2018-12-28 20:30:06 +01:00
|
|
|
impl<'a, 'tcx> Lift<'tcx> for &'a List<$ty> {
|
2019-12-24 17:38:22 -05:00
|
|
|
type Lifted = &'tcx List<$lifted>;
|
2020-10-16 21:59:49 +02:00
|
|
|
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
|
2019-12-24 17:38:22 -05:00
|
|
|
if self.is_empty() {
|
|
|
|
return Some(List::empty());
|
2018-12-28 20:30:06 +01:00
|
|
|
}
|
2023-02-15 11:43:41 +00:00
|
|
|
tcx.interners
|
|
|
|
.$set
|
|
|
|
.contains_pointer_to(&InternedInSet(self))
|
|
|
|
.then(|| unsafe { mem::transmute(self) })
|
2019-12-24 17:38:22 -05:00
|
|
|
}
|
|
|
|
}
|
2018-12-28 20:30:06 +01:00
|
|
|
};
|
2018-05-08 18:15:48 -03:00
|
|
|
}
|
|
|
|
|
2020-01-02 00:44:34 +01:00
|
|
|
nop_lift! {type_; Ty<'a> => Ty<'tcx>}
|
2022-01-28 11:25:15 +11:00
|
|
|
nop_lift! {region; Region<'a> => Region<'tcx>}
|
2022-02-02 14:24:45 +11:00
|
|
|
nop_lift! {const_; Const<'a> => Const<'tcx>}
|
Introduce `ConstAllocation`.
Currently some `Allocation`s are interned, some are not, and it's very
hard to tell at a use point which is which.
This commit introduces `ConstAllocation` for the known-interned ones,
which makes the division much clearer. `ConstAllocation::inner()` is
used to get the underlying `Allocation`.
In some places it's natural to use an `Allocation`, in some it's natural
to use a `ConstAllocation`, and in some places there's no clear choice.
I've tried to make things look as nice as possible, while generally
favouring `ConstAllocation`, which is the type that embodies more
information. This does require quite a few calls to `inner()`.
The commit also tweaks how `PartialOrd` works for `Interned`. The
previous code was too clever by half, building on `T: Ord` to make the
code shorter. That caused problems with deriving `PartialOrd` and `Ord`
for `ConstAllocation`, so I changed it to build on `T: PartialOrd`,
which is slightly more verbose but much more standard and avoided the
problems.
2022-03-02 07:15:04 +11:00
|
|
|
nop_lift! {const_allocation; ConstAllocation<'a> => ConstAllocation<'tcx>}
|
2022-01-27 17:00:16 +11:00
|
|
|
nop_lift! {predicate; Predicate<'a> => Predicate<'tcx>}
|
2018-11-23 19:47:22 +01:00
|
|
|
|
2022-11-19 03:28:56 +00:00
|
|
|
nop_list_lift! {poly_existential_predicates; PolyExistentialPredicate<'a> => PolyExistentialPredicate<'tcx>}
|
2020-01-02 00:44:34 +01:00
|
|
|
nop_list_lift! {predicates; Predicate<'a> => Predicate<'tcx>}
|
2020-10-28 01:11:03 +00:00
|
|
|
nop_list_lift! {canonical_var_infos; CanonicalVarInfo<'a> => CanonicalVarInfo<'tcx>}
|
2020-01-02 00:44:34 +01:00
|
|
|
nop_list_lift! {projs; ProjectionKind => ProjectionKind}
|
2020-10-05 20:41:46 -04:00
|
|
|
nop_list_lift! {bound_variable_kinds; ty::BoundVariableKind => ty::BoundVariableKind}
|
2015-09-06 21:51:58 +03:00
|
|
|
|
2019-09-06 03:57:44 +01:00
|
|
|
// This is the impl for `&'a InternalSubsts<'a>`.
|
2020-01-02 00:44:34 +01:00
|
|
|
nop_list_lift! {substs; GenericArg<'a> => GenericArg<'tcx>}
|
2018-12-11 19:56:59 +01:00
|
|
|
|
2022-09-08 09:04:52 +00:00
|
|
|
CloneLiftImpls! { for<'tcx> {
|
|
|
|
Constness, traits::WellFormedLoc, ImplPolarity, crate::mir::ReturnConstraint,
|
|
|
|
} }
|
2020-11-22 02:13:53 +01:00
|
|
|
|
2015-09-06 21:51:58 +03:00
|
|
|
macro_rules! sty_debug_print {
|
2020-07-28 16:15:40 +02:00
|
|
|
($fmt: expr, $ctxt: expr, $($variant: ident),*) => {{
|
2019-09-06 03:57:44 +01:00
|
|
|
// Curious inner module to allow variant names to be used as
|
2015-09-06 21:51:58 +03:00
|
|
|
// variable names.
|
|
|
|
#[allow(non_snake_case)]
|
|
|
|
mod inner {
|
2019-02-05 11:20:45 -06:00
|
|
|
use crate::ty::{self, TyCtxt};
|
2022-02-04 14:27:17 +11:00
|
|
|
use crate::ty::context::InternedInSet;
|
2016-03-23 04:56:49 +02:00
|
|
|
|
2015-09-06 21:51:58 +03:00
|
|
|
#[derive(Copy, Clone)]
|
|
|
|
struct DebugStat {
|
|
|
|
total: usize,
|
2019-02-20 01:14:56 +00:00
|
|
|
lt_infer: usize,
|
2015-09-06 21:51:58 +03:00
|
|
|
ty_infer: usize,
|
2019-02-20 01:14:56 +00:00
|
|
|
ct_infer: usize,
|
|
|
|
all_infer: usize,
|
2015-09-06 21:51:58 +03:00
|
|
|
}
|
|
|
|
|
2020-07-28 16:15:40 +02:00
|
|
|
pub fn go(fmt: &mut std::fmt::Formatter<'_>, tcx: TyCtxt<'_>) -> std::fmt::Result {
|
2015-09-06 21:51:58 +03:00
|
|
|
let mut total = DebugStat {
|
|
|
|
total: 0,
|
2019-02-20 01:14:56 +00:00
|
|
|
lt_infer: 0,
|
|
|
|
ty_infer: 0,
|
|
|
|
ct_infer: 0,
|
|
|
|
all_infer: 0,
|
2015-09-06 21:51:58 +03:00
|
|
|
};
|
|
|
|
$(let mut $variant = total;)*
|
|
|
|
|
2019-06-12 14:39:12 +02:00
|
|
|
let shards = tcx.interners.type_.lock_shards();
|
|
|
|
let types = shards.iter().flat_map(|shard| shard.keys());
|
2022-02-04 14:27:17 +11:00
|
|
|
for &InternedInSet(t) in types {
|
2022-11-25 16:55:25 +00:00
|
|
|
let variant = match t.internee {
|
2018-08-22 01:35:55 +01:00
|
|
|
ty::Bool | ty::Char | ty::Int(..) | ty::Uint(..) |
|
|
|
|
ty::Float(..) | ty::Str | ty::Never => continue,
|
2020-05-05 23:02:09 -05:00
|
|
|
ty::Error(_) => /* unimportant */ continue,
|
2015-09-06 21:51:58 +03:00
|
|
|
$(ty::$variant(..) => &mut $variant,)*
|
|
|
|
};
|
Overhaul `TyS` and `Ty`.
Specifically, change `Ty` from this:
```
pub type Ty<'tcx> = &'tcx TyS<'tcx>;
```
to this
```
pub struct Ty<'tcx>(Interned<'tcx, TyS<'tcx>>);
```
There are two benefits to this.
- It's now a first class type, so we can define methods on it. This
means we can move a lot of methods away from `TyS`, leaving `TyS` as a
barely-used type, which is appropriate given that it's not meant to
be used directly.
- The uniqueness requirement is now explicit, via the `Interned` type.
E.g. the pointer-based `Eq` and `Hash` comes from `Interned`, rather
than via `TyS`, which wasn't obvious at all.
Much of this commit is boring churn. The interesting changes are in
these files:
- compiler/rustc_middle/src/arena.rs
- compiler/rustc_middle/src/mir/visit.rs
- compiler/rustc_middle/src/ty/context.rs
- compiler/rustc_middle/src/ty/mod.rs
Specifically:
- Most mentions of `TyS` are removed. It's very much a dumb struct now;
`Ty` has all the smarts.
- `TyS` now has `crate` visibility instead of `pub`.
- `TyS::make_for_test` is removed in favour of the static `BOOL_TY`,
which just works better with the new structure.
- The `Eq`/`Ord`/`Hash` impls are removed from `TyS`. `Interned`s impls
of `Eq`/`Hash` now suffice. `Ord` is now partly on `Interned`
(pointer-based, for the `Equal` case) and partly on `TyS`
(contents-based, for the other cases).
- There are many tedious sigil adjustments, i.e. adding or removing `*`
or `&`. They seem to be unavoidable.
2022-01-25 14:13:38 +11:00
|
|
|
let lt = t.flags.intersects(ty::TypeFlags::HAS_RE_INFER);
|
|
|
|
let ty = t.flags.intersects(ty::TypeFlags::HAS_TY_INFER);
|
|
|
|
let ct = t.flags.intersects(ty::TypeFlags::HAS_CT_INFER);
|
2015-09-06 21:51:58 +03:00
|
|
|
|
|
|
|
variant.total += 1;
|
|
|
|
total.total += 1;
|
2019-02-20 01:14:56 +00:00
|
|
|
if lt { total.lt_infer += 1; variant.lt_infer += 1 }
|
2015-09-06 21:51:58 +03:00
|
|
|
if ty { total.ty_infer += 1; variant.ty_infer += 1 }
|
2019-02-20 01:14:56 +00:00
|
|
|
if ct { total.ct_infer += 1; variant.ct_infer += 1 }
|
|
|
|
if lt && ty && ct { total.all_infer += 1; variant.all_infer += 1 }
|
2015-09-06 21:51:58 +03:00
|
|
|
}
|
2020-07-28 16:15:40 +02:00
|
|
|
writeln!(fmt, "Ty interner total ty lt ct all")?;
|
|
|
|
$(writeln!(fmt, " {:18}: {uses:6} {usespc:4.1}%, \
|
2019-02-20 01:14:56 +00:00
|
|
|
{ty:4.1}% {lt:5.1}% {ct:4.1}% {all:4.1}%",
|
|
|
|
stringify!($variant),
|
|
|
|
uses = $variant.total,
|
|
|
|
usespc = $variant.total as f64 * 100.0 / total.total as f64,
|
|
|
|
ty = $variant.ty_infer as f64 * 100.0 / total.total as f64,
|
|
|
|
lt = $variant.lt_infer as f64 * 100.0 / total.total as f64,
|
|
|
|
ct = $variant.ct_infer as f64 * 100.0 / total.total as f64,
|
2020-07-28 16:15:40 +02:00
|
|
|
all = $variant.all_infer as f64 * 100.0 / total.total as f64)?;
|
2019-02-20 01:14:56 +00:00
|
|
|
)*
|
2020-07-28 16:15:40 +02:00
|
|
|
writeln!(fmt, " total {uses:6} \
|
2019-02-20 01:14:56 +00:00
|
|
|
{ty:4.1}% {lt:5.1}% {ct:4.1}% {all:4.1}%",
|
|
|
|
uses = total.total,
|
|
|
|
ty = total.ty_infer as f64 * 100.0 / total.total as f64,
|
|
|
|
lt = total.lt_infer as f64 * 100.0 / total.total as f64,
|
|
|
|
ct = total.ct_infer as f64 * 100.0 / total.total as f64,
|
|
|
|
all = total.all_infer as f64 * 100.0 / total.total as f64)
|
2015-09-06 21:51:58 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-28 16:15:40 +02:00
|
|
|
inner::go($fmt, $ctxt)
|
2015-09-06 21:51:58 +03:00
|
|
|
}}
|
|
|
|
}
|
|
|
|
|
2019-06-14 00:48:52 +03:00
|
|
|
impl<'tcx> TyCtxt<'tcx> {
|
2020-07-28 16:15:40 +02:00
|
|
|
pub fn debug_stats(self) -> impl std::fmt::Debug + 'tcx {
|
2020-07-29 11:37:33 +02:00
|
|
|
struct DebugStats<'tcx>(TyCtxt<'tcx>);
|
|
|
|
|
2021-12-15 19:32:30 -05:00
|
|
|
impl<'tcx> std::fmt::Debug for DebugStats<'tcx> {
|
2020-07-29 11:37:33 +02:00
|
|
|
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
|
sty_debug_print!(
|
|
|
|
fmt,
|
|
|
|
self.0,
|
|
|
|
Adt,
|
|
|
|
Array,
|
|
|
|
Slice,
|
|
|
|
RawPtr,
|
|
|
|
Ref,
|
|
|
|
FnDef,
|
|
|
|
FnPtr,
|
|
|
|
Placeholder,
|
|
|
|
Generator,
|
|
|
|
GeneratorWitness,
|
2022-10-01 14:56:24 +02:00
|
|
|
GeneratorWitnessMIR,
|
2020-07-29 11:37:33 +02:00
|
|
|
Dynamic,
|
|
|
|
Closure,
|
|
|
|
Tuple,
|
|
|
|
Bound,
|
|
|
|
Param,
|
|
|
|
Infer,
|
2022-11-26 21:51:55 +00:00
|
|
|
Alias,
|
2020-07-29 11:37:33 +02:00
|
|
|
Foreign
|
|
|
|
)?;
|
|
|
|
|
|
|
|
writeln!(fmt, "InternalSubsts interner: #{}", self.0.interners.substs.len())?;
|
|
|
|
writeln!(fmt, "Region interner: #{}", self.0.interners.region.len())?;
|
2021-08-26 19:47:07 +03:00
|
|
|
writeln!(
|
|
|
|
fmt,
|
|
|
|
"Const Allocation interner: #{}",
|
|
|
|
self.0.interners.const_allocation.len()
|
|
|
|
)?;
|
|
|
|
writeln!(fmt, "Layout interner: #{}", self.0.interners.layout.len())?;
|
2020-07-29 11:37:33 +02:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
2020-07-28 16:15:40 +02:00
|
|
|
|
2020-07-29 11:37:33 +02:00
|
|
|
DebugStats(self)
|
2015-09-06 21:51:58 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-21 13:25:26 +11:00
|
|
|
// This type holds a `T` in the interner. The `T` is stored in the arena and
|
|
|
|
// this type just holds a pointer to it, but it still effectively owns it. It
|
|
|
|
// impls `Borrow` so that it can be looked up using the original
|
|
|
|
// (non-arena-memory-owning) types.
|
2022-02-04 14:27:17 +11:00
|
|
|
struct InternedInSet<'tcx, T: ?Sized>(&'tcx T);
|
2015-09-06 21:51:58 +03:00
|
|
|
|
2022-02-04 14:27:17 +11:00
|
|
|
impl<'tcx, T: 'tcx + ?Sized> Clone for InternedInSet<'tcx, T> {
|
2018-05-17 05:19:08 +02:00
|
|
|
fn clone(&self) -> Self {
|
2022-02-04 14:27:17 +11:00
|
|
|
InternedInSet(self.0)
|
2018-05-17 05:19:08 +02:00
|
|
|
}
|
|
|
|
}
|
2022-01-21 13:25:26 +11:00
|
|
|
|
2022-02-04 14:27:17 +11:00
|
|
|
impl<'tcx, T: 'tcx + ?Sized> Copy for InternedInSet<'tcx, T> {}
|
2018-05-17 05:19:08 +02:00
|
|
|
|
2022-02-04 14:27:17 +11:00
|
|
|
impl<'tcx, T: 'tcx + ?Sized> IntoPointer for InternedInSet<'tcx, T> {
|
2020-01-02 00:44:34 +01:00
|
|
|
fn into_pointer(&self) -> *const () {
|
|
|
|
self.0 as *const _ as *const ()
|
|
|
|
}
|
|
|
|
}
|
2022-01-21 13:25:26 +11:00
|
|
|
|
|
|
|
#[allow(rustc::usage_of_ty_tykind)]
|
2022-11-30 14:52:05 +00:00
|
|
|
impl<'tcx, T> Borrow<T> for InternedInSet<'tcx, WithCachedTypeInfo<T>> {
|
2022-12-20 22:10:40 +01:00
|
|
|
fn borrow(&self) -> &T {
|
2022-11-25 16:55:25 +00:00
|
|
|
&self.0.internee
|
2015-09-06 21:51:58 +03:00
|
|
|
}
|
|
|
|
}
|
2022-01-21 13:25:26 +11:00
|
|
|
|
2022-11-30 14:52:05 +00:00
|
|
|
impl<'tcx, T: PartialEq> PartialEq for InternedInSet<'tcx, WithCachedTypeInfo<T>> {
|
|
|
|
fn eq(&self, other: &InternedInSet<'tcx, WithCachedTypeInfo<T>>) -> bool {
|
2022-01-21 13:25:26 +11:00
|
|
|
// The `Borrow` trait requires that `x.borrow() == y.borrow()` equals
|
|
|
|
// `x == y`.
|
2022-11-25 16:55:25 +00:00
|
|
|
self.0.internee == other.0.internee
|
2020-06-10 09:30:39 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-30 14:52:05 +00:00
|
|
|
impl<'tcx, T: Eq> Eq for InternedInSet<'tcx, WithCachedTypeInfo<T>> {}
|
2020-06-10 09:30:39 +01:00
|
|
|
|
2022-11-30 14:52:05 +00:00
|
|
|
impl<'tcx, T: Hash> Hash for InternedInSet<'tcx, WithCachedTypeInfo<T>> {
|
2020-06-10 09:30:39 +01:00
|
|
|
fn hash<H: Hasher>(&self, s: &mut H) {
|
2022-01-21 13:25:26 +11:00
|
|
|
// The `Borrow` trait requires that `x.borrow().hash(s) == x.hash(s)`.
|
2022-11-30 14:47:40 +00:00
|
|
|
self.0.internee.hash(s)
|
2020-06-10 09:30:39 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-04 14:27:17 +11:00
|
|
|
impl<'tcx, T> Borrow<[T]> for InternedInSet<'tcx, List<T>> {
|
2022-12-20 22:10:40 +01:00
|
|
|
fn borrow(&self) -> &[T] {
|
2022-01-21 13:25:26 +11:00
|
|
|
&self.0[..]
|
2020-06-10 09:30:39 +01:00
|
|
|
}
|
|
|
|
}
|
2015-09-06 21:51:58 +03:00
|
|
|
|
2022-02-04 14:27:17 +11:00
|
|
|
impl<'tcx, T: PartialEq> PartialEq for InternedInSet<'tcx, List<T>> {
|
|
|
|
fn eq(&self, other: &InternedInSet<'tcx, List<T>>) -> bool {
|
2022-01-21 13:25:26 +11:00
|
|
|
// The `Borrow` trait requires that `x.borrow() == y.borrow()` equals
|
|
|
|
// `x == y`.
|
2016-09-02 11:08:16 +03:00
|
|
|
self.0[..] == other.0[..]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-04 14:27:17 +11:00
|
|
|
impl<'tcx, T: Eq> Eq for InternedInSet<'tcx, List<T>> {}
|
2016-09-02 11:08:16 +03:00
|
|
|
|
2022-02-04 14:27:17 +11:00
|
|
|
impl<'tcx, T: Hash> Hash for InternedInSet<'tcx, List<T>> {
|
2016-09-02 11:08:16 +03:00
|
|
|
fn hash<H: Hasher>(&self, s: &mut H) {
|
2022-01-21 13:25:26 +11:00
|
|
|
// The `Borrow` trait requires that `x.borrow().hash(s) == x.hash(s)`.
|
2016-09-02 11:08:16 +03:00
|
|
|
self.0[..].hash(s)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! direct_interners {
|
2023-02-17 14:33:08 +11:00
|
|
|
($($name:ident: $vis:vis $method:ident($ty:ty): $ret_ctor:ident -> $ret_ty:ty,)+) => {
|
2022-01-28 11:25:15 +11:00
|
|
|
$(impl<'tcx> Borrow<$ty> for InternedInSet<'tcx, $ty> {
|
|
|
|
fn borrow<'a>(&'a self) -> &'a $ty {
|
|
|
|
&self.0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'tcx> PartialEq for InternedInSet<'tcx, $ty> {
|
|
|
|
fn eq(&self, other: &Self) -> bool {
|
|
|
|
// The `Borrow` trait requires that `x.borrow() == y.borrow()`
|
|
|
|
// equals `x == y`.
|
|
|
|
self.0 == other.0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'tcx> Eq for InternedInSet<'tcx, $ty> {}
|
|
|
|
|
|
|
|
impl<'tcx> Hash for InternedInSet<'tcx, $ty> {
|
|
|
|
fn hash<H: Hasher>(&self, s: &mut H) {
|
|
|
|
// The `Borrow` trait requires that `x.borrow().hash(s) ==
|
|
|
|
// x.hash(s)`.
|
|
|
|
self.0.hash(s)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'tcx> TyCtxt<'tcx> {
|
2023-02-17 14:33:08 +11:00
|
|
|
$vis fn $method(self, v: $ty) -> $ret_ty {
|
2022-01-28 11:25:15 +11:00
|
|
|
$ret_ctor(Interned::new_unchecked(self.interners.$name.intern(v, |v| {
|
|
|
|
InternedInSet(self.interners.arena.alloc(v))
|
|
|
|
}).0))
|
|
|
|
}
|
|
|
|
})+
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-17 14:33:08 +11:00
|
|
|
// Functions with a `mk_` prefix are intended for use outside this file and
|
|
|
|
// crate. Functions with an `intern_` prefix are intended for use within this
|
|
|
|
// file only, and have a corresponding `mk_` function.
|
2022-01-28 11:25:15 +11:00
|
|
|
direct_interners! {
|
2023-02-13 13:03:45 +11:00
|
|
|
region: intern_region(RegionKind<'tcx>): Region -> Region<'tcx>,
|
2023-02-17 14:33:08 +11:00
|
|
|
const_: intern_const(ConstData<'tcx>): Const -> Const<'tcx>,
|
|
|
|
const_allocation: pub mk_const_alloc(Allocation): ConstAllocation -> ConstAllocation<'tcx>,
|
|
|
|
layout: pub mk_layout(LayoutS): Layout -> Layout<'tcx>,
|
|
|
|
adt_def: pub mk_adt_def_from_data(AdtDefData): AdtDef -> AdtDef<'tcx>,
|
|
|
|
external_constraints: pub mk_external_constraints(ExternalConstraintsData<'tcx>):
|
|
|
|
ExternalConstraints -> ExternalConstraints<'tcx>,
|
2020-06-10 09:30:39 +01:00
|
|
|
}
|
2016-05-11 04:14:41 +03:00
|
|
|
|
2016-10-16 21:21:25 -06:00
|
|
|
macro_rules! slice_interners {
|
2023-02-17 14:33:08 +11:00
|
|
|
($($field:ident: $vis:vis $method:ident($ty:ty)),+ $(,)?) => (
|
2020-10-24 11:55:00 +02:00
|
|
|
impl<'tcx> TyCtxt<'tcx> {
|
2023-02-17 14:33:08 +11:00
|
|
|
$($vis fn $method(self, v: &[$ty]) -> &'tcx List<$ty> {
|
2023-02-17 14:24:13 +11:00
|
|
|
if v.is_empty() {
|
|
|
|
List::empty()
|
|
|
|
} else {
|
|
|
|
self.interners.$field.intern_ref(v, || {
|
|
|
|
InternedInSet(List::from_arena(&*self.arena, v))
|
|
|
|
}).0
|
|
|
|
}
|
2020-10-24 11:55:00 +02:00
|
|
|
})+
|
|
|
|
}
|
2019-03-28 18:00:17 -07:00
|
|
|
);
|
2016-10-16 21:21:25 -06:00
|
|
|
}
|
2016-09-02 11:08:16 +03:00
|
|
|
|
2023-02-17 14:33:08 +11:00
|
|
|
// These functions intern slices. They all have a corresponding
|
|
|
|
// `mk_foo_from_iter` function that interns an iterator. The slice version
|
|
|
|
// should be used when possible, because it's faster.
|
2016-10-16 21:21:25 -06:00
|
|
|
slice_interners!(
|
2023-02-17 14:33:08 +11:00
|
|
|
const_lists: pub mk_const_list(Const<'tcx>),
|
|
|
|
substs: pub mk_substs(GenericArg<'tcx>),
|
|
|
|
canonical_var_infos: pub mk_canonical_var_infos(CanonicalVarInfo<'tcx>),
|
|
|
|
poly_existential_predicates: intern_poly_existential_predicates(PolyExistentialPredicate<'tcx>),
|
|
|
|
predicates: intern_predicates(Predicate<'tcx>),
|
|
|
|
projs: pub mk_projs(ProjectionKind),
|
|
|
|
place_elems: pub mk_place_elems(PlaceElem<'tcx>),
|
|
|
|
bound_variable_kinds: pub mk_bound_variable_kinds(ty::BoundVariableKind),
|
2016-10-09 11:36:12 -07:00
|
|
|
);
|
|
|
|
|
2019-06-14 00:48:52 +03:00
|
|
|
impl<'tcx> TyCtxt<'tcx> {
|
2017-12-12 14:21:10 -05:00
|
|
|
/// Given a `fn` type, returns an equivalent `unsafe fn` type;
|
|
|
|
/// that is, a `fn` type that is equivalent in every way for being
|
|
|
|
/// unsafe.
|
2017-02-13 10:51:06 +02:00
|
|
|
pub fn safe_to_unsafe_fn_ty(self, sig: PolyFnSig<'tcx>) -> Ty<'tcx> {
|
|
|
|
assert_eq!(sig.unsafety(), hir::Unsafety::Normal);
|
2019-12-24 17:38:22 -05:00
|
|
|
self.mk_fn_ptr(sig.map_bound(|sig| ty::FnSig { unsafety: hir::Unsafety::Unsafe, ..sig }))
|
2015-09-06 21:51:58 +03:00
|
|
|
}
|
|
|
|
|
2020-12-03 20:10:55 -03:00
|
|
|
/// Given the def_id of a Trait `trait_def_id` and the name of an associated item `assoc_name`
|
|
|
|
/// returns true if the `trait_def_id` defines an associated item of name `assoc_name`.
|
|
|
|
pub fn trait_may_define_assoc_type(self, trait_def_id: DefId, assoc_name: Ident) -> bool {
|
|
|
|
self.super_traits_of(trait_def_id).any(|trait_did| {
|
|
|
|
self.associated_items(trait_did)
|
|
|
|
.find_by_name_and_kind(self, assoc_name, ty::AssocKind::Type, trait_did)
|
|
|
|
.is_some()
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-06-21 19:43:46 -05:00
|
|
|
/// Given a `ty`, return whether it's an `impl Future<...>`.
|
|
|
|
pub fn ty_is_opaque_future(self, ty: Ty<'_>) -> bool {
|
2022-12-13 11:07:42 +00:00
|
|
|
let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = ty.kind() else { return false };
|
2022-11-22 17:19:19 +00:00
|
|
|
let future_trait = self.require_lang_item(LangItem::Future, None);
|
2022-06-21 19:43:46 -05:00
|
|
|
|
|
|
|
self.explicit_item_bounds(def_id).iter().any(|(predicate, _)| {
|
2022-11-24 18:14:58 -03:00
|
|
|
let ty::PredicateKind::Clause(ty::Clause::Trait(trait_predicate)) = predicate.kind().skip_binder() else {
|
2022-06-21 19:43:46 -05:00
|
|
|
return false;
|
|
|
|
};
|
|
|
|
trait_predicate.trait_ref.def_id == future_trait
|
|
|
|
&& trait_predicate.polarity == ImplPolarity::Positive
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2021-10-02 07:21:01 +07:00
|
|
|
/// Computes the def-ids of the transitive supertraits of `trait_def_id`. This (intentionally)
|
2020-12-03 20:10:55 -03:00
|
|
|
/// does not compute the full elaborated super-predicates but just the set of def-ids. It is used
|
|
|
|
/// to identify which traits may define a given associated type to help avoid cycle errors.
|
|
|
|
/// Returns a `DefId` iterator.
|
|
|
|
fn super_traits_of(self, trait_def_id: DefId) -> impl Iterator<Item = DefId> + 'tcx {
|
|
|
|
let mut set = FxHashSet::default();
|
|
|
|
let mut stack = vec![trait_def_id];
|
|
|
|
|
|
|
|
set.insert(trait_def_id);
|
|
|
|
|
|
|
|
iter::from_fn(move || -> Option<DefId> {
|
|
|
|
let trait_did = stack.pop()?;
|
|
|
|
let generic_predicates = self.super_predicates_of(trait_did);
|
|
|
|
|
|
|
|
for (predicate, _) in generic_predicates.predicates {
|
2022-11-24 18:14:58 -03:00
|
|
|
if let ty::PredicateKind::Clause(ty::Clause::Trait(data)) =
|
|
|
|
predicate.kind().skip_binder()
|
|
|
|
{
|
2020-12-03 20:10:55 -03:00
|
|
|
if set.insert(data.def_id()) {
|
|
|
|
stack.push(data.def_id());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Some(trait_did)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2020-05-07 13:11:24 +08:00
|
|
|
/// Given a closure signature, returns an equivalent fn signature. Detuples
|
|
|
|
/// and so forth -- so e.g., if we have a sig with `Fn<(u32, i32)>` then
|
|
|
|
/// you would get a `fn(u32, i32)`.
|
|
|
|
/// `unsafety` determines the unsafety of the fn signature. If you pass
|
2019-04-01 00:00:43 +09:00
|
|
|
/// `hir::Unsafety::Unsafe` in the previous example, then you would get
|
|
|
|
/// an `unsafe fn (u32, i32)`.
|
|
|
|
/// It cannot convert a closure that requires unsafe.
|
2020-05-07 13:11:24 +08:00
|
|
|
pub fn signature_unclosure(
|
|
|
|
self,
|
|
|
|
sig: PolyFnSig<'tcx>,
|
|
|
|
unsafety: hir::Unsafety,
|
|
|
|
) -> PolyFnSig<'tcx> {
|
|
|
|
sig.map_bound(|s| {
|
2023-02-16 16:05:08 +11:00
|
|
|
let params = match s.inputs()[0].kind() {
|
|
|
|
ty::Tuple(params) => *params,
|
2017-11-30 12:22:11 -03:00
|
|
|
_ => bug!(),
|
|
|
|
};
|
2023-02-16 16:05:08 +11:00
|
|
|
self.mk_fn_sig(params, s.output(), s.c_variadic, unsafety, abi::Abi::Rust)
|
2020-05-07 13:11:24 +08:00
|
|
|
})
|
2017-11-30 12:22:11 -03:00
|
|
|
}
|
|
|
|
|
2023-02-08 12:28:03 +11:00
|
|
|
// Avoid this in favour of more specific `mk_*` methods, where possible.
|
2019-08-11 12:55:14 -04:00
|
|
|
#[allow(rustc::usage_of_ty_tykind)]
|
2018-11-29 21:13:04 +01:00
|
|
|
#[inline]
|
2023-02-20 10:19:09 +11:00
|
|
|
pub fn mk_ty_from_kind(self, st: TyKind<'tcx>) -> Ty<'tcx> {
|
2022-05-30 18:49:17 +02:00
|
|
|
self.interners.intern_ty(
|
|
|
|
st,
|
|
|
|
self.sess,
|
|
|
|
// This is only used to create a stable hashing context.
|
2022-12-07 14:31:50 +00:00
|
|
|
&self.untracked,
|
2022-05-30 18:49:17 +02:00
|
|
|
)
|
2015-09-06 21:51:58 +03:00
|
|
|
}
|
|
|
|
|
2020-05-11 22:06:41 +02:00
|
|
|
#[inline]
|
2020-10-05 16:51:33 -04:00
|
|
|
pub fn mk_predicate(self, binder: Binder<'tcx, PredicateKind<'tcx>>) -> Predicate<'tcx> {
|
2022-03-14 16:54:31 +00:00
|
|
|
self.interners.intern_predicate(
|
|
|
|
binder,
|
|
|
|
self.sess,
|
|
|
|
// This is only used to create a stable hashing context.
|
2022-12-07 14:31:50 +00:00
|
|
|
&self.untracked,
|
2022-03-14 16:54:31 +00:00
|
|
|
)
|
2020-05-11 22:06:41 +02:00
|
|
|
}
|
|
|
|
|
2020-06-24 18:06:04 +02:00
|
|
|
#[inline]
|
|
|
|
pub fn reuse_or_mk_predicate(
|
|
|
|
self,
|
|
|
|
pred: Predicate<'tcx>,
|
2020-10-05 16:51:33 -04:00
|
|
|
binder: Binder<'tcx, PredicateKind<'tcx>>,
|
2020-06-24 18:06:04 +02:00
|
|
|
) -> Predicate<'tcx> {
|
2022-06-14 17:34:37 +02:00
|
|
|
if pred.kind() != binder { self.mk_predicate(binder) } else { pred }
|
2020-06-24 18:06:04 +02:00
|
|
|
}
|
|
|
|
|
2020-12-12 15:28:49 +01:00
|
|
|
pub fn mk_mach_int(self, tm: IntTy) -> Ty<'tcx> {
|
2015-09-06 21:51:58 +03:00
|
|
|
match tm {
|
2020-12-12 15:28:49 +01:00
|
|
|
IntTy::Isize => self.types.isize,
|
|
|
|
IntTy::I8 => self.types.i8,
|
|
|
|
IntTy::I16 => self.types.i16,
|
|
|
|
IntTy::I32 => self.types.i32,
|
|
|
|
IntTy::I64 => self.types.i64,
|
|
|
|
IntTy::I128 => self.types.i128,
|
2015-09-06 21:51:58 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-12 15:28:49 +01:00
|
|
|
pub fn mk_mach_uint(self, tm: UintTy) -> Ty<'tcx> {
|
2015-09-06 21:51:58 +03:00
|
|
|
match tm {
|
2020-12-12 15:28:49 +01:00
|
|
|
UintTy::Usize => self.types.usize,
|
|
|
|
UintTy::U8 => self.types.u8,
|
|
|
|
UintTy::U16 => self.types.u16,
|
|
|
|
UintTy::U32 => self.types.u32,
|
|
|
|
UintTy::U64 => self.types.u64,
|
|
|
|
UintTy::U128 => self.types.u128,
|
2015-09-06 21:51:58 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-12 15:28:49 +01:00
|
|
|
pub fn mk_mach_float(self, tm: FloatTy) -> Ty<'tcx> {
|
2015-09-06 21:51:58 +03:00
|
|
|
match tm {
|
2020-12-12 15:28:49 +01:00
|
|
|
FloatTy::F32 => self.types.f32,
|
|
|
|
FloatTy::F64 => self.types.f64,
|
2015-09-06 21:51:58 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-29 21:13:04 +01:00
|
|
|
#[inline]
|
2016-05-03 04:56:42 +03:00
|
|
|
pub fn mk_static_str(self) -> Ty<'tcx> {
|
2020-05-28 13:02:02 +02:00
|
|
|
self.mk_imm_ref(self.lifetimes.re_static, self.types.str_)
|
2015-09-06 21:51:58 +03:00
|
|
|
}
|
|
|
|
|
2018-11-29 21:13:04 +01:00
|
|
|
#[inline]
|
2022-03-05 07:28:41 +11:00
|
|
|
pub fn mk_adt(self, def: AdtDef<'tcx>, substs: SubstsRef<'tcx>) -> Ty<'tcx> {
|
2019-09-06 03:57:44 +01:00
|
|
|
// Take a copy of substs so that we own the vectors inside.
|
2023-02-20 10:19:09 +11:00
|
|
|
self.mk_ty_from_kind(Adt(def, substs))
|
2015-09-06 21:51:58 +03:00
|
|
|
}
|
|
|
|
|
2018-11-29 21:13:04 +01:00
|
|
|
#[inline]
|
2017-09-03 19:53:58 +01:00
|
|
|
pub fn mk_foreign(self, def_id: DefId) -> Ty<'tcx> {
|
2023-02-20 10:19:09 +11:00
|
|
|
self.mk_ty_from_kind(Foreign(def_id))
|
2017-09-03 19:53:58 +01:00
|
|
|
}
|
|
|
|
|
2019-07-26 19:36:26 -07:00
|
|
|
fn mk_generic_adt(self, wrapper_def_id: DefId, ty_param: Ty<'tcx>) -> Ty<'tcx> {
|
|
|
|
let adt_def = self.adt_def(wrapper_def_id);
|
2019-12-24 17:38:22 -05:00
|
|
|
let substs =
|
|
|
|
InternalSubsts::for_item(self, wrapper_def_id, |param, substs| match param.kind {
|
2020-08-11 00:02:45 +00:00
|
|
|
GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => bug!(),
|
2018-05-16 13:03:04 +03:00
|
|
|
GenericParamDefKind::Type { has_default, .. } => {
|
2018-05-14 18:27:13 +01:00
|
|
|
if param.index == 0 {
|
2019-07-26 19:36:26 -07:00
|
|
|
ty_param.into()
|
2018-05-14 18:27:13 +01:00
|
|
|
} else {
|
2018-05-16 13:03:04 +03:00
|
|
|
assert!(has_default);
|
2023-02-07 01:29:48 -07:00
|
|
|
self.type_of(param.def_id).subst(self, substs).into()
|
2018-05-10 23:02:41 +01:00
|
|
|
}
|
|
|
|
}
|
2019-12-24 17:38:22 -05:00
|
|
|
});
|
2023-02-20 10:19:09 +11:00
|
|
|
self.mk_ty_from_kind(Adt(adt_def, substs))
|
2015-09-06 21:51:58 +03:00
|
|
|
}
|
|
|
|
|
2019-07-26 19:36:26 -07:00
|
|
|
#[inline]
|
|
|
|
pub fn mk_box(self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
2020-08-18 11:47:27 +01:00
|
|
|
let def_id = self.require_lang_item(LangItem::OwnedBox, None);
|
2019-07-26 19:36:26 -07:00
|
|
|
self.mk_generic_adt(def_id, ty)
|
|
|
|
}
|
|
|
|
|
2019-09-01 02:22:42 -07:00
|
|
|
#[inline]
|
2020-08-18 11:47:27 +01:00
|
|
|
pub fn mk_lang_item(self, ty: Ty<'tcx>, item: LangItem) -> Option<Ty<'tcx>> {
|
2022-10-26 17:01:00 -05:00
|
|
|
let def_id = self.lang_items().get(item)?;
|
2019-09-14 02:40:20 +08:00
|
|
|
Some(self.mk_generic_adt(def_id, ty))
|
2019-09-01 02:22:42 -07:00
|
|
|
}
|
|
|
|
|
2020-04-08 04:26:48 +03:00
|
|
|
#[inline]
|
|
|
|
pub fn mk_diagnostic_item(self, ty: Ty<'tcx>, name: Symbol) -> Option<Ty<'tcx>> {
|
|
|
|
let def_id = self.get_diagnostic_item(name)?;
|
|
|
|
Some(self.mk_generic_adt(def_id, ty))
|
|
|
|
}
|
|
|
|
|
2019-07-26 19:36:26 -07:00
|
|
|
#[inline]
|
|
|
|
pub fn mk_maybe_uninit(self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
2020-08-18 11:47:27 +01:00
|
|
|
let def_id = self.require_lang_item(LangItem::MaybeUninit, None);
|
2019-07-26 19:36:26 -07:00
|
|
|
self.mk_generic_adt(def_id, ty)
|
|
|
|
}
|
|
|
|
|
2018-11-29 21:13:04 +01:00
|
|
|
#[inline]
|
2016-05-03 04:56:42 +03:00
|
|
|
pub fn mk_ptr(self, tm: TypeAndMut<'tcx>) -> Ty<'tcx> {
|
2023-02-20 10:19:09 +11:00
|
|
|
self.mk_ty_from_kind(RawPtr(tm))
|
2015-09-06 21:51:58 +03:00
|
|
|
}
|
|
|
|
|
2018-11-29 21:13:04 +01:00
|
|
|
#[inline]
|
2017-04-20 04:45:53 -04:00
|
|
|
pub fn mk_ref(self, r: Region<'tcx>, tm: TypeAndMut<'tcx>) -> Ty<'tcx> {
|
2023-02-20 10:19:09 +11:00
|
|
|
self.mk_ty_from_kind(Ref(r, tm.ty, tm.mutbl))
|
2015-09-06 21:51:58 +03:00
|
|
|
}
|
|
|
|
|
2018-11-29 21:13:04 +01:00
|
|
|
#[inline]
|
2017-04-20 04:45:53 -04:00
|
|
|
pub fn mk_mut_ref(self, r: Region<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
|
2020-03-06 19:28:44 +01:00
|
|
|
self.mk_ref(r, TypeAndMut { ty, mutbl: hir::Mutability::Mut })
|
2015-09-06 21:51:58 +03:00
|
|
|
}
|
|
|
|
|
2018-11-29 21:13:04 +01:00
|
|
|
#[inline]
|
2017-04-20 04:45:53 -04:00
|
|
|
pub fn mk_imm_ref(self, r: Region<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
|
2020-03-06 19:28:44 +01:00
|
|
|
self.mk_ref(r, TypeAndMut { ty, mutbl: hir::Mutability::Not })
|
2015-09-06 21:51:58 +03:00
|
|
|
}
|
|
|
|
|
2018-11-29 21:13:04 +01:00
|
|
|
#[inline]
|
2016-05-03 04:56:42 +03:00
|
|
|
pub fn mk_mut_ptr(self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
2020-03-06 19:28:44 +01:00
|
|
|
self.mk_ptr(TypeAndMut { ty, mutbl: hir::Mutability::Mut })
|
2015-09-06 21:51:58 +03:00
|
|
|
}
|
|
|
|
|
2018-11-29 21:13:04 +01:00
|
|
|
#[inline]
|
2016-05-03 04:56:42 +03:00
|
|
|
pub fn mk_imm_ptr(self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
2020-03-06 19:28:44 +01:00
|
|
|
self.mk_ptr(TypeAndMut { ty, mutbl: hir::Mutability::Not })
|
2015-09-06 21:51:58 +03:00
|
|
|
}
|
|
|
|
|
2018-11-29 21:13:04 +01:00
|
|
|
#[inline]
|
2017-08-05 12:27:28 +03:00
|
|
|
pub fn mk_array(self, ty: Ty<'tcx>, n: u64) -> Ty<'tcx> {
|
2023-02-20 10:19:09 +11:00
|
|
|
self.mk_ty_from_kind(Array(ty, ty::Const::from_target_usize(self, n)))
|
2015-09-06 21:51:58 +03:00
|
|
|
}
|
|
|
|
|
2023-02-08 12:28:03 +11:00
|
|
|
#[inline]
|
|
|
|
pub fn mk_array_with_const_len(self, ty: Ty<'tcx>, ct: Const<'tcx>) -> Ty<'tcx> {
|
2023-02-20 10:19:09 +11:00
|
|
|
self.mk_ty_from_kind(Array(ty, ct))
|
2023-02-08 12:28:03 +11:00
|
|
|
}
|
|
|
|
|
2018-11-29 21:13:04 +01:00
|
|
|
#[inline]
|
2016-05-03 04:56:42 +03:00
|
|
|
pub fn mk_slice(self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
2023-02-20 10:19:09 +11:00
|
|
|
self.mk_ty_from_kind(Slice(ty))
|
2015-09-06 21:51:58 +03:00
|
|
|
}
|
|
|
|
|
2018-11-29 21:13:04 +01:00
|
|
|
#[inline]
|
2023-02-17 14:33:08 +11:00
|
|
|
pub fn mk_tup(self, ts: &[Ty<'tcx>]) -> Ty<'tcx> {
|
2023-02-20 10:19:09 +11:00
|
|
|
if ts.is_empty() {
|
|
|
|
self.types.unit
|
|
|
|
} else {
|
|
|
|
self.mk_ty_from_kind(Tuple(self.mk_type_list(&ts)))
|
|
|
|
}
|
2016-10-24 18:23:29 -06:00
|
|
|
}
|
|
|
|
|
2023-02-17 14:33:08 +11:00
|
|
|
pub fn mk_tup_from_iter<I, T>(self, iter: I) -> T::Output
|
Clarify iterator interners.
There are two traits, `InternAs` and `InternIteratorElement`. I found
them confusing to use, particularly this:
```
pub fn mk_tup<I: InternAs<Ty<'tcx>, Ty<'tcx>>>(self, iter: I) -> I::Output {
iter.intern_with(|ts| self.intern_tup(ts))
}
```
where I thought there might have been two levels of interning going on
(there isn't) due to the `intern_with`/`InternAs` + `intern_tup` naming.
And then I found the actual traits and impls themselves *very*
confusing.
- `InternAs` has a single impl, for iterators, with four type variables.
- `InternAs` is only implemented for iterators because it wouldn't
really make sense to implement for any other type. And you can't
really understand the trait without seeing that single impl, which is
suspicious.
- `InternAs` is basically just a wrapper for `InternIteratorElement`
which does all the actual work.
- Neither trait actually does any interning. They just have `Intern` in
their name because they are used *by* interning code.
- There are no comments.
So this commit improves things.
- It removes `InternAs` completely. This makes the `mk_*` function
signatures slightly more verbose -- two trait bounds instead of one --
but much easier to read, because you only need to understand one trait
instead of two.
- It renames `InternIteratorElement` as `CollectAndApply`. Likewise, it
renames its method `intern_with` as `collect_and_apply`. These names
describe better what's going on: we collect the iterator elements into
a slice and then apply a function to the slice.
- It adds comments, making clear that all this is all there just to
provide an optimized version of `f(&iter.collect::<Vec<_>>())`.
It took me a couple of attempts to come up with this commit. My initial
attempt kept `InternAs` around, but renamed things and added comments,
and I wasn't happy with it. I think this version is much better. The
resulting code is shorter, despite the addition of the comments.
2023-02-16 12:06:36 +11:00
|
|
|
where
|
|
|
|
I: Iterator<Item = T>,
|
|
|
|
T: CollectAndApply<Ty<'tcx>, Ty<'tcx>>,
|
|
|
|
{
|
2023-02-17 14:33:08 +11:00
|
|
|
T::collect_and_apply(iter, |ts| self.mk_tup(ts))
|
2015-09-06 21:51:58 +03:00
|
|
|
}
|
|
|
|
|
2018-11-29 21:13:04 +01:00
|
|
|
#[inline]
|
2018-09-10 11:07:13 +09:00
|
|
|
pub fn mk_unit(self) -> Ty<'tcx> {
|
2018-11-29 21:13:04 +01:00
|
|
|
self.types.unit
|
2016-08-02 19:56:33 +08:00
|
|
|
}
|
|
|
|
|
2018-11-29 21:13:04 +01:00
|
|
|
#[inline]
|
2018-04-20 17:11:28 +02:00
|
|
|
pub fn mk_diverging_default(self) -> Ty<'tcx> {
|
2022-06-14 17:34:37 +02:00
|
|
|
if self.features().never_type_fallback { self.types.never } else { self.types.unit }
|
2018-04-20 17:11:28 +02:00
|
|
|
}
|
|
|
|
|
2018-11-29 21:13:04 +01:00
|
|
|
#[inline]
|
2022-12-13 10:37:19 +00:00
|
|
|
pub fn mk_fn_def(
|
|
|
|
self,
|
|
|
|
def_id: DefId,
|
2023-02-21 03:49:03 +00:00
|
|
|
substs: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
|
2022-12-13 10:37:19 +00:00
|
|
|
) -> Ty<'tcx> {
|
2023-02-17 14:33:08 +11:00
|
|
|
let substs = self.check_and_mk_substs(def_id, substs);
|
2023-02-20 10:19:09 +11:00
|
|
|
self.mk_ty_from_kind(FnDef(def_id, substs))
|
2015-06-13 13:15:03 -07:00
|
|
|
}
|
|
|
|
|
2022-12-14 14:37:16 +00:00
|
|
|
#[inline(always)]
|
2023-02-17 14:33:08 +11:00
|
|
|
fn check_and_mk_substs(
|
2022-12-14 14:37:16 +00:00
|
|
|
self,
|
2022-12-14 15:37:47 +00:00
|
|
|
_def_id: DefId,
|
2023-02-21 03:49:03 +00:00
|
|
|
substs: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
|
2022-12-14 14:37:16 +00:00
|
|
|
) -> SubstsRef<'tcx> {
|
|
|
|
let substs = substs.into_iter().map(Into::into);
|
|
|
|
#[cfg(debug_assertions)]
|
|
|
|
{
|
2022-12-14 15:37:47 +00:00
|
|
|
let n = self.generics_of(_def_id).count();
|
2022-12-14 14:37:16 +00:00
|
|
|
assert_eq!(
|
|
|
|
(n, Some(n)),
|
|
|
|
substs.size_hint(),
|
2022-12-14 15:37:47 +00:00
|
|
|
"wrong number of generic parameters for {_def_id:?}: {:?}",
|
2022-12-14 14:37:16 +00:00
|
|
|
substs.collect::<Vec<_>>(),
|
|
|
|
);
|
|
|
|
}
|
2023-02-17 14:33:08 +11:00
|
|
|
self.mk_substs_from_iter(substs)
|
2022-12-14 14:37:16 +00:00
|
|
|
}
|
|
|
|
|
2018-11-29 21:13:04 +01:00
|
|
|
#[inline]
|
2017-02-13 10:51:06 +02:00
|
|
|
pub fn mk_fn_ptr(self, fty: PolyFnSig<'tcx>) -> Ty<'tcx> {
|
2023-02-20 10:19:09 +11:00
|
|
|
self.mk_ty_from_kind(FnPtr(fty))
|
2015-09-06 21:51:58 +03:00
|
|
|
}
|
|
|
|
|
2018-11-29 21:13:04 +01:00
|
|
|
#[inline]
|
2016-11-16 09:21:49 -07:00
|
|
|
pub fn mk_dynamic(
|
|
|
|
self,
|
2022-11-19 03:28:56 +00:00
|
|
|
obj: &'tcx List<PolyExistentialPredicate<'tcx>>,
|
2019-12-24 17:38:22 -05:00
|
|
|
reg: ty::Region<'tcx>,
|
2022-08-29 03:53:33 +00:00
|
|
|
repr: DynKind,
|
2016-11-16 09:21:49 -07:00
|
|
|
) -> Ty<'tcx> {
|
2023-02-20 10:19:09 +11:00
|
|
|
self.mk_ty_from_kind(Dynamic(obj, reg, repr))
|
2015-09-06 21:51:58 +03:00
|
|
|
}
|
|
|
|
|
2018-11-29 21:13:04 +01:00
|
|
|
#[inline]
|
2022-12-13 10:44:35 +00:00
|
|
|
pub fn mk_projection(
|
|
|
|
self,
|
|
|
|
item_def_id: DefId,
|
2023-02-21 03:49:03 +00:00
|
|
|
substs: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
|
2022-12-13 10:44:35 +00:00
|
|
|
) -> Ty<'tcx> {
|
2023-02-08 12:28:03 +11:00
|
|
|
self.mk_alias(ty::Projection, self.mk_alias_ty(item_def_id, substs))
|
2019-12-24 17:38:22 -05:00
|
|
|
}
|
2015-09-06 21:51:58 +03:00
|
|
|
|
2018-11-29 21:13:04 +01:00
|
|
|
#[inline]
|
2019-12-24 17:38:22 -05:00
|
|
|
pub fn mk_closure(self, closure_id: DefId, closure_substs: SubstsRef<'tcx>) -> Ty<'tcx> {
|
2023-02-20 10:19:09 +11:00
|
|
|
self.mk_ty_from_kind(Closure(closure_id, closure_substs))
|
2015-09-06 21:51:58 +03:00
|
|
|
}
|
|
|
|
|
2018-11-29 21:13:04 +01:00
|
|
|
#[inline]
|
2019-12-24 17:38:22 -05:00
|
|
|
pub fn mk_generator(
|
|
|
|
self,
|
|
|
|
id: DefId,
|
|
|
|
generator_substs: SubstsRef<'tcx>,
|
|
|
|
movability: hir::Movability,
|
|
|
|
) -> Ty<'tcx> {
|
2023-02-20 10:19:09 +11:00
|
|
|
self.mk_ty_from_kind(Generator(id, generator_substs, movability))
|
2016-12-26 14:34:03 +01:00
|
|
|
}
|
|
|
|
|
2018-11-29 21:13:04 +01:00
|
|
|
#[inline]
|
2020-10-05 16:51:33 -04:00
|
|
|
pub fn mk_generator_witness(self, types: ty::Binder<'tcx, &'tcx List<Ty<'tcx>>>) -> Ty<'tcx> {
|
2023-02-20 10:19:09 +11:00
|
|
|
self.mk_ty_from_kind(GeneratorWitness(types))
|
2017-10-07 16:36:28 +02:00
|
|
|
}
|
|
|
|
|
2022-12-20 15:15:29 +01:00
|
|
|
/// Creates a `&mut Context<'_>` [`Ty`] with erased lifetimes.
|
|
|
|
pub fn mk_task_context(self) -> Ty<'tcx> {
|
|
|
|
let context_did = self.require_lang_item(LangItem::Context, None);
|
|
|
|
let context_adt_ref = self.adt_def(context_did);
|
2023-02-17 14:33:08 +11:00
|
|
|
let context_substs = self.mk_substs(&[self.lifetimes.re_erased.into()]);
|
2022-12-20 15:15:29 +01:00
|
|
|
let context_ty = self.mk_adt(context_adt_ref, context_substs);
|
|
|
|
self.mk_mut_ref(self.lifetimes.re_erased, context_ty)
|
|
|
|
}
|
|
|
|
|
2022-10-01 14:56:24 +02:00
|
|
|
#[inline]
|
|
|
|
pub fn mk_generator_witness_mir(self, id: DefId, substs: SubstsRef<'tcx>) -> Ty<'tcx> {
|
2023-02-20 10:19:09 +11:00
|
|
|
self.mk_ty_from_kind(GeneratorWitnessMIR(id, substs))
|
2022-10-01 14:56:24 +02:00
|
|
|
}
|
|
|
|
|
2018-11-29 21:13:04 +01:00
|
|
|
#[inline]
|
2023-02-08 11:52:19 +11:00
|
|
|
pub fn mk_const(self, kind: impl Into<ty::ConstKind<'tcx>>, ty: Ty<'tcx>) -> Const<'tcx> {
|
2023-02-17 14:33:08 +11:00
|
|
|
self.intern_const(ty::ConstData { kind: kind.into(), ty })
|
2015-09-06 21:51:58 +03:00
|
|
|
}
|
|
|
|
|
2022-11-04 20:33:32 +00:00
|
|
|
#[inline]
|
2023-02-08 11:52:19 +11:00
|
|
|
pub fn mk_ty_var(self, v: TyVid) -> Ty<'tcx> {
|
|
|
|
// Use a pre-interned one when possible.
|
2023-02-20 10:19:09 +11:00
|
|
|
self.types
|
|
|
|
.ty_vars
|
|
|
|
.get(v.as_usize())
|
|
|
|
.copied()
|
|
|
|
.unwrap_or_else(|| self.mk_ty_from_kind(Infer(TyVar(v))))
|
2019-02-20 01:14:56 +00:00
|
|
|
}
|
|
|
|
|
2018-11-29 21:13:04 +01:00
|
|
|
#[inline]
|
2016-05-03 04:56:42 +03:00
|
|
|
pub fn mk_int_var(self, v: IntVid) -> Ty<'tcx> {
|
2023-02-20 10:19:09 +11:00
|
|
|
self.mk_ty_from_kind(Infer(IntVar(v)))
|
2015-09-06 21:51:58 +03:00
|
|
|
}
|
|
|
|
|
2018-11-29 21:13:04 +01:00
|
|
|
#[inline]
|
2016-05-03 04:56:42 +03:00
|
|
|
pub fn mk_float_var(self, v: FloatVid) -> Ty<'tcx> {
|
2023-02-20 10:19:09 +11:00
|
|
|
self.mk_ty_from_kind(Infer(FloatVar(v)))
|
2023-02-08 11:52:19 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn mk_fresh_ty(self, n: u32) -> Ty<'tcx> {
|
|
|
|
// Use a pre-interned one when possible.
|
|
|
|
self.types
|
|
|
|
.fresh_tys
|
|
|
|
.get(n as usize)
|
|
|
|
.copied()
|
2023-02-20 10:19:09 +11:00
|
|
|
.unwrap_or_else(|| self.mk_ty_from_kind(Infer(ty::FreshTy(n))))
|
2023-02-08 11:52:19 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn mk_fresh_int_ty(self, n: u32) -> Ty<'tcx> {
|
|
|
|
// Use a pre-interned one when possible.
|
|
|
|
self.types
|
|
|
|
.fresh_int_tys
|
|
|
|
.get(n as usize)
|
|
|
|
.copied()
|
2023-02-20 10:19:09 +11:00
|
|
|
.unwrap_or_else(|| self.mk_ty_from_kind(Infer(ty::FreshIntTy(n))))
|
2015-09-06 21:51:58 +03:00
|
|
|
}
|
|
|
|
|
2018-11-29 21:13:04 +01:00
|
|
|
#[inline]
|
2023-02-08 11:52:19 +11:00
|
|
|
pub fn mk_fresh_float_ty(self, n: u32) -> Ty<'tcx> {
|
|
|
|
// Use a pre-interned one when possible.
|
|
|
|
self.types
|
|
|
|
.fresh_float_tys
|
|
|
|
.get(n as usize)
|
|
|
|
.copied()
|
2023-02-20 10:19:09 +11:00
|
|
|
.unwrap_or_else(|| self.mk_ty_from_kind(Infer(ty::FreshFloatTy(n))))
|
2015-09-06 21:51:58 +03:00
|
|
|
}
|
|
|
|
|
2018-11-29 21:13:04 +01:00
|
|
|
#[inline]
|
2019-10-18 13:22:50 +11:00
|
|
|
pub fn mk_ty_param(self, index: u32, name: Symbol) -> Ty<'tcx> {
|
2023-02-20 10:19:09 +11:00
|
|
|
self.mk_ty_from_kind(Param(ParamTy { index, name }))
|
2015-09-06 21:51:58 +03:00
|
|
|
}
|
|
|
|
|
2019-09-25 16:39:44 +01:00
|
|
|
pub fn mk_param_from_def(self, param: &ty::GenericParamDef) -> GenericArg<'tcx> {
|
2018-05-15 13:35:53 +01:00
|
|
|
match param.kind {
|
|
|
|
GenericParamDefKind::Lifetime => {
|
2023-02-13 13:03:45 +11:00
|
|
|
self.mk_re_early_bound(param.to_early_bound_region_data()).into()
|
2018-05-15 13:35:53 +01:00
|
|
|
}
|
2019-02-20 01:14:56 +00:00
|
|
|
GenericParamDefKind::Type { .. } => self.mk_ty_param(param.index, param.name).into(),
|
2022-11-28 11:27:18 +00:00
|
|
|
GenericParamDefKind::Const { .. } => self
|
|
|
|
.mk_const(
|
|
|
|
ParamConst { index: param.index, name: param.name },
|
2023-02-14 14:17:38 -07:00
|
|
|
self.type_of(param.def_id)
|
|
|
|
.no_bound_vars()
|
|
|
|
.expect("const parameter types cannot be generic"),
|
2022-11-28 11:27:18 +00:00
|
|
|
)
|
|
|
|
.into(),
|
2018-05-15 13:35:53 +01:00
|
|
|
}
|
2015-09-06 21:51:58 +03:00
|
|
|
}
|
2015-12-22 16:39:33 -05:00
|
|
|
|
2023-02-08 12:28:03 +11:00
|
|
|
#[inline]
|
|
|
|
pub fn mk_bound(self, index: ty::DebruijnIndex, bound_ty: ty::BoundTy) -> Ty<'tcx> {
|
2023-02-20 10:19:09 +11:00
|
|
|
self.mk_ty_from_kind(Bound(index, bound_ty))
|
2023-02-08 12:28:03 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn mk_placeholder(self, placeholder: ty::PlaceholderType) -> Ty<'tcx> {
|
2023-02-20 10:19:09 +11:00
|
|
|
self.mk_ty_from_kind(Placeholder(placeholder))
|
2023-02-08 12:28:03 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn mk_alias(self, kind: ty::AliasKind, alias_ty: ty::AliasTy<'tcx>) -> Ty<'tcx> {
|
2023-03-14 22:56:20 +00:00
|
|
|
debug_assert_matches!(
|
|
|
|
(kind, self.def_kind(alias_ty.def_id)),
|
|
|
|
(ty::Opaque, DefKind::OpaqueTy)
|
2023-03-14 23:12:42 +00:00
|
|
|
| (ty::Projection, DefKind::AssocTy)
|
2023-03-14 22:56:20 +00:00
|
|
|
| (ty::Opaque | ty::Projection, DefKind::ImplTraitPlaceholder)
|
|
|
|
);
|
2023-02-20 10:19:09 +11:00
|
|
|
self.mk_ty_from_kind(Alias(kind, alias_ty))
|
2023-02-08 12:28:03 +11:00
|
|
|
}
|
|
|
|
|
2018-11-29 21:13:04 +01:00
|
|
|
#[inline]
|
2019-02-09 22:11:53 +08:00
|
|
|
pub fn mk_opaque(self, def_id: DefId, substs: SubstsRef<'tcx>) -> Ty<'tcx> {
|
2023-02-08 12:28:03 +11:00
|
|
|
self.mk_alias(ty::Opaque, self.mk_alias_ty(def_id, substs))
|
2016-07-22 18:56:22 +03:00
|
|
|
}
|
|
|
|
|
2023-02-13 13:03:45 +11:00
|
|
|
#[inline]
|
|
|
|
pub fn mk_re_early_bound(self, early_bound_region: ty::EarlyBoundRegion) -> Region<'tcx> {
|
|
|
|
self.intern_region(ty::ReEarlyBound(early_bound_region))
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn mk_re_late_bound(
|
|
|
|
self,
|
|
|
|
debruijn: ty::DebruijnIndex,
|
|
|
|
bound_region: ty::BoundRegion,
|
|
|
|
) -> Region<'tcx> {
|
2023-02-13 15:37:44 +11:00
|
|
|
// Use a pre-interned one when possible.
|
|
|
|
if let ty::BoundRegion { var, kind: ty::BrAnon(v, None) } = bound_region
|
|
|
|
&& var.as_u32() == v
|
|
|
|
&& let Some(inner) = self.lifetimes.re_late_bounds.get(debruijn.as_usize())
|
|
|
|
&& let Some(re) = inner.get(v as usize).copied()
|
|
|
|
{
|
|
|
|
re
|
|
|
|
} else {
|
|
|
|
self.intern_region(ty::ReLateBound(debruijn, bound_region))
|
|
|
|
}
|
2023-02-13 13:03:45 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn mk_re_free(self, scope: DefId, bound_region: ty::BoundRegionKind) -> Region<'tcx> {
|
|
|
|
self.intern_region(ty::ReFree(ty::FreeRegion { scope, bound_region }))
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2023-02-13 15:37:44 +11:00
|
|
|
pub fn mk_re_var(self, v: ty::RegionVid) -> Region<'tcx> {
|
|
|
|
// Use a pre-interned one when possible.
|
|
|
|
self.lifetimes
|
|
|
|
.re_vars
|
|
|
|
.get(v.as_usize())
|
|
|
|
.copied()
|
|
|
|
.unwrap_or_else(|| self.intern_region(ty::ReVar(v)))
|
2023-02-13 13:03:45 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn mk_re_placeholder(self, placeholder: ty::PlaceholderRegion) -> Region<'tcx> {
|
|
|
|
self.intern_region(ty::RePlaceholder(placeholder))
|
|
|
|
}
|
|
|
|
|
|
|
|
// Avoid this in favour of more specific `mk_re_*` methods, where possible,
|
|
|
|
// to avoid the cost of the `match`.
|
2023-02-20 10:19:09 +11:00
|
|
|
pub fn mk_region_from_kind(self, kind: ty::RegionKind<'tcx>) -> Region<'tcx> {
|
2023-02-13 13:03:45 +11:00
|
|
|
match kind {
|
|
|
|
ty::ReEarlyBound(region) => self.mk_re_early_bound(region),
|
|
|
|
ty::ReLateBound(debruijn, region) => self.mk_re_late_bound(debruijn, region),
|
|
|
|
ty::ReFree(ty::FreeRegion { scope, bound_region }) => {
|
|
|
|
self.mk_re_free(scope, bound_region)
|
|
|
|
}
|
|
|
|
ty::ReStatic => self.lifetimes.re_static,
|
|
|
|
ty::ReVar(vid) => self.mk_re_var(vid),
|
|
|
|
ty::RePlaceholder(region) => self.mk_re_placeholder(region),
|
|
|
|
ty::ReErased => self.lifetimes.re_erased,
|
|
|
|
ty::ReError(reported) => self.mk_re_error(reported),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-20 21:04:59 -04:00
|
|
|
pub fn mk_place_field(self, place: Place<'tcx>, f: Field, ty: Ty<'tcx>) -> Place<'tcx> {
|
|
|
|
self.mk_place_elem(place, PlaceElem::Field(f, ty))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn mk_place_deref(self, place: Place<'tcx>) -> Place<'tcx> {
|
|
|
|
self.mk_place_elem(place, PlaceElem::Deref)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn mk_place_downcast(
|
|
|
|
self,
|
|
|
|
place: Place<'tcx>,
|
2022-03-05 07:28:41 +11:00
|
|
|
adt_def: AdtDef<'tcx>,
|
2019-10-20 21:04:59 -04:00
|
|
|
variant_index: VariantIdx,
|
|
|
|
) -> Place<'tcx> {
|
|
|
|
self.mk_place_elem(
|
|
|
|
place,
|
2022-03-05 07:28:41 +11:00
|
|
|
PlaceElem::Downcast(Some(adt_def.variant(variant_index).name), variant_index),
|
2019-10-20 21:04:59 -04:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn mk_place_downcast_unnamed(
|
|
|
|
self,
|
|
|
|
place: Place<'tcx>,
|
|
|
|
variant_index: VariantIdx,
|
|
|
|
) -> Place<'tcx> {
|
|
|
|
self.mk_place_elem(place, PlaceElem::Downcast(None, variant_index))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn mk_place_index(self, place: Place<'tcx>, index: Local) -> Place<'tcx> {
|
|
|
|
self.mk_place_elem(place, PlaceElem::Index(index))
|
|
|
|
}
|
|
|
|
|
|
|
|
/// This method copies `Place`'s projection, add an element and reintern it. Should not be used
|
|
|
|
/// to build a full `Place` it's just a convenient way to grab a projection and modify it in
|
|
|
|
/// flight.
|
|
|
|
pub fn mk_place_elem(self, place: Place<'tcx>, elem: PlaceElem<'tcx>) -> Place<'tcx> {
|
|
|
|
let mut projection = place.projection.to_vec();
|
|
|
|
projection.push(elem);
|
|
|
|
|
2023-02-17 14:33:08 +11:00
|
|
|
Place { local: place.local, projection: self.mk_place_elems(&projection) }
|
2019-10-20 21:04:59 -04:00
|
|
|
}
|
|
|
|
|
2023-02-17 14:33:08 +11:00
|
|
|
pub fn mk_poly_existential_predicates(
|
2019-12-24 17:38:22 -05:00
|
|
|
self,
|
2022-11-19 03:28:56 +00:00
|
|
|
eps: &[PolyExistentialPredicate<'tcx>],
|
|
|
|
) -> &'tcx List<PolyExistentialPredicate<'tcx>> {
|
2016-11-16 09:21:49 -07:00
|
|
|
assert!(!eps.is_empty());
|
2022-06-14 17:34:37 +02:00
|
|
|
assert!(
|
|
|
|
eps.array_windows()
|
|
|
|
.all(|[a, b]| a.skip_binder().stable_cmp(self, &b.skip_binder())
|
|
|
|
!= Ordering::Greater)
|
|
|
|
);
|
2023-02-17 14:33:08 +11:00
|
|
|
self.intern_poly_existential_predicates(eps)
|
2016-11-16 09:21:49 -07:00
|
|
|
}
|
|
|
|
|
2023-02-17 14:33:08 +11:00
|
|
|
pub fn mk_predicates(self, preds: &[Predicate<'tcx>]) -> &'tcx List<Predicate<'tcx>> {
|
2017-05-02 14:37:00 -04:00
|
|
|
// FIXME consider asking the input slice to be sorted to avoid
|
|
|
|
// re-interning permutations, in which case that would be asserted
|
|
|
|
// here.
|
2023-02-17 14:33:08 +11:00
|
|
|
self.intern_predicates(preds)
|
2017-05-02 14:37:00 -04:00
|
|
|
}
|
|
|
|
|
2023-02-17 14:33:08 +11:00
|
|
|
pub fn mk_const_list_from_iter<I, T>(self, iter: I) -> T::Output
|
Clarify iterator interners.
There are two traits, `InternAs` and `InternIteratorElement`. I found
them confusing to use, particularly this:
```
pub fn mk_tup<I: InternAs<Ty<'tcx>, Ty<'tcx>>>(self, iter: I) -> I::Output {
iter.intern_with(|ts| self.intern_tup(ts))
}
```
where I thought there might have been two levels of interning going on
(there isn't) due to the `intern_with`/`InternAs` + `intern_tup` naming.
And then I found the actual traits and impls themselves *very*
confusing.
- `InternAs` has a single impl, for iterators, with four type variables.
- `InternAs` is only implemented for iterators because it wouldn't
really make sense to implement for any other type. And you can't
really understand the trait without seeing that single impl, which is
suspicious.
- `InternAs` is basically just a wrapper for `InternIteratorElement`
which does all the actual work.
- Neither trait actually does any interning. They just have `Intern` in
their name because they are used *by* interning code.
- There are no comments.
So this commit improves things.
- It removes `InternAs` completely. This makes the `mk_*` function
signatures slightly more verbose -- two trait bounds instead of one --
but much easier to read, because you only need to understand one trait
instead of two.
- It renames `InternIteratorElement` as `CollectAndApply`. Likewise, it
renames its method `intern_with` as `collect_and_apply`. These names
describe better what's going on: we collect the iterator elements into
a slice and then apply a function to the slice.
- It adds comments, making clear that all this is all there just to
provide an optimized version of `f(&iter.collect::<Vec<_>>())`.
It took me a couple of attempts to come up with this commit. My initial
attempt kept `InternAs` around, but renamed things and added comments,
and I wasn't happy with it. I think this version is much better. The
resulting code is shorter, despite the addition of the comments.
2023-02-16 12:06:36 +11:00
|
|
|
where
|
|
|
|
I: Iterator<Item = T>,
|
|
|
|
T: CollectAndApply<ty::Const<'tcx>, &'tcx List<ty::Const<'tcx>>>,
|
|
|
|
{
|
2023-02-17 14:33:08 +11:00
|
|
|
T::collect_and_apply(iter, |xs| self.mk_const_list(xs))
|
2022-07-27 07:27:52 +00:00
|
|
|
}
|
|
|
|
|
2023-02-17 14:33:08 +11:00
|
|
|
pub fn mk_type_list(self, ts: &[Ty<'tcx>]) -> &'tcx List<Ty<'tcx>> {
|
2023-02-17 14:24:13 +11:00
|
|
|
// Actually intern type lists as lists of `GenericArg`s.
|
|
|
|
//
|
|
|
|
// Transmuting from `Ty<'tcx>` to `GenericArg<'tcx>` is sound
|
2023-03-03 04:15:15 +01:00
|
|
|
// as explained in `ty_slice_as_generic_arg`. With this,
|
2023-02-17 14:24:13 +11:00
|
|
|
// we guarantee that even when transmuting between `List<Ty<'tcx>>`
|
|
|
|
// and `List<GenericArg<'tcx>>`, the uniqueness requirement for
|
|
|
|
// lists is upheld.
|
2023-02-17 14:33:08 +11:00
|
|
|
let substs = self.mk_substs(ty::subst::ty_slice_as_generic_args(ts));
|
2023-02-17 14:24:13 +11:00
|
|
|
substs.try_as_type_list().unwrap()
|
2020-10-05 20:41:46 -04:00
|
|
|
}
|
|
|
|
|
2023-02-17 14:33:08 +11:00
|
|
|
// Unlike various other `mk_*_from_iter` functions, this one uses `I:
|
|
|
|
// IntoIterator` instead of `I: Iterator`, and it doesn't have a slice
|
|
|
|
// variant, because of the need to combine `inputs` and `output`. This
|
|
|
|
// explains the lack of `_from_iter` suffix.
|
2023-02-16 11:55:23 +11:00
|
|
|
pub fn mk_fn_sig<I, T>(
|
2019-12-24 17:38:22 -05:00
|
|
|
self,
|
|
|
|
inputs: I,
|
|
|
|
output: I::Item,
|
|
|
|
c_variadic: bool,
|
|
|
|
unsafety: hir::Unsafety,
|
|
|
|
abi: abi::Abi,
|
2023-02-16 11:55:23 +11:00
|
|
|
) -> T::Output
|
2019-07-31 21:00:35 +02:00
|
|
|
where
|
2023-02-16 16:05:08 +11:00
|
|
|
I: IntoIterator<Item = T>,
|
Clarify iterator interners.
There are two traits, `InternAs` and `InternIteratorElement`. I found
them confusing to use, particularly this:
```
pub fn mk_tup<I: InternAs<Ty<'tcx>, Ty<'tcx>>>(self, iter: I) -> I::Output {
iter.intern_with(|ts| self.intern_tup(ts))
}
```
where I thought there might have been two levels of interning going on
(there isn't) due to the `intern_with`/`InternAs` + `intern_tup` naming.
And then I found the actual traits and impls themselves *very*
confusing.
- `InternAs` has a single impl, for iterators, with four type variables.
- `InternAs` is only implemented for iterators because it wouldn't
really make sense to implement for any other type. And you can't
really understand the trait without seeing that single impl, which is
suspicious.
- `InternAs` is basically just a wrapper for `InternIteratorElement`
which does all the actual work.
- Neither trait actually does any interning. They just have `Intern` in
their name because they are used *by* interning code.
- There are no comments.
So this commit improves things.
- It removes `InternAs` completely. This makes the `mk_*` function
signatures slightly more verbose -- two trait bounds instead of one --
but much easier to read, because you only need to understand one trait
instead of two.
- It renames `InternIteratorElement` as `CollectAndApply`. Likewise, it
renames its method `intern_with` as `collect_and_apply`. These names
describe better what's going on: we collect the iterator elements into
a slice and then apply a function to the slice.
- It adds comments, making clear that all this is all there just to
provide an optimized version of `f(&iter.collect::<Vec<_>>())`.
It took me a couple of attempts to come up with this commit. My initial
attempt kept `InternAs` around, but renamed things and added comments,
and I wasn't happy with it. I think this version is much better. The
resulting code is shorter, despite the addition of the comments.
2023-02-16 12:06:36 +11:00
|
|
|
T: CollectAndApply<Ty<'tcx>, ty::FnSig<'tcx>>,
|
2016-11-28 20:25:33 -07:00
|
|
|
{
|
2023-02-16 16:05:08 +11:00
|
|
|
T::collect_and_apply(inputs.into_iter().chain(iter::once(output)), |xs| ty::FnSig {
|
2023-02-17 14:33:08 +11:00
|
|
|
inputs_and_output: self.mk_type_list(xs),
|
2019-12-24 17:38:22 -05:00
|
|
|
c_variadic,
|
|
|
|
unsafety,
|
|
|
|
abi,
|
2016-11-28 20:25:33 -07:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2023-02-17 14:33:08 +11:00
|
|
|
pub fn mk_poly_existential_predicates_from_iter<I, T>(self, iter: I) -> T::Output
|
Clarify iterator interners.
There are two traits, `InternAs` and `InternIteratorElement`. I found
them confusing to use, particularly this:
```
pub fn mk_tup<I: InternAs<Ty<'tcx>, Ty<'tcx>>>(self, iter: I) -> I::Output {
iter.intern_with(|ts| self.intern_tup(ts))
}
```
where I thought there might have been two levels of interning going on
(there isn't) due to the `intern_with`/`InternAs` + `intern_tup` naming.
And then I found the actual traits and impls themselves *very*
confusing.
- `InternAs` has a single impl, for iterators, with four type variables.
- `InternAs` is only implemented for iterators because it wouldn't
really make sense to implement for any other type. And you can't
really understand the trait without seeing that single impl, which is
suspicious.
- `InternAs` is basically just a wrapper for `InternIteratorElement`
which does all the actual work.
- Neither trait actually does any interning. They just have `Intern` in
their name because they are used *by* interning code.
- There are no comments.
So this commit improves things.
- It removes `InternAs` completely. This makes the `mk_*` function
signatures slightly more verbose -- two trait bounds instead of one --
but much easier to read, because you only need to understand one trait
instead of two.
- It renames `InternIteratorElement` as `CollectAndApply`. Likewise, it
renames its method `intern_with` as `collect_and_apply`. These names
describe better what's going on: we collect the iterator elements into
a slice and then apply a function to the slice.
- It adds comments, making clear that all this is all there just to
provide an optimized version of `f(&iter.collect::<Vec<_>>())`.
It took me a couple of attempts to come up with this commit. My initial
attempt kept `InternAs` around, but renamed things and added comments,
and I wasn't happy with it. I think this version is much better. The
resulting code is shorter, despite the addition of the comments.
2023-02-16 12:06:36 +11:00
|
|
|
where
|
|
|
|
I: Iterator<Item = T>,
|
|
|
|
T: CollectAndApply<
|
|
|
|
PolyExistentialPredicate<'tcx>,
|
|
|
|
&'tcx List<PolyExistentialPredicate<'tcx>>,
|
|
|
|
>,
|
|
|
|
{
|
2023-02-17 14:33:08 +11:00
|
|
|
T::collect_and_apply(iter, |xs| self.mk_poly_existential_predicates(xs))
|
2016-11-16 09:21:49 -07:00
|
|
|
}
|
|
|
|
|
2023-02-17 14:33:08 +11:00
|
|
|
pub fn mk_predicates_from_iter<I, T>(self, iter: I) -> T::Output
|
Clarify iterator interners.
There are two traits, `InternAs` and `InternIteratorElement`. I found
them confusing to use, particularly this:
```
pub fn mk_tup<I: InternAs<Ty<'tcx>, Ty<'tcx>>>(self, iter: I) -> I::Output {
iter.intern_with(|ts| self.intern_tup(ts))
}
```
where I thought there might have been two levels of interning going on
(there isn't) due to the `intern_with`/`InternAs` + `intern_tup` naming.
And then I found the actual traits and impls themselves *very*
confusing.
- `InternAs` has a single impl, for iterators, with four type variables.
- `InternAs` is only implemented for iterators because it wouldn't
really make sense to implement for any other type. And you can't
really understand the trait without seeing that single impl, which is
suspicious.
- `InternAs` is basically just a wrapper for `InternIteratorElement`
which does all the actual work.
- Neither trait actually does any interning. They just have `Intern` in
their name because they are used *by* interning code.
- There are no comments.
So this commit improves things.
- It removes `InternAs` completely. This makes the `mk_*` function
signatures slightly more verbose -- two trait bounds instead of one --
but much easier to read, because you only need to understand one trait
instead of two.
- It renames `InternIteratorElement` as `CollectAndApply`. Likewise, it
renames its method `intern_with` as `collect_and_apply`. These names
describe better what's going on: we collect the iterator elements into
a slice and then apply a function to the slice.
- It adds comments, making clear that all this is all there just to
provide an optimized version of `f(&iter.collect::<Vec<_>>())`.
It took me a couple of attempts to come up with this commit. My initial
attempt kept `InternAs` around, but renamed things and added comments,
and I wasn't happy with it. I think this version is much better. The
resulting code is shorter, despite the addition of the comments.
2023-02-16 12:06:36 +11:00
|
|
|
where
|
|
|
|
I: Iterator<Item = T>,
|
|
|
|
T: CollectAndApply<Predicate<'tcx>, &'tcx List<Predicate<'tcx>>>,
|
|
|
|
{
|
2023-02-17 14:33:08 +11:00
|
|
|
T::collect_and_apply(iter, |xs| self.mk_predicates(xs))
|
2017-05-02 14:37:00 -04:00
|
|
|
}
|
|
|
|
|
2023-02-17 14:33:08 +11:00
|
|
|
pub fn mk_type_list_from_iter<I, T>(self, iter: I) -> T::Output
|
Clarify iterator interners.
There are two traits, `InternAs` and `InternIteratorElement`. I found
them confusing to use, particularly this:
```
pub fn mk_tup<I: InternAs<Ty<'tcx>, Ty<'tcx>>>(self, iter: I) -> I::Output {
iter.intern_with(|ts| self.intern_tup(ts))
}
```
where I thought there might have been two levels of interning going on
(there isn't) due to the `intern_with`/`InternAs` + `intern_tup` naming.
And then I found the actual traits and impls themselves *very*
confusing.
- `InternAs` has a single impl, for iterators, with four type variables.
- `InternAs` is only implemented for iterators because it wouldn't
really make sense to implement for any other type. And you can't
really understand the trait without seeing that single impl, which is
suspicious.
- `InternAs` is basically just a wrapper for `InternIteratorElement`
which does all the actual work.
- Neither trait actually does any interning. They just have `Intern` in
their name because they are used *by* interning code.
- There are no comments.
So this commit improves things.
- It removes `InternAs` completely. This makes the `mk_*` function
signatures slightly more verbose -- two trait bounds instead of one --
but much easier to read, because you only need to understand one trait
instead of two.
- It renames `InternIteratorElement` as `CollectAndApply`. Likewise, it
renames its method `intern_with` as `collect_and_apply`. These names
describe better what's going on: we collect the iterator elements into
a slice and then apply a function to the slice.
- It adds comments, making clear that all this is all there just to
provide an optimized version of `f(&iter.collect::<Vec<_>>())`.
It took me a couple of attempts to come up with this commit. My initial
attempt kept `InternAs` around, but renamed things and added comments,
and I wasn't happy with it. I think this version is much better. The
resulting code is shorter, despite the addition of the comments.
2023-02-16 12:06:36 +11:00
|
|
|
where
|
|
|
|
I: Iterator<Item = T>,
|
|
|
|
T: CollectAndApply<Ty<'tcx>, &'tcx List<Ty<'tcx>>>,
|
|
|
|
{
|
2023-02-17 14:33:08 +11:00
|
|
|
T::collect_and_apply(iter, |xs| self.mk_type_list(xs))
|
2016-10-24 18:23:29 -06:00
|
|
|
}
|
|
|
|
|
2023-02-17 14:33:08 +11:00
|
|
|
pub fn mk_substs_from_iter<I, T>(self, iter: I) -> T::Output
|
Clarify iterator interners.
There are two traits, `InternAs` and `InternIteratorElement`. I found
them confusing to use, particularly this:
```
pub fn mk_tup<I: InternAs<Ty<'tcx>, Ty<'tcx>>>(self, iter: I) -> I::Output {
iter.intern_with(|ts| self.intern_tup(ts))
}
```
where I thought there might have been two levels of interning going on
(there isn't) due to the `intern_with`/`InternAs` + `intern_tup` naming.
And then I found the actual traits and impls themselves *very*
confusing.
- `InternAs` has a single impl, for iterators, with four type variables.
- `InternAs` is only implemented for iterators because it wouldn't
really make sense to implement for any other type. And you can't
really understand the trait without seeing that single impl, which is
suspicious.
- `InternAs` is basically just a wrapper for `InternIteratorElement`
which does all the actual work.
- Neither trait actually does any interning. They just have `Intern` in
their name because they are used *by* interning code.
- There are no comments.
So this commit improves things.
- It removes `InternAs` completely. This makes the `mk_*` function
signatures slightly more verbose -- two trait bounds instead of one --
but much easier to read, because you only need to understand one trait
instead of two.
- It renames `InternIteratorElement` as `CollectAndApply`. Likewise, it
renames its method `intern_with` as `collect_and_apply`. These names
describe better what's going on: we collect the iterator elements into
a slice and then apply a function to the slice.
- It adds comments, making clear that all this is all there just to
provide an optimized version of `f(&iter.collect::<Vec<_>>())`.
It took me a couple of attempts to come up with this commit. My initial
attempt kept `InternAs` around, but renamed things and added comments,
and I wasn't happy with it. I think this version is much better. The
resulting code is shorter, despite the addition of the comments.
2023-02-16 12:06:36 +11:00
|
|
|
where
|
|
|
|
I: Iterator<Item = T>,
|
|
|
|
T: CollectAndApply<GenericArg<'tcx>, &'tcx List<GenericArg<'tcx>>>,
|
|
|
|
{
|
2023-02-17 14:33:08 +11:00
|
|
|
T::collect_and_apply(iter, |xs| self.mk_substs(xs))
|
2016-10-24 18:23:29 -06:00
|
|
|
}
|
|
|
|
|
2023-02-20 10:46:37 +11:00
|
|
|
pub fn mk_canonical_var_infos_from_iter<I, T>(self, iter: I) -> T::Output
|
|
|
|
where
|
|
|
|
I: Iterator<Item = T>,
|
|
|
|
T: CollectAndApply<CanonicalVarInfo<'tcx>, &'tcx List<CanonicalVarInfo<'tcx>>>,
|
|
|
|
{
|
|
|
|
T::collect_and_apply(iter, |xs| self.mk_canonical_var_infos(xs))
|
|
|
|
}
|
|
|
|
|
2023-02-17 14:33:08 +11:00
|
|
|
pub fn mk_place_elems_from_iter<I, T>(self, iter: I) -> T::Output
|
Clarify iterator interners.
There are two traits, `InternAs` and `InternIteratorElement`. I found
them confusing to use, particularly this:
```
pub fn mk_tup<I: InternAs<Ty<'tcx>, Ty<'tcx>>>(self, iter: I) -> I::Output {
iter.intern_with(|ts| self.intern_tup(ts))
}
```
where I thought there might have been two levels of interning going on
(there isn't) due to the `intern_with`/`InternAs` + `intern_tup` naming.
And then I found the actual traits and impls themselves *very*
confusing.
- `InternAs` has a single impl, for iterators, with four type variables.
- `InternAs` is only implemented for iterators because it wouldn't
really make sense to implement for any other type. And you can't
really understand the trait without seeing that single impl, which is
suspicious.
- `InternAs` is basically just a wrapper for `InternIteratorElement`
which does all the actual work.
- Neither trait actually does any interning. They just have `Intern` in
their name because they are used *by* interning code.
- There are no comments.
So this commit improves things.
- It removes `InternAs` completely. This makes the `mk_*` function
signatures slightly more verbose -- two trait bounds instead of one --
but much easier to read, because you only need to understand one trait
instead of two.
- It renames `InternIteratorElement` as `CollectAndApply`. Likewise, it
renames its method `intern_with` as `collect_and_apply`. These names
describe better what's going on: we collect the iterator elements into
a slice and then apply a function to the slice.
- It adds comments, making clear that all this is all there just to
provide an optimized version of `f(&iter.collect::<Vec<_>>())`.
It took me a couple of attempts to come up with this commit. My initial
attempt kept `InternAs` around, but renamed things and added comments,
and I wasn't happy with it. I think this version is much better. The
resulting code is shorter, despite the addition of the comments.
2023-02-16 12:06:36 +11:00
|
|
|
where
|
|
|
|
I: Iterator<Item = T>,
|
|
|
|
T: CollectAndApply<PlaceElem<'tcx>, &'tcx List<PlaceElem<'tcx>>>,
|
|
|
|
{
|
2023-02-17 14:33:08 +11:00
|
|
|
T::collect_and_apply(iter, |xs| self.mk_place_elems(xs))
|
2019-10-20 16:11:04 -04:00
|
|
|
}
|
|
|
|
|
2022-11-17 13:00:35 +00:00
|
|
|
pub fn mk_substs_trait(
|
|
|
|
self,
|
|
|
|
self_ty: Ty<'tcx>,
|
|
|
|
rest: impl IntoIterator<Item = GenericArg<'tcx>>,
|
|
|
|
) -> SubstsRef<'tcx> {
|
2023-02-17 14:33:08 +11:00
|
|
|
self.mk_substs_from_iter(iter::once(self_ty.into()).chain(rest))
|
2016-10-24 18:23:29 -06:00
|
|
|
}
|
2017-07-26 21:51:09 -07:00
|
|
|
|
2022-11-17 11:21:39 +00:00
|
|
|
pub fn mk_trait_ref(
|
|
|
|
self,
|
|
|
|
trait_def_id: DefId,
|
2023-02-21 03:49:03 +00:00
|
|
|
substs: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
|
2022-11-17 11:21:39 +00:00
|
|
|
) -> ty::TraitRef<'tcx> {
|
2023-02-17 14:33:08 +11:00
|
|
|
let substs = self.check_and_mk_substs(trait_def_id, substs);
|
2022-12-13 11:25:31 +00:00
|
|
|
ty::TraitRef { def_id: trait_def_id, substs, _use_mk_trait_ref_instead: () }
|
2022-11-17 11:21:39 +00:00
|
|
|
}
|
|
|
|
|
2022-12-13 10:25:21 +00:00
|
|
|
pub fn mk_alias_ty(
|
|
|
|
self,
|
|
|
|
def_id: DefId,
|
2023-02-21 03:49:03 +00:00
|
|
|
substs: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
|
2022-12-13 10:25:21 +00:00
|
|
|
) -> ty::AliasTy<'tcx> {
|
2023-02-17 14:33:08 +11:00
|
|
|
let substs = self.check_and_mk_substs(def_id, substs);
|
2022-12-13 11:07:42 +00:00
|
|
|
ty::AliasTy { def_id, substs, _use_mk_alias_ty_instead: () }
|
2022-12-13 10:25:21 +00:00
|
|
|
}
|
|
|
|
|
2023-02-17 14:33:08 +11:00
|
|
|
pub fn mk_bound_variable_kinds_from_iter<I, T>(self, iter: I) -> T::Output
|
Clarify iterator interners.
There are two traits, `InternAs` and `InternIteratorElement`. I found
them confusing to use, particularly this:
```
pub fn mk_tup<I: InternAs<Ty<'tcx>, Ty<'tcx>>>(self, iter: I) -> I::Output {
iter.intern_with(|ts| self.intern_tup(ts))
}
```
where I thought there might have been two levels of interning going on
(there isn't) due to the `intern_with`/`InternAs` + `intern_tup` naming.
And then I found the actual traits and impls themselves *very*
confusing.
- `InternAs` has a single impl, for iterators, with four type variables.
- `InternAs` is only implemented for iterators because it wouldn't
really make sense to implement for any other type. And you can't
really understand the trait without seeing that single impl, which is
suspicious.
- `InternAs` is basically just a wrapper for `InternIteratorElement`
which does all the actual work.
- Neither trait actually does any interning. They just have `Intern` in
their name because they are used *by* interning code.
- There are no comments.
So this commit improves things.
- It removes `InternAs` completely. This makes the `mk_*` function
signatures slightly more verbose -- two trait bounds instead of one --
but much easier to read, because you only need to understand one trait
instead of two.
- It renames `InternIteratorElement` as `CollectAndApply`. Likewise, it
renames its method `intern_with` as `collect_and_apply`. These names
describe better what's going on: we collect the iterator elements into
a slice and then apply a function to the slice.
- It adds comments, making clear that all this is all there just to
provide an optimized version of `f(&iter.collect::<Vec<_>>())`.
It took me a couple of attempts to come up with this commit. My initial
attempt kept `InternAs` around, but renamed things and added comments,
and I wasn't happy with it. I think this version is much better. The
resulting code is shorter, despite the addition of the comments.
2023-02-16 12:06:36 +11:00
|
|
|
where
|
|
|
|
I: Iterator<Item = T>,
|
|
|
|
T: CollectAndApply<ty::BoundVariableKind, &'tcx List<ty::BoundVariableKind>>,
|
|
|
|
{
|
2023-02-17 14:33:08 +11:00
|
|
|
T::collect_and_apply(iter, |xs| self.mk_bound_variable_kinds(xs))
|
2020-10-05 20:41:46 -04:00
|
|
|
}
|
|
|
|
|
2022-06-29 16:07:46 +01:00
|
|
|
/// Emit a lint at `span` from a lint struct (some type that implements `DecorateLint`,
|
|
|
|
/// typically generated by `#[derive(LintDiagnostic)]`).
|
|
|
|
pub fn emit_spanned_lint(
|
|
|
|
self,
|
|
|
|
lint: &'static Lint,
|
|
|
|
hir_id: HirId,
|
|
|
|
span: impl Into<MultiSpan>,
|
|
|
|
decorator: impl for<'a> DecorateLint<'a, ()>,
|
|
|
|
) {
|
2022-10-29 18:03:47 +08:00
|
|
|
let msg = decorator.msg();
|
|
|
|
let (level, src) = self.lint_level_at_node(lint, hir_id);
|
|
|
|
struct_lint_level(self.sess, lint, level, src, Some(span.into()), msg, |diag| {
|
2022-09-16 11:01:02 +04:00
|
|
|
decorator.decorate_lint(diag)
|
|
|
|
})
|
2022-06-29 16:07:46 +01:00
|
|
|
}
|
|
|
|
|
2022-10-12 14:16:24 +00:00
|
|
|
/// Emit a lint at the appropriate level for a hir node, with an associated span.
|
|
|
|
///
|
|
|
|
/// Return value of the `decorate` closure is ignored, see [`struct_lint_level`] for a detailed explanation.
|
|
|
|
///
|
|
|
|
/// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature
|
2022-10-29 18:03:47 +08:00
|
|
|
#[rustc_lint_diagnostics]
|
2020-01-05 10:58:44 +01:00
|
|
|
pub fn struct_span_lint_hir(
|
2019-12-24 17:38:22 -05:00
|
|
|
self,
|
|
|
|
lint: &'static Lint,
|
|
|
|
hir_id: HirId,
|
2020-01-05 10:58:44 +01:00
|
|
|
span: impl Into<MultiSpan>,
|
2022-09-16 11:01:02 +04:00
|
|
|
msg: impl Into<DiagnosticMessage>,
|
|
|
|
decorate: impl for<'a, 'b> FnOnce(
|
|
|
|
&'b mut DiagnosticBuilder<'a, ()>,
|
|
|
|
) -> &'b mut DiagnosticBuilder<'a, ()>,
|
2020-01-31 22:24:57 +10:00
|
|
|
) {
|
2019-02-26 11:48:34 +01:00
|
|
|
let (level, src) = self.lint_level_at_node(lint, hir_id);
|
2022-09-16 11:01:02 +04:00
|
|
|
struct_lint_level(self.sess, lint, level, src, Some(span.into()), msg, decorate);
|
2017-07-26 21:51:09 -07:00
|
|
|
}
|
|
|
|
|
2022-06-29 16:07:46 +01:00
|
|
|
/// Emit a lint from a lint struct (some type that implements `DecorateLint`, typically
|
|
|
|
/// generated by `#[derive(LintDiagnostic)]`).
|
|
|
|
pub fn emit_lint(
|
|
|
|
self,
|
|
|
|
lint: &'static Lint,
|
|
|
|
id: HirId,
|
|
|
|
decorator: impl for<'a> DecorateLint<'a, ()>,
|
|
|
|
) {
|
2022-09-16 11:01:02 +04:00
|
|
|
self.struct_lint_node(lint, id, decorator.msg(), |diag| decorator.decorate_lint(diag))
|
2022-06-29 16:07:46 +01:00
|
|
|
}
|
|
|
|
|
2022-10-12 14:16:24 +00:00
|
|
|
/// Emit a lint at the appropriate level for a hir node.
|
|
|
|
///
|
|
|
|
/// Return value of the `decorate` closure is ignored, see [`struct_lint_level`] for a detailed explanation.
|
|
|
|
///
|
|
|
|
/// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature
|
2022-11-07 19:23:29 -05:00
|
|
|
#[rustc_lint_diagnostics]
|
2019-12-24 17:38:22 -05:00
|
|
|
pub fn struct_lint_node(
|
|
|
|
self,
|
|
|
|
lint: &'static Lint,
|
|
|
|
id: HirId,
|
2022-09-16 11:01:02 +04:00
|
|
|
msg: impl Into<DiagnosticMessage>,
|
|
|
|
decorate: impl for<'a, 'b> FnOnce(
|
|
|
|
&'b mut DiagnosticBuilder<'a, ()>,
|
|
|
|
) -> &'b mut DiagnosticBuilder<'a, ()>,
|
2020-01-31 22:24:57 +10:00
|
|
|
) {
|
2017-07-26 21:51:09 -07:00
|
|
|
let (level, src) = self.lint_level_at_node(lint, id);
|
2022-09-16 11:01:02 +04:00
|
|
|
struct_lint_level(self.sess, lint, level, src, None, msg, decorate);
|
2017-07-26 21:51:09 -07:00
|
|
|
}
|
2017-09-08 13:51:57 -07:00
|
|
|
|
2021-05-11 10:38:54 +02:00
|
|
|
pub fn in_scope_traits(self, id: HirId) -> Option<&'tcx [TraitCandidate]> {
|
|
|
|
let map = self.in_scope_traits_map(id.owner)?;
|
|
|
|
let candidates = map.get(&id.local_id)?;
|
|
|
|
Some(&*candidates)
|
2017-09-08 13:51:57 -07:00
|
|
|
}
|
|
|
|
|
2023-02-06 18:38:52 +00:00
|
|
|
pub fn named_bound_var(self, id: HirId) -> Option<resolve_bound_vars::ResolvedArg> {
|
2021-02-27 21:31:56 -05:00
|
|
|
debug!(?id, "named_region");
|
2023-02-06 18:38:52 +00:00
|
|
|
self.named_variable_map(id.owner).and_then(|map| map.get(&id.local_id).cloned())
|
2017-09-08 13:51:57 -07:00
|
|
|
}
|
|
|
|
|
2022-05-26 08:59:15 +02:00
|
|
|
pub fn is_late_bound(self, id: HirId) -> bool {
|
2022-11-05 15:33:58 +00:00
|
|
|
self.is_late_bound_map(id.owner).map_or(false, |set| set.contains(&id.local_id))
|
2022-05-26 08:59:15 +02:00
|
|
|
}
|
|
|
|
|
2020-10-26 14:18:31 -04:00
|
|
|
pub fn late_bound_vars(self, id: HirId) -> &'tcx List<ty::BoundVariableKind> {
|
2023-02-17 14:33:08 +11:00
|
|
|
self.mk_bound_variable_kinds(
|
2023-02-16 16:27:05 +11:00
|
|
|
&self
|
|
|
|
.late_bound_vars_map(id.owner)
|
2020-10-26 14:18:31 -04:00
|
|
|
.and_then(|map| map.get(&id.local_id).cloned())
|
|
|
|
.unwrap_or_else(|| {
|
2023-01-31 12:09:54 +01:00
|
|
|
bug!("No bound vars found for {}", self.hir().node_to_string(id))
|
2023-02-16 16:27:05 +11:00
|
|
|
}),
|
2020-10-26 14:18:31 -04:00
|
|
|
)
|
|
|
|
}
|
2021-02-18 21:01:44 +01:00
|
|
|
|
2021-09-15 10:03:03 +00:00
|
|
|
/// Whether the `def_id` counts as const fn in the current crate, considering all active
|
|
|
|
/// feature gates
|
|
|
|
pub fn is_const_fn(self, def_id: DefId) -> bool {
|
|
|
|
if self.is_const_fn_raw(def_id) {
|
|
|
|
match self.lookup_const_stability(def_id) {
|
2022-02-08 04:52:11 -05:00
|
|
|
Some(stability) if stability.is_const_unstable() => {
|
2021-09-15 10:03:03 +00:00
|
|
|
// has a `rustc_const_unstable` attribute, check whether the user enabled the
|
|
|
|
// corresponding feature gate.
|
2021-09-15 11:28:10 +00:00
|
|
|
self.features()
|
|
|
|
.declared_lib_features
|
|
|
|
.iter()
|
|
|
|
.any(|&(sym, _)| sym == stability.feature)
|
2021-09-15 10:03:03 +00:00
|
|
|
}
|
|
|
|
// functions without const stability are either stable user written
|
|
|
|
// const fn or the user is using feature gates and we thus don't
|
|
|
|
// care what they do
|
|
|
|
_ => true,
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
false
|
|
|
|
}
|
|
|
|
}
|
2022-02-13 05:54:00 -05:00
|
|
|
|
|
|
|
/// Whether the trait impl is marked const. This does not consider stability or feature gates.
|
|
|
|
pub fn is_const_trait_impl_raw(self, def_id: DefId) -> bool {
|
|
|
|
let Some(local_def_id) = def_id.as_local() else { return false };
|
|
|
|
let hir_id = self.local_def_id_to_hir_id(local_def_id);
|
|
|
|
let node = self.hir().get(hir_id);
|
|
|
|
|
|
|
|
matches!(
|
|
|
|
node,
|
|
|
|
hir::Node::Item(hir::Item {
|
|
|
|
kind: hir::ItemKind::Impl(hir::Impl { constness: hir::Constness::Const, .. }),
|
|
|
|
..
|
|
|
|
})
|
|
|
|
)
|
|
|
|
}
|
2023-02-10 14:29:28 +00:00
|
|
|
|
2022-12-15 13:20:27 -03:00
|
|
|
pub fn local_def_id_to_hir_id(self, local_def_id: LocalDefId) -> HirId {
|
|
|
|
self.opt_local_def_id_to_hir_id(local_def_id).unwrap()
|
|
|
|
}
|
|
|
|
|
2023-02-10 14:29:28 +00:00
|
|
|
pub fn trait_solver_next(self) -> bool {
|
|
|
|
self.sess.opts.unstable_opts.trait_solver == rustc_session::config::TraitSolver::Next
|
|
|
|
}
|
2023-03-03 18:27:25 -03:00
|
|
|
|
|
|
|
pub fn lower_impl_trait_in_trait_to_assoc_ty(self) -> bool {
|
|
|
|
self.sess.opts.unstable_opts.lower_impl_trait_in_trait_to_assoc_ty
|
|
|
|
}
|
2023-03-06 11:33:51 -03:00
|
|
|
|
|
|
|
pub fn is_impl_trait_in_trait(self, def_id: DefId) -> bool {
|
|
|
|
if self.lower_impl_trait_in_trait_to_assoc_ty() {
|
2023-03-12 20:32:50 +00:00
|
|
|
self.opt_rpitit_info(def_id).is_some()
|
2023-03-06 11:33:51 -03:00
|
|
|
} else {
|
|
|
|
self.def_kind(def_id) == DefKind::ImplTraitPlaceholder
|
|
|
|
}
|
|
|
|
}
|
2015-09-06 21:51:58 +03:00
|
|
|
}
|
2016-10-24 18:23:29 -06:00
|
|
|
|
2021-12-15 19:32:30 -05:00
|
|
|
impl<'tcx> TyCtxtAt<'tcx> {
|
2021-03-27 22:16:17 -04:00
|
|
|
/// Constructs a `TyKind::Error` type and registers a `delay_span_bug` to ensure it gets used.
|
|
|
|
#[track_caller]
|
2023-02-22 22:23:10 +00:00
|
|
|
pub fn ty_error_misc(self) -> Ty<'tcx> {
|
2021-03-27 22:16:17 -04:00
|
|
|
self.tcx.ty_error_with_message(self.span, "TyKind::Error constructed but no error reported")
|
|
|
|
}
|
|
|
|
|
2023-03-03 04:10:46 +01:00
|
|
|
/// Constructs a `TyKind::Error` type and registers a `delay_span_bug` with the given `msg` to
|
2021-03-27 22:16:17 -04:00
|
|
|
/// ensure it gets used.
|
|
|
|
#[track_caller]
|
|
|
|
pub fn ty_error_with_message(self, msg: &str) -> Ty<'tcx> {
|
|
|
|
self.tcx.ty_error_with_message(self.span, msg)
|
|
|
|
}
|
2022-11-17 14:39:19 +00:00
|
|
|
|
|
|
|
pub fn mk_trait_ref(
|
|
|
|
self,
|
|
|
|
trait_lang_item: LangItem,
|
2023-02-21 03:49:03 +00:00
|
|
|
substs: impl IntoIterator<Item: Into<ty::GenericArg<'tcx>>>,
|
2022-11-17 14:39:19 +00:00
|
|
|
) -> ty::TraitRef<'tcx> {
|
|
|
|
let trait_def_id = self.require_lang_item(trait_lang_item, Some(self.span));
|
2022-11-21 12:24:53 +00:00
|
|
|
self.tcx.mk_trait_ref(trait_def_id, substs)
|
2022-11-17 14:39:19 +00:00
|
|
|
}
|
2021-03-27 22:16:17 -04:00
|
|
|
}
|
|
|
|
|
Introduce deduced parameter attributes, and use them for deducing `readonly` on
indirect immutable freeze by-value function parameters.
Right now, `rustc` only examines function signatures and the platform ABI when
determining the LLVM attributes to apply to parameters. This results in missed
optimizations, because there are some attributes that can be determined via
analysis of the MIR making up the function body. In particular, `readonly`
could be applied to most indirectly-passed by-value function arguments
(specifically, those that are freeze and are observed not to be mutated), but
it currently is not.
This patch introduces the machinery that allows `rustc` to determine those
attributes. It consists of a query, `deduced_param_attrs`, that, when
evaluated, analyzes the MIR of the function to determine supplementary
attributes. The results of this query for each function are written into the
crate metadata so that the deduced parameter attributes can be applied to
cross-crate functions. In this patch, we simply check the parameter for
mutations to determine whether the `readonly` attribute should be applied to
parameters that are indirect immutable freeze by-value. More attributes could
conceivably be deduced in the future: `nocapture` and `noalias` come to mind.
Adding `readonly` to indirect function parameters where applicable enables some
potential optimizations in LLVM that are discussed in [issue 103103] and [PR
103070] around avoiding stack-to-stack memory copies that appear in functions
like `core::fmt::Write::write_fmt` and `core::panicking::assert_failed`. These
functions pass a large structure unchanged by value to a subfunction that also
doesn't mutate it. Since the structure in this case is passed as an indirect
parameter, it's a pointer from LLVM's perspective. As a result, the
intermediate copy of the structure that our codegen emits could be optimized
away by LLVM's MemCpyOptimizer if it knew that the pointer is `readonly
nocapture noalias` in both the caller and callee. We already pass `nocapture
noalias`, but we're missing `readonly`, as we can't determine whether a
by-value parameter is mutated by examining the signature in Rust. I didn't have
much success with having LLVM infer the `readonly` attribute, even with fat
LTO; it seems that deducing it at the MIR level is necessary.
No large benefits should be expected from this optimization *now*; LLVM needs
some changes (discussed in [PR 103070]) to more aggressively use the `noalias
nocapture readonly` combination in its alias analysis. I have some LLVM patches
for these optimizations and have had them looked over. With all the patches
applied locally, I enabled LLVM to remove all the `memcpy`s from the following
code:
```rust
fn main() {
println!("Hello {}", 3);
}
```
which is a significant codegen improvement over the status quo. I expect that
if this optimization kicks in in multiple places even for such a simple
program, then it will apply to Rust code all over the place.
[issue 103103]: https://github.com/rust-lang/rust/issues/103103
[PR 103070]: https://github.com/rust-lang/rust/pull/103070
2022-10-17 19:42:15 -07:00
|
|
|
/// Parameter attributes that can only be determined by examining the body of a function instead
|
|
|
|
/// of just its signature.
|
|
|
|
///
|
|
|
|
/// These can be useful for optimization purposes when a function is directly called. We compute
|
|
|
|
/// them and store them into the crate metadata so that downstream crates can make use of them.
|
|
|
|
///
|
|
|
|
/// Right now, we only have `read_only`, but `no_capture` and `no_alias` might be useful in the
|
|
|
|
/// future.
|
|
|
|
#[derive(Clone, Copy, PartialEq, Debug, Default, TyDecodable, TyEncodable, HashStable)]
|
|
|
|
pub struct DeducedParamAttrs {
|
|
|
|
/// The parameter is marked immutable in the function and contains no `UnsafeCell` (i.e. its
|
|
|
|
/// type is freeze).
|
|
|
|
pub read_only: bool,
|
|
|
|
}
|
|
|
|
|
2020-07-05 23:00:14 +03:00
|
|
|
pub fn provide(providers: &mut ty::query::Providers) {
|
2021-12-21 11:24:43 +08:00
|
|
|
providers.module_reexports =
|
|
|
|
|tcx, id| tcx.resolutions(()).reexport_map.get(&id).map(|v| &v[..]);
|
2022-05-31 16:59:28 -07:00
|
|
|
providers.maybe_unused_trait_imports =
|
|
|
|
|tcx, ()| &tcx.resolutions(()).maybe_unused_trait_imports;
|
2021-04-04 14:40:35 +02:00
|
|
|
providers.names_imported_by_glob_use = |tcx, id| {
|
2023-02-21 15:18:10 +01:00
|
|
|
tcx.arena.alloc(UnordSet::from(
|
|
|
|
tcx.resolutions(()).glob_map.get(&id).cloned().unwrap_or_default(),
|
|
|
|
))
|
2021-04-04 14:40:35 +02:00
|
|
|
};
|
2017-08-31 15:08:34 -07:00
|
|
|
|
2021-04-04 14:40:35 +02:00
|
|
|
providers.extern_mod_stmt_cnum =
|
|
|
|
|tcx, id| tcx.resolutions(()).extern_crate_map.get(&id).cloned();
|
2018-02-27 19:28:21 +01:00
|
|
|
providers.is_panic_runtime = |tcx, cnum| {
|
|
|
|
assert_eq!(cnum, LOCAL_CRATE);
|
2020-07-30 11:27:50 +10:00
|
|
|
tcx.sess.contains_name(tcx.hir().krate_attrs(), sym::panic_runtime)
|
2018-02-27 19:28:21 +01:00
|
|
|
};
|
|
|
|
providers.is_compiler_builtins = |tcx, cnum| {
|
|
|
|
assert_eq!(cnum, LOCAL_CRATE);
|
2020-07-30 11:27:50 +10:00
|
|
|
tcx.sess.contains_name(tcx.hir().krate_attrs(), sym::compiler_builtins)
|
2018-02-27 19:28:21 +01:00
|
|
|
};
|
2019-10-28 17:07:15 -04:00
|
|
|
providers.has_panic_handler = |tcx, cnum| {
|
|
|
|
assert_eq!(cnum, LOCAL_CRATE);
|
|
|
|
// We want to check if the panic handler was defined in this crate
|
|
|
|
tcx.lang_items().panic_impl().map_or(false, |did| did.is_local())
|
|
|
|
};
|
2023-02-21 08:37:10 +00:00
|
|
|
providers.source_span = |tcx, def_id| tcx.untracked.source_span.get(def_id).unwrap_or(DUMMY_SP);
|
2017-08-29 11:10:22 -07:00
|
|
|
}
|