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 krate = tcx.hir().krate();
21 let mut collect = InherentCollect { tcx, impls_map: Default::default() };
22 krate.visit_all_item_likes(&mut collect);
26 /// On-demand query: yields a vector of the inherent impls for a specific type.
27 pub fn inherent_impls(tcx: TyCtxt<'_>, ty_def_id: DefId) -> &[DefId] {
28 let ty_def_id = ty_def_id.expect_local();
30 let crate_map = tcx.crate_inherent_impls(());
31 match crate_map.inherent_impls.get(&ty_def_id) {
37 struct InherentCollect<'tcx> {
39 impls_map: CrateInherentImpls,
42 impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
43 fn visit_item(&mut self, item: &hir::Item<'_>) {
44 let (ty, assoc_items) = match item.kind {
45 hir::ItemKind::Impl(hir::Impl { of_trait: None, ref self_ty, items, .. }) => {
51 let self_ty = self.tcx.type_of(item.def_id);
52 let lang_items = self.tcx.lang_items();
53 match *self_ty.kind() {
55 self.check_def_id(item, def.did);
58 self.check_def_id(item, did);
60 ty::Dynamic(ref data, ..) if data.principal_def_id().is_some() => {
61 self.check_def_id(item, data.principal_def_id().unwrap());
64 self.check_primitive_impl(
66 lang_items.bool_impl(),
75 self.check_primitive_impl(
77 lang_items.char_impl(),
86 self.check_primitive_impl(
88 lang_items.str_impl(),
89 lang_items.str_alloc_impl(),
96 ty::Slice(slice_item) if slice_item == self.tcx.types.u8 => {
97 self.check_primitive_impl(
99 lang_items.slice_u8_impl(),
100 lang_items.slice_u8_alloc_impl(),
108 self.check_primitive_impl(
110 lang_items.slice_impl(),
111 lang_items.slice_alloc_impl(),
119 self.check_primitive_impl(
121 lang_items.array_impl(),
129 ty::RawPtr(ty::TypeAndMut { ty: inner, mutbl: hir::Mutability::Not })
130 if matches!(inner.kind(), ty::Slice(_)) =>
132 self.check_primitive_impl(
134 lang_items.const_slice_ptr_impl(),
142 ty::RawPtr(ty::TypeAndMut { ty: inner, mutbl: hir::Mutability::Mut })
143 if matches!(inner.kind(), ty::Slice(_)) =>
145 self.check_primitive_impl(
147 lang_items.mut_slice_ptr_impl(),
155 ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::Mutability::Not }) => {
156 self.check_primitive_impl(
158 lang_items.const_ptr_impl(),
166 ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::Mutability::Mut }) => {
167 self.check_primitive_impl(
169 lang_items.mut_ptr_impl(),
177 ty::Int(ty::IntTy::I8) => {
178 self.check_primitive_impl(
180 lang_items.i8_impl(),
188 ty::Int(ty::IntTy::I16) => {
189 self.check_primitive_impl(
191 lang_items.i16_impl(),
199 ty::Int(ty::IntTy::I32) => {
200 self.check_primitive_impl(
202 lang_items.i32_impl(),
210 ty::Int(ty::IntTy::I64) => {
211 self.check_primitive_impl(
213 lang_items.i64_impl(),
221 ty::Int(ty::IntTy::I128) => {
222 self.check_primitive_impl(
224 lang_items.i128_impl(),
232 ty::Int(ty::IntTy::Isize) => {
233 self.check_primitive_impl(
235 lang_items.isize_impl(),
243 ty::Uint(ty::UintTy::U8) => {
244 self.check_primitive_impl(
246 lang_items.u8_impl(),
254 ty::Uint(ty::UintTy::U16) => {
255 self.check_primitive_impl(
257 lang_items.u16_impl(),
265 ty::Uint(ty::UintTy::U32) => {
266 self.check_primitive_impl(
268 lang_items.u32_impl(),
276 ty::Uint(ty::UintTy::U64) => {
277 self.check_primitive_impl(
279 lang_items.u64_impl(),
287 ty::Uint(ty::UintTy::U128) => {
288 self.check_primitive_impl(
290 lang_items.u128_impl(),
298 ty::Uint(ty::UintTy::Usize) => {
299 self.check_primitive_impl(
301 lang_items.usize_impl(),
309 ty::Float(ty::FloatTy::F32) => {
310 self.check_primitive_impl(
312 lang_items.f32_impl(),
313 lang_items.f32_runtime_impl(),
320 ty::Float(ty::FloatTy::F64) => {
321 self.check_primitive_impl(
323 lang_items.f64_impl(),
324 lang_items.f64_runtime_impl(),
333 let mut err = struct_span_err!(
337 "no nominal type found for inherent implementation"
340 err.span_label(ty.span, "impl requires a nominal type")
341 .note("either implement a trait on it or create a newtype to wrap it instead");
343 if let ty::Ref(_, subty, _) = self_ty.kind() {
345 "you could also try moving the reference to \
346 uses of `{}` (such as `self`) within the implementation",
356 fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {}
358 fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {}
360 fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'_>) {}
363 impl InherentCollect<'tcx> {
364 fn check_def_id(&mut self, item: &hir::Item<'_>, def_id: DefId) {
365 if let Some(def_id) = def_id.as_local() {
366 // Add the implementation to the mapping from implementation to base
367 // type def ID, if there is a base type for this implementation and
368 // the implementation does not have any associated traits.
369 let vec = self.impls_map.inherent_impls.entry(def_id).or_default();
370 vec.push(item.def_id.to_def_id());
376 "cannot define inherent `impl` for a type outside of the crate \
377 where the type is defined"
379 .span_label(item.span, "impl for type defined outside of crate.")
380 .note("define and implement a trait or new type instead")
385 fn check_primitive_impl(
387 impl_def_id: LocalDefId,
388 lang_def_id: Option<DefId>,
389 lang_def_id2: Option<DefId>,
393 assoc_items: &[hir::ImplItemRef<'_>],
395 match (lang_def_id, lang_def_id2) {
396 (Some(lang_def_id), _) if lang_def_id == impl_def_id.to_def_id() => {
399 (_, Some(lang_def_id)) if lang_def_id == impl_def_id.to_def_id() => {
403 let to_implement = if assoc_items.len() == 0 {
406 let plural = assoc_items.len() > 1;
407 let assoc_items_kind = {
408 let item_types = assoc_items.iter().map(|x| x.kind);
409 if item_types.clone().all(|x| x == hir::AssocItemKind::Const) {
413 .all(|x| matches! {x, hir::AssocItemKind::Fn{ .. } })
422 " to implement {} {}{}",
423 if plural { "these" } else { "this" },
425 if plural { "s" } else { "" }
433 "only a single inherent implementation marked with `#[lang = \
434 \"{}\"]` is allowed for the `{}` primitive",
438 .help(&format!("consider using a trait{}", to_implement))