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_errors
::struct_span_err
;
12 use rustc_hir
::def_id
::{DefId, LocalDefId}
;
13 use rustc_hir
::itemlikevisit
::ItemLikeVisitor
;
14 use rustc_middle
::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(tcx
: TyCtxt
<'_
>, (): ()) -> CrateInherentImpls
{
20 let mut collect
= InherentCollect { tcx, impls_map: Default::default() }
;
21 tcx
.hir().visit_all_item_likes(&mut collect
);
25 /// On-demand query: yields a vector of the inherent impls for a specific type.
26 pub fn inherent_impls(tcx
: TyCtxt
<'_
>, ty_def_id
: DefId
) -> &[DefId
] {
27 let ty_def_id
= ty_def_id
.expect_local();
29 let crate_map
= tcx
.crate_inherent_impls(());
30 match crate_map
.inherent_impls
.get(&ty_def_id
) {
36 struct InherentCollect
<'tcx
> {
38 impls_map
: CrateInherentImpls
,
41 impl ItemLikeVisitor
<'v
> for InherentCollect
<'tcx
> {
42 fn visit_item(&mut self, item
: &hir
::Item
<'_
>) {
43 let (ty
, assoc_items
) = match item
.kind
{
44 hir
::ItemKind
::Impl(hir
::Impl { of_trait: None, ref self_ty, items, .. }
) => {
50 let self_ty
= self.tcx
.type_of(item
.def_id
);
51 let lang_items
= self.tcx
.lang_items();
52 match *self_ty
.kind() {
54 self.check_def_id(item
, def
.did
);
57 self.check_def_id(item
, did
);
59 ty
::Dynamic(data
, ..) if data
.principal_def_id().is_some() => {
60 self.check_def_id(item
, data
.principal_def_id().unwrap());
67 "cannot define inherent `impl` for a dyn auto trait"
69 .span_label(ty
.span
, "impl requires at least one non-auto trait")
70 .note("define and implement a new trait or type instead")
74 self.check_primitive_impl(
76 lang_items
.bool_impl(),
85 self.check_primitive_impl(
87 lang_items
.char_impl(),
96 self.check_primitive_impl(
98 lang_items
.str_impl(),
99 lang_items
.str_alloc_impl(),
106 ty
::Slice(slice_item
) if slice_item
== self.tcx
.types
.u8 => {
107 self.check_primitive_impl(
109 lang_items
.slice_u8_impl(),
110 lang_items
.slice_u8_alloc_impl(),
118 self.check_primitive_impl(
120 lang_items
.slice_impl(),
121 lang_items
.slice_alloc_impl(),
129 self.check_primitive_impl(
131 lang_items
.array_impl(),
139 ty
::RawPtr(ty
::TypeAndMut { ty: inner, mutbl: hir::Mutability::Not }
)
140 if matches
!(inner
.kind(), ty
::Slice(_
)) =>
142 self.check_primitive_impl(
144 lang_items
.const_slice_ptr_impl(),
152 ty
::RawPtr(ty
::TypeAndMut { ty: inner, mutbl: hir::Mutability::Mut }
)
153 if matches
!(inner
.kind(), ty
::Slice(_
)) =>
155 self.check_primitive_impl(
157 lang_items
.mut_slice_ptr_impl(),
165 ty
::RawPtr(ty
::TypeAndMut { ty: _, mutbl: hir::Mutability::Not }
) => {
166 self.check_primitive_impl(
168 lang_items
.const_ptr_impl(),
176 ty
::RawPtr(ty
::TypeAndMut { ty: _, mutbl: hir::Mutability::Mut }
) => {
177 self.check_primitive_impl(
179 lang_items
.mut_ptr_impl(),
187 ty
::Int(ty
::IntTy
::I8
) => {
188 self.check_primitive_impl(
190 lang_items
.i8_impl(),
198 ty
::Int(ty
::IntTy
::I16
) => {
199 self.check_primitive_impl(
201 lang_items
.i16_impl(),
209 ty
::Int(ty
::IntTy
::I32
) => {
210 self.check_primitive_impl(
212 lang_items
.i32_impl(),
220 ty
::Int(ty
::IntTy
::I64
) => {
221 self.check_primitive_impl(
223 lang_items
.i64_impl(),
231 ty
::Int(ty
::IntTy
::I128
) => {
232 self.check_primitive_impl(
234 lang_items
.i128_impl(),
242 ty
::Int(ty
::IntTy
::Isize
) => {
243 self.check_primitive_impl(
245 lang_items
.isize_impl(),
253 ty
::Uint(ty
::UintTy
::U8
) => {
254 self.check_primitive_impl(
256 lang_items
.u8_impl(),
264 ty
::Uint(ty
::UintTy
::U16
) => {
265 self.check_primitive_impl(
267 lang_items
.u16_impl(),
275 ty
::Uint(ty
::UintTy
::U32
) => {
276 self.check_primitive_impl(
278 lang_items
.u32_impl(),
286 ty
::Uint(ty
::UintTy
::U64
) => {
287 self.check_primitive_impl(
289 lang_items
.u64_impl(),
297 ty
::Uint(ty
::UintTy
::U128
) => {
298 self.check_primitive_impl(
300 lang_items
.u128_impl(),
308 ty
::Uint(ty
::UintTy
::Usize
) => {
309 self.check_primitive_impl(
311 lang_items
.usize_impl(),
319 ty
::Float(ty
::FloatTy
::F32
) => {
320 self.check_primitive_impl(
322 lang_items
.f32_impl(),
323 lang_items
.f32_runtime_impl(),
330 ty
::Float(ty
::FloatTy
::F64
) => {
331 self.check_primitive_impl(
333 lang_items
.f64_impl(),
334 lang_items
.f64_runtime_impl(),
343 let mut err
= struct_span_err
!(
347 "no nominal type found for inherent implementation"
350 err
.span_label(ty
.span
, "impl requires a nominal type")
351 .note("either implement a trait on it or create a newtype to wrap it instead");
353 if let ty
::Ref(_
, subty
, _
) = self_ty
.kind() {
355 "you could also try moving the reference to \
356 uses of `{}` (such as `self`) within the implementation",
366 fn visit_trait_item(&mut self, _trait_item
: &hir
::TraitItem
<'_
>) {}
368 fn visit_impl_item(&mut self, _impl_item
: &hir
::ImplItem
<'_
>) {}
370 fn visit_foreign_item(&mut self, _foreign_item
: &hir
::ForeignItem
<'_
>) {}
373 impl InherentCollect
<'tcx
> {
374 fn check_def_id(&mut self, item
: &hir
::Item
<'_
>, def_id
: DefId
) {
375 if let Some(def_id
) = def_id
.as_local() {
376 // Add the implementation to the mapping from implementation to base
377 // type def ID, if there is a base type for this implementation and
378 // the implementation does not have any associated traits.
379 let vec
= self.impls_map
.inherent_impls
.entry(def_id
).or_default();
380 vec
.push(item
.def_id
.to_def_id());
386 "cannot define inherent `impl` for a type outside of the crate \
387 where the type is defined"
389 .span_label(item
.span
, "impl for type defined outside of crate.")
390 .note("define and implement a trait or new type instead")
395 fn check_primitive_impl(
397 impl_def_id
: LocalDefId
,
398 lang_def_id
: Option
<DefId
>,
399 lang_def_id2
: Option
<DefId
>,
403 assoc_items
: &[hir
::ImplItemRef
],
405 match (lang_def_id
, lang_def_id2
) {
406 (Some(lang_def_id
), _
) if lang_def_id
== impl_def_id
.to_def_id() => {
409 (_
, Some(lang_def_id
)) if lang_def_id
== impl_def_id
.to_def_id() => {
413 let to_implement
= if assoc_items
.is_empty() {
416 let plural
= assoc_items
.len() > 1;
417 let assoc_items_kind
= {
418 let item_types
= assoc_items
.iter().map(|x
| x
.kind
);
419 if item_types
.clone().all(|x
| x
== hir
::AssocItemKind
::Const
) {
423 .all(|x
| matches
! {x, hir::AssocItemKind::Fn{ .. }
})
432 " to implement {} {}{}",
433 if plural { "these" }
else { "this" }
,
435 if plural { "s" }
else { "" }
443 "only a single inherent implementation marked with `#[lang = \
444 \"{}\"]` is allowed for the `{}` primitive",
448 .help(&format
!("consider using a trait{}", to_implement
))