]>
Commit | Line | Data |
---|---|---|
e9174d1e SL |
1 | // Copyright 2014 The Rust Project Developers. See the COPYRIGHT |
2 | // file at the top-level directory of this distribution and at | |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
476ff2be | 11 | use astconv::ExplicitSelf; |
8bb4bdeb | 12 | use check::{Inherited, FnCtxt}; |
e9174d1e | 13 | use constrained_type_params::{identify_constrained_type_params, Parameter}; |
476ff2be | 14 | |
54a0048b | 15 | use hir::def_id::DefId; |
9cc50fc6 | 16 | use middle::region::{CodeExtent}; |
476ff2be | 17 | use rustc::traits::{self, ObligationCauseCode}; |
54a0048b | 18 | use rustc::ty::{self, Ty, TyCtxt}; |
476ff2be SL |
19 | use rustc::util::nodemap::{FxHashSet, FxHashMap}; |
20 | use rustc::middle::lang_items; | |
e9174d1e | 21 | |
e9174d1e | 22 | use syntax::ast; |
3157f602 XL |
23 | use syntax_pos::Span; |
24 | use errors::DiagnosticBuilder; | |
25 | ||
476ff2be | 26 | use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; |
54a0048b | 27 | use rustc::hir; |
e9174d1e | 28 | |
8bb4bdeb XL |
29 | pub struct CheckTypeWellFormedVisitor<'a, 'tcx:'a> { |
30 | tcx: TyCtxt<'a, 'tcx, 'tcx>, | |
476ff2be | 31 | code: ObligationCauseCode<'tcx>, |
e9174d1e SL |
32 | } |
33 | ||
a7813a04 XL |
34 | /// Helper type of a temporary returned by .for_item(...). |
35 | /// Necessary because we can't write the following bound: | |
36 | /// F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(FnCtxt<'b, 'gcx, 'tcx>). | |
37 | struct CheckWfFcxBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { | |
38 | inherited: super::InheritedBuilder<'a, 'gcx, 'tcx>, | |
476ff2be | 39 | code: ObligationCauseCode<'gcx>, |
a7813a04 XL |
40 | id: ast::NodeId, |
41 | span: Span | |
42 | } | |
43 | ||
44 | impl<'a, 'gcx, 'tcx> CheckWfFcxBuilder<'a, 'gcx, 'tcx> { | |
45 | fn with_fcx<F>(&'tcx mut self, f: F) where | |
46 | F: for<'b> FnOnce(&FnCtxt<'b, 'gcx, 'tcx>, | |
47 | &mut CheckTypeWellFormedVisitor<'b, 'gcx>) -> Vec<Ty<'tcx>> | |
48 | { | |
49 | let code = self.code.clone(); | |
50 | let id = self.id; | |
51 | let span = self.span; | |
52 | self.inherited.enter(|inh| { | |
8bb4bdeb | 53 | let fcx = FnCtxt::new(&inh, None, id); |
a7813a04 | 54 | let wf_tys = f(&fcx, &mut CheckTypeWellFormedVisitor { |
8bb4bdeb | 55 | tcx: fcx.tcx.global_tcx(), |
a7813a04 XL |
56 | code: code |
57 | }); | |
58 | fcx.select_all_obligations_or_error(); | |
59 | fcx.regionck_item(id, span, &wf_tys); | |
60 | }); | |
61 | } | |
62 | } | |
63 | ||
8bb4bdeb XL |
64 | impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> { |
65 | pub fn new(tcx: TyCtxt<'a, 'gcx, 'gcx>) | |
66 | -> CheckTypeWellFormedVisitor<'a, 'gcx> { | |
e9174d1e | 67 | CheckTypeWellFormedVisitor { |
8bb4bdeb | 68 | tcx: tcx, |
476ff2be | 69 | code: ObligationCauseCode::MiscObligation |
e9174d1e SL |
70 | } |
71 | } | |
72 | ||
e9174d1e SL |
73 | /// Checks that the field types (in a struct def'n) or argument types (in an enum def'n) are |
74 | /// well-formed, meaning that they do not require any constraints not declared in the struct | |
75 | /// definition itself. For example, this definition would be illegal: | |
76 | /// | |
77 | /// struct Ref<'a, T> { x: &'a T } | |
78 | /// | |
79 | /// because the type did not declare that `T:'a`. | |
80 | /// | |
81 | /// We do this check as a pre-pass before checking fn bodies because if these constraints are | |
82 | /// not included it frequently leads to confusing errors in fn bodies. So it's better to check | |
83 | /// the types first. | |
84 | fn check_item_well_formed(&mut self, item: &hir::Item) { | |
8bb4bdeb | 85 | let tcx = self.tcx; |
b039eaaf | 86 | debug!("check_item_well_formed(it.id={}, it.name={})", |
e9174d1e | 87 | item.id, |
8bb4bdeb | 88 | tcx.item_path_str(tcx.hir.local_def_id(item.id))); |
e9174d1e SL |
89 | |
90 | match item.node { | |
91 | /// Right now we check that every default trait implementation | |
92 | /// has an implementation of itself. Basically, a case like: | |
93 | /// | |
94 | /// `impl Trait for T {}` | |
95 | /// | |
96 | /// has a requirement of `T: Trait` which was required for default | |
97 | /// method implementations. Although this could be improved now that | |
98 | /// there's a better infrastructure in place for this, it's being left | |
99 | /// for a follow-up work. | |
100 | /// | |
101 | /// Since there's such a requirement, we need to check *just* positive | |
102 | /// implementations, otherwise things like: | |
103 | /// | |
104 | /// impl !Send for T {} | |
105 | /// | |
106 | /// won't be allowed unless there's an *explicit* implementation of `Send` | |
107 | /// for `T` | |
108 | hir::ItemImpl(_, hir::ImplPolarity::Positive, _, | |
109 | ref trait_ref, ref self_ty, _) => { | |
110 | self.check_impl(item, self_ty, trait_ref); | |
111 | } | |
9e0c209e | 112 | hir::ItemImpl(_, hir::ImplPolarity::Negative, _, Some(_), ..) => { |
e9174d1e SL |
113 | // FIXME(#27579) what amount of WF checking do we need for neg impls? |
114 | ||
8bb4bdeb XL |
115 | let trait_ref = tcx.impl_trait_ref(tcx.hir.local_def_id(item.id)).unwrap(); |
116 | if !tcx.trait_has_default_impl(trait_ref.def_id) { | |
117 | error_192(tcx, item.span); | |
e9174d1e SL |
118 | } |
119 | } | |
476ff2be SL |
120 | hir::ItemFn(.., body_id) => { |
121 | self.check_item_fn(item, body_id); | |
e9174d1e SL |
122 | } |
123 | hir::ItemStatic(..) => { | |
124 | self.check_item_type(item); | |
125 | } | |
126 | hir::ItemConst(..) => { | |
127 | self.check_item_type(item); | |
128 | } | |
129 | hir::ItemStruct(ref struct_def, ref ast_generics) => { | |
9e0c209e SL |
130 | self.check_type_defn(item, false, |fcx| { |
131 | vec![fcx.struct_variant(struct_def)] | |
132 | }); | |
133 | ||
134 | self.check_variances_for_type_defn(item, ast_generics); | |
135 | } | |
136 | hir::ItemUnion(ref struct_def, ref ast_generics) => { | |
137 | self.check_type_defn(item, true, |fcx| { | |
a7813a04 | 138 | vec![fcx.struct_variant(struct_def)] |
e9174d1e SL |
139 | }); |
140 | ||
141 | self.check_variances_for_type_defn(item, ast_generics); | |
142 | } | |
143 | hir::ItemEnum(ref enum_def, ref ast_generics) => { | |
c30ab7b3 | 144 | self.check_type_defn(item, true, |fcx| { |
a7813a04 | 145 | fcx.enum_variants(enum_def) |
e9174d1e SL |
146 | }); |
147 | ||
148 | self.check_variances_for_type_defn(item, ast_generics); | |
149 | } | |
476ff2be SL |
150 | hir::ItemTrait(..) => { |
151 | self.check_trait(item); | |
e9174d1e SL |
152 | } |
153 | _ => {} | |
154 | } | |
155 | } | |
156 | ||
32a655c1 SL |
157 | fn check_associated_item(&mut self, |
158 | item_id: ast::NodeId, | |
159 | span: Span, | |
160 | sig_if_method: Option<&hir::MethodSig>) { | |
e9174d1e | 161 | let code = self.code.clone(); |
a7813a04 XL |
162 | self.for_id(item_id, span).with_fcx(|fcx, this| { |
163 | let free_substs = &fcx.parameter_environment.free_substs; | |
164 | let free_id_outlive = fcx.parameter_environment.free_id_outlive; | |
e9174d1e | 165 | |
32a655c1 | 166 | let item = fcx.tcx.associated_item(fcx.tcx.hir.local_def_id(item_id)); |
e9174d1e | 167 | |
476ff2be | 168 | let (mut implied_bounds, self_ty) = match item.container { |
a7813a04 XL |
169 | ty::TraitContainer(_) => (vec![], fcx.tcx.mk_self_type()), |
170 | ty::ImplContainer(def_id) => (fcx.impl_implied_bounds(def_id, span), | |
476ff2be | 171 | fcx.tcx.item_type(def_id)) |
e9174d1e SL |
172 | }; |
173 | ||
476ff2be SL |
174 | match item.kind { |
175 | ty::AssociatedKind::Const => { | |
176 | let ty = fcx.tcx.item_type(item.def_id); | |
177 | let ty = fcx.instantiate_type_scheme(span, free_substs, &ty); | |
e9174d1e SL |
178 | fcx.register_wf_obligation(ty, span, code.clone()); |
179 | } | |
476ff2be SL |
180 | ty::AssociatedKind::Method => { |
181 | reject_shadowing_type_parameters(fcx.tcx, item.def_id); | |
182 | let method_ty = fcx.tcx.item_type(item.def_id); | |
183 | let method_ty = fcx.instantiate_type_scheme(span, free_substs, &method_ty); | |
184 | let predicates = fcx.instantiate_bounds(span, item.def_id, free_substs); | |
8bb4bdeb XL |
185 | let sig = method_ty.fn_sig(); |
186 | this.check_fn_or_method(fcx, span, sig, &predicates, | |
9cc50fc6 | 187 | free_id_outlive, &mut implied_bounds); |
5bcae85e | 188 | let sig_if_method = sig_if_method.expect("bad signature for method"); |
476ff2be | 189 | this.check_method_receiver(fcx, sig_if_method, &item, |
9cc50fc6 | 190 | free_id_outlive, self_ty); |
e9174d1e | 191 | } |
476ff2be SL |
192 | ty::AssociatedKind::Type => { |
193 | if item.defaultness.has_value() { | |
194 | let ty = fcx.tcx.item_type(item.def_id); | |
195 | let ty = fcx.instantiate_type_scheme(span, free_substs, &ty); | |
e9174d1e SL |
196 | fcx.register_wf_obligation(ty, span, code.clone()); |
197 | } | |
198 | } | |
199 | } | |
200 | ||
201 | implied_bounds | |
202 | }) | |
203 | } | |
204 | ||
a7813a04 | 205 | fn for_item<'tcx>(&self, item: &hir::Item) |
8bb4bdeb | 206 | -> CheckWfFcxBuilder<'a, 'gcx, 'tcx> { |
a7813a04 | 207 | self.for_id(item.id, item.span) |
e9174d1e SL |
208 | } |
209 | ||
a7813a04 | 210 | fn for_id<'tcx>(&self, id: ast::NodeId, span: Span) |
8bb4bdeb | 211 | -> CheckWfFcxBuilder<'a, 'gcx, 'tcx> { |
a7813a04 | 212 | CheckWfFcxBuilder { |
8bb4bdeb | 213 | inherited: Inherited::build(self.tcx, id), |
a7813a04 XL |
214 | code: self.code.clone(), |
215 | id: id, | |
216 | span: span | |
217 | } | |
e9174d1e SL |
218 | } |
219 | ||
220 | /// In a type definition, we check that to ensure that the types of the fields are well-formed. | |
9e0c209e SL |
221 | fn check_type_defn<F>(&mut self, item: &hir::Item, all_sized: bool, mut lookup_fields: F) |
222 | where F: for<'fcx, 'tcx> FnMut(&FnCtxt<'fcx, 'gcx, 'tcx>) -> Vec<AdtVariant<'tcx>> | |
e9174d1e | 223 | { |
a7813a04 | 224 | self.for_item(item).with_fcx(|fcx, this| { |
e9174d1e SL |
225 | let variants = lookup_fields(fcx); |
226 | ||
227 | for variant in &variants { | |
228 | // For DST, all intermediate types must be sized. | |
9e0c209e SL |
229 | let unsized_len = if all_sized || variant.fields.is_empty() { 0 } else { 1 }; |
230 | for field in &variant.fields[..variant.fields.len() - unsized_len] { | |
476ff2be | 231 | fcx.register_bound( |
9e0c209e | 232 | field.ty, |
476ff2be | 233 | fcx.tcx.require_lang_item(lang_items::SizedTraitLangItem), |
9e0c209e SL |
234 | traits::ObligationCause::new(field.span, |
235 | fcx.body_id, | |
236 | traits::FieldSized)); | |
e9174d1e SL |
237 | } |
238 | ||
239 | // All field types must be well-formed. | |
240 | for field in &variant.fields { | |
241 | fcx.register_wf_obligation(field.ty, field.span, this.code.clone()) | |
242 | } | |
243 | } | |
244 | ||
a7813a04 | 245 | let free_substs = &fcx.parameter_environment.free_substs; |
32a655c1 | 246 | let def_id = fcx.tcx.hir.local_def_id(item.id); |
476ff2be | 247 | let predicates = fcx.instantiate_bounds(item.span, def_id, free_substs); |
e9174d1e SL |
248 | this.check_where_clauses(fcx, item.span, &predicates); |
249 | ||
250 | vec![] // no implied bounds in a struct def'n | |
251 | }); | |
252 | } | |
253 | ||
476ff2be | 254 | fn check_auto_trait(&mut self, trait_def_id: DefId, span: Span) { |
9e0c209e SL |
255 | // We want to ensure: |
256 | // | |
257 | // 1) that there are no items contained within | |
258 | // the trait defintion | |
259 | // | |
260 | // 2) that the definition doesn't violate the no-super trait rule | |
261 | // for auto traits. | |
262 | // | |
263 | // 3) that the trait definition does not have any type parameters | |
264 | ||
8bb4bdeb | 265 | let predicates = self.tcx.item_predicates(trait_def_id); |
9e0c209e SL |
266 | |
267 | // We must exclude the Self : Trait predicate contained by all | |
268 | // traits. | |
269 | let has_predicates = | |
270 | predicates.predicates.iter().any(|predicate| { | |
271 | match predicate { | |
272 | &ty::Predicate::Trait(ref poly_trait_ref) => { | |
273 | let self_ty = poly_trait_ref.0.self_ty(); | |
274 | !(self_ty.is_self() && poly_trait_ref.def_id() == trait_def_id) | |
275 | }, | |
276 | _ => true, | |
277 | } | |
278 | }); | |
279 | ||
8bb4bdeb | 280 | let has_ty_params = self.tcx.item_generics(trait_def_id).types.len() > 1; |
9e0c209e SL |
281 | |
282 | // We use an if-else here, since the generics will also trigger | |
283 | // an extraneous error message when we find predicates like | |
284 | // `T : Sized` for a trait like: `trait Magic<T>`. | |
285 | // | |
286 | // We also put the check on the number of items here, | |
287 | // as it seems confusing to report an error about | |
288 | // extraneous predicates created by things like | |
289 | // an associated type inside the trait. | |
290 | let mut err = None; | |
8bb4bdeb XL |
291 | if !self.tcx.associated_item_def_ids(trait_def_id).is_empty() { |
292 | error_380(self.tcx, span); | |
9e0c209e | 293 | } else if has_ty_params { |
8bb4bdeb | 294 | err = Some(struct_span_err!(self.tcx.sess, span, E0567, |
9e0c209e SL |
295 | "traits with auto impls (`e.g. impl \ |
296 | Trait for ..`) can not have type parameters")); | |
297 | } else if has_predicates { | |
8bb4bdeb | 298 | err = Some(struct_span_err!(self.tcx.sess, span, E0568, |
9e0c209e SL |
299 | "traits with auto impls (`e.g. impl \ |
300 | Trait for ..`) cannot have predicates")); | |
301 | } | |
302 | ||
303 | // Finally if either of the above conditions apply we should add a note | |
304 | // indicating that this error is the result of a recent soundness fix. | |
305 | match err { | |
306 | None => {}, | |
307 | Some(mut e) => { | |
308 | e.note("the new auto trait rules are the result of a \ | |
309 | recent soundness fix; see #29859 for more details"); | |
310 | e.emit(); | |
311 | } | |
312 | } | |
313 | } | |
314 | ||
476ff2be | 315 | fn check_trait(&mut self, item: &hir::Item) { |
8bb4bdeb | 316 | let trait_def_id = self.tcx.hir.local_def_id(item.id); |
e9174d1e | 317 | |
8bb4bdeb | 318 | if self.tcx.trait_has_default_impl(trait_def_id) { |
476ff2be | 319 | self.check_auto_trait(trait_def_id, item.span); |
e9174d1e SL |
320 | } |
321 | ||
a7813a04 XL |
322 | self.for_item(item).with_fcx(|fcx, this| { |
323 | let free_substs = &fcx.parameter_environment.free_substs; | |
476ff2be | 324 | let predicates = fcx.instantiate_bounds(item.span, trait_def_id, free_substs); |
e9174d1e SL |
325 | this.check_where_clauses(fcx, item.span, &predicates); |
326 | vec![] | |
327 | }); | |
328 | } | |
329 | ||
330 | fn check_item_fn(&mut self, | |
331 | item: &hir::Item, | |
32a655c1 | 332 | body_id: hir::BodyId) |
e9174d1e | 333 | { |
a7813a04 XL |
334 | self.for_item(item).with_fcx(|fcx, this| { |
335 | let free_substs = &fcx.parameter_environment.free_substs; | |
32a655c1 | 336 | let def_id = fcx.tcx.hir.local_def_id(item.id); |
476ff2be SL |
337 | let ty = fcx.tcx.item_type(def_id); |
338 | let item_ty = fcx.instantiate_type_scheme(item.span, free_substs, &ty); | |
8bb4bdeb | 339 | let sig = item_ty.fn_sig(); |
e9174d1e | 340 | |
476ff2be | 341 | let predicates = fcx.instantiate_bounds(item.span, def_id, free_substs); |
e9174d1e SL |
342 | |
343 | let mut implied_bounds = vec![]; | |
32a655c1 | 344 | let free_id_outlive = fcx.tcx.region_maps.call_site_extent(item.id, body_id.node_id); |
8bb4bdeb | 345 | this.check_fn_or_method(fcx, item.span, sig, &predicates, |
9cc50fc6 | 346 | free_id_outlive, &mut implied_bounds); |
e9174d1e SL |
347 | implied_bounds |
348 | }) | |
349 | } | |
350 | ||
351 | fn check_item_type(&mut self, | |
352 | item: &hir::Item) | |
353 | { | |
354 | debug!("check_item_type: {:?}", item); | |
355 | ||
a7813a04 | 356 | self.for_item(item).with_fcx(|fcx, this| { |
32a655c1 | 357 | let ty = fcx.tcx.item_type(fcx.tcx.hir.local_def_id(item.id)); |
e9174d1e | 358 | let item_ty = fcx.instantiate_type_scheme(item.span, |
a7813a04 | 359 | &fcx.parameter_environment |
e9174d1e | 360 | .free_substs, |
476ff2be | 361 | &ty); |
e9174d1e SL |
362 | |
363 | fcx.register_wf_obligation(item_ty, item.span, this.code.clone()); | |
364 | ||
365 | vec![] // no implied bounds in a const etc | |
366 | }); | |
367 | } | |
368 | ||
369 | fn check_impl(&mut self, | |
370 | item: &hir::Item, | |
371 | ast_self_ty: &hir::Ty, | |
372 | ast_trait_ref: &Option<hir::TraitRef>) | |
373 | { | |
374 | debug!("check_impl: {:?}", item); | |
375 | ||
a7813a04 XL |
376 | self.for_item(item).with_fcx(|fcx, this| { |
377 | let free_substs = &fcx.parameter_environment.free_substs; | |
32a655c1 | 378 | let item_def_id = fcx.tcx.hir.local_def_id(item.id); |
e9174d1e SL |
379 | |
380 | match *ast_trait_ref { | |
381 | Some(ref ast_trait_ref) => { | |
a7813a04 | 382 | let trait_ref = fcx.tcx.impl_trait_ref(item_def_id).unwrap(); |
e9174d1e SL |
383 | let trait_ref = |
384 | fcx.instantiate_type_scheme( | |
385 | ast_trait_ref.path.span, free_substs, &trait_ref); | |
386 | let obligations = | |
a7813a04 | 387 | ty::wf::trait_obligations(fcx, |
e9174d1e SL |
388 | fcx.body_id, |
389 | &trait_ref, | |
9cc50fc6 | 390 | ast_trait_ref.path.span); |
e9174d1e SL |
391 | for obligation in obligations { |
392 | fcx.register_predicate(obligation); | |
393 | } | |
394 | } | |
395 | None => { | |
476ff2be | 396 | let self_ty = fcx.tcx.item_type(item_def_id); |
e9174d1e SL |
397 | let self_ty = fcx.instantiate_type_scheme(item.span, free_substs, &self_ty); |
398 | fcx.register_wf_obligation(self_ty, ast_self_ty.span, this.code.clone()); | |
399 | } | |
400 | } | |
401 | ||
476ff2be | 402 | let predicates = fcx.instantiate_bounds(item.span, item_def_id, free_substs); |
e9174d1e SL |
403 | this.check_where_clauses(fcx, item.span, &predicates); |
404 | ||
476ff2be | 405 | fcx.impl_implied_bounds(item_def_id, item.span) |
e9174d1e SL |
406 | }); |
407 | } | |
408 | ||
a7813a04 XL |
409 | fn check_where_clauses<'fcx, 'tcx>(&mut self, |
410 | fcx: &FnCtxt<'fcx, 'gcx, 'tcx>, | |
411 | span: Span, | |
412 | predicates: &ty::InstantiatedPredicates<'tcx>) | |
e9174d1e SL |
413 | { |
414 | let obligations = | |
415 | predicates.predicates | |
416 | .iter() | |
a7813a04 | 417 | .flat_map(|p| ty::wf::predicate_obligations(fcx, |
e9174d1e SL |
418 | fcx.body_id, |
419 | p, | |
9cc50fc6 | 420 | span)); |
e9174d1e SL |
421 | |
422 | for obligation in obligations { | |
423 | fcx.register_predicate(obligation); | |
424 | } | |
425 | } | |
426 | ||
a7813a04 XL |
427 | fn check_fn_or_method<'fcx, 'tcx>(&mut self, |
428 | fcx: &FnCtxt<'fcx, 'gcx, 'tcx>, | |
429 | span: Span, | |
8bb4bdeb | 430 | sig: ty::PolyFnSig<'tcx>, |
a7813a04 XL |
431 | predicates: &ty::InstantiatedPredicates<'tcx>, |
432 | free_id_outlive: CodeExtent, | |
433 | implied_bounds: &mut Vec<Ty<'tcx>>) | |
e9174d1e | 434 | { |
a7813a04 | 435 | let free_substs = &fcx.parameter_environment.free_substs; |
8bb4bdeb XL |
436 | let sig = fcx.instantiate_type_scheme(span, free_substs, &sig); |
437 | let sig = fcx.tcx.liberate_late_bound_regions(free_id_outlive, &sig); | |
e9174d1e | 438 | |
476ff2be SL |
439 | for input_ty in sig.inputs() { |
440 | fcx.register_wf_obligation(&input_ty, span, self.code.clone()); | |
e9174d1e | 441 | } |
476ff2be | 442 | implied_bounds.extend(sig.inputs()); |
e9174d1e | 443 | |
476ff2be | 444 | fcx.register_wf_obligation(sig.output(), span, self.code.clone()); |
e9174d1e | 445 | |
5bcae85e | 446 | // FIXME(#25759) return types should not be implied bounds |
476ff2be | 447 | implied_bounds.push(sig.output()); |
e9174d1e SL |
448 | |
449 | self.check_where_clauses(fcx, span, predicates); | |
450 | } | |
451 | ||
a7813a04 XL |
452 | fn check_method_receiver<'fcx, 'tcx>(&mut self, |
453 | fcx: &FnCtxt<'fcx, 'gcx, 'tcx>, | |
5bcae85e | 454 | method_sig: &hir::MethodSig, |
476ff2be | 455 | method: &ty::AssociatedItem, |
a7813a04 XL |
456 | free_id_outlive: CodeExtent, |
457 | self_ty: ty::Ty<'tcx>) | |
9cc50fc6 SL |
458 | { |
459 | // check that the type of the method's receiver matches the | |
460 | // method's first parameter. | |
476ff2be SL |
461 | debug!("check_method_receiver({:?}, self_ty={:?})", |
462 | method, self_ty); | |
9cc50fc6 | 463 | |
476ff2be SL |
464 | if !method.method_has_self_argument { |
465 | return; | |
466 | } | |
5bcae85e | 467 | |
32a655c1 | 468 | let span = method_sig.decl.inputs[0].span; |
5bcae85e SL |
469 | |
470 | let free_substs = &fcx.parameter_environment.free_substs; | |
476ff2be SL |
471 | let method_ty = fcx.tcx.item_type(method.def_id); |
472 | let fty = fcx.instantiate_type_scheme(span, free_substs, &method_ty); | |
473 | let sig = fcx.tcx.liberate_late_bound_regions(free_id_outlive, &fty.fn_sig()); | |
5bcae85e SL |
474 | |
475 | debug!("check_method_receiver: sig={:?}", sig); | |
476 | ||
476ff2be SL |
477 | let self_arg_ty = sig.inputs()[0]; |
478 | let rcvr_ty = match ExplicitSelf::determine(self_ty, self_arg_ty) { | |
479 | ExplicitSelf::ByValue => self_ty, | |
480 | ExplicitSelf::ByReference(region, mutbl) => { | |
481 | fcx.tcx.mk_ref(region, ty::TypeAndMut { | |
482 | ty: self_ty, | |
483 | mutbl: mutbl | |
484 | }) | |
485 | } | |
486 | ExplicitSelf::ByBox => fcx.tcx.mk_box(self_ty) | |
487 | }; | |
9cc50fc6 | 488 | let rcvr_ty = fcx.instantiate_type_scheme(span, free_substs, &rcvr_ty); |
a7813a04 XL |
489 | let rcvr_ty = fcx.tcx.liberate_late_bound_regions(free_id_outlive, |
490 | &ty::Binder(rcvr_ty)); | |
9cc50fc6 SL |
491 | |
492 | debug!("check_method_receiver: receiver ty = {:?}", rcvr_ty); | |
493 | ||
476ff2be | 494 | let cause = fcx.cause(span, ObligationCauseCode::MethodReceiver); |
32a655c1 SL |
495 | if let Some(mut err) = fcx.demand_eqtype_with_origin(&cause, rcvr_ty, self_arg_ty) { |
496 | err.emit(); | |
497 | } | |
9cc50fc6 SL |
498 | } |
499 | ||
e9174d1e SL |
500 | fn check_variances_for_type_defn(&self, |
501 | item: &hir::Item, | |
502 | ast_generics: &hir::Generics) | |
503 | { | |
8bb4bdeb XL |
504 | let item_def_id = self.tcx.hir.local_def_id(item.id); |
505 | let ty = self.tcx.item_type(item_def_id); | |
506 | if self.tcx.has_error_field(ty) { | |
5bcae85e SL |
507 | return; |
508 | } | |
509 | ||
8bb4bdeb | 510 | let ty_predicates = self.tcx.item_predicates(item_def_id); |
9e0c209e | 511 | assert_eq!(ty_predicates.parent, None); |
8bb4bdeb | 512 | let variances = self.tcx.item_variances(item_def_id); |
e9174d1e | 513 | |
476ff2be | 514 | let mut constrained_parameters: FxHashSet<_> = |
9e0c209e SL |
515 | variances.iter().enumerate() |
516 | .filter(|&(_, &variance)| variance != ty::Bivariant) | |
517 | .map(|(index, _)| Parameter(index as u32)) | |
e9174d1e SL |
518 | .collect(); |
519 | ||
a7813a04 | 520 | identify_constrained_type_params(ty_predicates.predicates.as_slice(), |
e9174d1e SL |
521 | None, |
522 | &mut constrained_parameters); | |
523 | ||
9e0c209e SL |
524 | for (index, _) in variances.iter().enumerate() { |
525 | if constrained_parameters.contains(&Parameter(index as u32)) { | |
e9174d1e SL |
526 | continue; |
527 | } | |
528 | ||
9e0c209e SL |
529 | let (span, name) = if index < ast_generics.lifetimes.len() { |
530 | (ast_generics.lifetimes[index].lifetime.span, | |
531 | ast_generics.lifetimes[index].lifetime.name) | |
532 | } else { | |
533 | let index = index - ast_generics.lifetimes.len(); | |
534 | (ast_generics.ty_params[index].span, | |
535 | ast_generics.ty_params[index].name) | |
536 | }; | |
e9174d1e SL |
537 | self.report_bivariance(span, name); |
538 | } | |
539 | } | |
540 | ||
e9174d1e SL |
541 | fn report_bivariance(&self, |
542 | span: Span, | |
543 | param_name: ast::Name) | |
544 | { | |
8bb4bdeb | 545 | let mut err = error_392(self.tcx, span, param_name); |
e9174d1e | 546 | |
8bb4bdeb | 547 | let suggested_marker_id = self.tcx.lang_items.phantom_data(); |
e9174d1e SL |
548 | match suggested_marker_id { |
549 | Some(def_id) => { | |
a7813a04 | 550 | err.help( |
e9174d1e SL |
551 | &format!("consider removing `{}` or using a marker such as `{}`", |
552 | param_name, | |
8bb4bdeb | 553 | self.tcx.item_path_str(def_id))); |
e9174d1e SL |
554 | } |
555 | None => { | |
556 | // no lang items, no help! | |
557 | } | |
558 | } | |
9cc50fc6 | 559 | err.emit(); |
e9174d1e SL |
560 | } |
561 | } | |
562 | ||
476ff2be SL |
563 | fn reject_shadowing_type_parameters(tcx: TyCtxt, def_id: DefId) { |
564 | let generics = tcx.item_generics(def_id); | |
565 | let parent = tcx.item_generics(generics.parent.unwrap()); | |
566 | let impl_params: FxHashMap<_, _> = parent.types | |
567 | .iter() | |
568 | .map(|tp| (tp.name, tp.def_id)) | |
569 | .collect(); | |
9e0c209e SL |
570 | |
571 | for method_param in &generics.types { | |
572 | if impl_params.contains_key(&method_param.name) { | |
573 | // Tighten up the span to focus on only the shadowing type | |
476ff2be | 574 | let type_span = tcx.def_span(method_param.def_id); |
e9174d1e | 575 | |
9e0c209e SL |
576 | // The expectation here is that the original trait declaration is |
577 | // local so it should be okay to just unwrap everything. | |
476ff2be SL |
578 | let trait_def_id = impl_params[&method_param.name]; |
579 | let trait_decl_span = tcx.def_span(trait_def_id); | |
9e0c209e | 580 | error_194(tcx, type_span, trait_decl_span, method_param.name); |
e9174d1e SL |
581 | } |
582 | } | |
583 | } | |
584 | ||
8bb4bdeb | 585 | impl<'a, 'tcx, 'v> Visitor<'v> for CheckTypeWellFormedVisitor<'a, 'tcx> { |
476ff2be SL |
586 | fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'v> { |
587 | NestedVisitorMap::None | |
588 | } | |
589 | ||
e9174d1e SL |
590 | fn visit_item(&mut self, i: &hir::Item) { |
591 | debug!("visit_item: {:?}", i); | |
592 | self.check_item_well_formed(i); | |
92a42be0 | 593 | intravisit::walk_item(self, i); |
e9174d1e SL |
594 | } |
595 | ||
596 | fn visit_trait_item(&mut self, trait_item: &'v hir::TraitItem) { | |
597 | debug!("visit_trait_item: {:?}", trait_item); | |
5bcae85e | 598 | let method_sig = match trait_item.node { |
32a655c1 | 599 | hir::TraitItemKind::Method(ref sig, _) => Some(sig), |
5bcae85e SL |
600 | _ => None |
601 | }; | |
32a655c1 | 602 | self.check_associated_item(trait_item.id, trait_item.span, method_sig); |
92a42be0 | 603 | intravisit::walk_trait_item(self, trait_item) |
e9174d1e SL |
604 | } |
605 | ||
606 | fn visit_impl_item(&mut self, impl_item: &'v hir::ImplItem) { | |
607 | debug!("visit_impl_item: {:?}", impl_item); | |
5bcae85e SL |
608 | let method_sig = match impl_item.node { |
609 | hir::ImplItemKind::Method(ref sig, _) => Some(sig), | |
610 | _ => None | |
611 | }; | |
32a655c1 | 612 | self.check_associated_item(impl_item.id, impl_item.span, method_sig); |
92a42be0 | 613 | intravisit::walk_impl_item(self, impl_item) |
e9174d1e SL |
614 | } |
615 | } | |
616 | ||
617 | /////////////////////////////////////////////////////////////////////////// | |
618 | // ADT | |
619 | ||
620 | struct AdtVariant<'tcx> { | |
621 | fields: Vec<AdtField<'tcx>>, | |
622 | } | |
623 | ||
624 | struct AdtField<'tcx> { | |
625 | ty: Ty<'tcx>, | |
626 | span: Span, | |
627 | } | |
628 | ||
a7813a04 XL |
629 | impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { |
630 | fn struct_variant(&self, struct_def: &hir::VariantData) -> AdtVariant<'tcx> { | |
631 | let fields = | |
632 | struct_def.fields().iter() | |
633 | .map(|field| { | |
32a655c1 | 634 | let field_ty = self.tcx.item_type(self.tcx.hir.local_def_id(field.id)); |
a7813a04 XL |
635 | let field_ty = self.instantiate_type_scheme(field.span, |
636 | &self.parameter_environment | |
637 | .free_substs, | |
638 | &field_ty); | |
639 | AdtField { ty: field_ty, span: field.span } | |
640 | }) | |
641 | .collect(); | |
642 | AdtVariant { fields: fields } | |
643 | } | |
e9174d1e | 644 | |
a7813a04 XL |
645 | fn enum_variants(&self, enum_def: &hir::EnumDef) -> Vec<AdtVariant<'tcx>> { |
646 | enum_def.variants.iter() | |
647 | .map(|variant| self.struct_variant(&variant.node.data)) | |
648 | .collect() | |
649 | } | |
e9174d1e | 650 | |
a7813a04 XL |
651 | fn impl_implied_bounds(&self, impl_def_id: DefId, span: Span) -> Vec<Ty<'tcx>> { |
652 | let free_substs = &self.parameter_environment.free_substs; | |
653 | match self.tcx.impl_trait_ref(impl_def_id) { | |
654 | Some(ref trait_ref) => { | |
655 | // Trait impl: take implied bounds from all types that | |
656 | // appear in the trait reference. | |
657 | let trait_ref = self.instantiate_type_scheme(span, free_substs, trait_ref); | |
9e0c209e | 658 | trait_ref.substs.types().collect() |
a7813a04 | 659 | } |
e9174d1e | 660 | |
a7813a04 XL |
661 | None => { |
662 | // Inherent impl: take implied bounds from the self type. | |
476ff2be | 663 | let self_ty = self.tcx.item_type(impl_def_id); |
a7813a04 XL |
664 | let self_ty = self.instantiate_type_scheme(span, free_substs, &self_ty); |
665 | vec![self_ty] | |
666 | } | |
e9174d1e SL |
667 | } |
668 | } | |
669 | } | |
670 | ||
8bb4bdeb XL |
671 | fn error_192(tcx: TyCtxt, span: Span) { |
672 | span_err!(tcx.sess, span, E0192, | |
e9174d1e SL |
673 | "negative impls are only allowed for traits with \ |
674 | default impls (e.g., `Send` and `Sync`)") | |
675 | } | |
676 | ||
8bb4bdeb XL |
677 | fn error_380(tcx: TyCtxt, span: Span) { |
678 | span_err!(tcx.sess, span, E0380, | |
9e0c209e | 679 | "traits with default impls (`e.g. impl \ |
e9174d1e SL |
680 | Trait for ..`) must have no methods or associated items") |
681 | } | |
682 | ||
8bb4bdeb | 683 | fn error_392<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, span: Span, param_name: ast::Name) |
9cc50fc6 | 684 | -> DiagnosticBuilder<'tcx> { |
8bb4bdeb | 685 | let mut err = struct_span_err!(tcx.sess, span, E0392, |
9e0c209e SL |
686 | "parameter `{}` is never used", param_name); |
687 | err.span_label(span, &format!("unused type parameter")); | |
688 | err | |
e9174d1e SL |
689 | } |
690 | ||
9e0c209e SL |
691 | fn error_194(tcx: TyCtxt, span: Span, trait_decl_span: Span, name: ast::Name) { |
692 | struct_span_err!(tcx.sess, span, E0194, | |
e9174d1e | 693 | "type parameter `{}` shadows another type parameter of the same name", |
9e0c209e SL |
694 | name) |
695 | .span_label(span, &format!("shadows another type parameter")) | |
696 | .span_label(trait_decl_span, &format!("first `{}` declared here", name)) | |
697 | .emit(); | |
e9174d1e | 698 | } |