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