|
1 | | -use rustc_hir::{def::DefKind, def_id::DefId}; |
| 1 | +use rustc_hir as hir; |
| 2 | +use rustc_hir::def::DefKind; |
| 3 | +use rustc_hir::def_id::LocalDefId; |
2 | 4 | use rustc_middle::query::Providers; |
3 | 5 | use rustc_middle::ty::{self, Ty, TyCtxt}; |
| 6 | +use rustc_span::Span; |
| 7 | +use std::iter; |
4 | 8 |
|
5 | 9 | pub fn provide(providers: &mut Providers) { |
6 | 10 | *providers = Providers { assumed_wf_types, ..*providers }; |
7 | 11 | } |
8 | 12 |
|
9 | | -fn assumed_wf_types(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::List<Ty<'_>> { |
| 13 | +fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<'tcx>, Span)] { |
10 | 14 | match tcx.def_kind(def_id) { |
11 | 15 | DefKind::Fn => { |
12 | 16 | let sig = tcx.fn_sig(def_id).subst_identity(); |
13 | | - let liberated_sig = tcx.liberate_late_bound_regions(def_id, sig); |
14 | | - liberated_sig.inputs_and_output |
| 17 | + let liberated_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), sig); |
| 18 | + tcx.arena.alloc_from_iter(itertools::zip_eq( |
| 19 | + liberated_sig.inputs_and_output, |
| 20 | + fn_sig_spans(tcx, def_id), |
| 21 | + )) |
15 | 22 | } |
16 | 23 | DefKind::AssocFn => { |
17 | 24 | let sig = tcx.fn_sig(def_id).subst_identity(); |
18 | | - let liberated_sig = tcx.liberate_late_bound_regions(def_id, sig); |
| 25 | + let liberated_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), sig); |
19 | 26 | let mut assumed_wf_types: Vec<_> = |
20 | | - tcx.assumed_wf_types(tcx.parent(def_id)).as_slice().into(); |
21 | | - assumed_wf_types.extend(liberated_sig.inputs_and_output); |
22 | | - tcx.mk_type_list(&assumed_wf_types) |
| 27 | + tcx.assumed_wf_types(tcx.local_parent(def_id)).into(); |
| 28 | + assumed_wf_types.extend(itertools::zip_eq( |
| 29 | + liberated_sig.inputs_and_output, |
| 30 | + fn_sig_spans(tcx, def_id), |
| 31 | + )); |
| 32 | + tcx.arena.alloc_slice(&assumed_wf_types) |
23 | 33 | } |
24 | 34 | DefKind::Impl { .. } => { |
25 | | - match tcx.impl_trait_ref(def_id) { |
26 | | - Some(trait_ref) => { |
27 | | - let types: Vec<_> = trait_ref.skip_binder().substs.types().collect(); |
28 | | - tcx.mk_type_list(&types) |
29 | | - } |
30 | | - // Only the impl self type |
31 | | - None => tcx.mk_type_list(&[tcx.type_of(def_id).subst_identity()]), |
32 | | - } |
| 35 | + // Trait arguments and the self type for trait impls or only the self type for |
| 36 | + // inherent impls. |
| 37 | + let tys = match tcx.impl_trait_ref(def_id) { |
| 38 | + Some(trait_ref) => trait_ref.skip_binder().substs.types().collect(), |
| 39 | + None => vec![tcx.type_of(def_id).subst_identity()], |
| 40 | + }; |
| 41 | + |
| 42 | + let mut impl_spans = impl_spans(tcx, def_id); |
| 43 | + tcx.arena.alloc_from_iter(tys.into_iter().map(|ty| (ty, impl_spans.next().unwrap()))) |
33 | 44 | } |
34 | | - DefKind::AssocConst | DefKind::AssocTy => tcx.assumed_wf_types(tcx.parent(def_id)), |
35 | | - DefKind::OpaqueTy => match tcx.def_kind(tcx.parent(def_id)) { |
| 45 | + DefKind::AssocConst | DefKind::AssocTy => tcx.assumed_wf_types(tcx.local_parent(def_id)), |
| 46 | + DefKind::OpaqueTy => match tcx.def_kind(tcx.local_parent(def_id)) { |
36 | 47 | DefKind::TyAlias => ty::List::empty(), |
37 | | - DefKind::AssocTy => tcx.assumed_wf_types(tcx.parent(def_id)), |
| 48 | + DefKind::AssocTy => tcx.assumed_wf_types(tcx.local_parent(def_id)), |
38 | 49 | // Nested opaque types only occur in associated types: |
39 | 50 | // ` type Opaque<T> = impl Trait<&'static T, AssocTy = impl Nested>; ` |
40 | 51 | // assumed_wf_types should include those of `Opaque<T>`, `Opaque<T>` itself |
41 | 52 | // and `&'static T`. |
42 | | - DefKind::OpaqueTy => bug!("unimplemented implied bounds for neseted opaque types"), |
| 53 | + DefKind::OpaqueTy => bug!("unimplemented implied bounds for nested opaque types"), |
43 | 54 | def_kind @ _ => { |
44 | 55 | bug!("unimplemented implied bounds for opaque types with parent {def_kind:?}") |
45 | 56 | } |
@@ -72,3 +83,28 @@ fn assumed_wf_types(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::List<Ty<'_>> { |
72 | 83 | | DefKind::Generator => ty::List::empty(), |
73 | 84 | } |
74 | 85 | } |
| 86 | + |
| 87 | +fn fn_sig_spans(tcx: TyCtxt<'_>, def_id: LocalDefId) -> impl Iterator<Item = Span> + '_ { |
| 88 | + let node = tcx.hir().get(tcx.local_def_id_to_hir_id(def_id)); |
| 89 | + if let Some(decl) = node.fn_decl() { |
| 90 | + decl.inputs.iter().map(|ty| ty.span).chain(iter::once(decl.output.span())) |
| 91 | + } else { |
| 92 | + bug!("unexpected item for fn {def_id:?}: {node:?}") |
| 93 | + } |
| 94 | +} |
| 95 | + |
| 96 | +fn impl_spans(tcx: TyCtxt<'_>, def_id: LocalDefId) -> impl Iterator<Item = Span> + '_ { |
| 97 | + let item = tcx.hir().expect_item(def_id); |
| 98 | + if let hir::ItemKind::Impl(impl_) = item.kind { |
| 99 | + let trait_args = impl_ |
| 100 | + .of_trait |
| 101 | + .into_iter() |
| 102 | + .flat_map(|trait_ref| trait_ref.path.segments.last().unwrap().args().args) |
| 103 | + .map(|arg| arg.span()); |
| 104 | + let dummy_spans_for_default_args = |
| 105 | + impl_.of_trait.into_iter().flat_map(|trait_ref| iter::repeat(trait_ref.path.span)); |
| 106 | + iter::once(impl_.self_ty.span).chain(trait_args).chain(dummy_spans_for_default_args) |
| 107 | + } else { |
| 108 | + bug!("unexpected item for impl {def_id:?}: {item:?}") |
| 109 | + } |
| 110 | +} |
0 commit comments