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