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.
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.
11 use astconv::ExplicitSelf;
12 use check::{Inherited, FnCtxt};
13 use constrained_type_params::{identify_constrained_type_params, Parameter};
15 use hir::def_id::DefId;
16 use middle::region::{CodeExtent};
17 use rustc::traits::{self, ObligationCauseCode};
18 use rustc::ty::{self, Ty, TyCtxt};
19 use rustc::util::nodemap::{FxHashSet, FxHashMap};
20 use rustc::middle::lang_items;
24 use errors::DiagnosticBuilder;
26 use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
29 pub struct CheckTypeWellFormedVisitor<'a, 'tcx:'a> {
30 tcx: TyCtxt<'a, 'tcx, 'tcx>,
31 code: ObligationCauseCode<'tcx>,
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>,
39 code: ObligationCauseCode<'gcx>,
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>>
49 let code = self.code.clone();
52 self.inherited.enter(|inh| {
53 let fcx = FnCtxt::new(&inh, id);
54 let wf_tys = f(&fcx, &mut CheckTypeWellFormedVisitor {
55 tcx: fcx.tcx.global_tcx(),
58 fcx.select_all_obligations_or_error();
59 fcx.regionck_item(id, span, &wf_tys);
64 impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
65 pub fn new(tcx: TyCtxt<'a, 'gcx, 'gcx>)
66 -> CheckTypeWellFormedVisitor<'a, 'gcx> {
67 CheckTypeWellFormedVisitor {
69 code: ObligationCauseCode::MiscObligation
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:
77 /// struct Ref<'a, T> { x: &'a T }
79 /// because the type did not declare that `T:'a`.
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
84 fn check_item_well_formed(&mut self, item: &hir::Item) {
86 debug!("check_item_well_formed(it.id={}, it.name={})",
88 tcx.item_path_str(tcx.hir.local_def_id(item.id)));
91 /// Right now we check that every default trait implementation
92 /// has an implementation of itself. Basically, a case like:
94 /// `impl Trait for T {}`
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.
101 /// Since there's such a requirement, we need to check *just* positive
102 /// implementations, otherwise things like:
104 /// impl !Send for T {}
106 /// won't be allowed unless there's an *explicit* implementation of `Send`
108 hir::ItemImpl(_, hir::ImplPolarity::Positive, _,
109 ref trait_ref, ref self_ty, _) => {
110 self.check_impl(item, self_ty, trait_ref);
112 hir::ItemImpl(_, hir::ImplPolarity::Negative, _, Some(_), ..) => {
113 // FIXME(#27579) what amount of WF checking do we need for neg impls?
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);
120 hir::ItemFn(.., body_id) => {
121 self.check_item_fn(item, body_id);
123 hir::ItemStatic(..) => {
124 self.check_item_type(item);
126 hir::ItemConst(..) => {
127 self.check_item_type(item);
129 hir::ItemStruct(ref struct_def, ref ast_generics) => {
130 self.check_type_defn(item, false, |fcx| {
131 vec![fcx.struct_variant(struct_def)]
134 self.check_variances_for_type_defn(item, ast_generics);
136 hir::ItemUnion(ref struct_def, ref ast_generics) => {
137 self.check_type_defn(item, true, |fcx| {
138 vec![fcx.struct_variant(struct_def)]
141 self.check_variances_for_type_defn(item, ast_generics);
143 hir::ItemEnum(ref enum_def, ref ast_generics) => {
144 self.check_type_defn(item, true, |fcx| {
145 fcx.enum_variants(enum_def)
148 self.check_variances_for_type_defn(item, ast_generics);
150 hir::ItemTrait(..) => {
151 self.check_trait(item);
157 fn check_associated_item(&mut self,
158 item_id: ast::NodeId,
160 sig_if_method: Option<&hir::MethodSig>) {
161 let code = self.code.clone();
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;
166 let item = fcx.tcx.associated_item(fcx.tcx.hir.local_def_id(item_id));
168 let (mut implied_bounds, self_ty) = match item.container {
169 ty::TraitContainer(_) => (vec![], fcx.tcx.mk_self_type()),
170 ty::ImplContainer(def_id) => (fcx.impl_implied_bounds(def_id, span),
171 fcx.tcx.item_type(def_id))
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);
178 fcx.register_wf_obligation(ty, span, code.clone());
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);
185 let sig = method_ty.fn_sig();
186 this.check_fn_or_method(fcx, span, sig, &predicates,
187 free_id_outlive, &mut implied_bounds);
188 let sig_if_method = sig_if_method.expect("bad signature for method");
189 this.check_method_receiver(fcx, sig_if_method, &item,
190 free_id_outlive, self_ty);
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);
196 fcx.register_wf_obligation(ty, span, code.clone());
205 fn for_item<'tcx>(&self, item: &hir::Item)
206 -> CheckWfFcxBuilder<'a, 'gcx, 'tcx> {
207 self.for_id(item.id, item.span)
210 fn for_id<'tcx>(&self, id: ast::NodeId, span: Span)
211 -> CheckWfFcxBuilder<'a, 'gcx, 'tcx> {
213 inherited: Inherited::build(self.tcx, id),
214 code: self.code.clone(),
220 /// In a type definition, we check that to ensure that the types of the fields are well-formed.
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>>
224 self.for_item(item).with_fcx(|fcx, this| {
225 let variants = lookup_fields(fcx);
227 for variant in &variants {
228 // For DST, all intermediate types must be sized.
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] {
233 fcx.tcx.require_lang_item(lang_items::SizedTraitLangItem),
234 traits::ObligationCause::new(field.span,
236 traits::FieldSized));
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())
245 let free_substs = &fcx.parameter_environment.free_substs;
246 let def_id = fcx.tcx.hir.local_def_id(item.id);
247 let predicates = fcx.instantiate_bounds(item.span, def_id, free_substs);
248 this.check_where_clauses(fcx, item.span, &predicates);
250 vec![] // no implied bounds in a struct def'n
254 fn check_auto_trait(&mut self, trait_def_id: DefId, span: Span) {
255 // We want to ensure:
257 // 1) that there are no items contained within
258 // the trait defintion
260 // 2) that the definition doesn't violate the no-super trait rule
263 // 3) that the trait definition does not have any type parameters
265 let predicates = self.tcx.item_predicates(trait_def_id);
267 // We must exclude the Self : Trait predicate contained by all
270 predicates.predicates.iter().any(|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)
280 let has_ty_params = self.tcx.item_generics(trait_def_id).types.len() > 1;
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>`.
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.
291 if !self.tcx.associated_item_def_ids(trait_def_id).is_empty() {
292 error_380(self.tcx, span);
293 } else if has_ty_params {
294 err = Some(struct_span_err!(self.tcx.sess, span, E0567,
295 "traits with auto impls (`e.g. impl \
296 Trait for ..`) can not have type parameters"));
297 } else if has_predicates {
298 err = Some(struct_span_err!(self.tcx.sess, span, E0568,
299 "traits with auto impls (`e.g. impl \
300 Trait for ..`) cannot have predicates"));
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.
308 e.note("the new auto trait rules are the result of a \
309 recent soundness fix; see #29859 for more details");
315 fn check_trait(&mut self, item: &hir::Item) {
316 let trait_def_id = self.tcx.hir.local_def_id(item.id);
318 if self.tcx.trait_has_default_impl(trait_def_id) {
319 self.check_auto_trait(trait_def_id, item.span);
322 self.for_item(item).with_fcx(|fcx, this| {
323 let free_substs = &fcx.parameter_environment.free_substs;
324 let predicates = fcx.instantiate_bounds(item.span, trait_def_id, free_substs);
325 this.check_where_clauses(fcx, item.span, &predicates);
330 fn check_item_fn(&mut self,
332 body_id: hir::BodyId)
334 self.for_item(item).with_fcx(|fcx, this| {
335 let free_substs = &fcx.parameter_environment.free_substs;
336 let def_id = fcx.tcx.hir.local_def_id(item.id);
337 let ty = fcx.tcx.item_type(def_id);
338 let item_ty = fcx.instantiate_type_scheme(item.span, free_substs, &ty);
339 let sig = item_ty.fn_sig();
341 let predicates = fcx.instantiate_bounds(item.span, def_id, free_substs);
343 let mut implied_bounds = vec![];
344 let free_id_outlive = fcx.tcx.region_maps.call_site_extent(item.id, body_id.node_id);
345 this.check_fn_or_method(fcx, item.span, sig, &predicates,
346 free_id_outlive, &mut implied_bounds);
351 fn check_item_type(&mut self,
354 debug!("check_item_type: {:?}", item);
356 self.for_item(item).with_fcx(|fcx, this| {
357 let ty = fcx.tcx.item_type(fcx.tcx.hir.local_def_id(item.id));
358 let item_ty = fcx.instantiate_type_scheme(item.span,
359 &fcx.parameter_environment
363 fcx.register_wf_obligation(item_ty, item.span, this.code.clone());
365 vec![] // no implied bounds in a const etc
369 fn check_impl(&mut self,
371 ast_self_ty: &hir::Ty,
372 ast_trait_ref: &Option<hir::TraitRef>)
374 debug!("check_impl: {:?}", item);
376 self.for_item(item).with_fcx(|fcx, this| {
377 let free_substs = &fcx.parameter_environment.free_substs;
378 let item_def_id = fcx.tcx.hir.local_def_id(item.id);
380 match *ast_trait_ref {
381 Some(ref ast_trait_ref) => {
382 let trait_ref = fcx.tcx.impl_trait_ref(item_def_id).unwrap();
384 fcx.instantiate_type_scheme(
385 ast_trait_ref.path.span, free_substs, &trait_ref);
387 ty::wf::trait_obligations(fcx,
390 ast_trait_ref.path.span);
391 for obligation in obligations {
392 fcx.register_predicate(obligation);
396 let self_ty = fcx.tcx.item_type(item_def_id);
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());
402 let predicates = fcx.instantiate_bounds(item.span, item_def_id, free_substs);
403 this.check_where_clauses(fcx, item.span, &predicates);
405 fcx.impl_implied_bounds(item_def_id, item.span)
409 fn check_where_clauses<'fcx, 'tcx>(&mut self,
410 fcx: &FnCtxt<'fcx, 'gcx, 'tcx>,
412 predicates: &ty::InstantiatedPredicates<'tcx>)
415 predicates.predicates
417 .flat_map(|p| ty::wf::predicate_obligations(fcx,
422 for obligation in obligations {
423 fcx.register_predicate(obligation);
427 fn check_fn_or_method<'fcx, 'tcx>(&mut self,
428 fcx: &FnCtxt<'fcx, 'gcx, 'tcx>,
430 sig: ty::PolyFnSig<'tcx>,
431 predicates: &ty::InstantiatedPredicates<'tcx>,
432 free_id_outlive: CodeExtent,
433 implied_bounds: &mut Vec<Ty<'tcx>>)
435 let free_substs = &fcx.parameter_environment.free_substs;
436 let sig = fcx.instantiate_type_scheme(span, free_substs, &sig);
437 let sig = fcx.tcx.liberate_late_bound_regions(free_id_outlive, &sig);
439 for input_ty in sig.inputs() {
440 fcx.register_wf_obligation(&input_ty, span, self.code.clone());
442 implied_bounds.extend(sig.inputs());
444 fcx.register_wf_obligation(sig.output(), span, self.code.clone());
446 // FIXME(#25759) return types should not be implied bounds
447 implied_bounds.push(sig.output());
449 self.check_where_clauses(fcx, span, predicates);
452 fn check_method_receiver<'fcx, 'tcx>(&mut self,
453 fcx: &FnCtxt<'fcx, 'gcx, 'tcx>,
454 method_sig: &hir::MethodSig,
455 method: &ty::AssociatedItem,
456 free_id_outlive: CodeExtent,
457 self_ty: ty::Ty<'tcx>)
459 // check that the type of the method's receiver matches the
460 // method's first parameter.
461 debug!("check_method_receiver({:?}, self_ty={:?})",
464 if !method.method_has_self_argument {
468 let span = method_sig.decl.inputs[0].span;
470 let free_substs = &fcx.parameter_environment.free_substs;
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());
475 debug!("check_method_receiver: sig={:?}", sig);
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 {
486 ExplicitSelf::ByBox => fcx.tcx.mk_box(self_ty)
488 let rcvr_ty = fcx.instantiate_type_scheme(span, free_substs, &rcvr_ty);
489 let rcvr_ty = fcx.tcx.liberate_late_bound_regions(free_id_outlive,
490 &ty::Binder(rcvr_ty));
492 debug!("check_method_receiver: receiver ty = {:?}", rcvr_ty);
494 let cause = fcx.cause(span, ObligationCauseCode::MethodReceiver);
495 if let Some(mut err) = fcx.demand_eqtype_with_origin(&cause, rcvr_ty, self_arg_ty) {
500 fn check_variances_for_type_defn(&self,
502 ast_generics: &hir::Generics)
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) {
510 let ty_predicates = self.tcx.item_predicates(item_def_id);
511 assert_eq!(ty_predicates.parent, None);
512 let variances = self.tcx.item_variances(item_def_id);
514 let mut constrained_parameters: FxHashSet<_> =
515 variances.iter().enumerate()
516 .filter(|&(_, &variance)| variance != ty::Bivariant)
517 .map(|(index, _)| Parameter(index as u32))
520 identify_constrained_type_params(ty_predicates.predicates.as_slice(),
522 &mut constrained_parameters);
524 for (index, _) in variances.iter().enumerate() {
525 if constrained_parameters.contains(&Parameter(index as u32)) {
529 let (span, name) = if index < ast_generics.lifetimes.len() {
530 (ast_generics.lifetimes[index].lifetime.span,
531 ast_generics.lifetimes[index].lifetime.name)
533 let index = index - ast_generics.lifetimes.len();
534 (ast_generics.ty_params[index].span,
535 ast_generics.ty_params[index].name)
537 self.report_bivariance(span, name);
541 fn report_bivariance(&self,
543 param_name: ast::Name)
545 let mut err = error_392(self.tcx, span, param_name);
547 let suggested_marker_id = self.tcx.lang_items.phantom_data();
548 match suggested_marker_id {
551 &format!("consider removing `{}` or using a marker such as `{}`",
553 self.tcx.item_path_str(def_id)));
556 // no lang items, no help!
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
568 .map(|tp| (tp.name, tp.def_id))
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
574 let type_span = tcx.def_span(method_param.def_id);
576 // The expectation here is that the original trait declaration is
577 // local so it should be okay to just unwrap everything.
578 let trait_def_id = impl_params[&method_param.name];
579 let trait_decl_span = tcx.def_span(trait_def_id);
580 error_194(tcx, type_span, trait_decl_span, method_param.name);
585 impl<'a, 'tcx, 'v> Visitor<'v> for CheckTypeWellFormedVisitor<'a, 'tcx> {
586 fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'v> {
587 NestedVisitorMap::None
590 fn visit_item(&mut self, i: &hir::Item) {
591 debug!("visit_item: {:?}", i);
592 self.check_item_well_formed(i);
593 intravisit::walk_item(self, i);
596 fn visit_trait_item(&mut self, trait_item: &'v hir::TraitItem) {
597 debug!("visit_trait_item: {:?}", trait_item);
598 let method_sig = match trait_item.node {
599 hir::TraitItemKind::Method(ref sig, _) => Some(sig),
602 self.check_associated_item(trait_item.id, trait_item.span, method_sig);
603 intravisit::walk_trait_item(self, trait_item)
606 fn visit_impl_item(&mut self, impl_item: &'v hir::ImplItem) {
607 debug!("visit_impl_item: {:?}", impl_item);
608 let method_sig = match impl_item.node {
609 hir::ImplItemKind::Method(ref sig, _) => Some(sig),
612 self.check_associated_item(impl_item.id, impl_item.span, method_sig);
613 intravisit::walk_impl_item(self, impl_item)
617 ///////////////////////////////////////////////////////////////////////////
620 struct AdtVariant<'tcx> {
621 fields: Vec<AdtField<'tcx>>,
624 struct AdtField<'tcx> {
629 impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
630 fn struct_variant(&self, struct_def: &hir::VariantData) -> AdtVariant<'tcx> {
632 struct_def.fields().iter()
634 let field_ty = self.tcx.item_type(self.tcx.hir.local_def_id(field.id));
635 let field_ty = self.instantiate_type_scheme(field.span,
636 &self.parameter_environment
639 AdtField { ty: field_ty, span: field.span }
642 AdtVariant { fields: fields }
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))
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);
658 trait_ref.substs.types().collect()
662 // Inherent impl: take implied bounds from the self type.
663 let self_ty = self.tcx.item_type(impl_def_id);
664 let self_ty = self.instantiate_type_scheme(span, free_substs, &self_ty);
671 fn error_192(tcx: TyCtxt, span: Span) {
672 span_err!(tcx.sess, span, E0192,
673 "negative impls are only allowed for traits with \
674 default impls (e.g., `Send` and `Sync`)")
677 fn error_380(tcx: TyCtxt, span: Span) {
678 span_err!(tcx.sess, span, E0380,
679 "traits with default impls (`e.g. impl \
680 Trait for ..`) must have no methods or associated items")
683 fn error_392<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, span: Span, param_name: ast::Name)
684 -> DiagnosticBuilder<'tcx> {
685 let mut err = struct_span_err!(tcx.sess, span, E0392,
686 "parameter `{}` is never used", param_name);
687 err.span_label(span, &format!("unused type parameter"));
691 fn error_194(tcx: TyCtxt, span: Span, trait_decl_span: Span, name: ast::Name) {
692 struct_span_err!(tcx.sess, span, E0194,
693 "type parameter `{}` shadows another type parameter of the same name",
695 .span_label(span, &format!("shadows another type parameter"))
696 .span_label(trait_decl_span, &format!("first `{}` declared here", name))