]>
Commit | Line | Data |
---|---|---|
3b2f2976 XL |
1 | //! Helper functions corresponding to lifetime errors due to |
2 | //! anonymous regions. | |
b7449926 | 3 | |
9fa01778 | 4 | use crate::infer::error_reporting::nice_region_error::NiceRegionError; |
dfeec247 | 5 | use rustc_hir as hir; |
f035d41b | 6 | use rustc_hir::def_id::LocalDefId; |
ba9703b0 | 7 | use rustc_middle::ty::{self, DefIdTree, Region, Ty}; |
dfeec247 | 8 | use rustc_span::Span; |
3b2f2976 | 9 | |
3dfed10e | 10 | /// Information about the anonymous region we are searching for. |
ea8adc8c | 11 | #[derive(Debug)] |
e1599b0c | 12 | pub(super) struct AnonymousParamInfo<'tcx> { |
3dfed10e | 13 | /// The parameter corresponding to the anonymous region. |
dfeec247 | 14 | pub param: &'tcx hir::Param<'tcx>, |
3dfed10e | 15 | /// The type corresponding to the anonymous region parameter. |
e1599b0c | 16 | pub param_ty: Ty<'tcx>, |
fc512014 XL |
17 | /// The ty::BoundRegionKind corresponding to the anonymous region. |
18 | pub bound_region: ty::BoundRegionKind, | |
3dfed10e | 19 | /// The `Span` of the parameter type. |
dfeec247 | 20 | pub param_ty_span: Span, |
3dfed10e | 21 | /// Signals that the argument is the first parameter in the declaration. |
3b2f2976 XL |
22 | pub is_first: bool, |
23 | } | |
24 | ||
dc9dc135 | 25 | impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { |
e1599b0c | 26 | // This method walks the Type of the function body parameters using |
3b2f2976 | 27 | // `fold_regions()` function and returns the |
e1599b0c | 28 | // &hir::Param of the function parameter corresponding to the anonymous |
3b2f2976 XL |
29 | // region and the Ty corresponding to the named region. |
30 | // Currently only the case where the function declaration consists of | |
31 | // one named region and one anonymous region is handled. | |
32 | // Consider the example `fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32` | |
e1599b0c | 33 | // Here, we would return the hir::Param for y, we return the type &'a |
3b2f2976 XL |
34 | // i32, which is the type of y but with the anonymous region replaced |
35 | // with 'a, the corresponding bound region and is_first which is true if | |
e1599b0c XL |
36 | // the hir::Param is the first parameter in the function declaration. |
37 | pub(super) fn find_param_with_region( | |
ff7c6d11 XL |
38 | &self, |
39 | anon_region: Region<'tcx>, | |
40 | replace_region: Region<'tcx>, | |
e1599b0c | 41 | ) -> Option<AnonymousParamInfo<'_>> { |
ea8adc8c XL |
42 | let (id, bound_region) = match *anon_region { |
43 | ty::ReFree(ref free_region) => (free_region.scope, free_region.bound_region), | |
48663c56 | 44 | ty::ReEarlyBound(ebr) => ( |
532ac7d7 | 45 | self.tcx().parent(ebr.def_id).unwrap(), |
fc512014 | 46 | ty::BoundRegionKind::BrNamed(ebr.def_id, ebr.name), |
ff7c6d11 | 47 | ), |
ea8adc8c XL |
48 | _ => return None, // not a free region |
49 | }; | |
50 | ||
9fa01778 | 51 | let hir = &self.tcx().hir(); |
3dfed10e | 52 | let hir_id = hir.local_def_id_to_hir_id(id.as_local()?); |
ba9703b0 XL |
53 | let body_id = hir.maybe_body_owned_by(hir_id)?; |
54 | let body = hir.body(body_id); | |
55 | let owner_id = hir.body_owner(body_id); | |
56 | let fn_decl = hir.fn_decl_by_hir_id(owner_id).unwrap(); | |
57 | let poly_fn_sig = self.tcx().fn_sig(id); | |
fc512014 | 58 | let fn_sig = self.tcx().liberate_late_bound_regions(id, poly_fn_sig); |
136023e0 XL |
59 | body.params |
60 | .iter() | |
61 | .take(if fn_sig.c_variadic { | |
62 | fn_sig.inputs().len() | |
63 | } else { | |
64 | assert_eq!(fn_sig.inputs().len(), body.params.len()); | |
65 | body.params.len() | |
66 | }) | |
67 | .enumerate() | |
68 | .find_map(|(index, param)| { | |
69 | // May return None; sometimes the tables are not yet populated. | |
70 | let ty = fn_sig.inputs()[index]; | |
71 | let mut found_anon_region = false; | |
72 | let new_param_ty = self.tcx().fold_regions(ty, &mut false, |r, _| { | |
73 | if *r == *anon_region { | |
74 | found_anon_region = true; | |
75 | replace_region | |
76 | } else { | |
77 | r | |
78 | } | |
79 | }); | |
80 | if found_anon_region { | |
81 | let ty_hir_id = fn_decl.inputs[index].hir_id; | |
82 | let param_ty_span = hir.span(ty_hir_id); | |
83 | let is_first = index == 0; | |
84 | Some(AnonymousParamInfo { | |
85 | param, | |
86 | param_ty: new_param_ty, | |
87 | param_ty_span, | |
88 | bound_region, | |
89 | is_first, | |
90 | }) | |
3b2f2976 | 91 | } else { |
136023e0 | 92 | None |
3b2f2976 | 93 | } |
136023e0 | 94 | }) |
3b2f2976 XL |
95 | } |
96 | ||
29967ef6 XL |
97 | pub(super) fn future_return_type( |
98 | &self, | |
99 | local_def_id: LocalDefId, | |
100 | ) -> Option<&rustc_hir::Ty<'_>> { | |
101 | if let Some(hir::IsAsync::Async) = self.asyncness(local_def_id) { | |
102 | if let rustc_middle::ty::Opaque(def_id, _) = | |
103 | self.tcx().type_of(local_def_id).fn_sig(self.tcx()).output().skip_binder().kind() | |
104 | { | |
105 | match self.tcx().hir().get_if_local(*def_id) { | |
106 | Some(hir::Node::Item(hir::Item { | |
107 | kind: | |
108 | hir::ItemKind::OpaqueTy(hir::OpaqueTy { | |
109 | bounds, | |
a2a8927a | 110 | origin: hir::OpaqueTyOrigin::AsyncFn(..), |
29967ef6 XL |
111 | .. |
112 | }), | |
113 | .. | |
114 | })) => { | |
115 | for b in bounds.iter() { | |
116 | if let hir::GenericBound::LangItemTrait( | |
117 | hir::LangItem::Future, | |
118 | _span, | |
119 | _hir_id, | |
120 | generic_args, | |
121 | ) = b | |
122 | { | |
123 | for type_binding in generic_args.bindings.iter() { | |
124 | if type_binding.ident.name == rustc_span::sym::Output { | |
125 | if let hir::TypeBindingKind::Equality { ty } = | |
126 | type_binding.kind | |
127 | { | |
128 | return Some(ty); | |
129 | } | |
130 | } | |
131 | } | |
132 | } | |
133 | } | |
134 | } | |
135 | _ => {} | |
136 | } | |
137 | } | |
138 | } | |
139 | None | |
140 | } | |
141 | ||
142 | pub(super) fn asyncness(&self, local_def_id: LocalDefId) -> Option<hir::IsAsync> { | |
fc512014 | 143 | // similar to the asyncness fn in rustc_ty_utils::ty |
29967ef6 XL |
144 | let hir_id = self.tcx().hir().local_def_id_to_hir_id(local_def_id); |
145 | let node = self.tcx().hir().get(hir_id); | |
3c0e092e XL |
146 | let fn_kind = node.fn_kind()?; |
147 | Some(fn_kind.asyncness()) | |
29967ef6 XL |
148 | } |
149 | ||
3b2f2976 XL |
150 | // Here, we check for the case where the anonymous region |
151 | // is in the return type. | |
152 | // FIXME(#42703) - Need to handle certain cases here. | |
ff7c6d11 XL |
153 | pub(super) fn is_return_type_anon( |
154 | &self, | |
f035d41b | 155 | scope_def_id: LocalDefId, |
fc512014 | 156 | br: ty::BoundRegionKind, |
dfeec247 | 157 | decl: &hir::FnDecl<'_>, |
ff7c6d11 | 158 | ) -> Option<Span> { |
9fa01778 | 159 | let ret_ty = self.tcx().type_of(scope_def_id); |
1b1a35ee | 160 | if let ty::FnDef(_, _) = ret_ty.kind() { |
9fa01778 | 161 | let sig = ret_ty.fn_sig(self.tcx()); |
dfeec247 XL |
162 | let late_bound_regions = |
163 | self.tcx().collect_referenced_late_bound_regions(&sig.output()); | |
0bf4aa26 XL |
164 | if late_bound_regions.iter().any(|r| *r == br) { |
165 | return Some(decl.output.span()); | |
3b2f2976 | 166 | } |
3b2f2976 | 167 | } |
ea8adc8c | 168 | None |
3b2f2976 | 169 | } |
8faf50e0 | 170 | |
3b2f2976 XL |
171 | // Here we check for the case where anonymous region |
172 | // corresponds to self and if yes, we display E0312. | |
173 | // FIXME(#42700) - Need to format self properly to | |
174 | // enable E0621 for it. | |
f035d41b | 175 | pub(super) fn is_self_anon(&self, is_first: bool, scope_def_id: LocalDefId) -> bool { |
ff7c6d11 | 176 | is_first |
f035d41b XL |
177 | && self |
178 | .tcx() | |
179 | .opt_associated_item(scope_def_id.to_def_id()) | |
180 | .map(|i| i.fn_has_self_parameter) | |
dfeec247 | 181 | == Some(true) |
3b2f2976 | 182 | } |
3b2f2976 | 183 | } |