1 //! The code in this module gathers up all of the inherent impls in
2 //! the current crate and organizes them in a map. It winds up
3 //! touching the whole crate and thus must be recomputed completely
4 //! for any change, but it is very cheap to compute. In practice, most
5 //! code in the compiler never *directly* requests this map. Instead,
6 //! it requests the inherent impls specific to some type (via
7 //! `tcx.inherent_impls(def_id)`). That value, however,
8 //! is computed by selecting an idea from this table.
10 use rustc
::hir
::def_id
::{CrateNum, DefId, LOCAL_CRATE}
;
12 use rustc
::hir
::itemlikevisit
::ItemLikeVisitor
;
13 use rustc
::ty
::{self, CrateInherentImpls, TyCtxt}
;
18 /// On-demand query: yields a map containing all types mapped to their inherent impls.
19 pub fn crate_inherent_impls(
22 ) -> &CrateInherentImpls
{
23 assert_eq
!(crate_num
, LOCAL_CRATE
);
25 let krate
= tcx
.hir().krate();
26 let mut collect
= InherentCollect
{
28 impls_map
: Default
::default(),
30 krate
.visit_all_item_likes(&mut collect
);
31 tcx
.arena
.alloc(collect
.impls_map
)
34 /// On-demand query: yields a vector of the inherent impls for a specific type.
35 pub fn inherent_impls(tcx
: TyCtxt
<'_
>, ty_def_id
: DefId
) -> &[DefId
] {
36 assert
!(ty_def_id
.is_local());
38 let crate_map
= tcx
.crate_inherent_impls(ty_def_id
.krate
);
39 match crate_map
.inherent_impls
.get(&ty_def_id
) {
45 struct InherentCollect
<'tcx
> {
47 impls_map
: CrateInherentImpls
,
50 impl ItemLikeVisitor
<'v
> for InherentCollect
<'tcx
> {
51 fn visit_item(&mut self, item
: &hir
::Item
) {
52 let ty
= match item
.node
{
53 hir
::ItemKind
::Impl(.., None
, ref ty
, _
) => ty
,
57 let def_id
= self.tcx
.hir().local_def_id(item
.hir_id
);
58 let self_ty
= self.tcx
.type_of(def_id
);
59 let lang_items
= self.tcx
.lang_items();
62 self.check_def_id(item
, def
.did
);
65 self.check_def_id(item
, did
);
67 ty
::Dynamic(ref data
, ..) if data
.principal_def_id().is_some() => {
68 self.check_def_id(item
, data
.principal_def_id().unwrap());
71 self.check_primitive_impl(def_id
,
72 lang_items
.bool_impl(),
79 self.check_primitive_impl(def_id
,
80 lang_items
.char_impl(),
87 self.check_primitive_impl(def_id
,
88 lang_items
.str_impl(),
89 lang_items
.str_alloc_impl(),
94 ty
::Slice(slice_item
) if slice_item
== self.tcx
.types
.u8 => {
95 self.check_primitive_impl(def_id
,
96 lang_items
.slice_u8_impl(),
97 lang_items
.slice_u8_alloc_impl(),
103 self.check_primitive_impl(def_id
,
104 lang_items
.slice_impl(),
105 lang_items
.slice_alloc_impl(),
110 ty
::RawPtr(ty
::TypeAndMut { ty: _, mutbl: hir::MutImmutable }
) => {
111 self.check_primitive_impl(def_id
,
112 lang_items
.const_ptr_impl(),
118 ty
::RawPtr(ty
::TypeAndMut { ty: _, mutbl: hir::MutMutable }
) => {
119 self.check_primitive_impl(def_id
,
120 lang_items
.mut_ptr_impl(),
126 ty
::Int(ast
::IntTy
::I8
) => {
127 self.check_primitive_impl(def_id
,
128 lang_items
.i8_impl(),
134 ty
::Int(ast
::IntTy
::I16
) => {
135 self.check_primitive_impl(def_id
,
136 lang_items
.i16_impl(),
142 ty
::Int(ast
::IntTy
::I32
) => {
143 self.check_primitive_impl(def_id
,
144 lang_items
.i32_impl(),
150 ty
::Int(ast
::IntTy
::I64
) => {
151 self.check_primitive_impl(def_id
,
152 lang_items
.i64_impl(),
158 ty
::Int(ast
::IntTy
::I128
) => {
159 self.check_primitive_impl(def_id
,
160 lang_items
.i128_impl(),
166 ty
::Int(ast
::IntTy
::Isize
) => {
167 self.check_primitive_impl(def_id
,
168 lang_items
.isize_impl(),
174 ty
::Uint(ast
::UintTy
::U8
) => {
175 self.check_primitive_impl(def_id
,
176 lang_items
.u8_impl(),
182 ty
::Uint(ast
::UintTy
::U16
) => {
183 self.check_primitive_impl(def_id
,
184 lang_items
.u16_impl(),
190 ty
::Uint(ast
::UintTy
::U32
) => {
191 self.check_primitive_impl(def_id
,
192 lang_items
.u32_impl(),
198 ty
::Uint(ast
::UintTy
::U64
) => {
199 self.check_primitive_impl(def_id
,
200 lang_items
.u64_impl(),
206 ty
::Uint(ast
::UintTy
::U128
) => {
207 self.check_primitive_impl(def_id
,
208 lang_items
.u128_impl(),
214 ty
::Uint(ast
::UintTy
::Usize
) => {
215 self.check_primitive_impl(def_id
,
216 lang_items
.usize_impl(),
222 ty
::Float(ast
::FloatTy
::F32
) => {
223 self.check_primitive_impl(def_id
,
224 lang_items
.f32_impl(),
225 lang_items
.f32_runtime_impl(),
230 ty
::Float(ast
::FloatTy
::F64
) => {
231 self.check_primitive_impl(def_id
,
232 lang_items
.f64_impl(),
233 lang_items
.f64_runtime_impl(),
242 struct_span_err
!(self.tcx
.sess
,
245 "no base type found for inherent implementation")
246 .span_label(ty
.span
, "impl requires a base type")
247 .note(&format
!("either implement a trait on it or create a newtype \
248 to wrap it instead"))
255 fn visit_trait_item(&mut self, _trait_item
: &hir
::TraitItem
) {
258 fn visit_impl_item(&mut self, _impl_item
: &hir
::ImplItem
) {
262 impl InherentCollect
<'tcx
> {
263 fn check_def_id(&mut self, item
: &hir
::Item
, def_id
: DefId
) {
264 if def_id
.is_local() {
265 // Add the implementation to the mapping from implementation to base
266 // type def ID, if there is a base type for this implementation and
267 // the implementation does not have any associated traits.
268 let impl_def_id
= self.tcx
.hir().local_def_id(item
.hir_id
);
269 let vec
= self.impls_map
.inherent_impls
.entry(def_id
).or_default();
270 vec
.push(impl_def_id
);
272 struct_span_err
!(self.tcx
.sess
,
275 "cannot define inherent `impl` for a type outside of the crate \
276 where the type is defined")
277 .span_label(item
.span
, "impl for type defined outside of crate.")
278 .note("define and implement a trait or new type instead")
283 fn check_primitive_impl(&self,
285 lang_def_id
: Option
<DefId
>,
286 lang_def_id2
: Option
<DefId
>,
290 match (lang_def_id
, lang_def_id2
) {
291 (Some(lang_def_id
), _
) if lang_def_id
== impl_def_id
=> {
294 (_
, Some(lang_def_id
)) if lang_def_id
== impl_def_id
=> {
298 struct_span_err
!(self.tcx
.sess
,
301 "only a single inherent implementation marked with `#[lang = \
302 \"{}\"]` is allowed for the `{}` primitive",
305 .span_help(span
, "consider using a trait to implement these methods")