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