]>
Commit | Line | Data |
---|---|---|
ea8adc8c XL |
1 | //! "Collection" is the process of determining the type and other external |
2 | //! details of each item in Rust. Collection is specifically concerned | |
dc9dc135 | 3 | //! with *inter-procedural* things -- for example, for a function |
ea8adc8c XL |
4 | //! definition, collection will figure out the type and signature of the |
5 | //! function, but it will not visit the *body* of the function in any way, | |
6 | //! nor examine type annotations on local variables (that's the job of | |
7 | //! type *checking*). | |
8 | //! | |
9 | //! Collecting is ultimately defined by a bundle of queries that | |
10 | //! inquire after various facts about the items in the crate (e.g., | |
11 | //! `type_of`, `generics_of`, `predicates_of`, etc). See the `provide` function | |
12 | //! for the full set. | |
13 | //! | |
14 | //! At present, however, we do run collection across all items in the | |
15 | //! crate as a kind of pass. This should eventually be factored away. | |
85aaf69f | 16 | |
c295e0f8 | 17 | use crate::astconv::AstConv; |
3dfed10e | 18 | use crate::bounds::Bounds; |
e74abb32 | 19 | use crate::check::intrinsic::intrinsic_operation_unsafety; |
dfeec247 | 20 | use crate::constrained_generic_params as cgp; |
1b1a35ee | 21 | use crate::errors; |
9fa01778 | 22 | use crate::middle::resolve_lifetime as rl; |
3dfed10e | 23 | use rustc_ast as ast; |
94222f64 | 24 | use rustc_ast::Attribute; |
29967ef6 XL |
25 | use rustc_ast::{MetaItemKind, NestedMetaItem}; |
26 | use rustc_attr::{list_contains_name, InlineAttr, InstructionSetAttr, OptimizeAttr}; | |
dfeec247 | 27 | use rustc_data_structures::captures::Captures; |
3dfed10e | 28 | use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; |
74b04a01 | 29 | use rustc_errors::{struct_span_err, Applicability}; |
dfeec247 XL |
30 | use rustc_hir as hir; |
31 | use rustc_hir::def::{CtorKind, DefKind, Res}; | |
f9f354fc | 32 | use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE}; |
dfeec247 | 33 | use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; |
ba9703b0 | 34 | use rustc_hir::weak_lang_items; |
3dfed10e | 35 | use rustc_hir::{GenericParamKind, HirId, Node}; |
ba9703b0 XL |
36 | use rustc_middle::hir::map::Map; |
37 | use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; | |
38 | use rustc_middle::mir::mono::Linkage; | |
39 | use rustc_middle::ty::query::Providers; | |
f035d41b | 40 | use rustc_middle::ty::subst::InternalSubsts; |
ba9703b0 XL |
41 | use rustc_middle::ty::util::Discr; |
42 | use rustc_middle::ty::util::IntTypeExt; | |
c295e0f8 | 43 | use rustc_middle::ty::{self, AdtKind, Const, DefIdTree, Ty, TyCtxt}; |
ba9703b0 XL |
44 | use rustc_middle::ty::{ReprOptions, ToPredicate, WithConstness}; |
45 | use rustc_session::lint; | |
46 | use rustc_session::parse::feature_err; | |
f9f354fc | 47 | use rustc_span::symbol::{kw, sym, Ident, Symbol}; |
dfeec247 | 48 | use rustc_span::{Span, DUMMY_SP}; |
c295e0f8 | 49 | use rustc_target::spec::{abi, PanicStrategy, SanitizerSet}; |
ba9703b0 | 50 | use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName; |
cdc7bbd5 | 51 | use std::iter; |
74b04a01 | 52 | |
29967ef6 | 53 | mod item_bounds; |
74b04a01 | 54 | mod type_of; |
dc9dc135 | 55 | |
a1dfa0c6 XL |
56 | struct OnlySelfBounds(bool); |
57 | ||
1a4d82fc JJ |
58 | /////////////////////////////////////////////////////////////////////////// |
59 | // Main entry point | |
60 | ||
f035d41b | 61 | fn collect_mod_item_types(tcx: TyCtxt<'_>, module_def_id: LocalDefId) { |
0731742a XL |
62 | tcx.hir().visit_item_likes_in_module( |
63 | module_def_id, | |
dfeec247 | 64 | &mut CollectItemTypesVisitor { tcx }.as_deep_visitor(), |
0731742a | 65 | ); |
8bb4bdeb XL |
66 | } |
67 | ||
f035d41b | 68 | pub fn provide(providers: &mut Providers) { |
8bb4bdeb | 69 | *providers = Providers { |
3dfed10e | 70 | opt_const_param_of: type_of::opt_const_param_of, |
94222f64 | 71 | default_anon_const_substs: type_of::default_anon_const_substs, |
74b04a01 | 72 | type_of: type_of::type_of, |
29967ef6 XL |
73 | item_bounds: item_bounds::item_bounds, |
74 | explicit_item_bounds: item_bounds::explicit_item_bounds, | |
7cac9316 XL |
75 | generics_of, |
76 | predicates_of, | |
8faf50e0 | 77 | predicates_defined_on, |
83c7162d | 78 | explicit_predicates_of, |
7cac9316 | 79 | super_predicates_of, |
6a06907d | 80 | super_predicates_that_define_assoc_type, |
29967ef6 | 81 | trait_explicit_predicates_and_bounds, |
8bb4bdeb XL |
82 | type_param_predicates, |
83 | trait_def, | |
84 | adt_def, | |
041b39d2 | 85 | fn_sig, |
8bb4bdeb | 86 | impl_trait_ref, |
cc61c64b XL |
87 | impl_polarity, |
88 | is_foreign_item, | |
48663c56 | 89 | static_mutability, |
74b04a01 | 90 | generator_kind, |
94b46f34 | 91 | codegen_fn_attrs, |
0731742a | 92 | collect_mod_item_types, |
136023e0 | 93 | should_inherit_track_caller, |
8bb4bdeb XL |
94 | ..*providers |
95 | }; | |
1a4d82fc JJ |
96 | } |
97 | ||
98 | /////////////////////////////////////////////////////////////////////////// | |
99 | ||
c34b1796 | 100 | /// Context specific to some particular item. This is what implements |
9fa01778 | 101 | /// `AstConv`. It has information about the predicates that are defined |
c34b1796 AL |
102 | /// on the trait. Unfortunately, this predicate information is |
103 | /// available in various different forms at various points in the | |
0731742a | 104 | /// process. So we can't just store a pointer to e.g., the AST or the |
c34b1796 | 105 | /// parsed ty form, we have to be more flexible. To this end, the |
8bb4bdeb XL |
106 | /// `ItemCtxt` is parameterized by a `DefId` that it uses to satisfy |
107 | /// `get_type_parameter_bounds` requests, drawing the information from | |
108 | /// the AST (`hir::Generics`), recursively. | |
dc9dc135 XL |
109 | pub struct ItemCtxt<'tcx> { |
110 | tcx: TyCtxt<'tcx>, | |
8bb4bdeb | 111 | item_def_id: DefId, |
1a4d82fc JJ |
112 | } |
113 | ||
114 | /////////////////////////////////////////////////////////////////////////// | |
1a4d82fc | 115 | |
dfeec247 XL |
116 | #[derive(Default)] |
117 | crate struct PlaceholderHirTyCollector(crate Vec<Span>); | |
118 | ||
119 | impl<'v> Visitor<'v> for PlaceholderHirTyCollector { | |
ba9703b0 | 120 | type Map = intravisit::ErasedMap<'v>; |
dfeec247 | 121 | |
ba9703b0 | 122 | fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> { |
dfeec247 XL |
123 | NestedVisitorMap::None |
124 | } | |
125 | fn visit_ty(&mut self, t: &'v hir::Ty<'v>) { | |
126 | if let hir::TyKind::Infer = t.kind { | |
127 | self.0.push(t.span); | |
128 | } | |
129 | intravisit::walk_ty(self, t) | |
130 | } | |
94222f64 XL |
131 | fn visit_generic_arg(&mut self, generic_arg: &'v hir::GenericArg<'v>) { |
132 | match generic_arg { | |
133 | hir::GenericArg::Infer(inf) => { | |
134 | self.0.push(inf.span); | |
135 | intravisit::walk_inf(self, inf); | |
136 | } | |
137 | hir::GenericArg::Type(t) => self.visit_ty(t), | |
138 | _ => {} | |
139 | } | |
140 | } | |
dfeec247 XL |
141 | } |
142 | ||
dc9dc135 XL |
143 | struct CollectItemTypesVisitor<'tcx> { |
144 | tcx: TyCtxt<'tcx>, | |
1a4d82fc JJ |
145 | } |
146 | ||
dfeec247 XL |
147 | /// If there are any placeholder types (`_`), emit an error explaining that this is not allowed |
148 | /// and suggest adding type parameters in the appropriate place, taking into consideration any and | |
149 | /// all already existing generic type parameters to avoid suggesting a name that is already in use. | |
150 | crate fn placeholder_type_error( | |
151 | tcx: TyCtxt<'tcx>, | |
3dfed10e | 152 | span: Option<Span>, |
dfeec247 XL |
153 | generics: &[hir::GenericParam<'_>], |
154 | placeholder_types: Vec<Span>, | |
155 | suggest: bool, | |
6a06907d | 156 | hir_ty: Option<&hir::Ty<'_>>, |
136023e0 | 157 | kind: &'static str, |
dfeec247 XL |
158 | ) { |
159 | if placeholder_types.is_empty() { | |
160 | return; | |
161 | } | |
dfeec247 | 162 | |
3dfed10e | 163 | let type_name = generics.next_type_param_name(None); |
dfeec247 | 164 | let mut sugg: Vec<_> = |
74b04a01 | 165 | placeholder_types.iter().map(|sp| (*sp, (*type_name).to_string())).collect(); |
3dfed10e | 166 | |
dfeec247 | 167 | if generics.is_empty() { |
3dfed10e XL |
168 | if let Some(span) = span { |
169 | sugg.push((span, format!("<{}>", type_name))); | |
170 | } | |
5869c6ff XL |
171 | } else if let Some(arg) = generics |
172 | .iter() | |
173 | .find(|arg| matches!(arg.name, hir::ParamName::Plain(Ident { name: kw::Underscore, .. }))) | |
174 | { | |
dfeec247 XL |
175 | // Account for `_` already present in cases like `struct S<_>(_);` and suggest |
176 | // `struct S<T>(T);` instead of `struct S<_, T>(T);`. | |
74b04a01 | 177 | sugg.push((arg.span, (*type_name).to_string())); |
dfeec247 | 178 | } else { |
ba9703b0 | 179 | let last = generics.iter().last().unwrap(); |
dfeec247 | 180 | sugg.push(( |
ba9703b0 XL |
181 | // Account for bounds, we want `fn foo<T: E, K>(_: K)` not `fn foo<T, K: E>(_: K)`. |
182 | last.bounds_span().unwrap_or(last.span).shrink_to_hi(), | |
dfeec247 XL |
183 | format!(", {}", type_name), |
184 | )); | |
185 | } | |
3dfed10e | 186 | |
136023e0 | 187 | let mut err = bad_placeholder_type(tcx, placeholder_types, kind); |
6a06907d XL |
188 | |
189 | // Suggest, but only if it is not a function in const or static | |
dfeec247 | 190 | if suggest { |
6a06907d | 191 | let mut is_fn = false; |
136023e0 | 192 | let mut is_const_or_static = false; |
6a06907d XL |
193 | |
194 | if let Some(hir_ty) = hir_ty { | |
195 | if let hir::TyKind::BareFn(_) = hir_ty.kind { | |
196 | is_fn = true; | |
197 | ||
198 | // Check if parent is const or static | |
199 | let parent_id = tcx.hir().get_parent_node(hir_ty.hir_id); | |
200 | let parent_node = tcx.hir().get(parent_id); | |
201 | ||
c295e0f8 XL |
202 | is_const_or_static = matches!( |
203 | parent_node, | |
136023e0 XL |
204 | Node::Item(&hir::Item { |
205 | kind: hir::ItemKind::Const(..) | hir::ItemKind::Static(..), | |
206 | .. | |
c295e0f8 | 207 | }) | Node::TraitItem(&hir::TraitItem { |
136023e0 XL |
208 | kind: hir::TraitItemKind::Const(..), |
209 | .. | |
c295e0f8 XL |
210 | }) | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. }) |
211 | ); | |
6a06907d XL |
212 | } |
213 | } | |
214 | ||
215 | // if function is wrapped around a const or static, | |
216 | // then don't show the suggestion | |
136023e0 | 217 | if !(is_fn && is_const_or_static) { |
6a06907d XL |
218 | err.multipart_suggestion( |
219 | "use type parameters instead", | |
220 | sugg, | |
221 | Applicability::HasPlaceholders, | |
222 | ); | |
223 | } | |
dfeec247 XL |
224 | } |
225 | err.emit(); | |
226 | } | |
227 | ||
228 | fn reject_placeholder_type_signatures_in_item(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) { | |
229 | let (generics, suggest) = match &item.kind { | |
230 | hir::ItemKind::Union(_, generics) | |
231 | | hir::ItemKind::Enum(_, generics) | |
232 | | hir::ItemKind::TraitAlias(generics, _) | |
233 | | hir::ItemKind::Trait(_, _, generics, ..) | |
5869c6ff | 234 | | hir::ItemKind::Impl(hir::Impl { generics, .. }) |
dfeec247 XL |
235 | | hir::ItemKind::Struct(_, generics) => (generics, true), |
236 | hir::ItemKind::OpaqueTy(hir::OpaqueTy { generics, .. }) | |
237 | | hir::ItemKind::TyAlias(_, generics) => (generics, false), | |
238 | // `static`, `fn` and `const` are handled elsewhere to suggest appropriate type. | |
239 | _ => return, | |
240 | }; | |
241 | ||
242 | let mut visitor = PlaceholderHirTyCollector::default(); | |
243 | visitor.visit_item(item); | |
244 | ||
136023e0 XL |
245 | placeholder_type_error( |
246 | tcx, | |
247 | Some(generics.span), | |
248 | generics.params, | |
249 | visitor.0, | |
250 | suggest, | |
251 | None, | |
252 | item.kind.descr(), | |
253 | ); | |
dfeec247 XL |
254 | } |
255 | ||
dc9dc135 | 256 | impl Visitor<'tcx> for CollectItemTypesVisitor<'tcx> { |
dfeec247 XL |
257 | type Map = Map<'tcx>; |
258 | ||
ba9703b0 XL |
259 | fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> { |
260 | NestedVisitorMap::OnlyBodies(self.tcx.hir()) | |
476ff2be SL |
261 | } |
262 | ||
dfeec247 | 263 | fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { |
6a06907d | 264 | convert_item(self.tcx, item.item_id()); |
dfeec247 | 265 | reject_placeholder_type_signatures_in_item(self.tcx, item); |
476ff2be SL |
266 | intravisit::walk_item(self, item); |
267 | } | |
268 | ||
dfeec247 XL |
269 | fn visit_generics(&mut self, generics: &'tcx hir::Generics<'tcx>) { |
270 | for param in generics.params { | |
8faf50e0 XL |
271 | match param.kind { |
272 | hir::GenericParamKind::Lifetime { .. } => {} | |
dfeec247 | 273 | hir::GenericParamKind::Type { default: Some(_), .. } => { |
416331ca | 274 | let def_id = self.tcx.hir().local_def_id(param.hir_id); |
f9f354fc | 275 | self.tcx.ensure().type_of(def_id); |
8faf50e0 XL |
276 | } |
277 | hir::GenericParamKind::Type { .. } => {} | |
cdc7bbd5 | 278 | hir::GenericParamKind::Const { default, .. } => { |
416331ca | 279 | let def_id = self.tcx.hir().local_def_id(param.hir_id); |
f9f354fc | 280 | self.tcx.ensure().type_of(def_id); |
cdc7bbd5 XL |
281 | if let Some(default) = default { |
282 | let default_def_id = self.tcx.hir().local_def_id(default.hir_id); | |
283 | // need to store default and type of default | |
284 | self.tcx.ensure().type_of(default_def_id); | |
285 | self.tcx.ensure().const_param_default(def_id); | |
286 | } | |
9fa01778 | 287 | } |
8bb4bdeb XL |
288 | } |
289 | } | |
290 | intravisit::walk_generics(self, generics); | |
291 | } | |
292 | ||
dfeec247 | 293 | fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) { |
e74abb32 | 294 | if let hir::ExprKind::Closure(..) = expr.kind { |
416331ca | 295 | let def_id = self.tcx.hir().local_def_id(expr.hir_id); |
f9f354fc XL |
296 | self.tcx.ensure().generics_of(def_id); |
297 | self.tcx.ensure().type_of(def_id); | |
476ff2be SL |
298 | } |
299 | intravisit::walk_expr(self, expr); | |
300 | } | |
301 | ||
dfeec247 | 302 | fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) { |
6a06907d | 303 | convert_trait_item(self.tcx, trait_item.trait_item_id()); |
32a655c1 SL |
304 | intravisit::walk_trait_item(self, trait_item); |
305 | } | |
306 | ||
dfeec247 | 307 | fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) { |
6a06907d | 308 | convert_impl_item(self.tcx, impl_item.impl_item_id()); |
476ff2be | 309 | intravisit::walk_impl_item(self, impl_item); |
1a4d82fc JJ |
310 | } |
311 | } | |
312 | ||
313 | /////////////////////////////////////////////////////////////////////////// | |
314 | // Utility types and common code for the above passes. | |
315 | ||
dfeec247 XL |
316 | fn bad_placeholder_type( |
317 | tcx: TyCtxt<'tcx>, | |
318 | mut spans: Vec<Span>, | |
136023e0 | 319 | kind: &'static str, |
dfeec247 | 320 | ) -> rustc_errors::DiagnosticBuilder<'tcx> { |
136023e0 XL |
321 | let kind = if kind.ends_with('s') { format!("{}es", kind) } else { format!("{}s", kind) }; |
322 | ||
dfeec247 XL |
323 | spans.sort(); |
324 | let mut err = struct_span_err!( | |
60c5eb7d | 325 | tcx.sess, |
dfeec247 | 326 | spans.clone(), |
60c5eb7d | 327 | E0121, |
136023e0 XL |
328 | "the type placeholder `_` is not allowed within types on item signatures for {}", |
329 | kind | |
416331ca | 330 | ); |
dfeec247 XL |
331 | for span in spans { |
332 | err.span_label(span, "not allowed in type signatures"); | |
333 | } | |
334 | err | |
416331ca XL |
335 | } |
336 | ||
dc9dc135 XL |
337 | impl ItemCtxt<'tcx> { |
338 | pub fn new(tcx: TyCtxt<'tcx>, item_def_id: DefId) -> ItemCtxt<'tcx> { | |
b7449926 | 339 | ItemCtxt { tcx, item_def_id } |
c34b1796 | 340 | } |
c34b1796 | 341 | |
6a06907d XL |
342 | pub fn to_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> { |
343 | <dyn AstConv<'_>>::ast_ty_to_ty(self, ast_ty) | |
c34b1796 | 344 | } |
74b04a01 XL |
345 | |
346 | pub fn hir_id(&self) -> hir::HirId { | |
3dfed10e | 347 | self.tcx.hir().local_def_id_to_hir_id(self.item_def_id.expect_local()) |
74b04a01 XL |
348 | } |
349 | ||
350 | pub fn node(&self) -> hir::Node<'tcx> { | |
351 | self.tcx.hir().get(self.hir_id()) | |
352 | } | |
c34b1796 AL |
353 | } |
354 | ||
dc9dc135 XL |
355 | impl AstConv<'tcx> for ItemCtxt<'tcx> { |
356 | fn tcx(&self) -> TyCtxt<'tcx> { | |
b7449926 XL |
357 | self.tcx |
358 | } | |
a7813a04 | 359 | |
60c5eb7d XL |
360 | fn item_def_id(&self) -> Option<DefId> { |
361 | Some(self.item_def_id) | |
362 | } | |
363 | ||
6a06907d XL |
364 | fn get_type_parameter_bounds( |
365 | &self, | |
366 | span: Span, | |
367 | def_id: DefId, | |
368 | assoc_name: Ident, | |
369 | ) -> ty::GenericPredicates<'tcx> { | |
370 | self.tcx.at(span).type_param_predicates(( | |
371 | self.item_def_id, | |
372 | def_id.expect_local(), | |
373 | assoc_name, | |
374 | )) | |
a7813a04 XL |
375 | } |
376 | ||
dfeec247 | 377 | fn re_infer(&self, _: Option<&ty::GenericParamDef>, _: Span) -> Option<ty::Region<'tcx>> { |
32a655c1 SL |
378 | None |
379 | } | |
380 | ||
dfeec247 XL |
381 | fn allow_ty_infer(&self) -> bool { |
382 | false | |
383 | } | |
0bf4aa26 | 384 | |
dfeec247 | 385 | fn ty_infer(&self, _: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx> { |
f035d41b | 386 | self.tcx().ty_error_with_message(span, "bad_placeholder_type") |
1a4d82fc JJ |
387 | } |
388 | ||
dc9dc135 XL |
389 | fn ct_infer( |
390 | &self, | |
ba9703b0 | 391 | ty: Ty<'tcx>, |
dc9dc135 XL |
392 | _: Option<&ty::GenericParamDef>, |
393 | span: Span, | |
394 | ) -> &'tcx Const<'tcx> { | |
136023e0 | 395 | bad_placeholder_type(self.tcx(), vec![span], "generic").emit(); |
5869c6ff XL |
396 | // Typeck doesn't expect erased regions to be returned from `type_of`. |
397 | let ty = self.tcx.fold_regions(ty, &mut false, |r, _| match r { | |
398 | ty::ReErased => self.tcx.lifetimes.re_static, | |
399 | _ => r, | |
400 | }); | |
f035d41b | 401 | self.tcx().const_error(ty) |
dc9dc135 XL |
402 | } |
403 | ||
b7449926 XL |
404 | fn projected_ty_from_poly_trait_ref( |
405 | &self, | |
406 | span: Span, | |
407 | item_def_id: DefId, | |
dfeec247 | 408 | item_segment: &hir::PathSegment<'_>, |
b7449926 XL |
409 | poly_trait_ref: ty::PolyTraitRef<'tcx>, |
410 | ) -> Ty<'tcx> { | |
a1dfa0c6 | 411 | if let Some(trait_ref) = poly_trait_ref.no_bound_vars() { |
dfeec247 XL |
412 | let item_substs = <dyn AstConv<'tcx>>::create_substs_for_associated_item( |
413 | self, | |
414 | self.tcx, | |
415 | span, | |
416 | item_def_id, | |
417 | item_segment, | |
418 | trait_ref.substs, | |
419 | ); | |
420 | self.tcx().mk_projection(item_def_id, item_substs) | |
a7813a04 | 421 | } else { |
416331ca | 422 | // There are no late-bound regions; we can just ignore the binder. |
74b04a01 | 423 | let mut err = struct_span_err!( |
b7449926 XL |
424 | self.tcx().sess, |
425 | span, | |
426 | E0212, | |
fc512014 XL |
427 | "cannot use the associated type of a trait \ |
428 | with uninferred generic parameters" | |
74b04a01 XL |
429 | ); |
430 | ||
431 | match self.node() { | |
432 | hir::Node::Field(_) | hir::Node::Ctor(_) | hir::Node::Variant(_) => { | |
433 | let item = | |
434 | self.tcx.hir().expect_item(self.tcx.hir().get_parent_item(self.hir_id())); | |
435 | match &item.kind { | |
436 | hir::ItemKind::Enum(_, generics) | |
437 | | hir::ItemKind::Struct(_, generics) | |
438 | | hir::ItemKind::Union(_, generics) => { | |
439 | let lt_name = get_new_lifetime_name(self.tcx, poly_trait_ref, generics); | |
6a06907d | 440 | let (lt_sp, sugg) = match generics.params { |
74b04a01 XL |
441 | [] => (generics.span, format!("<{}>", lt_name)), |
442 | [bound, ..] => { | |
443 | (bound.span.shrink_to_lo(), format!("{}, ", lt_name)) | |
444 | } | |
445 | }; | |
446 | let suggestions = vec![ | |
447 | (lt_sp, sugg), | |
448 | ( | |
c295e0f8 | 449 | span.with_hi(item_segment.ident.span.lo()), |
74b04a01 | 450 | format!( |
c295e0f8 | 451 | "{}::", |
74b04a01 XL |
452 | // Replace the existing lifetimes with a new named lifetime. |
453 | self.tcx | |
fc512014 | 454 | .replace_late_bound_regions(poly_trait_ref, |_| { |
74b04a01 XL |
455 | self.tcx.mk_region(ty::ReEarlyBound( |
456 | ty::EarlyBoundRegion { | |
457 | def_id: item_def_id, | |
458 | index: 0, | |
459 | name: Symbol::intern(<_name), | |
460 | }, | |
461 | )) | |
462 | }) | |
463 | .0, | |
74b04a01 XL |
464 | ), |
465 | ), | |
466 | ]; | |
467 | err.multipart_suggestion( | |
468 | "use a fully qualified path with explicit lifetimes", | |
469 | suggestions, | |
470 | Applicability::MaybeIncorrect, | |
471 | ); | |
472 | } | |
473 | _ => {} | |
474 | } | |
475 | } | |
ba9703b0 XL |
476 | hir::Node::Item(hir::Item { |
477 | kind: | |
478 | hir::ItemKind::Struct(..) | hir::ItemKind::Enum(..) | hir::ItemKind::Union(..), | |
479 | .. | |
480 | }) => {} | |
74b04a01 XL |
481 | hir::Node::Item(_) |
482 | | hir::Node::ForeignItem(_) | |
483 | | hir::Node::TraitItem(_) | |
484 | | hir::Node::ImplItem(_) => { | |
c295e0f8 XL |
485 | err.span_suggestion_verbose( |
486 | span.with_hi(item_segment.ident.span.lo()), | |
74b04a01 XL |
487 | "use a fully qualified path with inferred lifetimes", |
488 | format!( | |
c295e0f8 | 489 | "{}::", |
74b04a01 | 490 | // Erase named lt, we want `<A as B<'_>::C`, not `<A as B<'a>::C`. |
fc512014 | 491 | self.tcx.anonymize_late_bound_regions(poly_trait_ref).skip_binder(), |
74b04a01 XL |
492 | ), |
493 | Applicability::MaybeIncorrect, | |
494 | ); | |
495 | } | |
496 | _ => {} | |
497 | } | |
498 | err.emit(); | |
f035d41b | 499 | self.tcx().ty_error() |
a7813a04 XL |
500 | } |
501 | } | |
502 | ||
8bb4bdeb | 503 | fn normalize_ty(&self, _span: Span, ty: Ty<'tcx>) -> Ty<'tcx> { |
416331ca | 504 | // Types in item signatures are not normalized to avoid undue dependencies. |
8bb4bdeb | 505 | ty |
1a4d82fc | 506 | } |
a7813a04 XL |
507 | |
508 | fn set_tainted_by_errors(&self) { | |
416331ca | 509 | // There's no obvious place to track this, so just let it go. |
a7813a04 | 510 | } |
ea8adc8c XL |
511 | |
512 | fn record_ty(&self, _hir_id: hir::HirId, _ty: Ty<'tcx>, _span: Span) { | |
416331ca | 513 | // There's no place to record types from signatures? |
ea8adc8c | 514 | } |
1a4d82fc JJ |
515 | } |
516 | ||
74b04a01 XL |
517 | /// Synthesize a new lifetime name that doesn't clash with any of the lifetimes already present. |
518 | fn get_new_lifetime_name<'tcx>( | |
519 | tcx: TyCtxt<'tcx>, | |
520 | poly_trait_ref: ty::PolyTraitRef<'tcx>, | |
521 | generics: &hir::Generics<'tcx>, | |
522 | ) -> String { | |
523 | let existing_lifetimes = tcx | |
524 | .collect_referenced_late_bound_regions(&poly_trait_ref) | |
525 | .into_iter() | |
526 | .filter_map(|lt| { | |
fc512014 | 527 | if let ty::BoundRegionKind::BrNamed(_, name) = lt { |
74b04a01 XL |
528 | Some(name.as_str().to_string()) |
529 | } else { | |
530 | None | |
531 | } | |
532 | }) | |
533 | .chain(generics.params.iter().filter_map(|param| { | |
534 | if let hir::GenericParamKind::Lifetime { .. } = ¶m.kind { | |
535 | Some(param.name.ident().as_str().to_string()) | |
536 | } else { | |
537 | None | |
538 | } | |
539 | })) | |
540 | .collect::<FxHashSet<String>>(); | |
541 | ||
542 | let a_to_z_repeat_n = |n| { | |
543 | (b'a'..=b'z').map(move |c| { | |
544 | let mut s = '\''.to_string(); | |
545 | s.extend(std::iter::repeat(char::from(c)).take(n)); | |
546 | s | |
547 | }) | |
548 | }; | |
549 | ||
550 | // If all single char lifetime names are present, we wrap around and double the chars. | |
551 | (1..).flat_map(a_to_z_repeat_n).find(|lt| !existing_lifetimes.contains(lt.as_str())).unwrap() | |
552 | } | |
553 | ||
416331ca XL |
554 | /// Returns the predicates defined on `item_def_id` of the form |
555 | /// `X: Foo` where `X` is the type parameter `def_id`. | |
556 | fn type_param_predicates( | |
557 | tcx: TyCtxt<'_>, | |
6a06907d | 558 | (item_def_id, def_id, assoc_name): (DefId, LocalDefId, Ident), |
e74abb32 | 559 | ) -> ty::GenericPredicates<'_> { |
dfeec247 | 560 | use rustc_hir::*; |
8bb4bdeb XL |
561 | |
562 | // In the AST, bounds can derive from two places. Either | |
416331ca XL |
563 | // written inline like `<T: Foo>` or in a where-clause like |
564 | // `where T: Foo`. | |
8bb4bdeb | 565 | |
3dfed10e | 566 | let param_id = tcx.hir().local_def_id_to_hir_id(def_id); |
0731742a | 567 | let param_owner = tcx.hir().ty_param_owner(param_id); |
416331ca | 568 | let param_owner_def_id = tcx.hir().local_def_id(param_owner); |
7cac9316 | 569 | let generics = tcx.generics_of(param_owner_def_id); |
f9f354fc | 570 | let index = generics.param_def_id_to_index[&def_id.to_def_id()]; |
e74abb32 | 571 | let ty = tcx.mk_ty_param(index, tcx.hir().ty_param_name(param_id)); |
8bb4bdeb XL |
572 | |
573 | // Don't look for bounds where the type parameter isn't in scope. | |
f9f354fc XL |
574 | let parent = if item_def_id == param_owner_def_id.to_def_id() { |
575 | None | |
576 | } else { | |
577 | tcx.generics_of(item_def_id).parent | |
578 | }; | |
c34b1796 | 579 | |
dfeec247 XL |
580 | let mut result = parent |
581 | .map(|parent| { | |
582 | let icx = ItemCtxt::new(tcx, parent); | |
6a06907d | 583 | icx.get_type_parameter_bounds(DUMMY_SP, def_id.to_def_id(), assoc_name) |
dfeec247 XL |
584 | }) |
585 | .unwrap_or_default(); | |
dc9dc135 | 586 | let mut extend = None; |
c34b1796 | 587 | |
3dfed10e | 588 | let item_hir_id = tcx.hir().local_def_id_to_hir_id(item_def_id.expect_local()); |
dc9dc135 | 589 | let ast_generics = match tcx.hir().get(item_hir_id) { |
b7449926 | 590 | Node::TraitItem(item) => &item.generics, |
c34b1796 | 591 | |
b7449926 | 592 | Node::ImplItem(item) => &item.generics, |
9e0c209e | 593 | |
b7449926 | 594 | Node::Item(item) => { |
e74abb32 | 595 | match item.kind { |
b7449926 | 596 | ItemKind::Fn(.., ref generics, _) |
5869c6ff | 597 | | ItemKind::Impl(hir::Impl { ref generics, .. }) |
416331ca | 598 | | ItemKind::TyAlias(_, ref generics) |
dfeec247 | 599 | | ItemKind::OpaqueTy(OpaqueTy { ref generics, impl_trait_fn: None, .. }) |
b7449926 XL |
600 | | ItemKind::Enum(_, ref generics) |
601 | | ItemKind::Struct(_, ref generics) | |
602 | | ItemKind::Union(_, ref generics) => generics, | |
8faf50e0 | 603 | ItemKind::Trait(_, _, ref generics, ..) => { |
8bb4bdeb | 604 | // Implied `Self: Trait` and supertrait bounds. |
532ac7d7 | 605 | if param_id == item_hir_id { |
0bf4aa26 | 606 | let identity_trait_ref = ty::TraitRef::identity(tcx, item_def_id); |
dfeec247 | 607 | extend = |
f9f354fc | 608 | Some((identity_trait_ref.without_const().to_predicate(tcx), item.span)); |
8bb4bdeb XL |
609 | } |
610 | generics | |
9e0c209e | 611 | } |
b7449926 | 612 | _ => return result, |
9e0c209e | 613 | } |
8bb4bdeb | 614 | } |
9e0c209e | 615 | |
e74abb32 | 616 | Node::ForeignItem(item) => match item.kind { |
b7449926 XL |
617 | ForeignItemKind::Fn(_, _, ref generics) => generics, |
618 | _ => return result, | |
619 | }, | |
c34b1796 | 620 | |
b7449926 | 621 | _ => return result, |
8bb4bdeb | 622 | }; |
c34b1796 | 623 | |
8bb4bdeb | 624 | let icx = ItemCtxt::new(tcx, item_def_id); |
e74abb32 | 625 | let extra_predicates = extend.into_iter().chain( |
6a06907d XL |
626 | icx.type_parameter_bounds_in_generics( |
627 | ast_generics, | |
628 | param_id, | |
629 | ty, | |
630 | OnlySelfBounds(true), | |
631 | Some(assoc_name), | |
632 | ) | |
633 | .into_iter() | |
634 | .filter(|(predicate, _)| match predicate.kind().skip_binder() { | |
94222f64 | 635 | ty::PredicateKind::Trait(data) => data.self_ty().is_param(index), |
6a06907d XL |
636 | _ => false, |
637 | }), | |
416331ca | 638 | ); |
dfeec247 XL |
639 | result.predicates = |
640 | tcx.arena.alloc_from_iter(result.predicates.iter().copied().chain(extra_predicates)); | |
e74abb32 | 641 | result |
8bb4bdeb | 642 | } |
c34b1796 | 643 | |
dc9dc135 | 644 | impl ItemCtxt<'tcx> { |
9fa01778 | 645 | /// Finds bounds from `hir::Generics`. This requires scanning through the |
8bb4bdeb | 646 | /// AST. We do this to avoid having to convert *all* the bounds, which |
416331ca | 647 | /// would create artificial cycles. Instead, we can only convert the |
8bb4bdeb | 648 | /// bounds for a type parameter `X` if `X::Foo` is used. |
b7449926 XL |
649 | fn type_parameter_bounds_in_generics( |
650 | &self, | |
dfeec247 | 651 | ast_generics: &'tcx hir::Generics<'tcx>, |
532ac7d7 | 652 | param_id: hir::HirId, |
b7449926 | 653 | ty: Ty<'tcx>, |
a1dfa0c6 | 654 | only_self_bounds: OnlySelfBounds, |
6a06907d | 655 | assoc_name: Option<Ident>, |
0bf4aa26 | 656 | ) -> Vec<(ty::Predicate<'tcx>, Span)> { |
b7449926 XL |
657 | let from_ty_params = ast_generics |
658 | .params | |
659 | .iter() | |
660 | .filter_map(|param| match param.kind { | |
532ac7d7 | 661 | GenericParamKind::Type { .. } if param.hir_id == param_id => Some(¶m.bounds), |
b7449926 XL |
662 | _ => None, |
663 | }) | |
664 | .flat_map(|bounds| bounds.iter()) | |
6a06907d XL |
665 | .filter(|b| match assoc_name { |
666 | Some(assoc_name) => self.bound_defines_assoc_item(b, assoc_name), | |
667 | None => true, | |
668 | }) | |
94222f64 | 669 | .flat_map(|b| predicates_from_bound(self, ty, b)); |
b7449926 XL |
670 | |
671 | let from_where_clauses = ast_generics | |
672 | .where_clause | |
673 | .predicates | |
674 | .iter() | |
675 | .filter_map(|wp| match *wp { | |
676 | hir::WherePredicate::BoundPredicate(ref bp) => Some(bp), | |
677 | _ => None, | |
678 | }) | |
a1dfa0c6 | 679 | .flat_map(|bp| { |
c295e0f8 | 680 | let bt = if is_param(self.tcx, bp.bounded_ty, param_id) { |
a1dfa0c6 XL |
681 | Some(ty) |
682 | } else if !only_self_bounds.0 { | |
c295e0f8 | 683 | Some(self.to_ty(bp.bounded_ty)) |
a1dfa0c6 XL |
684 | } else { |
685 | None | |
686 | }; | |
6a06907d XL |
687 | bp.bounds |
688 | .iter() | |
689 | .filter(|b| match assoc_name { | |
690 | Some(assoc_name) => self.bound_defines_assoc_item(b, assoc_name), | |
691 | None => true, | |
692 | }) | |
693 | .filter_map(move |b| bt.map(|bt| (bt, b))) | |
a1dfa0c6 | 694 | }) |
94222f64 | 695 | .flat_map(|(bt, b)| predicates_from_bound(self, bt, b)); |
c34b1796 AL |
696 | |
697 | from_ty_params.chain(from_where_clauses).collect() | |
698 | } | |
6a06907d XL |
699 | |
700 | fn bound_defines_assoc_item(&self, b: &hir::GenericBound<'_>, assoc_name: Ident) -> bool { | |
701 | debug!("bound_defines_assoc_item(b={:?}, assoc_name={:?})", b, assoc_name); | |
702 | ||
703 | match b { | |
704 | hir::GenericBound::Trait(poly_trait_ref, _) => { | |
705 | let trait_ref = &poly_trait_ref.trait_ref; | |
706 | if let Some(trait_did) = trait_ref.trait_def_id() { | |
707 | self.tcx.trait_may_define_assoc_type(trait_did, assoc_name) | |
708 | } else { | |
709 | false | |
710 | } | |
711 | } | |
712 | _ => false, | |
713 | } | |
714 | } | |
c34b1796 AL |
715 | } |
716 | ||
717 | /// Tests whether this is the AST for a reference to the type | |
9fa01778 | 718 | /// parameter with ID `param_id`. We use this so as to avoid running |
c34b1796 AL |
719 | /// `ast_ty_to_ty`, because we want to avoid triggering an all-out |
720 | /// conversion of the type to avoid inducing unnecessary cycles. | |
dfeec247 | 721 | fn is_param(tcx: TyCtxt<'_>, ast_ty: &hir::Ty<'_>, param_id: hir::HirId) -> bool { |
c295e0f8 | 722 | if let hir::TyKind::Path(hir::QPath::Resolved(None, path)) = ast_ty.kind { |
48663c56 XL |
723 | match path.res { |
724 | Res::SelfTy(Some(def_id), None) | Res::Def(DefKind::TyParam, def_id) => { | |
f9f354fc | 725 | def_id == tcx.hir().local_def_id(param_id).to_def_id() |
9346a6ac | 726 | } |
b7449926 | 727 | _ => false, |
c34b1796 AL |
728 | } |
729 | } else { | |
730 | false | |
731 | } | |
732 | } | |
733 | ||
6a06907d XL |
734 | fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { |
735 | let it = tcx.hir().item(item_id); | |
736 | debug!("convert: item {} with id {}", it.ident, it.hir_id()); | |
737 | let def_id = item_id.def_id; | |
738 | ||
e74abb32 | 739 | match it.kind { |
1a4d82fc | 740 | // These don't define types. |
b7449926 XL |
741 | hir::ItemKind::ExternCrate(_) |
742 | | hir::ItemKind::Use(..) | |
94222f64 | 743 | | hir::ItemKind::Macro(_) |
b7449926 XL |
744 | | hir::ItemKind::Mod(_) |
745 | | hir::ItemKind::GlobalAsm(_) => {} | |
fc512014 XL |
746 | hir::ItemKind::ForeignMod { items, .. } => { |
747 | for item in items { | |
748 | let item = tcx.hir().foreign_item(item.id); | |
6a06907d XL |
749 | tcx.ensure().generics_of(item.def_id); |
750 | tcx.ensure().type_of(item.def_id); | |
751 | tcx.ensure().predicates_of(item.def_id); | |
cdc7bbd5 XL |
752 | match item.kind { |
753 | hir::ForeignItemKind::Fn(..) => tcx.ensure().fn_sig(item.def_id), | |
754 | hir::ForeignItemKind::Static(..) => { | |
755 | let mut visitor = PlaceholderHirTyCollector::default(); | |
756 | visitor.visit_foreign_item(item); | |
136023e0 XL |
757 | placeholder_type_error( |
758 | tcx, | |
759 | None, | |
760 | &[], | |
761 | visitor.0, | |
762 | false, | |
763 | None, | |
764 | "static variable", | |
765 | ); | |
cdc7bbd5 XL |
766 | } |
767 | _ => (), | |
041b39d2 | 768 | } |
9cc50fc6 | 769 | } |
85aaf69f | 770 | } |
8faf50e0 | 771 | hir::ItemKind::Enum(ref enum_definition, _) => { |
f9f354fc XL |
772 | tcx.ensure().generics_of(def_id); |
773 | tcx.ensure().type_of(def_id); | |
774 | tcx.ensure().predicates_of(def_id); | |
c295e0f8 | 775 | convert_enum_variant_types(tcx, def_id.to_def_id(), enum_definition.variants); |
b7449926 | 776 | } |
dfeec247 | 777 | hir::ItemKind::Impl { .. } => { |
f9f354fc XL |
778 | tcx.ensure().generics_of(def_id); |
779 | tcx.ensure().type_of(def_id); | |
780 | tcx.ensure().impl_trait_ref(def_id); | |
781 | tcx.ensure().predicates_of(def_id); | |
b7449926 | 782 | } |
8faf50e0 | 783 | hir::ItemKind::Trait(..) => { |
f9f354fc XL |
784 | tcx.ensure().generics_of(def_id); |
785 | tcx.ensure().trait_def(def_id); | |
7cac9316 | 786 | tcx.at(it.span).super_predicates_of(def_id); |
f9f354fc | 787 | tcx.ensure().predicates_of(def_id); |
b7449926 | 788 | } |
8faf50e0 | 789 | hir::ItemKind::TraitAlias(..) => { |
f9f354fc | 790 | tcx.ensure().generics_of(def_id); |
a1dfa0c6 | 791 | tcx.at(it.span).super_predicates_of(def_id); |
f9f354fc | 792 | tcx.ensure().predicates_of(def_id); |
b7449926 XL |
793 | } |
794 | hir::ItemKind::Struct(ref struct_def, _) | hir::ItemKind::Union(ref struct_def, _) => { | |
f9f354fc XL |
795 | tcx.ensure().generics_of(def_id); |
796 | tcx.ensure().type_of(def_id); | |
797 | tcx.ensure().predicates_of(def_id); | |
8bb4bdeb XL |
798 | |
799 | for f in struct_def.fields() { | |
416331ca | 800 | let def_id = tcx.hir().local_def_id(f.hir_id); |
f9f354fc XL |
801 | tcx.ensure().generics_of(def_id); |
802 | tcx.ensure().type_of(def_id); | |
803 | tcx.ensure().predicates_of(def_id); | |
e9174d1e SL |
804 | } |
805 | ||
532ac7d7 XL |
806 | if let Some(ctor_hir_id) = struct_def.ctor_hir_id() { |
807 | convert_variant_ctor(tcx, ctor_hir_id); | |
e9174d1e | 808 | } |
b7449926 | 809 | } |
8faf50e0 | 810 | |
dc9dc135 | 811 | // Desugared from `impl Trait`, so visited by the function's return type. |
dfeec247 | 812 | hir::ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn: Some(_), .. }) => {} |
b7449926 | 813 | |
1b1a35ee XL |
814 | // Don't call `type_of` on opaque types, since that depends on type |
815 | // checking function bodies. `check_item_type` ensures that it's called | |
816 | // instead. | |
817 | hir::ItemKind::OpaqueTy(..) => { | |
818 | tcx.ensure().generics_of(def_id); | |
819 | tcx.ensure().predicates_of(def_id); | |
29967ef6 | 820 | tcx.ensure().explicit_item_bounds(def_id); |
1b1a35ee XL |
821 | } |
822 | hir::ItemKind::TyAlias(..) | |
b7449926 XL |
823 | | hir::ItemKind::Static(..) |
824 | | hir::ItemKind::Const(..) | |
825 | | hir::ItemKind::Fn(..) => { | |
f9f354fc XL |
826 | tcx.ensure().generics_of(def_id); |
827 | tcx.ensure().type_of(def_id); | |
828 | tcx.ensure().predicates_of(def_id); | |
29967ef6 XL |
829 | match it.kind { |
830 | hir::ItemKind::Fn(..) => tcx.ensure().fn_sig(def_id), | |
831 | hir::ItemKind::OpaqueTy(..) => tcx.ensure().item_bounds(def_id), | |
136023e0 XL |
832 | hir::ItemKind::Const(ty, ..) | hir::ItemKind::Static(ty, ..) => { |
833 | // (#75889): Account for `const C: dyn Fn() -> _ = "";` | |
834 | if let hir::TyKind::TraitObject(..) = ty.kind { | |
835 | let mut visitor = PlaceholderHirTyCollector::default(); | |
836 | visitor.visit_item(it); | |
837 | placeholder_type_error( | |
838 | tcx, | |
839 | None, | |
840 | &[], | |
841 | visitor.0, | |
842 | false, | |
843 | None, | |
844 | it.kind.descr(), | |
845 | ); | |
846 | } | |
847 | } | |
29967ef6 | 848 | _ => (), |
041b39d2 | 849 | } |
cc61c64b | 850 | } |
1a4d82fc JJ |
851 | } |
852 | } | |
853 | ||
6a06907d XL |
854 | fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) { |
855 | let trait_item = tcx.hir().trait_item(trait_item_id); | |
856 | tcx.ensure().generics_of(trait_item_id.def_id); | |
32a655c1 | 857 | |
e74abb32 | 858 | match trait_item.kind { |
ba9703b0 | 859 | hir::TraitItemKind::Fn(..) => { |
6a06907d XL |
860 | tcx.ensure().type_of(trait_item_id.def_id); |
861 | tcx.ensure().fn_sig(trait_item_id.def_id); | |
74b04a01 XL |
862 | } |
863 | ||
864 | hir::TraitItemKind::Const(.., Some(_)) => { | |
6a06907d | 865 | tcx.ensure().type_of(trait_item_id.def_id); |
74b04a01 XL |
866 | } |
867 | ||
29967ef6 | 868 | hir::TraitItemKind::Const(..) => { |
6a06907d | 869 | tcx.ensure().type_of(trait_item_id.def_id); |
29967ef6 XL |
870 | // Account for `const C: _;`. |
871 | let mut visitor = PlaceholderHirTyCollector::default(); | |
872 | visitor.visit_trait_item(trait_item); | |
136023e0 | 873 | placeholder_type_error(tcx, None, &[], visitor.0, false, None, "constant"); |
29967ef6 XL |
874 | } |
875 | ||
876 | hir::TraitItemKind::Type(_, Some(_)) => { | |
6a06907d XL |
877 | tcx.ensure().item_bounds(trait_item_id.def_id); |
878 | tcx.ensure().type_of(trait_item_id.def_id); | |
29967ef6 | 879 | // Account for `type T = _;`. |
74b04a01 XL |
880 | let mut visitor = PlaceholderHirTyCollector::default(); |
881 | visitor.visit_trait_item(trait_item); | |
136023e0 | 882 | placeholder_type_error(tcx, None, &[], visitor.0, false, None, "associated type"); |
32a655c1 SL |
883 | } |
884 | ||
3dfed10e | 885 | hir::TraitItemKind::Type(_, None) => { |
6a06907d | 886 | tcx.ensure().item_bounds(trait_item_id.def_id); |
3dfed10e XL |
887 | // #74612: Visit and try to find bad placeholders |
888 | // even if there is no concrete type. | |
889 | let mut visitor = PlaceholderHirTyCollector::default(); | |
890 | visitor.visit_trait_item(trait_item); | |
6a06907d | 891 | |
136023e0 | 892 | placeholder_type_error(tcx, None, &[], visitor.0, false, None, "associated type"); |
3dfed10e | 893 | } |
8bb4bdeb | 894 | }; |
32a655c1 | 895 | |
6a06907d | 896 | tcx.ensure().predicates_of(trait_item_id.def_id); |
32a655c1 SL |
897 | } |
898 | ||
6a06907d XL |
899 | fn convert_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::ImplItemId) { |
900 | let def_id = impl_item_id.def_id; | |
f9f354fc XL |
901 | tcx.ensure().generics_of(def_id); |
902 | tcx.ensure().type_of(def_id); | |
903 | tcx.ensure().predicates_of(def_id); | |
6a06907d | 904 | let impl_item = tcx.hir().impl_item(impl_item_id); |
74b04a01 | 905 | match impl_item.kind { |
ba9703b0 | 906 | hir::ImplItemKind::Fn(..) => { |
f9f354fc | 907 | tcx.ensure().fn_sig(def_id); |
74b04a01 | 908 | } |
f035d41b | 909 | hir::ImplItemKind::TyAlias(_) => { |
74b04a01 XL |
910 | // Account for `type T = _;` |
911 | let mut visitor = PlaceholderHirTyCollector::default(); | |
912 | visitor.visit_impl_item(impl_item); | |
6a06907d | 913 | |
136023e0 | 914 | placeholder_type_error(tcx, None, &[], visitor.0, false, None, "associated type"); |
74b04a01 XL |
915 | } |
916 | hir::ImplItemKind::Const(..) => {} | |
041b39d2 | 917 | } |
476ff2be SL |
918 | } |
919 | ||
416331ca XL |
920 | fn convert_variant_ctor(tcx: TyCtxt<'_>, ctor_id: hir::HirId) { |
921 | let def_id = tcx.hir().local_def_id(ctor_id); | |
f9f354fc XL |
922 | tcx.ensure().generics_of(def_id); |
923 | tcx.ensure().type_of(def_id); | |
924 | tcx.ensure().predicates_of(def_id); | |
e9174d1e SL |
925 | } |
926 | ||
dfeec247 | 927 | fn convert_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId, variants: &[hir::Variant<'_>]) { |
7cac9316 | 928 | let def = tcx.adt_def(def_id); |
8bb4bdeb XL |
929 | let repr_type = def.repr.discr_type(); |
930 | let initial = repr_type.initial_discriminant(tcx); | |
e1599b0c | 931 | let mut prev_discr = None::<Discr<'_>>; |
8bb4bdeb XL |
932 | |
933 | // fill the discriminant values and field types | |
934 | for variant in variants { | |
0531ce1d | 935 | let wrapped_discr = prev_discr.map_or(initial, |d| d.wrap_incr(tcx)); |
b7449926 | 936 | prev_discr = Some( |
e1599b0c | 937 | if let Some(ref e) = variant.disr_expr { |
416331ca | 938 | let expr_did = tcx.hir().local_def_id(e.hir_id); |
f9f354fc | 939 | def.eval_explicit_discr(tcx, expr_did.to_def_id()) |
b7449926 XL |
940 | } else if let Some(discr) = repr_type.disr_incr(tcx, prev_discr) { |
941 | Some(discr) | |
942 | } else { | |
dfeec247 XL |
943 | struct_span_err!(tcx.sess, variant.span, E0370, "enum discriminant overflowed") |
944 | .span_label( | |
945 | variant.span, | |
946 | format!("overflowed on value after {}", prev_discr.unwrap()), | |
947 | ) | |
948 | .note(&format!( | |
949 | "explicitly set `{} = {}` if that is desired outcome", | |
950 | variant.ident, wrapped_discr | |
951 | )) | |
952 | .emit(); | |
b7449926 | 953 | None |
dfeec247 XL |
954 | } |
955 | .unwrap_or(wrapped_discr), | |
b7449926 | 956 | ); |
8bb4bdeb | 957 | |
e1599b0c | 958 | for f in variant.data.fields() { |
416331ca | 959 | let def_id = tcx.hir().local_def_id(f.hir_id); |
f9f354fc XL |
960 | tcx.ensure().generics_of(def_id); |
961 | tcx.ensure().type_of(def_id); | |
962 | tcx.ensure().predicates_of(def_id); | |
b039eaaf | 963 | } |
e9174d1e SL |
964 | |
965 | // Convert the ctor, if any. This also registers the variant as | |
966 | // an item. | |
e1599b0c | 967 | if let Some(ctor_hir_id) = variant.data.ctor_hir_id() { |
532ac7d7 XL |
968 | convert_variant_ctor(tcx, ctor_hir_id); |
969 | } | |
e9174d1e SL |
970 | } |
971 | } | |
972 | ||
416331ca XL |
973 | fn convert_variant( |
974 | tcx: TyCtxt<'_>, | |
f9f354fc XL |
975 | variant_did: Option<LocalDefId>, |
976 | ctor_did: Option<LocalDefId>, | |
0731742a | 977 | ident: Ident, |
b7449926 | 978 | discr: ty::VariantDiscr, |
dfeec247 | 979 | def: &hir::VariantData<'_>, |
0bf4aa26 | 980 | adt_kind: ty::AdtKind, |
f9f354fc | 981 | parent_did: LocalDefId, |
b7449926 | 982 | ) -> ty::VariantDef { |
f9f354fc | 983 | let mut seen_fields: FxHashMap<Ident, Span> = Default::default(); |
b7449926 XL |
984 | let fields = def |
985 | .fields() | |
986 | .iter() | |
987 | .map(|f| { | |
416331ca | 988 | let fid = tcx.hir().local_def_id(f.hir_id); |
ba9703b0 | 989 | let dup_span = seen_fields.get(&f.ident.normalize_to_macros_2_0()).cloned(); |
b7449926 | 990 | if let Some(prev_span) = dup_span { |
1b1a35ee XL |
991 | tcx.sess.emit_err(errors::FieldAlreadyDeclared { |
992 | field_name: f.ident, | |
993 | span: f.span, | |
994 | prev_span, | |
995 | }); | |
b7449926 | 996 | } else { |
ba9703b0 | 997 | seen_fields.insert(f.ident.normalize_to_macros_2_0(), f.span); |
b7449926 | 998 | } |
54a0048b | 999 | |
29967ef6 | 1000 | ty::FieldDef { did: fid.to_def_id(), ident: f.ident, vis: tcx.visibility(fid) } |
b7449926 XL |
1001 | }) |
1002 | .collect(); | |
532ac7d7 XL |
1003 | let recovered = match def { |
1004 | hir::VariantData::Struct(_, r) => *r, | |
1005 | _ => false, | |
1006 | }; | |
1007 | ty::VariantDef::new( | |
0731742a | 1008 | ident, |
f9f354fc XL |
1009 | variant_did.map(LocalDefId::to_def_id), |
1010 | ctor_did.map(LocalDefId::to_def_id), | |
3b2f2976 XL |
1011 | discr, |
1012 | fields, | |
0bf4aa26 | 1013 | CtorKind::from_hir(def), |
532ac7d7 | 1014 | adt_kind, |
f9f354fc | 1015 | parent_did.to_def_id(), |
532ac7d7 | 1016 | recovered, |
3dfed10e XL |
1017 | adt_kind == AdtKind::Struct && tcx.has_attr(parent_did.to_def_id(), sym::non_exhaustive) |
1018 | || variant_did.map_or(false, |variant_did| { | |
1019 | tcx.has_attr(variant_did.to_def_id(), sym::non_exhaustive) | |
1020 | }), | |
0731742a | 1021 | ) |
e9174d1e | 1022 | } |
1a4d82fc | 1023 | |
416331ca | 1024 | fn adt_def(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::AdtDef { |
dfeec247 | 1025 | use rustc_hir::*; |
476ff2be | 1026 | |
f9f354fc | 1027 | let def_id = def_id.expect_local(); |
3dfed10e | 1028 | let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); |
dc9dc135 | 1029 | let item = match tcx.hir().get(hir_id) { |
b7449926 XL |
1030 | Node::Item(item) => item, |
1031 | _ => bug!(), | |
8bb4bdeb | 1032 | }; |
a7813a04 | 1033 | |
f9f354fc | 1034 | let repr = ReprOptions::new(tcx, def_id.to_def_id()); |
e74abb32 | 1035 | let (kind, variants) = match item.kind { |
8faf50e0 | 1036 | ItemKind::Enum(ref def, _) => { |
8bb4bdeb | 1037 | let mut distance_from_explicit = 0; |
dfeec247 XL |
1038 | let variants = def |
1039 | .variants | |
532ac7d7 XL |
1040 | .iter() |
1041 | .map(|v| { | |
e1599b0c | 1042 | let variant_did = Some(tcx.hir().local_def_id(v.id)); |
dfeec247 XL |
1043 | let ctor_did = |
1044 | v.data.ctor_hir_id().map(|hir_id| tcx.hir().local_def_id(hir_id)); | |
532ac7d7 | 1045 | |
e1599b0c | 1046 | let discr = if let Some(ref e) = v.disr_expr { |
532ac7d7 | 1047 | distance_from_explicit = 0; |
f9f354fc | 1048 | ty::VariantDiscr::Explicit(tcx.hir().local_def_id(e.hir_id).to_def_id()) |
532ac7d7 XL |
1049 | } else { |
1050 | ty::VariantDiscr::Relative(distance_from_explicit) | |
1051 | }; | |
1052 | distance_from_explicit += 1; | |
1053 | ||
dfeec247 XL |
1054 | convert_variant( |
1055 | tcx, | |
1056 | variant_did, | |
1057 | ctor_did, | |
1058 | v.ident, | |
1059 | discr, | |
1060 | &v.data, | |
1061 | AdtKind::Enum, | |
1062 | def_id, | |
1063 | ) | |
532ac7d7 XL |
1064 | }) |
1065 | .collect(); | |
8bb4bdeb | 1066 | |
532ac7d7 | 1067 | (AdtKind::Enum, variants) |
8bb4bdeb | 1068 | } |
8faf50e0 | 1069 | ItemKind::Struct(ref def, _) => { |
f9f354fc | 1070 | let variant_did = None::<LocalDefId>; |
dfeec247 | 1071 | let ctor_did = def.ctor_hir_id().map(|hir_id| tcx.hir().local_def_id(hir_id)); |
532ac7d7 XL |
1072 | |
1073 | let variants = std::iter::once(convert_variant( | |
dfeec247 XL |
1074 | tcx, |
1075 | variant_did, | |
1076 | ctor_did, | |
1077 | item.ident, | |
1078 | ty::VariantDiscr::Relative(0), | |
1079 | def, | |
1080 | AdtKind::Struct, | |
1081 | def_id, | |
1082 | )) | |
1083 | .collect(); | |
532ac7d7 XL |
1084 | |
1085 | (AdtKind::Struct, variants) | |
1086 | } | |
1087 | ItemKind::Union(ref def, _) => { | |
1088 | let variant_did = None; | |
dfeec247 | 1089 | let ctor_did = def.ctor_hir_id().map(|hir_id| tcx.hir().local_def_id(hir_id)); |
532ac7d7 XL |
1090 | |
1091 | let variants = std::iter::once(convert_variant( | |
dfeec247 XL |
1092 | tcx, |
1093 | variant_did, | |
1094 | ctor_did, | |
1095 | item.ident, | |
1096 | ty::VariantDiscr::Relative(0), | |
1097 | def, | |
1098 | AdtKind::Union, | |
1099 | def_id, | |
1100 | )) | |
1101 | .collect(); | |
532ac7d7 XL |
1102 | |
1103 | (AdtKind::Union, variants) | |
dfeec247 | 1104 | } |
b7449926 | 1105 | _ => bug!(), |
8bb4bdeb | 1106 | }; |
f9f354fc | 1107 | tcx.alloc_adt_def(def_id.to_def_id(), kind, variants, repr) |
8bb4bdeb | 1108 | } |
e9174d1e | 1109 | |
dc9dc135 XL |
1110 | /// Ensures that the super-predicates of the trait with a `DefId` |
1111 | /// of `trait_def_id` are converted and stored. This also ensures that | |
1112 | /// the transitive super-predicates are converted. | |
dfeec247 | 1113 | fn super_predicates_of(tcx: TyCtxt<'_>, trait_def_id: DefId) -> ty::GenericPredicates<'_> { |
8bb4bdeb | 1114 | debug!("super_predicates(trait_def_id={:?})", trait_def_id); |
6a06907d XL |
1115 | tcx.super_predicates_that_define_assoc_type((trait_def_id, None)) |
1116 | } | |
8bb4bdeb | 1117 | |
6a06907d XL |
1118 | /// Ensures that the super-predicates of the trait with a `DefId` |
1119 | /// of `trait_def_id` are converted and stored. This also ensures that | |
1120 | /// the transitive super-predicates are converted. | |
1121 | fn super_predicates_that_define_assoc_type( | |
1122 | tcx: TyCtxt<'_>, | |
1123 | (trait_def_id, assoc_name): (DefId, Option<Ident>), | |
1124 | ) -> ty::GenericPredicates<'_> { | |
1125 | debug!( | |
1126 | "super_predicates_that_define_assoc_type(trait_def_id={:?}, assoc_name={:?})", | |
1127 | trait_def_id, assoc_name | |
1128 | ); | |
1129 | if trait_def_id.is_local() { | |
1130 | debug!("super_predicates_that_define_assoc_type: local trait_def_id={:?}", trait_def_id); | |
1131 | let trait_hir_id = tcx.hir().local_def_id_to_hir_id(trait_def_id.expect_local()); | |
a7813a04 | 1132 | |
6a06907d XL |
1133 | let item = match tcx.hir().get(trait_hir_id) { |
1134 | Node::Item(item) => item, | |
1135 | _ => bug!("trait_node_id {} is not an item", trait_hir_id), | |
1136 | }; | |
476ff2be | 1137 | |
6a06907d XL |
1138 | let (generics, bounds) = match item.kind { |
1139 | hir::ItemKind::Trait(.., ref generics, ref supertraits, _) => (generics, supertraits), | |
1140 | hir::ItemKind::TraitAlias(ref generics, ref supertraits) => (generics, supertraits), | |
1141 | _ => span_bug!(item.span, "super_predicates invoked on non-trait"), | |
1142 | }; | |
c34b1796 | 1143 | |
6a06907d | 1144 | let icx = ItemCtxt::new(tcx, trait_def_id); |
c34b1796 | 1145 | |
6a06907d XL |
1146 | // Convert the bounds that follow the colon, e.g., `Bar + Zed` in `trait Foo: Bar + Zed`. |
1147 | let self_param_ty = tcx.types.self_param; | |
1148 | let superbounds1 = if let Some(assoc_name) = assoc_name { | |
1149 | <dyn AstConv<'_>>::compute_bounds_that_match_assoc_type( | |
1150 | &icx, | |
1151 | self_param_ty, | |
c295e0f8 | 1152 | bounds, |
6a06907d XL |
1153 | assoc_name, |
1154 | ) | |
1155 | } else { | |
c295e0f8 | 1156 | <dyn AstConv<'_>>::compute_bounds(&icx, self_param_ty, bounds) |
6a06907d XL |
1157 | }; |
1158 | ||
1159 | let superbounds1 = superbounds1.predicates(tcx, self_param_ty); | |
1160 | ||
1161 | // Convert any explicit superbounds in the where-clause, | |
1162 | // e.g., `trait Foo where Self: Bar`. | |
1163 | // In the case of trait aliases, however, we include all bounds in the where-clause, | |
1164 | // so e.g., `trait Foo = where u32: PartialEq<Self>` would include `u32: PartialEq<Self>` | |
1165 | // as one of its "superpredicates". | |
1166 | let is_trait_alias = tcx.is_trait_alias(trait_def_id); | |
1167 | let superbounds2 = icx.type_parameter_bounds_in_generics( | |
1168 | generics, | |
1169 | item.hir_id(), | |
1170 | self_param_ty, | |
1171 | OnlySelfBounds(!is_trait_alias), | |
1172 | assoc_name, | |
1173 | ); | |
1174 | ||
1175 | // Combine the two lists to form the complete set of superbounds: | |
1176 | let superbounds = &*tcx.arena.alloc_from_iter(superbounds1.into_iter().chain(superbounds2)); | |
1177 | ||
1178 | // Now require that immediate supertraits are converted, | |
1179 | // which will, in turn, reach indirect supertraits. | |
1180 | if assoc_name.is_none() { | |
1181 | // Now require that immediate supertraits are converted, | |
1182 | // which will, in turn, reach indirect supertraits. | |
1183 | for &(pred, span) in superbounds { | |
1184 | debug!("superbound: {:?}", pred); | |
94222f64 | 1185 | if let ty::PredicateKind::Trait(bound) = pred.kind().skip_binder() { |
6a06907d XL |
1186 | tcx.at(span).super_predicates_of(bound.def_id()); |
1187 | } | |
1188 | } | |
0bf4aa26 | 1189 | } |
c34b1796 | 1190 | |
6a06907d XL |
1191 | ty::GenericPredicates { parent: None, predicates: superbounds } |
1192 | } else { | |
1193 | // if `assoc_name` is None, then the query should've been redirected to an | |
1194 | // external provider | |
1195 | assert!(assoc_name.is_some()); | |
1196 | tcx.super_predicates_of(trait_def_id) | |
1197 | } | |
8bb4bdeb | 1198 | } |
c34b1796 | 1199 | |
f9f354fc | 1200 | fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef { |
3dfed10e | 1201 | let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); |
dc9dc135 | 1202 | let item = tcx.hir().expect_item(hir_id); |
c34b1796 | 1203 | |
e74abb32 | 1204 | let (is_auto, unsafety) = match item.kind { |
8faf50e0 XL |
1205 | hir::ItemKind::Trait(is_auto, unsafety, ..) => (is_auto == hir::IsAuto::Yes, unsafety), |
1206 | hir::ItemKind::TraitAlias(..) => (false, hir::Unsafety::Normal), | |
8bb4bdeb XL |
1207 | _ => span_bug!(item.span, "trait_def_of_item invoked on non-trait"), |
1208 | }; | |
c34b1796 | 1209 | |
48663c56 | 1210 | let paren_sugar = tcx.has_attr(def_id, sym::rustc_paren_sugar); |
0531ce1d | 1211 | if paren_sugar && !tcx.features().unboxed_closures { |
dfeec247 XL |
1212 | tcx.sess |
1213 | .struct_span_err( | |
1214 | item.span, | |
1215 | "the `#[rustc_paren_sugar]` attribute is a temporary means of controlling \ | |
74b04a01 | 1216 | which traits can use parenthetical notation", |
dfeec247 XL |
1217 | ) |
1218 | .help("add `#![feature(unboxed_closures)]` to the crate attributes to use it") | |
1219 | .emit(); | |
8bb4bdeb | 1220 | } |
c34b1796 | 1221 | |
48663c56 | 1222 | let is_marker = tcx.has_attr(def_id, sym::marker); |
cdc7bbd5 XL |
1223 | let skip_array_during_method_dispatch = |
1224 | tcx.has_attr(def_id, sym::rustc_skip_array_during_method_dispatch); | |
ba9703b0 XL |
1225 | let spec_kind = if tcx.has_attr(def_id, sym::rustc_unsafe_specialization_marker) { |
1226 | ty::trait_def::TraitSpecializationKind::Marker | |
1227 | } else if tcx.has_attr(def_id, sym::rustc_specialization_trait) { | |
1228 | ty::trait_def::TraitSpecializationKind::AlwaysApplicable | |
1229 | } else { | |
1230 | ty::trait_def::TraitSpecializationKind::None | |
1231 | }; | |
cc61c64b | 1232 | let def_path_hash = tcx.def_path_hash(def_id); |
cdc7bbd5 XL |
1233 | ty::TraitDef::new( |
1234 | def_id, | |
1235 | unsafety, | |
1236 | paren_sugar, | |
1237 | is_auto, | |
1238 | is_marker, | |
1239 | skip_array_during_method_dispatch, | |
1240 | spec_kind, | |
1241 | def_path_hash, | |
1242 | ) | |
1a4d82fc JJ |
1243 | } |
1244 | ||
dc9dc135 XL |
1245 | fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option<Span> { |
1246 | struct LateBoundRegionsDetector<'tcx> { | |
1247 | tcx: TyCtxt<'tcx>, | |
94b46f34 | 1248 | outer_index: ty::DebruijnIndex, |
3b2f2976 XL |
1249 | has_late_bound_regions: Option<Span>, |
1250 | } | |
1251 | ||
dc9dc135 | 1252 | impl Visitor<'tcx> for LateBoundRegionsDetector<'tcx> { |
ba9703b0 | 1253 | type Map = intravisit::ErasedMap<'tcx>; |
dfeec247 | 1254 | |
ba9703b0 | 1255 | fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> { |
3b2f2976 XL |
1256 | NestedVisitorMap::None |
1257 | } | |
1258 | ||
dfeec247 | 1259 | fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) { |
b7449926 XL |
1260 | if self.has_late_bound_regions.is_some() { |
1261 | return; | |
1262 | } | |
e74abb32 | 1263 | match ty.kind { |
8faf50e0 | 1264 | hir::TyKind::BareFn(..) => { |
94b46f34 | 1265 | self.outer_index.shift_in(1); |
3b2f2976 | 1266 | intravisit::walk_ty(self, ty); |
94b46f34 | 1267 | self.outer_index.shift_out(1); |
3b2f2976 | 1268 | } |
b7449926 | 1269 | _ => intravisit::walk_ty(self, ty), |
3b2f2976 XL |
1270 | } |
1271 | } | |
1272 | ||
b7449926 XL |
1273 | fn visit_poly_trait_ref( |
1274 | &mut self, | |
dfeec247 | 1275 | tr: &'tcx hir::PolyTraitRef<'tcx>, |
b7449926 XL |
1276 | m: hir::TraitBoundModifier, |
1277 | ) { | |
1278 | if self.has_late_bound_regions.is_some() { | |
1279 | return; | |
1280 | } | |
94b46f34 | 1281 | self.outer_index.shift_in(1); |
3b2f2976 | 1282 | intravisit::walk_poly_trait_ref(self, tr, m); |
94b46f34 | 1283 | self.outer_index.shift_out(1); |
3b2f2976 XL |
1284 | } |
1285 | ||
1286 | fn visit_lifetime(&mut self, lt: &'tcx hir::Lifetime) { | |
b7449926 XL |
1287 | if self.has_late_bound_regions.is_some() { |
1288 | return; | |
1289 | } | |
3b2f2976 | 1290 | |
9fa01778 | 1291 | match self.tcx.named_region(lt.hir_id) { |
ba9703b0 XL |
1292 | Some(rl::Region::Static | rl::Region::EarlyBound(..)) => {} |
1293 | Some( | |
cdc7bbd5 XL |
1294 | rl::Region::LateBound(debruijn, _, _, _) |
1295 | | rl::Region::LateBoundAnon(debruijn, _, _), | |
ba9703b0 XL |
1296 | ) if debruijn < self.outer_index => {} |
1297 | Some( | |
1298 | rl::Region::LateBound(..) | |
1299 | | rl::Region::LateBoundAnon(..) | |
1300 | | rl::Region::Free(..), | |
1301 | ) | |
b7449926 | 1302 | | None => { |
94b46f34 XL |
1303 | self.has_late_bound_regions = Some(lt.span); |
1304 | } | |
3b2f2976 XL |
1305 | } |
1306 | } | |
1307 | } | |
1308 | ||
dc9dc135 XL |
1309 | fn has_late_bound_regions<'tcx>( |
1310 | tcx: TyCtxt<'tcx>, | |
dfeec247 XL |
1311 | generics: &'tcx hir::Generics<'tcx>, |
1312 | decl: &'tcx hir::FnDecl<'tcx>, | |
b7449926 | 1313 | ) -> Option<Span> { |
3b2f2976 | 1314 | let mut visitor = LateBoundRegionsDetector { |
94b46f34 XL |
1315 | tcx, |
1316 | outer_index: ty::INNERMOST, | |
1317 | has_late_bound_regions: None, | |
3b2f2976 | 1318 | }; |
dfeec247 | 1319 | for param in generics.params { |
0bf4aa26 | 1320 | if let GenericParamKind::Lifetime { .. } = param.kind { |
9fa01778 | 1321 | if tcx.is_late_bound(param.hir_id) { |
0bf4aa26 | 1322 | return Some(param.span); |
8faf50e0 | 1323 | } |
3b2f2976 XL |
1324 | } |
1325 | } | |
1326 | visitor.visit_fn_decl(decl); | |
1327 | visitor.has_late_bound_regions | |
1328 | } | |
1329 | ||
1330 | match node { | |
e74abb32 | 1331 | Node::TraitItem(item) => match item.kind { |
ba9703b0 | 1332 | hir::TraitItemKind::Fn(ref sig, _) => { |
c295e0f8 | 1333 | has_late_bound_regions(tcx, &item.generics, sig.decl) |
b7449926 | 1334 | } |
3b2f2976 XL |
1335 | _ => None, |
1336 | }, | |
e74abb32 | 1337 | Node::ImplItem(item) => match item.kind { |
ba9703b0 | 1338 | hir::ImplItemKind::Fn(ref sig, _) => { |
c295e0f8 | 1339 | has_late_bound_regions(tcx, &item.generics, sig.decl) |
b7449926 | 1340 | } |
3b2f2976 XL |
1341 | _ => None, |
1342 | }, | |
e74abb32 | 1343 | Node::ForeignItem(item) => match item.kind { |
c295e0f8 | 1344 | hir::ForeignItemKind::Fn(fn_decl, _, ref generics) => { |
b7449926 XL |
1345 | has_late_bound_regions(tcx, generics, fn_decl) |
1346 | } | |
3b2f2976 XL |
1347 | _ => None, |
1348 | }, | |
e74abb32 | 1349 | Node::Item(item) => match item.kind { |
60c5eb7d | 1350 | hir::ItemKind::Fn(ref sig, .., ref generics, _) => { |
c295e0f8 | 1351 | has_late_bound_regions(tcx, generics, sig.decl) |
b7449926 | 1352 | } |
3b2f2976 XL |
1353 | _ => None, |
1354 | }, | |
b7449926 | 1355 | _ => None, |
3b2f2976 XL |
1356 | } |
1357 | } | |
1358 | ||
cdc7bbd5 XL |
1359 | struct AnonConstInParamTyDetector { |
1360 | in_param_ty: bool, | |
1361 | found_anon_const_in_param_ty: bool, | |
3dfed10e XL |
1362 | ct: HirId, |
1363 | } | |
1364 | ||
cdc7bbd5 | 1365 | impl<'v> Visitor<'v> for AnonConstInParamTyDetector { |
3dfed10e XL |
1366 | type Map = intravisit::ErasedMap<'v>; |
1367 | ||
1368 | fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> { | |
1369 | NestedVisitorMap::None | |
1370 | } | |
1371 | ||
1372 | fn visit_generic_param(&mut self, p: &'v hir::GenericParam<'v>) { | |
c295e0f8 | 1373 | if let GenericParamKind::Const { ty, default: _ } = p.kind { |
cdc7bbd5 XL |
1374 | let prev = self.in_param_ty; |
1375 | self.in_param_ty = true; | |
1376 | self.visit_ty(ty); | |
1377 | self.in_param_ty = prev; | |
1378 | } | |
3dfed10e XL |
1379 | } |
1380 | ||
1381 | fn visit_anon_const(&mut self, c: &'v hir::AnonConst) { | |
cdc7bbd5 XL |
1382 | if self.in_param_ty && self.ct == c.hir_id { |
1383 | self.found_anon_const_in_param_ty = true; | |
3dfed10e XL |
1384 | } else { |
1385 | intravisit::walk_anon_const(self, c) | |
1386 | } | |
1387 | } | |
1388 | } | |
1389 | ||
f9f354fc | 1390 | fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { |
dfeec247 | 1391 | use rustc_hir::*; |
8bb4bdeb | 1392 | |
3dfed10e | 1393 | let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); |
8bb4bdeb | 1394 | |
dc9dc135 | 1395 | let node = tcx.hir().get(hir_id); |
8bb4bdeb | 1396 | let parent_def_id = match node { |
dfeec247 XL |
1397 | Node::ImplItem(_) |
1398 | | Node::TraitItem(_) | |
1399 | | Node::Variant(_) | |
1400 | | Node::Ctor(..) | |
1401 | | Node::Field(_) => { | |
532ac7d7 | 1402 | let parent_id = tcx.hir().get_parent_item(hir_id); |
f9f354fc | 1403 | Some(tcx.hir().local_def_id(parent_id).to_def_id()) |
8bb4bdeb | 1404 | } |
f9f354fc XL |
1405 | // FIXME(#43408) always enable this once `lazy_normalization` is |
1406 | // stable enough and does not need a feature gate anymore. | |
60c5eb7d | 1407 | Node::AnonConst(_) => { |
ba9703b0 XL |
1408 | let parent_id = tcx.hir().get_parent_item(hir_id); |
1409 | let parent_def_id = tcx.hir().local_def_id(parent_id); | |
1410 | ||
cdc7bbd5 | 1411 | let mut in_param_ty = false; |
3dfed10e XL |
1412 | for (_parent, node) in tcx.hir().parent_iter(hir_id) { |
1413 | if let Some(generics) = node.generics() { | |
cdc7bbd5 XL |
1414 | let mut visitor = AnonConstInParamTyDetector { |
1415 | in_param_ty: false, | |
1416 | found_anon_const_in_param_ty: false, | |
3dfed10e XL |
1417 | ct: hir_id, |
1418 | }; | |
1419 | ||
1420 | visitor.visit_generics(generics); | |
cdc7bbd5 | 1421 | in_param_ty = visitor.found_anon_const_in_param_ty; |
3dfed10e XL |
1422 | break; |
1423 | } | |
1424 | } | |
1425 | ||
cdc7bbd5 | 1426 | if in_param_ty { |
3dfed10e | 1427 | // We do not allow generic parameters in anon consts if we are inside |
cdc7bbd5 | 1428 | // of a const parameter type, e.g. `struct Foo<const N: usize, const M: [u8; N]>` is not allowed. |
3dfed10e XL |
1429 | None |
1430 | } else if tcx.lazy_normalization() { | |
94222f64 XL |
1431 | if let Some(param_id) = tcx.hir().opt_const_param_default_param_hir_id(hir_id) { |
1432 | // If the def_id we are calling generics_of on is an anon ct default i.e: | |
1433 | // | |
1434 | // struct Foo<const N: usize = { .. }>; | |
1435 | // ^^^ ^ ^^^^^^ def id of this anon const | |
1436 | // ^ ^ param_id | |
1437 | // ^ parent_def_id | |
1438 | // | |
1439 | // then we only want to return generics for params to the left of `N`. If we don't do that we | |
1440 | // end up with that const looking like: `ty::ConstKind::Unevaluated(def_id, substs: [N#0])`. | |
1441 | // | |
1442 | // This causes ICEs (#86580) when building the substs for Foo in `fn foo() -> Foo { .. }` as | |
1443 | // we substitute the defaults with the partially built substs when we build the substs. Subst'ing | |
1444 | // the `N#0` on the unevaluated const indexes into the empty substs we're in the process of building. | |
1445 | // | |
1446 | // We fix this by having this function return the parent's generics ourselves and truncating the | |
1447 | // generics to only include non-forward declared params (with the exception of the `Self` ty) | |
1448 | // | |
1449 | // For the above code example that means we want `substs: []` | |
1450 | // For the following struct def we want `substs: [N#0]` when generics_of is called on | |
1451 | // the def id of the `{ N + 1 }` anon const | |
1452 | // struct Foo<const N: usize, const M: usize = { N + 1 }>; | |
1453 | // | |
1454 | // This has some implications for how we get the predicates available to the anon const | |
1455 | // see `explicit_predicates_of` for more information on this | |
1456 | let generics = tcx.generics_of(parent_def_id.to_def_id()); | |
1457 | let param_def = tcx.hir().local_def_id(param_id).to_def_id(); | |
1458 | let param_def_idx = generics.param_def_id_to_index[¶m_def]; | |
1459 | // In the above example this would be .params[..N#0] | |
1460 | let params = generics.params[..param_def_idx as usize].to_owned(); | |
1461 | let param_def_id_to_index = | |
1462 | params.iter().map(|param| (param.def_id, param.index)).collect(); | |
1463 | ||
1464 | return ty::Generics { | |
1465 | // we set the parent of these generics to be our parent's parent so that we | |
1466 | // dont end up with substs: [N, M, N] for the const default on a struct like this: | |
1467 | // struct Foo<const N: usize, const M: usize = { ... }>; | |
1468 | parent: generics.parent, | |
1469 | parent_count: generics.parent_count, | |
1470 | params, | |
1471 | param_def_id_to_index, | |
1472 | has_self: generics.has_self, | |
1473 | has_late_bound_regions: generics.has_late_bound_regions, | |
1474 | }; | |
1475 | } | |
1476 | ||
3dfed10e | 1477 | // HACK(eddyb) this provides the correct generics when |
94222f64 | 1478 | // `feature(generic_const_expressions)` is enabled, so that const expressions |
3dfed10e XL |
1479 | // used with const generics, e.g. `Foo<{N+1}>`, can work at all. |
1480 | // | |
1481 | // Note that we do not supply the parent generics when using | |
5869c6ff | 1482 | // `min_const_generics`. |
f9f354fc | 1483 | Some(parent_def_id.to_def_id()) |
e1599b0c | 1484 | } else { |
ba9703b0 XL |
1485 | let parent_node = tcx.hir().get(tcx.hir().get_parent_node(hir_id)); |
1486 | match parent_node { | |
1487 | // HACK(eddyb) this provides the correct generics for repeat | |
f9f354fc XL |
1488 | // expressions' count (i.e. `N` in `[x; N]`), and explicit |
1489 | // `enum` discriminants (i.e. `D` in `enum Foo { Bar = D }`), | |
1490 | // as they shouldn't be able to cause query cycle errors. | |
ba9703b0 | 1491 | Node::Expr(&Expr { kind: ExprKind::Repeat(_, ref constant), .. }) |
f9f354fc | 1492 | | Node::Variant(Variant { disr_expr: Some(ref constant), .. }) |
ba9703b0 XL |
1493 | if constant.hir_id == hir_id => |
1494 | { | |
f9f354fc | 1495 | Some(parent_def_id.to_def_id()) |
ba9703b0 XL |
1496 | } |
1497 | ||
1498 | _ => None, | |
1499 | } | |
e1599b0c XL |
1500 | } |
1501 | } | |
dfeec247 XL |
1502 | Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure(..), .. }) => { |
1503 | Some(tcx.closure_base_def_id(def_id)) | |
1504 | } | |
e74abb32 | 1505 | Node::Item(item) => match item.kind { |
74b04a01 XL |
1506 | ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn, .. }) => { |
1507 | impl_trait_fn.or_else(|| { | |
1508 | let parent_id = tcx.hir().get_parent_item(hir_id); | |
f035d41b XL |
1509 | assert!(parent_id != hir_id && parent_id != CRATE_HIR_ID); |
1510 | debug!("generics_of: parent of opaque ty {:?} is {:?}", def_id, parent_id); | |
1511 | // Opaque types are always nested within another item, and | |
1512 | // inherit the generics of the item. | |
1513 | Some(tcx.hir().local_def_id(parent_id).to_def_id()) | |
74b04a01 XL |
1514 | }) |
1515 | } | |
b7449926 | 1516 | _ => None, |
94b46f34 | 1517 | }, |
b7449926 | 1518 | _ => None, |
8bb4bdeb | 1519 | }; |
85aaf69f | 1520 | |
8bb4bdeb XL |
1521 | let mut opt_self = None; |
1522 | let mut allow_defaults = false; | |
1a4d82fc | 1523 | |
8bb4bdeb | 1524 | let no_generics = hir::Generics::empty(); |
ff7c6d11 | 1525 | let ast_generics = match node { |
b7449926 | 1526 | Node::TraitItem(item) => &item.generics, |
c34b1796 | 1527 | |
b7449926 | 1528 | Node::ImplItem(item) => &item.generics, |
c34b1796 | 1529 | |
b7449926 | 1530 | Node::Item(item) => { |
e74abb32 | 1531 | match item.kind { |
5869c6ff XL |
1532 | ItemKind::Fn(.., ref generics, _) |
1533 | | ItemKind::Impl(hir::Impl { ref generics, .. }) => generics, | |
b7449926 | 1534 | |
416331ca | 1535 | ItemKind::TyAlias(_, ref generics) |
b7449926 XL |
1536 | | ItemKind::Enum(_, ref generics) |
1537 | | ItemKind::Struct(_, ref generics) | |
416331ca | 1538 | | ItemKind::OpaqueTy(hir::OpaqueTy { ref generics, .. }) |
b7449926 | 1539 | | ItemKind::Union(_, ref generics) => { |
8bb4bdeb | 1540 | allow_defaults = true; |
ff7c6d11 | 1541 | generics |
8bb4bdeb | 1542 | } |
85aaf69f | 1543 | |
b7449926 XL |
1544 | ItemKind::Trait(_, _, ref generics, ..) |
1545 | | ItemKind::TraitAlias(ref generics, ..) => { | |
8bb4bdeb XL |
1546 | // Add in the self type parameter. |
1547 | // | |
1548 | // Something of a hack: use the node id for the trait, also as | |
1549 | // the node id for the Self type parameter. | |
6a06907d | 1550 | let param_id = item.def_id; |
8bb4bdeb | 1551 | |
94b46f34 | 1552 | opt_self = Some(ty::GenericParamDef { |
8bb4bdeb | 1553 | index: 0, |
e74abb32 | 1554 | name: kw::SelfUpper, |
6a06907d | 1555 | def_id: param_id.to_def_id(), |
8bb4bdeb | 1556 | pure_wrt_drop: false, |
94b46f34 XL |
1557 | kind: ty::GenericParamDefKind::Type { |
1558 | has_default: false, | |
1559 | object_lifetime_default: rl::Set1::Empty, | |
1560 | synthetic: None, | |
1561 | }, | |
8bb4bdeb XL |
1562 | }); |
1563 | ||
1564 | allow_defaults = true; | |
ff7c6d11 | 1565 | generics |
8bb4bdeb | 1566 | } |
85aaf69f | 1567 | |
ff7c6d11 | 1568 | _ => &no_generics, |
8bb4bdeb XL |
1569 | } |
1570 | } | |
476ff2be | 1571 | |
e74abb32 | 1572 | Node::ForeignItem(item) => match item.kind { |
b7449926 XL |
1573 | ForeignItemKind::Static(..) => &no_generics, |
1574 | ForeignItemKind::Fn(_, _, ref generics) => generics, | |
1575 | ForeignItemKind::Type => &no_generics, | |
1576 | }, | |
8bb4bdeb | 1577 | |
ff7c6d11 | 1578 | _ => &no_generics, |
85aaf69f SL |
1579 | }; |
1580 | ||
8bb4bdeb XL |
1581 | let has_self = opt_self.is_some(); |
1582 | let mut parent_has_self = false; | |
1583 | let mut own_start = has_self as u32; | |
94b46f34 | 1584 | let parent_count = parent_def_id.map_or(0, |def_id| { |
7cac9316 | 1585 | let generics = tcx.generics_of(def_id); |
c295e0f8 | 1586 | assert!(!has_self); |
8bb4bdeb XL |
1587 | parent_has_self = generics.has_self; |
1588 | own_start = generics.count() as u32; | |
94b46f34 | 1589 | generics.parent_count + generics.params.len() |
8bb4bdeb | 1590 | }); |
85aaf69f | 1591 | |
fc512014 XL |
1592 | let mut params: Vec<_> = Vec::with_capacity(ast_generics.params.len() + has_self as usize); |
1593 | ||
1594 | if let Some(opt_self) = opt_self { | |
1595 | params.push(opt_self); | |
1596 | } | |
94b46f34 | 1597 | |
8bb4bdeb | 1598 | let early_lifetimes = early_bound_lifetimes_from_generics(tcx, ast_generics); |
dfeec247 XL |
1599 | params.extend(early_lifetimes.enumerate().map(|(i, param)| ty::GenericParamDef { |
1600 | name: param.name.ident().name, | |
1601 | index: own_start + i as u32, | |
f9f354fc | 1602 | def_id: tcx.hir().local_def_id(param.hir_id).to_def_id(), |
dfeec247 XL |
1603 | pure_wrt_drop: param.pure_wrt_drop, |
1604 | kind: ty::GenericParamDefKind::Lifetime, | |
1605 | })); | |
85aaf69f | 1606 | |
ea8adc8c | 1607 | let object_lifetime_defaults = tcx.object_lifetime_defaults(hir_id); |
85aaf69f | 1608 | |
74b04a01 | 1609 | // Now create the real type and const parameters. |
94b46f34 | 1610 | let type_start = own_start - has_self as u32 + params.len() as u32; |
8faf50e0 | 1611 | let mut i = 0; |
9fa01778 | 1612 | |
3dfed10e XL |
1613 | params.extend(ast_generics.params.iter().filter_map(|param| match param.kind { |
1614 | GenericParamKind::Lifetime { .. } => None, | |
1615 | GenericParamKind::Type { ref default, synthetic, .. } => { | |
ba9703b0 XL |
1616 | if !allow_defaults && default.is_some() { |
1617 | if !tcx.features().default_type_parameter_fallback { | |
1618 | tcx.struct_span_lint_hir( | |
1619 | lint::builtin::INVALID_TYPE_PARAM_DEFAULT, | |
1620 | param.hir_id, | |
1621 | param.span, | |
1622 | |lint| { | |
1623 | lint.build( | |
1624 | "defaults for type parameters are only allowed in \ | |
cdc7bbd5 | 1625 | `struct`, `enum`, `type`, or `trait` definitions", |
ba9703b0 XL |
1626 | ) |
1627 | .emit(); | |
1628 | }, | |
1629 | ); | |
dfeec247 XL |
1630 | } |
1631 | } | |
dfeec247 | 1632 | |
ba9703b0 XL |
1633 | let kind = ty::GenericParamDefKind::Type { |
1634 | has_default: default.is_some(), | |
1635 | object_lifetime_default: object_lifetime_defaults | |
1636 | .as_ref() | |
1637 | .map_or(rl::Set1::Empty, |o| o[i]), | |
1638 | synthetic, | |
1639 | }; | |
1640 | ||
1641 | let param_def = ty::GenericParamDef { | |
1642 | index: type_start + i as u32, | |
1643 | name: param.name.ident().name, | |
f9f354fc | 1644 | def_id: tcx.hir().local_def_id(param.hir_id).to_def_id(), |
ba9703b0 XL |
1645 | pure_wrt_drop: param.pure_wrt_drop, |
1646 | kind, | |
1647 | }; | |
1648 | i += 1; | |
1649 | Some(param_def) | |
ba9703b0 | 1650 | } |
cdc7bbd5 XL |
1651 | GenericParamKind::Const { default, .. } => { |
1652 | if !allow_defaults && default.is_some() { | |
1653 | tcx.sess.span_err( | |
1654 | param.span, | |
1655 | "defaults for const parameters are only allowed in \ | |
1656 | `struct`, `enum`, `type`, or `trait` definitions", | |
1657 | ); | |
1658 | } | |
1659 | ||
ba9703b0 XL |
1660 | let param_def = ty::GenericParamDef { |
1661 | index: type_start + i as u32, | |
1662 | name: param.name.ident().name, | |
f9f354fc | 1663 | def_id: tcx.hir().local_def_id(param.hir_id).to_def_id(), |
ba9703b0 | 1664 | pure_wrt_drop: param.pure_wrt_drop, |
cdc7bbd5 | 1665 | kind: ty::GenericParamDefKind::Const { has_default: default.is_some() }, |
ba9703b0 XL |
1666 | }; |
1667 | i += 1; | |
1668 | Some(param_def) | |
ba9703b0 | 1669 | } |
dfeec247 | 1670 | })); |
8bb4bdeb XL |
1671 | |
1672 | // provide junk type parameter defs - the only place that | |
1673 | // cares about anything but the length is instantiation, | |
1674 | // and we don't do that for closures. | |
dfeec247 | 1675 | if let Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure(.., gen), .. }) = node { |
94b46f34 | 1676 | let dummy_args = if gen.is_some() { |
ba9703b0 | 1677 | &["<resume_ty>", "<yield_ty>", "<return_ty>", "<witness>", "<upvars>"][..] |
94b46f34 | 1678 | } else { |
ba9703b0 | 1679 | &["<closure_kind>", "<closure_signature>", "<upvars>"][..] |
94b46f34 | 1680 | }; |
ff7c6d11 | 1681 | |
dfeec247 XL |
1682 | params.extend(dummy_args.iter().enumerate().map(|(i, &arg)| ty::GenericParamDef { |
1683 | index: type_start + i as u32, | |
1684 | name: Symbol::intern(arg), | |
1685 | def_id, | |
1686 | pure_wrt_drop: false, | |
1687 | kind: ty::GenericParamDefKind::Type { | |
1688 | has_default: false, | |
1689 | object_lifetime_default: rl::Set1::Empty, | |
1690 | synthetic: None, | |
1691 | }, | |
1692 | })); | |
1a4d82fc | 1693 | } |
8bb4bdeb | 1694 | |
dfeec247 | 1695 | let param_def_id_to_index = params.iter().map(|param| (param.def_id, param.index)).collect(); |
8bb4bdeb | 1696 | |
f9f354fc | 1697 | ty::Generics { |
8bb4bdeb | 1698 | parent: parent_def_id, |
94b46f34 XL |
1699 | parent_count, |
1700 | params, | |
1701 | param_def_id_to_index, | |
3b2f2976 XL |
1702 | has_self: has_self || parent_has_self, |
1703 | has_late_bound_regions: has_late_bound_regions(tcx, node), | |
f9f354fc | 1704 | } |
85aaf69f SL |
1705 | } |
1706 | ||
dfeec247 | 1707 | fn are_suggestable_generic_args(generic_args: &[hir::GenericArg<'_>]) -> bool { |
94222f64 XL |
1708 | generic_args.iter().any(|arg| match arg { |
1709 | hir::GenericArg::Type(ty) => is_suggestable_infer_ty(ty), | |
1710 | hir::GenericArg::Infer(_) => true, | |
1711 | _ => false, | |
1712 | }) | |
dfeec247 XL |
1713 | } |
1714 | ||
74b04a01 | 1715 | /// Whether `ty` is a type with `_` placeholders that can be inferred. Used in diagnostics only to |
dfeec247 XL |
1716 | /// use inference to provide suggestions for the appropriate type if possible. |
1717 | fn is_suggestable_infer_ty(ty: &hir::Ty<'_>) -> bool { | |
1718 | use hir::TyKind::*; | |
1719 | match &ty.kind { | |
1720 | Infer => true, | |
1721 | Slice(ty) | Array(ty, _) => is_suggestable_infer_ty(ty), | |
1722 | Tup(tys) => tys.iter().any(is_suggestable_infer_ty), | |
1723 | Ptr(mut_ty) | Rptr(_, mut_ty) => is_suggestable_infer_ty(mut_ty.ty), | |
f035d41b | 1724 | OpaqueDef(_, generic_args) => are_suggestable_generic_args(generic_args), |
dfeec247 | 1725 | Path(hir::QPath::TypeRelative(ty, segment)) => { |
5869c6ff | 1726 | is_suggestable_infer_ty(ty) || are_suggestable_generic_args(segment.args().args) |
dfeec247 XL |
1727 | } |
1728 | Path(hir::QPath::Resolved(ty_opt, hir::Path { segments, .. })) => { | |
1729 | ty_opt.map_or(false, is_suggestable_infer_ty) | |
5869c6ff | 1730 | || segments.iter().any(|segment| are_suggestable_generic_args(segment.args().args)) |
dfeec247 XL |
1731 | } |
1732 | _ => false, | |
1733 | } | |
1734 | } | |
1735 | ||
74b04a01 | 1736 | pub fn get_infer_ret_ty(output: &'hir hir::FnRetTy<'hir>) -> Option<&'hir hir::Ty<'hir>> { |
c295e0f8 | 1737 | if let hir::FnRetTy::Return(ty) = output { |
dfeec247 | 1738 | if is_suggestable_infer_ty(ty) { |
c295e0f8 | 1739 | return Some(&*ty); |
416331ca XL |
1740 | } |
1741 | } | |
1742 | None | |
1743 | } | |
1744 | ||
1745 | fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> { | |
dfeec247 XL |
1746 | use rustc_hir::Node::*; |
1747 | use rustc_hir::*; | |
041b39d2 | 1748 | |
f9f354fc | 1749 | let def_id = def_id.expect_local(); |
3dfed10e | 1750 | let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); |
041b39d2 | 1751 | |
f9f354fc | 1752 | let icx = ItemCtxt::new(tcx, def_id.to_def_id()); |
041b39d2 | 1753 | |
dc9dc135 | 1754 | match tcx.hir().get(hir_id) { |
b7449926 | 1755 | TraitItem(hir::TraitItem { |
ba9703b0 | 1756 | kind: TraitItemKind::Fn(sig, TraitFn::Provided(_)), |
dfeec247 XL |
1757 | ident, |
1758 | generics, | |
b7449926 XL |
1759 | .. |
1760 | }) | |
ba9703b0 | 1761 | | ImplItem(hir::ImplItem { kind: ImplItemKind::Fn(sig, _), ident, generics, .. }) |
dfeec247 XL |
1762 | | Item(hir::Item { kind: ItemKind::Fn(sig, generics, _), ident, .. }) => { |
1763 | match get_infer_ret_ty(&sig.decl.output) { | |
1764 | Some(ty) => { | |
3dfed10e | 1765 | let fn_sig = tcx.typeck(def_id).liberated_fn_sigs()[hir_id]; |
5869c6ff XL |
1766 | // Typeck doesn't expect erased regions to be returned from `type_of`. |
1767 | let fn_sig = tcx.fold_regions(fn_sig, &mut false, |r, _| match r { | |
1768 | ty::ReErased => tcx.lifetimes.re_static, | |
1769 | _ => r, | |
1770 | }); | |
136023e0 | 1771 | let fn_sig = ty::Binder::dummy(fn_sig); |
5869c6ff | 1772 | |
dfeec247 XL |
1773 | let mut visitor = PlaceholderHirTyCollector::default(); |
1774 | visitor.visit_ty(ty); | |
136023e0 XL |
1775 | let mut diag = bad_placeholder_type(tcx, visitor.0, "return type"); |
1776 | let ret_ty = fn_sig.skip_binder().output(); | |
f035d41b | 1777 | if ret_ty != tcx.ty_error() { |
5869c6ff XL |
1778 | if !ret_ty.is_closure() { |
1779 | let ret_ty_str = match ret_ty.kind() { | |
1780 | // Suggest a function pointer return type instead of a unique function definition | |
1781 | // (e.g. `fn() -> i32` instead of `fn() -> i32 { f }`, the latter of which is invalid | |
1782 | // syntax) | |
1783 | ty::FnDef(..) => ret_ty.fn_sig(tcx).to_string(), | |
1784 | _ => ret_ty.to_string(), | |
1785 | }; | |
1786 | diag.span_suggestion( | |
1787 | ty.span, | |
1788 | "replace with the correct return type", | |
1789 | ret_ty_str, | |
1790 | Applicability::MaybeIncorrect, | |
1791 | ); | |
1792 | } else { | |
1793 | // We're dealing with a closure, so we should suggest using `impl Fn` or trait bounds | |
1794 | // to prevent the user from getting a papercut while trying to use the unique closure | |
1795 | // syntax (e.g. `[closure@src/lib.rs:2:5: 2:9]`). | |
1796 | diag.help("consider using an `Fn`, `FnMut`, or `FnOnce` trait bound"); | |
1797 | diag.note("for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html"); | |
1798 | } | |
dfeec247 XL |
1799 | } |
1800 | diag.emit(); | |
5869c6ff | 1801 | |
136023e0 | 1802 | fn_sig |
416331ca | 1803 | } |
6a06907d | 1804 | None => <dyn AstConv<'_>>::ty_of_fn( |
dfeec247 | 1805 | &icx, |
cdc7bbd5 | 1806 | hir_id, |
dfeec247 XL |
1807 | sig.header.unsafety, |
1808 | sig.header.abi, | |
c295e0f8 XL |
1809 | sig.decl, |
1810 | generics, | |
dfeec247 | 1811 | Some(ident.span), |
6a06907d | 1812 | None, |
dfeec247 XL |
1813 | ), |
1814 | } | |
1815 | } | |
416331ca XL |
1816 | |
1817 | TraitItem(hir::TraitItem { | |
3dfed10e | 1818 | kind: TraitItemKind::Fn(FnSig { header, decl, span: _ }, _), |
dfeec247 XL |
1819 | ident, |
1820 | generics, | |
416331ca | 1821 | .. |
6a06907d XL |
1822 | }) => <dyn AstConv<'_>>::ty_of_fn( |
1823 | &icx, | |
cdc7bbd5 | 1824 | hir_id, |
6a06907d XL |
1825 | header.unsafety, |
1826 | header.abi, | |
1827 | decl, | |
c295e0f8 | 1828 | generics, |
6a06907d XL |
1829 | Some(ident.span), |
1830 | None, | |
1831 | ), | |
dfeec247 | 1832 | |
ba9703b0 | 1833 | ForeignItem(&hir::ForeignItem { |
c295e0f8 | 1834 | kind: ForeignItemKind::Fn(fn_decl, _, _), ident, .. |
ba9703b0 | 1835 | }) => { |
dc9dc135 | 1836 | let abi = tcx.hir().get_foreign_abi(hir_id); |
f9f354fc | 1837 | compute_sig_of_foreign_fn_decl(tcx, def_id.to_def_id(), fn_decl, abi, ident) |
041b39d2 XL |
1838 | } |
1839 | ||
dfeec247 | 1840 | Ctor(data) | Variant(hir::Variant { data, .. }) if data.ctor_hir_id().is_some() => { |
ba9703b0 | 1841 | let ty = tcx.type_of(tcx.hir().get_parent_did(hir_id).to_def_id()); |
dfeec247 XL |
1842 | let inputs = |
1843 | data.fields().iter().map(|f| tcx.type_of(tcx.hir().local_def_id(f.hir_id))); | |
136023e0 XL |
1844 | ty::Binder::dummy(tcx.mk_fn_sig( |
1845 | inputs, | |
1846 | ty, | |
1847 | false, | |
1848 | hir::Unsafety::Normal, | |
1849 | abi::Abi::Rust, | |
1850 | )) | |
041b39d2 XL |
1851 | } |
1852 | ||
dfeec247 | 1853 | Expr(&hir::Expr { kind: hir::ExprKind::Closure(..), .. }) => { |
ff7c6d11 XL |
1854 | // Closure signatures are not like other function |
1855 | // signatures and cannot be accessed through `fn_sig`. For | |
1856 | // example, a closure signature excludes the `self` | |
1857 | // argument. In any case they are embedded within the | |
1858 | // closure type as part of the `ClosureSubsts`. | |
1859 | // | |
ba9703b0 XL |
1860 | // To get the signature of a closure, you should use the |
1861 | // `sig` method on the `ClosureSubsts`: | |
ff7c6d11 | 1862 | // |
ba9703b0 XL |
1863 | // substs.as_closure().sig(def_id, tcx) |
1864 | bug!( | |
1865 | "to get the signature of a closure, use `substs.as_closure().sig()` not `fn_sig()`", | |
1866 | ); | |
041b39d2 XL |
1867 | } |
1868 | ||
1869 | x => { | |
1870 | bug!("unexpected sort of node in fn_sig(): {:?}", x); | |
1871 | } | |
1872 | } | |
1873 | } | |
1874 | ||
416331ca | 1875 | fn impl_trait_ref(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::TraitRef<'_>> { |
8bb4bdeb | 1876 | let icx = ItemCtxt::new(tcx, def_id); |
85aaf69f | 1877 | |
3dfed10e | 1878 | let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); |
e74abb32 | 1879 | match tcx.hir().expect_item(hir_id).kind { |
5869c6ff | 1880 | hir::ItemKind::Impl(ref impl_) => impl_.of_trait.as_ref().map(|ast_trait_ref| { |
dfeec247 | 1881 | let selfty = tcx.type_of(def_id); |
6a06907d | 1882 | <dyn AstConv<'_>>::instantiate_mono_trait_ref(&icx, ast_trait_ref, selfty) |
dfeec247 | 1883 | }), |
b7449926 | 1884 | _ => bug!(), |
8bb4bdeb | 1885 | } |
85aaf69f SL |
1886 | } |
1887 | ||
e74abb32 | 1888 | fn impl_polarity(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ImplPolarity { |
3dfed10e | 1889 | let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); |
e74abb32 XL |
1890 | let is_rustc_reservation = tcx.has_attr(def_id, sym::rustc_reservation_impl); |
1891 | let item = tcx.hir().expect_item(hir_id); | |
1892 | match &item.kind { | |
5869c6ff XL |
1893 | hir::ItemKind::Impl(hir::Impl { |
1894 | polarity: hir::ImplPolarity::Negative(span), | |
1895 | of_trait, | |
1896 | .. | |
1897 | }) => { | |
e74abb32 | 1898 | if is_rustc_reservation { |
5869c6ff | 1899 | let span = span.to(of_trait.as_ref().map_or(*span, |t| t.path.span)); |
ba9703b0 | 1900 | tcx.sess.span_err(span, "reservation impls can't be negative"); |
e74abb32 XL |
1901 | } |
1902 | ty::ImplPolarity::Negative | |
1903 | } | |
5869c6ff XL |
1904 | hir::ItemKind::Impl(hir::Impl { |
1905 | polarity: hir::ImplPolarity::Positive, | |
1906 | of_trait: None, | |
1907 | .. | |
1908 | }) => { | |
e74abb32 XL |
1909 | if is_rustc_reservation { |
1910 | tcx.sess.span_err(item.span, "reservation impls can't be inherent"); | |
1911 | } | |
1912 | ty::ImplPolarity::Positive | |
1913 | } | |
5869c6ff XL |
1914 | hir::ItemKind::Impl(hir::Impl { |
1915 | polarity: hir::ImplPolarity::Positive, | |
1916 | of_trait: Some(_), | |
1917 | .. | |
1918 | }) => { | |
e74abb32 XL |
1919 | if is_rustc_reservation { |
1920 | ty::ImplPolarity::Reservation | |
1921 | } else { | |
1922 | ty::ImplPolarity::Positive | |
1923 | } | |
1924 | } | |
5869c6ff | 1925 | item => bug!("impl_polarity: {:?} not an impl", item), |
cc61c64b XL |
1926 | } |
1927 | } | |
1928 | ||
c34b1796 | 1929 | /// Returns the early-bound lifetimes declared in this generics |
9fa01778 | 1930 | /// listing. For anything other than fns/methods, this is just all |
c34b1796 AL |
1931 | /// the lifetimes that are declared. For fns or methods, we have to |
1932 | /// screen out those that do not appear in any where-clauses etc using | |
1933 | /// `resolve_lifetime::early_bound_lifetimes`. | |
dc9dc135 XL |
1934 | fn early_bound_lifetimes_from_generics<'a, 'tcx: 'a>( |
1935 | tcx: TyCtxt<'tcx>, | |
dfeec247 XL |
1936 | generics: &'a hir::Generics<'a>, |
1937 | ) -> impl Iterator<Item = &'a hir::GenericParam<'a>> + Captures<'tcx> { | |
1938 | generics.params.iter().filter(move |param| match param.kind { | |
1939 | GenericParamKind::Lifetime { .. } => !tcx.is_late_bound(param.hir_id), | |
1940 | _ => false, | |
1941 | }) | |
c34b1796 AL |
1942 | } |
1943 | ||
9fa01778 XL |
1944 | /// Returns a list of type predicates for the definition with ID `def_id`, including inferred |
1945 | /// lifetime constraints. This includes all predicates returned by `explicit_predicates_of`, plus | |
1946 | /// inferred constraints concerning which regions outlive other regions. | |
dfeec247 | 1947 | fn predicates_defined_on(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> { |
13cf67c4 | 1948 | debug!("predicates_defined_on({:?})", def_id); |
a1dfa0c6 | 1949 | let mut result = tcx.explicit_predicates_of(def_id); |
dfeec247 | 1950 | debug!("predicates_defined_on: explicit_predicates_of({:?}) = {:?}", def_id, result,); |
a1dfa0c6 XL |
1951 | let inferred_outlives = tcx.inferred_outlives_of(def_id); |
1952 | if !inferred_outlives.is_empty() { | |
a1dfa0c6 XL |
1953 | debug!( |
1954 | "predicates_defined_on: inferred_outlives_of({:?}) = {:?}", | |
dfeec247 | 1955 | def_id, inferred_outlives, |
a1dfa0c6 | 1956 | ); |
e74abb32 XL |
1957 | if result.predicates.is_empty() { |
1958 | result.predicates = inferred_outlives; | |
1959 | } else { | |
dfeec247 XL |
1960 | result.predicates = tcx |
1961 | .arena | |
1962 | .alloc_from_iter(result.predicates.iter().chain(inferred_outlives).copied()); | |
e74abb32 | 1963 | } |
abe05a73 | 1964 | } |
1b1a35ee | 1965 | |
0731742a | 1966 | debug!("predicates_defined_on({:?}) = {:?}", def_id, result); |
a1dfa0c6 | 1967 | result |
ea8adc8c XL |
1968 | } |
1969 | ||
9fa01778 XL |
1970 | /// Returns a list of all type predicates (explicit and implicit) for the definition with |
1971 | /// ID `def_id`. This includes all predicates returned by `predicates_defined_on`, plus | |
1972 | /// `Self: Trait` predicates for traits. | |
e74abb32 | 1973 | fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> { |
a1dfa0c6 | 1974 | let mut result = tcx.predicates_defined_on(def_id); |
8faf50e0 XL |
1975 | |
1976 | if tcx.is_trait(def_id) { | |
1977 | // For traits, add `Self: Trait` predicate. This is | |
1978 | // not part of the predicates that a user writes, but it | |
1979 | // is something that one must prove in order to invoke a | |
1980 | // method or project an associated type. | |
1981 | // | |
1982 | // In the chalk setup, this predicate is not part of the | |
1983 | // "predicates" for a trait item. But it is useful in | |
1984 | // rustc because if you directly (e.g.) invoke a trait | |
1985 | // method like `Trait::method(...)`, you must naturally | |
1986 | // prove that the trait applies to the types that were | |
1987 | // used, and adding the predicate into this list ensures | |
1988 | // that this is done. | |
94222f64 XL |
1989 | let mut span = tcx.def_span(def_id); |
1990 | if tcx.sess.source_map().is_local_span(span) { | |
1991 | // `guess_head_span` reads the actual source file from | |
1992 | // disk to try to determine the 'head' snippet of the span. | |
1993 | // Don't do this for a span that comes from a file outside | |
1994 | // of our crate, since this would make our query output | |
1995 | // (and overall crate metadata) dependent on the | |
1996 | // *current* state of an external file. | |
1997 | span = tcx.sess.source_map().guess_head_span(span); | |
1998 | } | |
dfeec247 XL |
1999 | result.predicates = |
2000 | tcx.arena.alloc_from_iter(result.predicates.iter().copied().chain(std::iter::once(( | |
f9f354fc | 2001 | ty::TraitRef::identity(tcx, def_id).without_const().to_predicate(tcx), |
dfeec247 XL |
2002 | span, |
2003 | )))); | |
8faf50e0 | 2004 | } |
0731742a | 2005 | debug!("predicates_of(def_id={:?}) = {:?}", def_id, result); |
a1dfa0c6 | 2006 | result |
8faf50e0 XL |
2007 | } |
2008 | ||
9fa01778 XL |
2009 | /// Returns a list of user-specified type predicates for the definition with ID `def_id`. |
2010 | /// N.B., this does not include any implied/inferred constraints. | |
29967ef6 | 2011 | fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> { |
dfeec247 | 2012 | use rustc_hir::*; |
8bb4bdeb | 2013 | |
ff7c6d11 XL |
2014 | debug!("explicit_predicates_of(def_id={:?})", def_id); |
2015 | ||
3dfed10e | 2016 | let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); |
dc9dc135 | 2017 | let node = tcx.hir().get(hir_id); |
8bb4bdeb XL |
2018 | |
2019 | let mut is_trait = None; | |
0531ce1d | 2020 | let mut is_default_impl_trait = None; |
8bb4bdeb XL |
2021 | |
2022 | let icx = ItemCtxt::new(tcx, def_id); | |
dc9dc135 | 2023 | |
dfeec247 | 2024 | const NO_GENERICS: &hir::Generics<'_> = &hir::Generics::empty(); |
8faf50e0 | 2025 | |
1b1a35ee | 2026 | // We use an `IndexSet` to preserves order of insertion. |
5869c6ff | 2027 | // Preserving the order of insertion is important here so as not to break UI tests. |
1b1a35ee | 2028 | let mut predicates: FxIndexSet<(ty::Predicate<'_>, Span)> = FxIndexSet::default(); |
8faf50e0 | 2029 | |
ff7c6d11 | 2030 | let ast_generics = match node { |
29967ef6 | 2031 | Node::TraitItem(item) => &item.generics, |
f035d41b XL |
2032 | |
2033 | Node::ImplItem(item) => &item.generics, | |
8bb4bdeb | 2034 | |
b7449926 | 2035 | Node::Item(item) => { |
e74abb32 | 2036 | match item.kind { |
5869c6ff XL |
2037 | ItemKind::Impl(ref impl_) => { |
2038 | if impl_.defaultness.is_default() { | |
c295e0f8 | 2039 | is_default_impl_trait = tcx.impl_trait_ref(def_id).map(ty::Binder::dummy); |
0531ce1d | 2040 | } |
5869c6ff | 2041 | &impl_.generics |
0531ce1d | 2042 | } |
b7449926 | 2043 | ItemKind::Fn(.., ref generics, _) |
416331ca | 2044 | | ItemKind::TyAlias(_, ref generics) |
b7449926 XL |
2045 | | ItemKind::Enum(_, ref generics) |
2046 | | ItemKind::Struct(_, ref generics) | |
2047 | | ItemKind::Union(_, ref generics) => generics, | |
8faf50e0 | 2048 | |
29967ef6 XL |
2049 | ItemKind::Trait(_, _, ref generics, ..) => { |
2050 | is_trait = Some(ty::TraitRef::identity(tcx, def_id)); | |
ff7c6d11 | 2051 | generics |
8bb4bdeb | 2052 | } |
a1dfa0c6 | 2053 | ItemKind::TraitAlias(ref generics, _) => { |
29967ef6 | 2054 | is_trait = Some(ty::TraitRef::identity(tcx, def_id)); |
a1dfa0c6 XL |
2055 | generics |
2056 | } | |
416331ca | 2057 | ItemKind::OpaqueTy(OpaqueTy { |
29967ef6 | 2058 | bounds: _, |
b7449926 XL |
2059 | impl_trait_fn, |
2060 | ref generics, | |
532ac7d7 | 2061 | origin: _, |
b7449926 | 2062 | }) => { |
8faf50e0 | 2063 | if impl_trait_fn.is_some() { |
29967ef6 XL |
2064 | // return-position impl trait |
2065 | // | |
2066 | // We don't inherit predicates from the parent here: | |
2067 | // If we have, say `fn f<'a, T: 'a>() -> impl Sized {}` | |
2068 | // then the return type is `f::<'static, T>::{{opaque}}`. | |
2069 | // | |
2070 | // If we inherited the predicates of `f` then we would | |
2071 | // require that `T: 'static` to show that the return | |
2072 | // type is well-formed. | |
2073 | // | |
2074 | // The only way to have something with this opaque type | |
2075 | // is from the return type of the containing function, | |
2076 | // which will ensure that the function's predicates | |
2077 | // hold. | |
2078 | return ty::GenericPredicates { parent: None, predicates: &[] }; | |
8faf50e0 | 2079 | } else { |
29967ef6 | 2080 | // type-alias impl trait |
8faf50e0 XL |
2081 | generics |
2082 | } | |
94b46f34 | 2083 | } |
8bb4bdeb | 2084 | |
dc9dc135 | 2085 | _ => NO_GENERICS, |
8bb4bdeb XL |
2086 | } |
2087 | } | |
2088 | ||
e74abb32 | 2089 | Node::ForeignItem(item) => match item.kind { |
dc9dc135 | 2090 | ForeignItemKind::Static(..) => NO_GENERICS, |
b7449926 | 2091 | ForeignItemKind::Fn(_, _, ref generics) => generics, |
dc9dc135 | 2092 | ForeignItemKind::Type => NO_GENERICS, |
b7449926 | 2093 | }, |
8bb4bdeb | 2094 | |
dc9dc135 | 2095 | _ => NO_GENERICS, |
9e0c209e | 2096 | }; |
8bb4bdeb | 2097 | |
7cac9316 | 2098 | let generics = tcx.generics_of(def_id); |
94b46f34 | 2099 | let parent_count = generics.parent_count as u32; |
8bb4bdeb XL |
2100 | let has_own_self = generics.has_self && parent_count == 0; |
2101 | ||
8bb4bdeb XL |
2102 | // Below we'll consider the bounds on the type parameters (including `Self`) |
2103 | // and the explicit where-clauses, but to get the full set of predicates | |
2104 | // on a trait we need to add in the supertrait bounds and bounds found on | |
2105 | // associated types. | |
29967ef6 | 2106 | if let Some(_trait_ref) = is_trait { |
a1dfa0c6 | 2107 | predicates.extend(tcx.super_predicates_of(def_id).predicates.iter().cloned()); |
8bb4bdeb | 2108 | } |
c34b1796 | 2109 | |
0531ce1d XL |
2110 | // In default impls, we can assume that the self type implements |
2111 | // the trait. So in: | |
2112 | // | |
2113 | // default impl Foo for Bar { .. } | |
2114 | // | |
2115 | // we add a default where clause `Foo: Bar`. We do a similar thing for traits | |
2116 | // (see below). Recall that a default impl is not itself an impl, but rather a | |
2117 | // set of defaults that can be incorporated into another impl. | |
2118 | if let Some(trait_ref) = is_default_impl_trait { | |
c295e0f8 | 2119 | predicates.insert((trait_ref.without_const().to_predicate(tcx), tcx.def_span(def_id))); |
0531ce1d XL |
2120 | } |
2121 | ||
c34b1796 AL |
2122 | // Collect the region predicates that were declared inline as |
2123 | // well. In the case of parameters declared on a fn or method, we | |
2124 | // have to be careful to only iterate over early-bound regions. | |
8bb4bdeb XL |
2125 | let mut index = parent_count + has_own_self as u32; |
2126 | for param in early_bound_lifetimes_from_generics(tcx, ast_generics) { | |
2127 | let region = tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion { | |
f9f354fc | 2128 | def_id: tcx.hir().local_def_id(param.hir_id).to_def_id(), |
3b2f2976 | 2129 | index, |
e74abb32 | 2130 | name: param.name.ident().name, |
9e0c209e | 2131 | })); |
8bb4bdeb XL |
2132 | index += 1; |
2133 | ||
8faf50e0 XL |
2134 | match param.kind { |
2135 | GenericParamKind::Lifetime { .. } => { | |
2136 | param.bounds.iter().for_each(|bound| match bound { | |
2137 | hir::GenericBound::Outlives(lt) => { | |
c295e0f8 | 2138 | let bound = <dyn AstConv<'_>>::ast_region_to_region(&icx, lt, None); |
136023e0 | 2139 | let outlives = ty::Binder::dummy(ty::OutlivesPredicate(region, bound)); |
1b1a35ee | 2140 | predicates.insert((outlives.to_predicate(tcx), lt.span)); |
8faf50e0 XL |
2141 | } |
2142 | _ => bug!(), | |
2143 | }); | |
b7449926 | 2144 | } |
8faf50e0 | 2145 | _ => bug!(), |
c34b1796 | 2146 | } |
1a4d82fc JJ |
2147 | } |
2148 | ||
9e0c209e | 2149 | // Collect the predicates that were written inline by the user on each |
dc9dc135 | 2150 | // type parameter (e.g., `<T: Foo>`). |
dfeec247 | 2151 | for param in ast_generics.params { |
3dfed10e XL |
2152 | match param.kind { |
2153 | // We already dealt with early bound lifetimes above. | |
2154 | GenericParamKind::Lifetime { .. } => (), | |
2155 | GenericParamKind::Type { .. } => { | |
2156 | let name = param.name.ident().name; | |
2157 | let param_ty = ty::ParamTy::new(index, name).to_ty(tcx); | |
2158 | index += 1; | |
2159 | ||
c295e0f8 XL |
2160 | let mut bounds = <dyn AstConv<'_>>::compute_bounds(&icx, param_ty, param.bounds); |
2161 | // Params are implicitly sized unless a `?Sized` bound is found | |
2162 | <dyn AstConv<'_>>::add_implicitly_sized( | |
6a06907d | 2163 | &icx, |
c295e0f8 XL |
2164 | &mut bounds, |
2165 | param.bounds, | |
2166 | Some((param.hir_id, ast_generics.where_clause.predicates)), | |
6a06907d XL |
2167 | param.span, |
2168 | ); | |
3dfed10e XL |
2169 | predicates.extend(bounds.predicates(tcx, param_ty)); |
2170 | } | |
2171 | GenericParamKind::Const { .. } => { | |
2172 | // Bounds on const parameters are currently not possible. | |
2173 | debug_assert!(param.bounds.is_empty()); | |
2174 | index += 1; | |
2175 | } | |
8faf50e0 | 2176 | } |
9e0c209e SL |
2177 | } |
2178 | ||
dc9dc135 | 2179 | // Add in the bounds that appear in the where-clause. |
c34b1796 | 2180 | let where_clause = &ast_generics.where_clause; |
dfeec247 | 2181 | for predicate in where_clause.predicates { |
1a4d82fc | 2182 | match predicate { |
5869c6ff | 2183 | hir::WherePredicate::BoundPredicate(bound_pred) => { |
c295e0f8 | 2184 | let ty = icx.to_ty(bound_pred.bounded_ty); |
cdc7bbd5 | 2185 | let bound_vars = icx.tcx.late_bound_vars(bound_pred.bounded_ty.hir_id); |
1a4d82fc | 2186 | |
a1dfa0c6 XL |
2187 | // Keep the type around in a dummy predicate, in case of no bounds. |
2188 | // That way, `where Ty:` is not a complete noop (see #53696) and `Ty` | |
2189 | // is still checked for WF. | |
b7449926 | 2190 | if bound_pred.bounds.is_empty() { |
1b1a35ee | 2191 | if let ty::Param(_) = ty.kind() { |
b7449926 XL |
2192 | // This is a `where T:`, which can be in the HIR from the |
2193 | // transformation that moves `?Sized` to `T`'s declaration. | |
2194 | // We can skip the predicate because type parameters are | |
2195 | // trivially WF, but also we *should*, to avoid exposing | |
2196 | // users who never wrote `where Type:,` themselves, to | |
2197 | // compiler/tooling bugs from not handling WF predicates. | |
2198 | } else { | |
0bf4aa26 | 2199 | let span = bound_pred.bounded_ty.span; |
74b04a01 | 2200 | let re_root_empty = tcx.lifetimes.re_root_empty; |
cdc7bbd5 XL |
2201 | let predicate = ty::Binder::bind_with_vars( |
2202 | ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate( | |
2203 | ty, | |
2204 | re_root_empty, | |
2205 | )), | |
2206 | bound_vars, | |
2207 | ); | |
5869c6ff | 2208 | predicates.insert((predicate.to_predicate(tcx), span)); |
b7449926 XL |
2209 | } |
2210 | } | |
2211 | ||
c295e0f8 XL |
2212 | let mut bounds = Bounds::default(); |
2213 | <dyn AstConv<'_>>::add_bounds( | |
2214 | &icx, | |
2215 | ty, | |
2216 | bound_pred.bounds.iter(), | |
2217 | &mut bounds, | |
2218 | bound_vars, | |
2219 | ); | |
2220 | predicates.extend(bounds.predicates(tcx, ty)); | |
1a4d82fc JJ |
2221 | } |
2222 | ||
5869c6ff | 2223 | hir::WherePredicate::RegionPredicate(region_pred) => { |
6a06907d | 2224 | let r1 = <dyn AstConv<'_>>::ast_region_to_region(&icx, ®ion_pred.lifetime, None); |
0bf4aa26 XL |
2225 | predicates.extend(region_pred.bounds.iter().map(|bound| { |
2226 | let (r2, span) = match bound { | |
8faf50e0 | 2227 | hir::GenericBound::Outlives(lt) => { |
6a06907d | 2228 | (<dyn AstConv<'_>>::ast_region_to_region(&icx, lt, None), lt.span) |
8faf50e0 XL |
2229 | } |
2230 | _ => bug!(), | |
2231 | }; | |
c295e0f8 XL |
2232 | let pred = ty::Binder::dummy(ty::PredicateKind::RegionOutlives( |
2233 | ty::OutlivesPredicate(r1, r2), | |
2234 | )) | |
2235 | .to_predicate(icx.tcx); | |
0bf4aa26 | 2236 | |
fc512014 | 2237 | (pred, span) |
0bf4aa26 | 2238 | })) |
1a4d82fc JJ |
2239 | } |
2240 | ||
5869c6ff | 2241 | hir::WherePredicate::EqPredicate(..) => { |
1a4d82fc | 2242 | // FIXME(#20041) |
1a4d82fc JJ |
2243 | } |
2244 | } | |
2245 | } | |
2246 | ||
94222f64 | 2247 | if tcx.features().generic_const_exprs { |
1b1a35ee XL |
2248 | predicates.extend(const_evaluatable_predicates_of(tcx, def_id.expect_local())); |
2249 | } | |
2250 | ||
2251 | let mut predicates: Vec<_> = predicates.into_iter().collect(); | |
0bf4aa26 | 2252 | |
8bb4bdeb XL |
2253 | // Subtle: before we store the predicates into the tcx, we |
2254 | // sort them so that predicates like `T: Foo<Item=U>` come | |
2255 | // before uses of `U`. This avoids false ambiguity errors | |
2256 | // in trait checking. See `setup_constraining_predicates` | |
2257 | // for details. | |
dfeec247 | 2258 | if let Node::Item(&Item { kind: ItemKind::Impl { .. }, .. }) = node { |
7cac9316 | 2259 | let self_ty = tcx.type_of(def_id); |
8bb4bdeb | 2260 | let trait_ref = tcx.impl_trait_ref(def_id); |
48663c56 | 2261 | cgp::setup_constraining_predicates( |
b7449926 XL |
2262 | tcx, |
2263 | &mut predicates, | |
2264 | trait_ref, | |
94222f64 | 2265 | &mut cgp::parameters_for_impl(tcx, self_ty, trait_ref), |
b7449926 | 2266 | ); |
9e0c209e SL |
2267 | } |
2268 | ||
e74abb32 | 2269 | let result = ty::GenericPredicates { |
8bb4bdeb | 2270 | parent: generics.parent, |
e74abb32 XL |
2271 | predicates: tcx.arena.alloc_from_iter(predicates), |
2272 | }; | |
0731742a XL |
2273 | debug!("explicit_predicates_of(def_id={:?}) = {:?}", def_id, result); |
2274 | result | |
1a4d82fc JJ |
2275 | } |
2276 | ||
1b1a35ee XL |
2277 | fn const_evaluatable_predicates_of<'tcx>( |
2278 | tcx: TyCtxt<'tcx>, | |
2279 | def_id: LocalDefId, | |
2280 | ) -> FxIndexSet<(ty::Predicate<'tcx>, Span)> { | |
2281 | struct ConstCollector<'tcx> { | |
2282 | tcx: TyCtxt<'tcx>, | |
2283 | preds: FxIndexSet<(ty::Predicate<'tcx>, Span)>, | |
2284 | } | |
2285 | ||
2286 | impl<'tcx> intravisit::Visitor<'tcx> for ConstCollector<'tcx> { | |
2287 | type Map = Map<'tcx>; | |
2288 | ||
2289 | fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> { | |
2290 | intravisit::NestedVisitorMap::None | |
2291 | } | |
2292 | ||
2293 | fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) { | |
2294 | let def_id = self.tcx.hir().local_def_id(c.hir_id); | |
2295 | let ct = ty::Const::from_anon_const(self.tcx, def_id); | |
cdc7bbd5 XL |
2296 | if let ty::ConstKind::Unevaluated(uv) = ct.val { |
2297 | assert_eq!(uv.promoted, None); | |
1b1a35ee XL |
2298 | let span = self.tcx.hir().span(c.hir_id); |
2299 | self.preds.insert(( | |
c295e0f8 XL |
2300 | ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(uv.shrink())) |
2301 | .to_predicate(self.tcx), | |
1b1a35ee XL |
2302 | span, |
2303 | )); | |
2304 | } | |
2305 | } | |
136023e0 XL |
2306 | |
2307 | fn visit_const_param_default(&mut self, _param: HirId, _ct: &'tcx hir::AnonConst) { | |
2308 | // Do not look into const param defaults, | |
2309 | // these get checked when they are actually instantiated. | |
2310 | // | |
2311 | // We do not want the following to error: | |
2312 | // | |
2313 | // struct Foo<const N: usize, const M: usize = { N + 1 }>; | |
2314 | // struct Bar<const N: usize>(Foo<N, 3>); | |
2315 | } | |
1b1a35ee XL |
2316 | } |
2317 | ||
2318 | let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); | |
2319 | let node = tcx.hir().get(hir_id); | |
2320 | ||
2321 | let mut collector = ConstCollector { tcx, preds: FxIndexSet::default() }; | |
2322 | if let hir::Node::Item(item) = node { | |
5869c6ff XL |
2323 | if let hir::ItemKind::Impl(ref impl_) = item.kind { |
2324 | if let Some(of_trait) = &impl_.of_trait { | |
29967ef6 | 2325 | debug!("const_evaluatable_predicates_of({:?}): visit impl trait_ref", def_id); |
1b1a35ee XL |
2326 | collector.visit_trait_ref(of_trait); |
2327 | } | |
2328 | ||
29967ef6 | 2329 | debug!("const_evaluatable_predicates_of({:?}): visit_self_ty", def_id); |
5869c6ff | 2330 | collector.visit_ty(impl_.self_ty); |
1b1a35ee XL |
2331 | } |
2332 | } | |
2333 | ||
2334 | if let Some(generics) = node.generics() { | |
29967ef6 | 2335 | debug!("const_evaluatable_predicates_of({:?}): visit_generics", def_id); |
1b1a35ee XL |
2336 | collector.visit_generics(generics); |
2337 | } | |
2338 | ||
2339 | if let Some(fn_sig) = tcx.hir().fn_sig_by_hir_id(hir_id) { | |
29967ef6 | 2340 | debug!("const_evaluatable_predicates_of({:?}): visit_fn_decl", def_id); |
1b1a35ee XL |
2341 | collector.visit_fn_decl(fn_sig.decl); |
2342 | } | |
29967ef6 | 2343 | debug!("const_evaluatable_predicates_of({:?}) = {:?}", def_id, collector.preds); |
1b1a35ee XL |
2344 | |
2345 | collector.preds | |
2346 | } | |
2347 | ||
29967ef6 XL |
2348 | fn trait_explicit_predicates_and_bounds( |
2349 | tcx: TyCtxt<'_>, | |
2350 | def_id: LocalDefId, | |
2351 | ) -> ty::GenericPredicates<'_> { | |
2352 | assert_eq!(tcx.def_kind(def_id), DefKind::Trait); | |
2353 | gather_explicit_predicates_of(tcx, def_id.to_def_id()) | |
2354 | } | |
2355 | ||
2356 | fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> { | |
94222f64 XL |
2357 | let def_kind = tcx.def_kind(def_id); |
2358 | if let DefKind::Trait = def_kind { | |
29967ef6 XL |
2359 | // Remove bounds on associated types from the predicates, they will be |
2360 | // returned by `explicit_item_bounds`. | |
2361 | let predicates_and_bounds = tcx.trait_explicit_predicates_and_bounds(def_id.expect_local()); | |
2362 | let trait_identity_substs = InternalSubsts::identity_for_item(tcx, def_id); | |
2363 | ||
2364 | let is_assoc_item_ty = |ty: Ty<'_>| { | |
2365 | // For a predicate from a where clause to become a bound on an | |
2366 | // associated type: | |
2367 | // * It must use the identity substs of the item. | |
2368 | // * Since any generic parameters on the item are not in scope, | |
2369 | // this means that the item is not a GAT, and its identity | |
2370 | // substs are the same as the trait's. | |
2371 | // * It must be an associated type for this trait (*not* a | |
2372 | // supertrait). | |
2373 | if let ty::Projection(projection) = ty.kind() { | |
fc512014 | 2374 | projection.substs == trait_identity_substs |
29967ef6 | 2375 | && tcx.associated_item(projection.item_def_id).container.id() == def_id |
29967ef6 XL |
2376 | } else { |
2377 | false | |
2378 | } | |
2379 | }; | |
2380 | ||
2381 | let predicates: Vec<_> = predicates_and_bounds | |
2382 | .predicates | |
2383 | .iter() | |
2384 | .copied() | |
5869c6ff | 2385 | .filter(|(pred, _)| match pred.kind().skip_binder() { |
94222f64 | 2386 | ty::PredicateKind::Trait(tr) => !is_assoc_item_ty(tr.self_ty()), |
5869c6ff | 2387 | ty::PredicateKind::Projection(proj) => { |
29967ef6 XL |
2388 | !is_assoc_item_ty(proj.projection_ty.self_ty()) |
2389 | } | |
5869c6ff | 2390 | ty::PredicateKind::TypeOutlives(outlives) => !is_assoc_item_ty(outlives.0), |
29967ef6 XL |
2391 | _ => true, |
2392 | }) | |
2393 | .collect(); | |
2394 | if predicates.len() == predicates_and_bounds.predicates.len() { | |
2395 | predicates_and_bounds | |
2396 | } else { | |
2397 | ty::GenericPredicates { | |
2398 | parent: predicates_and_bounds.parent, | |
2399 | predicates: tcx.arena.alloc_slice(&predicates), | |
2400 | } | |
2401 | } | |
2402 | } else { | |
94222f64 XL |
2403 | if matches!(def_kind, DefKind::AnonConst) && tcx.lazy_normalization() { |
2404 | let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); | |
c295e0f8 | 2405 | if tcx.hir().opt_const_param_default_param_hir_id(hir_id).is_some() { |
94222f64 XL |
2406 | // In `generics_of` we set the generics' parent to be our parent's parent which means that |
2407 | // we lose out on the predicates of our actual parent if we dont return those predicates here. | |
2408 | // (See comment in `generics_of` for more information on why the parent shenanigans is necessary) | |
2409 | // | |
2410 | // struct Foo<T, const N: usize = { <T as Trait>::ASSOC }>(T) where T: Trait; | |
2411 | // ^^^ ^^^^^^^^^^^^^^^^^^^^^^^ the def id we are calling | |
2412 | // ^^^ explicit_predicates_of on | |
2413 | // parent item we dont have set as the | |
2414 | // parent of generics returned by `generics_of` | |
2415 | // | |
2416 | // In the above code we want the anon const to have predicates in its param env for `T: Trait` | |
2417 | let item_id = tcx.hir().get_parent_item(hir_id); | |
2418 | let item_def_id = tcx.hir().local_def_id(item_id).to_def_id(); | |
2419 | // In the above code example we would be calling `explicit_predicates_of(Foo)` here | |
2420 | return tcx.explicit_predicates_of(item_def_id); | |
2421 | } | |
2422 | } | |
29967ef6 XL |
2423 | gather_explicit_predicates_of(tcx, def_id) |
2424 | } | |
2425 | } | |
2426 | ||
a1dfa0c6 | 2427 | /// Converts a specific `GenericBound` from the AST into a set of |
9fa01778 XL |
2428 | /// predicates that apply to the self type. A vector is returned |
2429 | /// because this can be anywhere from zero predicates (`T: ?Sized` adds no | |
416331ca | 2430 | /// predicates) to one (`T: Foo`) to many (`T: Bar<X = i32>` adds `T: Bar` |
c34b1796 | 2431 | /// and `<T as Bar>::X == i32`). |
b7449926 | 2432 | fn predicates_from_bound<'tcx>( |
dc9dc135 | 2433 | astconv: &dyn AstConv<'tcx>, |
b7449926 | 2434 | param_ty: Ty<'tcx>, |
dfeec247 | 2435 | bound: &'tcx hir::GenericBound<'tcx>, |
0bf4aa26 | 2436 | ) -> Vec<(ty::Predicate<'tcx>, Span)> { |
c295e0f8 XL |
2437 | let mut bounds = Bounds::default(); |
2438 | astconv.add_bounds( | |
2439 | param_ty, | |
2440 | std::array::IntoIter::new([bound]), | |
2441 | &mut bounds, | |
2442 | ty::List::empty(), | |
2443 | ); | |
2444 | bounds.predicates(astconv.tcx(), param_ty) | |
1a4d82fc JJ |
2445 | } |
2446 | ||
dc9dc135 XL |
2447 | fn compute_sig_of_foreign_fn_decl<'tcx>( |
2448 | tcx: TyCtxt<'tcx>, | |
9e0c209e | 2449 | def_id: DefId, |
dfeec247 | 2450 | decl: &'tcx hir::FnDecl<'tcx>, |
b7449926 | 2451 | abi: abi::Abi, |
ba9703b0 | 2452 | ident: Ident, |
b7449926 XL |
2453 | ) -> ty::PolyFnSig<'tcx> { |
2454 | let unsafety = if abi == abi::Abi::RustIntrinsic { | |
f035d41b | 2455 | intrinsic_operation_unsafety(tcx.item_name(def_id)) |
b7449926 XL |
2456 | } else { |
2457 | hir::Unsafety::Unsafe | |
2458 | }; | |
cdc7bbd5 | 2459 | let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); |
6a06907d | 2460 | let fty = <dyn AstConv<'_>>::ty_of_fn( |
74b04a01 | 2461 | &ItemCtxt::new(tcx, def_id), |
cdc7bbd5 | 2462 | hir_id, |
74b04a01 XL |
2463 | unsafety, |
2464 | abi, | |
2465 | decl, | |
2466 | &hir::Generics::empty(), | |
ba9703b0 | 2467 | Some(ident.span), |
6a06907d | 2468 | None, |
74b04a01 | 2469 | ); |
1a4d82fc | 2470 | |
dc9dc135 XL |
2471 | // Feature gate SIMD types in FFI, since I am not sure that the |
2472 | // ABIs are handled at all correctly. -huonw | |
b7449926 XL |
2473 | if abi != abi::Abi::RustIntrinsic |
2474 | && abi != abi::Abi::PlatformIntrinsic | |
2475 | && !tcx.features().simd_ffi | |
2476 | { | |
dfeec247 | 2477 | let check = |ast_ty: &hir::Ty<'_>, ty: Ty<'_>| { |
54a0048b | 2478 | if ty.is_simd() { |
ba9703b0 XL |
2479 | let snip = tcx |
2480 | .sess | |
2481 | .source_map() | |
2482 | .span_to_snippet(ast_ty.span) | |
6a06907d | 2483 | .map_or_else(|_| String::new(), |s| format!(" `{}`", s)); |
b7449926 | 2484 | tcx.sess |
dfeec247 XL |
2485 | .struct_span_err( |
2486 | ast_ty.span, | |
2487 | &format!( | |
ba9703b0 | 2488 | "use of SIMD type{} in FFI is highly experimental and \ |
74b04a01 | 2489 | may result in invalid code", |
ba9703b0 | 2490 | snip |
dfeec247 XL |
2491 | ), |
2492 | ) | |
2493 | .help("add `#![feature(simd_ffi)]` to the crate attributes to enable") | |
2494 | .emit(); | |
54a0048b SL |
2495 | } |
2496 | }; | |
cdc7bbd5 | 2497 | for (input, ty) in iter::zip(decl.inputs, fty.inputs().skip_binder()) { |
c295e0f8 | 2498 | check(input, ty) |
54a0048b | 2499 | } |
74b04a01 | 2500 | if let hir::FnRetTy::Return(ref ty) = decl.output { |
c295e0f8 | 2501 | check(ty, fty.output().skip_binder()) |
54a0048b SL |
2502 | } |
2503 | } | |
2504 | ||
041b39d2 | 2505 | fty |
1a4d82fc | 2506 | } |
cc61c64b | 2507 | |
416331ca | 2508 | fn is_foreign_item(tcx: TyCtxt<'_>, def_id: DefId) -> bool { |
0731742a | 2509 | match tcx.hir().get_if_local(def_id) { |
b7449926 | 2510 | Some(Node::ForeignItem(..)) => true, |
cc61c64b | 2511 | Some(_) => false, |
b7449926 | 2512 | _ => bug!("is_foreign_item applied to non-local def-id {:?}", def_id), |
cc61c64b XL |
2513 | } |
2514 | } | |
0531ce1d | 2515 | |
416331ca | 2516 | fn static_mutability(tcx: TyCtxt<'_>, def_id: DefId) -> Option<hir::Mutability> { |
48663c56 | 2517 | match tcx.hir().get_if_local(def_id) { |
ba9703b0 XL |
2518 | Some( |
2519 | Node::Item(&hir::Item { kind: hir::ItemKind::Static(_, mutbl, _), .. }) | |
2520 | | Node::ForeignItem(&hir::ForeignItem { | |
2521 | kind: hir::ForeignItemKind::Static(_, mutbl), | |
2522 | .. | |
2523 | }), | |
2524 | ) => Some(mutbl), | |
48663c56 XL |
2525 | Some(_) => None, |
2526 | _ => bug!("static_mutability applied to non-local def-id {:?}", def_id), | |
2527 | } | |
2528 | } | |
2529 | ||
74b04a01 XL |
2530 | fn generator_kind(tcx: TyCtxt<'_>, def_id: DefId) -> Option<hir::GeneratorKind> { |
2531 | match tcx.hir().get_if_local(def_id) { | |
2532 | Some(Node::Expr(&rustc_hir::Expr { | |
2533 | kind: rustc_hir::ExprKind::Closure(_, _, body_id, _, _), | |
2534 | .. | |
2535 | })) => tcx.hir().body(body_id).generator_kind(), | |
2536 | Some(_) => None, | |
2537 | _ => bug!("generator_kind applied to non-local def-id {:?}", def_id), | |
2538 | } | |
2539 | } | |
2540 | ||
0531ce1d | 2541 | fn from_target_feature( |
dc9dc135 | 2542 | tcx: TyCtxt<'_>, |
83c7162d | 2543 | id: DefId, |
0531ce1d | 2544 | attr: &ast::Attribute, |
f035d41b | 2545 | supported_target_features: &FxHashMap<String, Option<Symbol>>, |
0531ce1d XL |
2546 | target_features: &mut Vec<Symbol>, |
2547 | ) { | |
2548 | let list = match attr.meta_item_list() { | |
2549 | Some(list) => list, | |
9fa01778 | 2550 | None => return, |
0531ce1d | 2551 | }; |
dc9dc135 XL |
2552 | let bad_item = |span| { |
2553 | let msg = "malformed `target_feature` attribute input"; | |
2554 | let code = "enable = \"..\"".to_owned(); | |
dfeec247 | 2555 | tcx.sess |
c295e0f8 | 2556 | .struct_span_err(span, msg) |
dc9dc135 XL |
2557 | .span_suggestion(span, "must be of the form", code, Applicability::HasPlaceholders) |
2558 | .emit(); | |
2559 | }; | |
83c7162d | 2560 | let rust_features = tcx.features(); |
0531ce1d | 2561 | for item in list { |
dc9dc135 | 2562 | // Only `enable = ...` is accepted in the meta-item list. |
3dfed10e | 2563 | if !item.has_name(sym::enable) { |
dc9dc135 | 2564 | bad_item(item.span()); |
b7449926 | 2565 | continue; |
0531ce1d | 2566 | } |
83c7162d | 2567 | |
dc9dc135 | 2568 | // Must be of the form `enable = "..."` (a string). |
0531ce1d | 2569 | let value = match item.value_str() { |
83c7162d | 2570 | Some(value) => value, |
0531ce1d | 2571 | None => { |
dc9dc135 | 2572 | bad_item(item.span()); |
b7449926 | 2573 | continue; |
0531ce1d XL |
2574 | } |
2575 | }; | |
0531ce1d | 2576 | |
dc9dc135 | 2577 | // We allow comma separation to enable multiple features. |
0bf4aa26 | 2578 | target_features.extend(value.as_str().split(',').filter_map(|feature| { |
f035d41b | 2579 | let feature_gate = match supported_target_features.get(feature) { |
83c7162d XL |
2580 | Some(g) => g, |
2581 | None => { | |
dfeec247 XL |
2582 | let msg = |
2583 | format!("the feature named `{}` is not valid for this target", feature); | |
532ac7d7 | 2584 | let mut err = tcx.sess.struct_span_err(item.span(), &msg); |
dc9dc135 XL |
2585 | err.span_label( |
2586 | item.span(), | |
2587 | format!("`{}` is not valid for this target", feature), | |
2588 | ); | |
1b1a35ee XL |
2589 | if let Some(stripped) = feature.strip_prefix('+') { |
2590 | let valid = supported_target_features.contains_key(stripped); | |
83c7162d XL |
2591 | if valid { |
2592 | err.help("consider removing the leading `+` in the feature name"); | |
2593 | } | |
2594 | } | |
2595 | err.emit(); | |
0bf4aa26 | 2596 | return None; |
0531ce1d | 2597 | } |
83c7162d XL |
2598 | }; |
2599 | ||
dc9dc135 | 2600 | // Only allow features whose feature gates have been enabled. |
74b04a01 | 2601 | let allowed = match feature_gate.as_ref().copied() { |
48663c56 XL |
2602 | Some(sym::arm_target_feature) => rust_features.arm_target_feature, |
2603 | Some(sym::aarch64_target_feature) => rust_features.aarch64_target_feature, | |
2604 | Some(sym::hexagon_target_feature) => rust_features.hexagon_target_feature, | |
2605 | Some(sym::powerpc_target_feature) => rust_features.powerpc_target_feature, | |
2606 | Some(sym::mips_target_feature) => rust_features.mips_target_feature, | |
f9f354fc | 2607 | Some(sym::riscv_target_feature) => rust_features.riscv_target_feature, |
48663c56 | 2608 | Some(sym::avx512_target_feature) => rust_features.avx512_target_feature, |
48663c56 XL |
2609 | Some(sym::sse4a_target_feature) => rust_features.sse4a_target_feature, |
2610 | Some(sym::tbm_target_feature) => rust_features.tbm_target_feature, | |
2611 | Some(sym::wasm_target_feature) => rust_features.wasm_target_feature, | |
2612 | Some(sym::cmpxchg16b_target_feature) => rust_features.cmpxchg16b_target_feature, | |
2613 | Some(sym::adx_target_feature) => rust_features.adx_target_feature, | |
2614 | Some(sym::movbe_target_feature) => rust_features.movbe_target_feature, | |
2615 | Some(sym::rtm_target_feature) => rust_features.rtm_target_feature, | |
2616 | Some(sym::f16c_target_feature) => rust_features.f16c_target_feature, | |
29967ef6 | 2617 | Some(sym::ermsb_target_feature) => rust_features.ermsb_target_feature, |
17df50a5 | 2618 | Some(sym::bpf_target_feature) => rust_features.bpf_target_feature, |
83c7162d XL |
2619 | Some(name) => bug!("unknown target feature gate {}", name), |
2620 | None => true, | |
2621 | }; | |
2622 | if !allowed && id.is_local() { | |
dfeec247 | 2623 | feature_err( |
83c7162d | 2624 | &tcx.sess.parse_sess, |
48663c56 | 2625 | feature_gate.unwrap(), |
532ac7d7 | 2626 | item.span(), |
b7449926 | 2627 | &format!("the target feature `{}` is currently unstable", feature), |
60c5eb7d XL |
2628 | ) |
2629 | .emit(); | |
0531ce1d | 2630 | } |
0bf4aa26 XL |
2631 | Some(Symbol::intern(feature)) |
2632 | })); | |
0531ce1d XL |
2633 | } |
2634 | } | |
2635 | ||
416331ca | 2636 | fn linkage_by_name(tcx: TyCtxt<'_>, def_id: DefId, name: &str) -> Linkage { |
ba9703b0 | 2637 | use rustc_middle::mir::mono::Linkage::*; |
0531ce1d XL |
2638 | |
2639 | // Use the names from src/llvm/docs/LangRef.rst here. Most types are only | |
2640 | // applicable to variable declarations and may not really make sense for | |
f035d41b XL |
2641 | // Rust code in the first place but allow them anyway and trust that the |
2642 | // user knows what s/he's doing. Who knows, unanticipated use cases may pop | |
2643 | // up in the future. | |
0531ce1d XL |
2644 | // |
2645 | // ghost, dllimport, dllexport and linkonce_odr_autohide are not supported | |
2646 | // and don't have to be, LLVM treats them as no-ops. | |
2647 | match name { | |
2648 | "appending" => Appending, | |
2649 | "available_externally" => AvailableExternally, | |
2650 | "common" => Common, | |
2651 | "extern_weak" => ExternalWeak, | |
2652 | "external" => External, | |
2653 | "internal" => Internal, | |
2654 | "linkonce" => LinkOnceAny, | |
2655 | "linkonce_odr" => LinkOnceODR, | |
2656 | "private" => Private, | |
2657 | "weak" => WeakAny, | |
2658 | "weak_odr" => WeakODR, | |
2659 | _ => { | |
0731742a | 2660 | let span = tcx.hir().span_if_local(def_id); |
0531ce1d XL |
2661 | if let Some(span) = span { |
2662 | tcx.sess.span_fatal(span, "invalid linkage specified") | |
2663 | } else { | |
dfeec247 | 2664 | tcx.sess.fatal(&format!("invalid linkage specified: {}", name)) |
0531ce1d XL |
2665 | } |
2666 | } | |
2667 | } | |
2668 | } | |
2669 | ||
416331ca | 2670 | fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { |
0531ce1d XL |
2671 | let attrs = tcx.get_attrs(id); |
2672 | ||
94b46f34 | 2673 | let mut codegen_fn_attrs = CodegenFnAttrs::new(); |
136023e0 | 2674 | if tcx.should_inherit_track_caller(id) { |
ba9703b0 XL |
2675 | codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER; |
2676 | } | |
0531ce1d | 2677 | |
c295e0f8 XL |
2678 | // With -Z panic-in-drop=abort, drop_in_place never unwinds. |
2679 | if tcx.sess.opts.debugging_opts.panic_in_drop == PanicStrategy::Abort { | |
2680 | if Some(id) == tcx.lang_items().drop_in_place_fn() { | |
2681 | codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND; | |
2682 | } | |
2683 | } | |
2684 | ||
f035d41b | 2685 | let supported_target_features = tcx.supported_target_features(LOCAL_CRATE); |
0531ce1d XL |
2686 | |
2687 | let mut inline_span = None; | |
e74abb32 | 2688 | let mut link_ordinal_span = None; |
74b04a01 | 2689 | let mut no_sanitize_span = None; |
0531ce1d | 2690 | for attr in attrs.iter() { |
94222f64 | 2691 | if attr.has_name(sym::cold) { |
94b46f34 | 2692 | codegen_fn_attrs.flags |= CodegenFnAttrFlags::COLD; |
94222f64 | 2693 | } else if attr.has_name(sym::rustc_allocator) { |
94b46f34 | 2694 | codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR; |
94222f64 | 2695 | } else if attr.has_name(sym::ffi_returns_twice) { |
9fa01778 XL |
2696 | if tcx.is_foreign_item(id) { |
2697 | codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_RETURNS_TWICE; | |
2698 | } else { | |
dc9dc135 | 2699 | // `#[ffi_returns_twice]` is only allowed `extern fn`s. |
9fa01778 XL |
2700 | struct_span_err!( |
2701 | tcx.sess, | |
2702 | attr.span, | |
2703 | E0724, | |
2704 | "`#[ffi_returns_twice]` may only be used on foreign functions" | |
dfeec247 XL |
2705 | ) |
2706 | .emit(); | |
9fa01778 | 2707 | } |
94222f64 | 2708 | } else if attr.has_name(sym::ffi_pure) { |
f9f354fc | 2709 | if tcx.is_foreign_item(id) { |
94222f64 | 2710 | if attrs.iter().any(|a| a.has_name(sym::ffi_const)) { |
f9f354fc XL |
2711 | // `#[ffi_const]` functions cannot be `#[ffi_pure]` |
2712 | struct_span_err!( | |
2713 | tcx.sess, | |
2714 | attr.span, | |
2715 | E0757, | |
2716 | "`#[ffi_const]` function cannot be `#[ffi_pure]`" | |
2717 | ) | |
2718 | .emit(); | |
2719 | } else { | |
2720 | codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_PURE; | |
2721 | } | |
2722 | } else { | |
2723 | // `#[ffi_pure]` is only allowed on foreign functions | |
2724 | struct_span_err!( | |
2725 | tcx.sess, | |
2726 | attr.span, | |
2727 | E0755, | |
2728 | "`#[ffi_pure]` may only be used on foreign functions" | |
2729 | ) | |
2730 | .emit(); | |
2731 | } | |
94222f64 | 2732 | } else if attr.has_name(sym::ffi_const) { |
f9f354fc XL |
2733 | if tcx.is_foreign_item(id) { |
2734 | codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_CONST; | |
2735 | } else { | |
2736 | // `#[ffi_const]` is only allowed on foreign functions | |
2737 | struct_span_err!( | |
2738 | tcx.sess, | |
2739 | attr.span, | |
2740 | E0756, | |
2741 | "`#[ffi_const]` may only be used on foreign functions" | |
2742 | ) | |
2743 | .emit(); | |
2744 | } | |
94222f64 XL |
2745 | } else if attr.has_name(sym::rustc_allocator_nounwind) { |
2746 | codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND; | |
2747 | } else if attr.has_name(sym::naked) { | |
94b46f34 | 2748 | codegen_fn_attrs.flags |= CodegenFnAttrFlags::NAKED; |
94222f64 | 2749 | } else if attr.has_name(sym::no_mangle) { |
94b46f34 | 2750 | codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE; |
94222f64 | 2751 | } else if attr.has_name(sym::no_coverage) { |
cdc7bbd5 | 2752 | codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_COVERAGE; |
94222f64 | 2753 | } else if attr.has_name(sym::rustc_std_internal_symbol) { |
94b46f34 | 2754 | codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL; |
94222f64 | 2755 | } else if attr.has_name(sym::used) { |
8faf50e0 | 2756 | codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED; |
94222f64 | 2757 | } else if attr.has_name(sym::cmse_nonsecure_entry) { |
6a06907d | 2758 | if !matches!(tcx.fn_sig(id).abi(), abi::Abi::C { .. }) { |
1b1a35ee XL |
2759 | struct_span_err!( |
2760 | tcx.sess, | |
2761 | attr.span, | |
2762 | E0776, | |
2763 | "`#[cmse_nonsecure_entry]` requires C ABI" | |
2764 | ) | |
2765 | .emit(); | |
2766 | } | |
29967ef6 | 2767 | if !tcx.sess.target.llvm_target.contains("thumbv8m") { |
1b1a35ee XL |
2768 | struct_span_err!(tcx.sess, attr.span, E0775, "`#[cmse_nonsecure_entry]` is only valid for targets with the TrustZone-M extension") |
2769 | .emit(); | |
2770 | } | |
2771 | codegen_fn_attrs.flags |= CodegenFnAttrFlags::CMSE_NONSECURE_ENTRY; | |
94222f64 | 2772 | } else if attr.has_name(sym::thread_local) { |
8faf50e0 | 2773 | codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL; |
94222f64 | 2774 | } else if attr.has_name(sym::track_caller) { |
c295e0f8 | 2775 | if !tcx.is_closure(id) && tcx.fn_sig(id).abi() != abi::Abi::Rust { |
dfeec247 XL |
2776 | struct_span_err!(tcx.sess, attr.span, E0737, "`#[track_caller]` requires Rust ABI") |
2777 | .emit(); | |
e74abb32 | 2778 | } |
c295e0f8 XL |
2779 | if tcx.is_closure(id) && !tcx.features().closure_track_caller { |
2780 | feature_err( | |
2781 | &tcx.sess.parse_sess, | |
2782 | sym::closure_track_caller, | |
2783 | attr.span, | |
2784 | "`#[track_caller]` on closures is currently unstable", | |
2785 | ) | |
2786 | .emit(); | |
2787 | } | |
e74abb32 | 2788 | codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER; |
94222f64 | 2789 | } else if attr.has_name(sym::export_name) { |
8faf50e0 | 2790 | if let Some(s) = attr.value_str() { |
74b04a01 | 2791 | if s.as_str().contains('\0') { |
8faf50e0 XL |
2792 | // `#[export_name = ...]` will be converted to a null-terminated string, |
2793 | // so it may not contain any null characters. | |
b7449926 XL |
2794 | struct_span_err!( |
2795 | tcx.sess, | |
2796 | attr.span, | |
2797 | E0648, | |
2798 | "`export_name` may not contain null characters" | |
dfeec247 XL |
2799 | ) |
2800 | .emit(); | |
8faf50e0 XL |
2801 | } |
2802 | codegen_fn_attrs.export_name = Some(s); | |
0531ce1d | 2803 | } |
94222f64 | 2804 | } else if attr.has_name(sym::target_feature) { |
1b1a35ee | 2805 | if !tcx.is_closure(id) && tcx.fn_sig(id).unsafety() == hir::Unsafety::Normal { |
17df50a5 XL |
2806 | if tcx.sess.target.is_like_wasm || tcx.sess.opts.actually_rustdoc { |
2807 | // The `#[target_feature]` attribute is allowed on | |
2808 | // WebAssembly targets on all functions, including safe | |
2809 | // ones. Other targets require that `#[target_feature]` is | |
2810 | // only applied to unsafe funtions (pending the | |
2811 | // `target_feature_11` feature) because on most targets | |
2812 | // execution of instructions that are not supported is | |
2813 | // considered undefined behavior. For WebAssembly which is a | |
2814 | // 100% safe target at execution time it's not possible to | |
2815 | // execute undefined instructions, and even if a future | |
2816 | // feature was added in some form for this it would be a | |
2817 | // deterministic trap. There is no undefined behavior when | |
2818 | // executing WebAssembly so `#[target_feature]` is allowed | |
2819 | // on safe functions (but again, only for WebAssembly) | |
2820 | // | |
2821 | // Note that this is also allowed if `actually_rustdoc` so | |
2822 | // if a target is documenting some wasm-specific code then | |
2823 | // it's not spuriously denied. | |
2824 | } else if !tcx.features().target_feature_11 { | |
1b1a35ee XL |
2825 | let mut err = feature_err( |
2826 | &tcx.sess.parse_sess, | |
2827 | sym::target_feature_11, | |
2828 | attr.span, | |
2829 | "`#[target_feature(..)]` can only be applied to `unsafe` functions", | |
2830 | ); | |
2831 | err.span_label(tcx.def_span(id), "not an `unsafe` function"); | |
2832 | err.emit(); | |
2833 | } else if let Some(local_id) = id.as_local() { | |
f9f354fc XL |
2834 | check_target_feature_trait_unsafe(tcx, local_id, attr.span); |
2835 | } | |
0531ce1d | 2836 | } |
f035d41b XL |
2837 | from_target_feature( |
2838 | tcx, | |
2839 | id, | |
2840 | attr, | |
c295e0f8 | 2841 | supported_target_features, |
f035d41b XL |
2842 | &mut codegen_fn_attrs.target_features, |
2843 | ); | |
94222f64 | 2844 | } else if attr.has_name(sym::linkage) { |
0531ce1d | 2845 | if let Some(val) = attr.value_str() { |
94b46f34 | 2846 | codegen_fn_attrs.linkage = Some(linkage_by_name(tcx, id, &val.as_str())); |
0531ce1d | 2847 | } |
94222f64 | 2848 | } else if attr.has_name(sym::link_section) { |
8faf50e0 XL |
2849 | if let Some(val) = attr.value_str() { |
2850 | if val.as_str().bytes().any(|b| b == 0) { | |
b7449926 XL |
2851 | let msg = format!( |
2852 | "illegal null byte in link_section \ | |
2853 | value: `{}`", | |
2854 | &val | |
2855 | ); | |
8faf50e0 XL |
2856 | tcx.sess.span_err(attr.span, &msg); |
2857 | } else { | |
2858 | codegen_fn_attrs.link_section = Some(val); | |
2859 | } | |
2860 | } | |
94222f64 | 2861 | } else if attr.has_name(sym::link_name) { |
b7449926 | 2862 | codegen_fn_attrs.link_name = attr.value_str(); |
94222f64 | 2863 | } else if attr.has_name(sym::link_ordinal) { |
c295e0f8 XL |
2864 | if link_ordinal_span.is_some() { |
2865 | tcx.sess | |
2866 | .struct_span_err( | |
2867 | attr.span, | |
2868 | "multiple `link_ordinal` attributes on a single definition", | |
2869 | ) | |
2870 | .emit(); | |
2871 | } | |
e74abb32 XL |
2872 | link_ordinal_span = Some(attr.span); |
2873 | if let ordinal @ Some(_) = check_link_ordinal(tcx, attr) { | |
2874 | codegen_fn_attrs.link_ordinal = ordinal; | |
2875 | } | |
94222f64 | 2876 | } else if attr.has_name(sym::no_sanitize) { |
74b04a01 XL |
2877 | no_sanitize_span = Some(attr.span); |
2878 | if let Some(list) = attr.meta_item_list() { | |
2879 | for item in list.iter() { | |
3dfed10e | 2880 | if item.has_name(sym::address) { |
f035d41b | 2881 | codegen_fn_attrs.no_sanitize |= SanitizerSet::ADDRESS; |
3dfed10e | 2882 | } else if item.has_name(sym::memory) { |
f035d41b | 2883 | codegen_fn_attrs.no_sanitize |= SanitizerSet::MEMORY; |
3dfed10e | 2884 | } else if item.has_name(sym::thread) { |
f035d41b | 2885 | codegen_fn_attrs.no_sanitize |= SanitizerSet::THREAD; |
6a06907d XL |
2886 | } else if item.has_name(sym::hwaddress) { |
2887 | codegen_fn_attrs.no_sanitize |= SanitizerSet::HWADDRESS; | |
74b04a01 XL |
2888 | } else { |
2889 | tcx.sess | |
2890 | .struct_span_err(item.span(), "invalid argument for `no_sanitize`") | |
6a06907d | 2891 | .note("expected one of: `address`, `hwaddress`, `memory` or `thread`") |
74b04a01 XL |
2892 | .emit(); |
2893 | } | |
2894 | } | |
2895 | } | |
94222f64 | 2896 | } else if attr.has_name(sym::instruction_set) { |
29967ef6 XL |
2897 | codegen_fn_attrs.instruction_set = match attr.meta().map(|i| i.kind) { |
2898 | Some(MetaItemKind::List(ref items)) => match items.as_slice() { | |
2899 | [NestedMetaItem::MetaItem(set)] => { | |
2900 | let segments = | |
2901 | set.path.segments.iter().map(|x| x.ident.name).collect::<Vec<_>>(); | |
2902 | match segments.as_slice() { | |
2903 | [sym::arm, sym::a32] | [sym::arm, sym::t32] => { | |
2904 | if !tcx.sess.target.has_thumb_interworking { | |
2905 | struct_span_err!( | |
2906 | tcx.sess.diagnostic(), | |
2907 | attr.span, | |
2908 | E0779, | |
2909 | "target does not support `#[instruction_set]`" | |
2910 | ) | |
2911 | .emit(); | |
2912 | None | |
2913 | } else if segments[1] == sym::a32 { | |
2914 | Some(InstructionSetAttr::ArmA32) | |
2915 | } else if segments[1] == sym::t32 { | |
2916 | Some(InstructionSetAttr::ArmT32) | |
2917 | } else { | |
2918 | unreachable!() | |
2919 | } | |
2920 | } | |
2921 | _ => { | |
2922 | struct_span_err!( | |
2923 | tcx.sess.diagnostic(), | |
2924 | attr.span, | |
2925 | E0779, | |
2926 | "invalid instruction set specified", | |
2927 | ) | |
2928 | .emit(); | |
2929 | None | |
2930 | } | |
2931 | } | |
2932 | } | |
2933 | [] => { | |
2934 | struct_span_err!( | |
2935 | tcx.sess.diagnostic(), | |
2936 | attr.span, | |
2937 | E0778, | |
2938 | "`#[instruction_set]` requires an argument" | |
2939 | ) | |
2940 | .emit(); | |
2941 | None | |
2942 | } | |
2943 | _ => { | |
2944 | struct_span_err!( | |
2945 | tcx.sess.diagnostic(), | |
2946 | attr.span, | |
2947 | E0779, | |
2948 | "cannot specify more than one instruction set" | |
2949 | ) | |
2950 | .emit(); | |
2951 | None | |
2952 | } | |
2953 | }, | |
2954 | _ => { | |
2955 | struct_span_err!( | |
2956 | tcx.sess.diagnostic(), | |
2957 | attr.span, | |
2958 | E0778, | |
2959 | "must specify an instruction set" | |
2960 | ) | |
2961 | .emit(); | |
2962 | None | |
2963 | } | |
2964 | }; | |
94222f64 | 2965 | } else if attr.has_name(sym::repr) { |
136023e0 XL |
2966 | codegen_fn_attrs.alignment = match attr.meta_item_list() { |
2967 | Some(items) => match items.as_slice() { | |
2968 | [item] => match item.name_value_literal() { | |
2969 | Some((sym::align, literal)) => { | |
2970 | let alignment = rustc_attr::parse_alignment(&literal.kind); | |
2971 | ||
2972 | match alignment { | |
2973 | Ok(align) => Some(align), | |
2974 | Err(msg) => { | |
2975 | struct_span_err!( | |
2976 | tcx.sess.diagnostic(), | |
2977 | attr.span, | |
2978 | E0589, | |
2979 | "invalid `repr(align)` attribute: {}", | |
2980 | msg | |
2981 | ) | |
2982 | .emit(); | |
2983 | ||
2984 | None | |
2985 | } | |
2986 | } | |
2987 | } | |
2988 | _ => None, | |
2989 | }, | |
2990 | [] => None, | |
2991 | _ => None, | |
2992 | }, | |
2993 | None => None, | |
2994 | }; | |
0531ce1d XL |
2995 | } |
2996 | } | |
2997 | ||
9fa01778 | 2998 | codegen_fn_attrs.inline = attrs.iter().fold(InlineAttr::None, |ia, attr| { |
60c5eb7d | 2999 | if !attr.has_name(sym::inline) { |
9fa01778 XL |
3000 | return ia; |
3001 | } | |
e74abb32 | 3002 | match attr.meta().map(|i| i.kind) { |
94222f64 | 3003 | Some(MetaItemKind::Word) => InlineAttr::Hint, |
9fa01778 | 3004 | Some(MetaItemKind::List(ref items)) => { |
9fa01778 XL |
3005 | inline_span = Some(attr.span); |
3006 | if items.len() != 1 { | |
dfeec247 | 3007 | struct_span_err!( |
9fa01778 XL |
3008 | tcx.sess.diagnostic(), |
3009 | attr.span, | |
3010 | E0534, | |
3011 | "expected one argument" | |
dfeec247 XL |
3012 | ) |
3013 | .emit(); | |
9fa01778 | 3014 | InlineAttr::None |
48663c56 | 3015 | } else if list_contains_name(&items[..], sym::always) { |
9fa01778 | 3016 | InlineAttr::Always |
48663c56 | 3017 | } else if list_contains_name(&items[..], sym::never) { |
9fa01778 XL |
3018 | InlineAttr::Never |
3019 | } else { | |
dfeec247 | 3020 | struct_span_err!( |
9fa01778 | 3021 | tcx.sess.diagnostic(), |
532ac7d7 | 3022 | items[0].span(), |
9fa01778 XL |
3023 | E0535, |
3024 | "invalid argument" | |
dfeec247 XL |
3025 | ) |
3026 | .emit(); | |
9fa01778 XL |
3027 | |
3028 | InlineAttr::None | |
3029 | } | |
3030 | } | |
3031 | Some(MetaItemKind::NameValue(_)) => ia, | |
3032 | None => ia, | |
3033 | } | |
3034 | }); | |
3035 | ||
3036 | codegen_fn_attrs.optimize = attrs.iter().fold(OptimizeAttr::None, |ia, attr| { | |
60c5eb7d | 3037 | if !attr.has_name(sym::optimize) { |
9fa01778 XL |
3038 | return ia; |
3039 | } | |
dfeec247 | 3040 | let err = |sp, s| struct_span_err!(tcx.sess.diagnostic(), sp, E0722, "{}", s).emit(); |
e74abb32 | 3041 | match attr.meta().map(|i| i.kind) { |
9fa01778 XL |
3042 | Some(MetaItemKind::Word) => { |
3043 | err(attr.span, "expected one argument"); | |
3044 | ia | |
3045 | } | |
3046 | Some(MetaItemKind::List(ref items)) => { | |
9fa01778 XL |
3047 | inline_span = Some(attr.span); |
3048 | if items.len() != 1 { | |
3049 | err(attr.span, "expected one argument"); | |
3050 | OptimizeAttr::None | |
48663c56 | 3051 | } else if list_contains_name(&items[..], sym::size) { |
9fa01778 | 3052 | OptimizeAttr::Size |
48663c56 | 3053 | } else if list_contains_name(&items[..], sym::speed) { |
9fa01778 XL |
3054 | OptimizeAttr::Speed |
3055 | } else { | |
532ac7d7 | 3056 | err(items[0].span(), "invalid argument"); |
9fa01778 XL |
3057 | OptimizeAttr::None |
3058 | } | |
3059 | } | |
3060 | Some(MetaItemKind::NameValue(_)) => ia, | |
3061 | None => ia, | |
3062 | } | |
3063 | }); | |
3064 | ||
29967ef6 XL |
3065 | // #73631: closures inherit `#[target_feature]` annotations |
3066 | if tcx.features().target_feature_11 && tcx.is_closure(id) { | |
3067 | let owner_id = tcx.parent(id).expect("closure should have a parent"); | |
3068 | codegen_fn_attrs | |
3069 | .target_features | |
3070 | .extend(tcx.codegen_fn_attrs(owner_id).target_features.iter().copied()) | |
3071 | } | |
3072 | ||
0531ce1d XL |
3073 | // If a function uses #[target_feature] it can't be inlined into general |
3074 | // purpose functions as they wouldn't have the right target features | |
3075 | // enabled. For that reason we also forbid #[inline(always)] as it can't be | |
3076 | // respected. | |
74b04a01 | 3077 | if !codegen_fn_attrs.target_features.is_empty() { |
94b46f34 | 3078 | if codegen_fn_attrs.inline == InlineAttr::Always { |
0531ce1d | 3079 | if let Some(span) = inline_span { |
b7449926 XL |
3080 | tcx.sess.span_err( |
3081 | span, | |
416331ca XL |
3082 | "cannot use `#[inline(always)]` with \ |
3083 | `#[target_feature]`", | |
b7449926 | 3084 | ); |
0531ce1d XL |
3085 | } |
3086 | } | |
3087 | } | |
3088 | ||
f035d41b | 3089 | if !codegen_fn_attrs.no_sanitize.is_empty() { |
74b04a01 XL |
3090 | if codegen_fn_attrs.inline == InlineAttr::Always { |
3091 | if let (Some(no_sanitize_span), Some(inline_span)) = (no_sanitize_span, inline_span) { | |
3dfed10e | 3092 | let hir_id = tcx.hir().local_def_id_to_hir_id(id.expect_local()); |
74b04a01 XL |
3093 | tcx.struct_span_lint_hir( |
3094 | lint::builtin::INLINE_NO_SANITIZE, | |
3095 | hir_id, | |
3096 | no_sanitize_span, | |
3097 | |lint| { | |
3098 | lint.build("`no_sanitize` will have no effect after inlining") | |
3099 | .span_note(inline_span, "inlining requested here") | |
3100 | .emit(); | |
3101 | }, | |
3102 | ) | |
3103 | } | |
3104 | } | |
3105 | } | |
3106 | ||
b7449926 XL |
3107 | // Weak lang items have the same semantics as "std internal" symbols in the |
3108 | // sense that they're preserved through all our LTO passes and only | |
3109 | // strippable by the linker. | |
3110 | // | |
3111 | // Additionally weak lang items have predetermined symbol names. | |
3112 | if tcx.is_weak_lang_item(id) { | |
3113 | codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL; | |
3114 | } | |
94222f64 | 3115 | let check_name = |attr: &Attribute, sym| attr.has_name(sym); |
c295e0f8 | 3116 | if let Some(name) = weak_lang_items::link_name(check_name, attrs) { |
b7449926 XL |
3117 | codegen_fn_attrs.export_name = Some(name); |
3118 | codegen_fn_attrs.link_name = Some(name); | |
3119 | } | |
e74abb32 | 3120 | check_link_name_xor_ordinal(tcx, &codegen_fn_attrs, link_ordinal_span); |
b7449926 XL |
3121 | |
3122 | // Internal symbols to the standard library all have no_mangle semantics in | |
3123 | // that they have defined symbol names present in the function name. This | |
3124 | // also applies to weak symbols where they all have known symbol names. | |
3125 | if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) { | |
3126 | codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE; | |
3127 | } | |
3128 | ||
94222f64 XL |
3129 | // Any linkage to LLVM intrinsics for now forcibly marks them all as never |
3130 | // unwinds since LLVM sometimes can't handle codegen which `invoke`s | |
3131 | // intrinsic functions. | |
3132 | if let Some(name) = &codegen_fn_attrs.link_name { | |
3133 | if name.as_str().starts_with("llvm.") { | |
3134 | codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND; | |
3135 | } | |
3136 | } | |
3137 | ||
94b46f34 | 3138 | codegen_fn_attrs |
0531ce1d | 3139 | } |
e74abb32 | 3140 | |
ba9703b0 XL |
3141 | /// Checks if the provided DefId is a method in a trait impl for a trait which has track_caller |
3142 | /// applied to the method prototype. | |
3143 | fn should_inherit_track_caller(tcx: TyCtxt<'_>, def_id: DefId) -> bool { | |
3144 | if let Some(impl_item) = tcx.opt_associated_item(def_id) { | |
3145 | if let ty::AssocItemContainer::ImplContainer(impl_def_id) = impl_item.container { | |
3146 | if let Some(trait_def_id) = tcx.trait_id_of_impl(impl_def_id) { | |
3147 | if let Some(trait_item) = tcx | |
3148 | .associated_items(trait_def_id) | |
3149 | .filter_by_name_unhygienic(impl_item.ident.name) | |
3150 | .find(move |trait_item| { | |
3151 | trait_item.kind == ty::AssocKind::Fn | |
3152 | && tcx.hygienic_eq(impl_item.ident, trait_item.ident, trait_def_id) | |
3153 | }) | |
3154 | { | |
3155 | return tcx | |
3156 | .codegen_fn_attrs(trait_item.def_id) | |
3157 | .flags | |
3158 | .intersects(CodegenFnAttrFlags::TRACK_CALLER); | |
3159 | } | |
3160 | } | |
3161 | } | |
3162 | } | |
3163 | ||
3164 | false | |
3165 | } | |
3166 | ||
c295e0f8 | 3167 | fn check_link_ordinal(tcx: TyCtxt<'_>, attr: &ast::Attribute) -> Option<u16> { |
3dfed10e | 3168 | use rustc_ast::{Lit, LitIntType, LitKind}; |
e74abb32 XL |
3169 | let meta_item_list = attr.meta_item_list(); |
3170 | let meta_item_list: Option<&[ast::NestedMetaItem]> = meta_item_list.as_ref().map(Vec::as_ref); | |
3171 | let sole_meta_list = match meta_item_list { | |
3172 | Some([item]) => item.literal(), | |
c295e0f8 XL |
3173 | Some(_) => { |
3174 | tcx.sess | |
3175 | .struct_span_err(attr.span, "incorrect number of arguments to `#[link_ordinal]`") | |
3176 | .note("the attribute requires exactly one argument") | |
3177 | .emit(); | |
3178 | return None; | |
3179 | } | |
e74abb32 XL |
3180 | _ => None, |
3181 | }; | |
3182 | if let Some(Lit { kind: LitKind::Int(ordinal, LitIntType::Unsuffixed), .. }) = sole_meta_list { | |
c295e0f8 XL |
3183 | // According to the table at https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#import-header, |
3184 | // the ordinal must fit into 16 bits. Similarly, the Ordinal field in COFFShortExport (defined | |
3185 | // in llvm/include/llvm/Object/COFFImportFile.h), which we use to communicate import information | |
3186 | // to LLVM for `#[link(kind = "raw-dylib"_])`, is also defined to be uint16_t. | |
3187 | // | |
3188 | // FIXME: should we allow an ordinal of 0? The MSVC toolchain has inconsistent support for this: | |
3189 | // both LINK.EXE and LIB.EXE signal errors and abort when given a .DEF file that specifies | |
3190 | // a zero ordinal. However, llvm-dlltool is perfectly happy to generate an import library | |
3191 | // for such a .DEF file, and MSVC's LINK.EXE is also perfectly happy to consume an import | |
3192 | // library produced by LLVM with an ordinal of 0, and it generates an .EXE. (I don't know yet | |
3193 | // if the resulting EXE runs, as I haven't yet built the necessary DLL -- see earlier comment | |
3194 | // about LINK.EXE failing.) | |
3195 | if *ordinal <= u16::MAX as u128 { | |
3196 | Some(*ordinal as u16) | |
e74abb32 | 3197 | } else { |
dfeec247 XL |
3198 | let msg = format!("ordinal value in `link_ordinal` is too large: `{}`", &ordinal); |
3199 | tcx.sess | |
3200 | .struct_span_err(attr.span, &msg) | |
c295e0f8 | 3201 | .note("the value may not exceed `u16::MAX`") |
e74abb32 XL |
3202 | .emit(); |
3203 | None | |
3204 | } | |
3205 | } else { | |
dfeec247 XL |
3206 | tcx.sess |
3207 | .struct_span_err(attr.span, "illegal ordinal format in `link_ordinal`") | |
e74abb32 XL |
3208 | .note("an unsuffixed integer value, e.g., `1`, is expected") |
3209 | .emit(); | |
3210 | None | |
3211 | } | |
3212 | } | |
3213 | ||
3214 | fn check_link_name_xor_ordinal( | |
3215 | tcx: TyCtxt<'_>, | |
3216 | codegen_fn_attrs: &CodegenFnAttrs, | |
3217 | inline_span: Option<Span>, | |
3218 | ) { | |
3219 | if codegen_fn_attrs.link_name.is_none() || codegen_fn_attrs.link_ordinal.is_none() { | |
3220 | return; | |
3221 | } | |
3222 | let msg = "cannot use `#[link_name]` with `#[link_ordinal]`"; | |
3223 | if let Some(span) = inline_span { | |
3224 | tcx.sess.span_err(span, msg); | |
3225 | } else { | |
3226 | tcx.sess.err(msg); | |
3227 | } | |
3228 | } | |
f9f354fc | 3229 | |
f9f354fc XL |
3230 | /// Checks the function annotated with `#[target_feature]` is not a safe |
3231 | /// trait method implementation, reporting an error if it is. | |
3232 | fn check_target_feature_trait_unsafe(tcx: TyCtxt<'_>, id: LocalDefId, attr_span: Span) { | |
3dfed10e | 3233 | let hir_id = tcx.hir().local_def_id_to_hir_id(id); |
f9f354fc XL |
3234 | let node = tcx.hir().get(hir_id); |
3235 | if let Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }) = node { | |
3236 | let parent_id = tcx.hir().get_parent_item(hir_id); | |
3237 | let parent_item = tcx.hir().expect_item(parent_id); | |
5869c6ff | 3238 | if let hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) = parent_item.kind { |
f9f354fc XL |
3239 | tcx.sess |
3240 | .struct_span_err( | |
3241 | attr_span, | |
3242 | "`#[target_feature(..)]` cannot be applied to safe trait method", | |
3243 | ) | |
3244 | .span_label(attr_span, "cannot be applied to safe trait method") | |
3245 | .span_label(tcx.def_span(id), "not an `unsafe` function") | |
3246 | .emit(); | |
3247 | } | |
3248 | } | |
3249 | } |