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