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::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
13 use rustc_hir::itemlikevisit::ItemLikeVisitor;
14 use rustc_middle::ty::{self, CrateInherentImpls, TyCtxt};
19 /// On-demand query: yields a map containing all types mapped to their inherent impls.
20 pub fn crate_inherent_impls(tcx: TyCtxt<'_>, crate_num: CrateNum) -> CrateInherentImpls {
21 assert_eq!(crate_num, LOCAL_CRATE);
23 let krate = tcx.hir().krate();
24 let mut collect = InherentCollect { tcx, impls_map: Default::default() };
25 krate.visit_all_item_likes(&mut collect);
29 /// On-demand query: yields a vector of the inherent impls for a specific type.
30 pub fn inherent_impls(tcx: TyCtxt<'_>, ty_def_id: DefId) -> &[DefId] {
31 assert!(ty_def_id.is_local());
33 let crate_map = tcx.crate_inherent_impls(ty_def_id.krate);
34 match crate_map.inherent_impls.get(&ty_def_id) {
40 struct InherentCollect<'tcx> {
42 impls_map: CrateInherentImpls,
45 impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
46 fn visit_item(&mut self, item: &hir::Item<'_>) {
47 let ty = match item.kind {
48 hir::ItemKind::Impl { of_trait: None, ref self_ty, .. } => self_ty,
52 let def_id = self.tcx.hir().local_def_id(item.hir_id);
53 let self_ty = self.tcx.type_of(def_id);
54 let lang_items = self.tcx.lang_items();
57 self.check_def_id(item, def.did);
60 self.check_def_id(item, did);
62 ty::Dynamic(ref data, ..) if data.principal_def_id().is_some() => {
63 self.check_def_id(item, data.principal_def_id().unwrap());
66 self.check_primitive_impl(
68 lang_items.bool_impl(),
76 self.check_primitive_impl(
78 lang_items.char_impl(),
86 self.check_primitive_impl(
88 lang_items.str_impl(),
89 lang_items.str_alloc_impl(),
95 ty::Slice(slice_item) if slice_item == self.tcx.types.u8 => {
96 self.check_primitive_impl(
98 lang_items.slice_u8_impl(),
99 lang_items.slice_u8_alloc_impl(),
106 self.check_primitive_impl(
108 lang_items.slice_impl(),
109 lang_items.slice_alloc_impl(),
116 self.check_primitive_impl(
118 lang_items.array_impl(),
125 ty::RawPtr(ty::TypeAndMut { ty: inner, mutbl: hir::Mutability::Not })
126 if matches!(inner.kind, ty::Slice(_)) =>
128 self.check_primitive_impl(
130 lang_items.const_slice_ptr_impl(),
137 ty::RawPtr(ty::TypeAndMut { ty: inner, mutbl: hir::Mutability::Mut })
138 if matches!(inner.kind, ty::Slice(_)) =>
140 self.check_primitive_impl(
142 lang_items.mut_slice_ptr_impl(),
149 ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::Mutability::Not }) => {
150 self.check_primitive_impl(
152 lang_items.const_ptr_impl(),
159 ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::Mutability::Mut }) => {
160 self.check_primitive_impl(
162 lang_items.mut_ptr_impl(),
169 ty::Int(ast::IntTy::I8) => {
170 self.check_primitive_impl(
172 lang_items.i8_impl(),
179 ty::Int(ast::IntTy::I16) => {
180 self.check_primitive_impl(
182 lang_items.i16_impl(),
189 ty::Int(ast::IntTy::I32) => {
190 self.check_primitive_impl(
192 lang_items.i32_impl(),
199 ty::Int(ast::IntTy::I64) => {
200 self.check_primitive_impl(
202 lang_items.i64_impl(),
209 ty::Int(ast::IntTy::I128) => {
210 self.check_primitive_impl(
212 lang_items.i128_impl(),
219 ty::Int(ast::IntTy::Isize) => {
220 self.check_primitive_impl(
222 lang_items.isize_impl(),
229 ty::Uint(ast::UintTy::U8) => {
230 self.check_primitive_impl(
232 lang_items.u8_impl(),
239 ty::Uint(ast::UintTy::U16) => {
240 self.check_primitive_impl(
242 lang_items.u16_impl(),
249 ty::Uint(ast::UintTy::U32) => {
250 self.check_primitive_impl(
252 lang_items.u32_impl(),
259 ty::Uint(ast::UintTy::U64) => {
260 self.check_primitive_impl(
262 lang_items.u64_impl(),
269 ty::Uint(ast::UintTy::U128) => {
270 self.check_primitive_impl(
272 lang_items.u128_impl(),
279 ty::Uint(ast::UintTy::Usize) => {
280 self.check_primitive_impl(
282 lang_items.usize_impl(),
289 ty::Float(ast::FloatTy::F32) => {
290 self.check_primitive_impl(
292 lang_items.f32_impl(),
293 lang_items.f32_runtime_impl(),
299 ty::Float(ast::FloatTy::F64) => {
300 self.check_primitive_impl(
302 lang_items.f64_impl(),
303 lang_items.f64_runtime_impl(),
315 "no base type found for inherent implementation"
317 .span_label(ty.span, "impl requires a base type")
319 "either implement a trait on it or create a newtype \
327 fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {}
329 fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {}
332 impl InherentCollect<'tcx> {
333 fn check_def_id(&mut self, item: &hir::Item<'_>, def_id: DefId) {
334 if def_id.is_local() {
335 // Add the implementation to the mapping from implementation to base
336 // type def ID, if there is a base type for this implementation and
337 // the implementation does not have any associated traits.
338 let impl_def_id = self.tcx.hir().local_def_id(item.hir_id);
339 let vec = self.impls_map.inherent_impls.entry(def_id).or_default();
340 vec.push(impl_def_id.to_def_id());
346 "cannot define inherent `impl` for a type outside of the crate \
347 where the type is defined"
349 .span_label(item.span, "impl for type defined outside of crate.")
350 .note("define and implement a trait or new type instead")
355 fn check_primitive_impl(
357 impl_def_id: LocalDefId,
358 lang_def_id: Option<DefId>,
359 lang_def_id2: Option<DefId>,
364 match (lang_def_id, lang_def_id2) {
365 (Some(lang_def_id), _) if lang_def_id == impl_def_id.to_def_id() => {
368 (_, Some(lang_def_id)) if lang_def_id == impl_def_id.to_def_id() => {
376 "only a single inherent implementation marked with `#[lang = \
377 \"{}\"]` is allowed for the `{}` primitive",
381 .span_help(span, "consider using a trait to implement these methods")