|
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