// Copyright 2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. use check::{Inherited, FnCtxt}; use constrained_type_params::{identify_constrained_type_params, Parameter}; use hir::def_id::DefId; use rustc::traits::{self, ObligationCauseCode}; use rustc::ty::{self, Lift, Ty, TyCtxt, TyKind, GenericParamDefKind, TypeFoldable}; use rustc::ty::subst::{Subst, Substs}; use rustc::ty::util::ExplicitSelf; use rustc::util::nodemap::{FxHashSet, FxHashMap}; use rustc::middle::lang_items; use rustc::infer::opaque_types::may_define_existential_type; use syntax::ast; use syntax::feature_gate::{self, GateIssue}; use syntax_pos::Span; use errors::{DiagnosticBuilder, DiagnosticId}; use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use rustc::hir; /// Helper type of a temporary returned by `.for_item(...)`. /// Necessary because we can't write the following bound: /// `F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(FnCtxt<'b, 'gcx, 'tcx>)`. struct CheckWfFcxBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { inherited: super::InheritedBuilder<'a, 'gcx, 'tcx>, id: ast::NodeId, span: Span, param_env: ty::ParamEnv<'tcx>, } impl<'a, 'gcx, 'tcx> CheckWfFcxBuilder<'a, 'gcx, 'tcx> { fn with_fcx(&'tcx mut self, f: F) where F: for<'b> FnOnce(&FnCtxt<'b, 'gcx, 'tcx>, TyCtxt<'b, 'gcx, 'gcx>) -> Vec> { let id = self.id; let span = self.span; let param_env = self.param_env; self.inherited.enter(|inh| { let fcx = FnCtxt::new(&inh, param_env, id); if !inh.tcx.features().trivial_bounds { // As predicates are cached rather than obligations, this // needsto be called first so that they are checked with an // empty param_env. check_false_global_bounds(&fcx, span, id); } let wf_tys = f(&fcx, fcx.tcx.global_tcx()); fcx.select_all_obligations_or_error(); fcx.regionck_item(id, span, &wf_tys); }); } } /// Checks that the field types (in a struct def'n) or argument types (in an enum def'n) are /// well-formed, meaning that they do not require any constraints not declared in the struct /// definition itself. For example, this definition would be illegal: /// /// struct Ref<'a, T> { x: &'a T } /// /// because the type did not declare that `T:'a`. /// /// We do this check as a pre-pass before checking fn bodies because if these constraints are /// not included it frequently leads to confusing errors in fn bodies. So it's better to check /// the types first. pub fn check_item_well_formed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) { let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); let item = tcx.hir.expect_item(node_id); debug!("check_item_well_formed(it.id={}, it.name={})", item.id, tcx.item_path_str(def_id)); match item.node { // Right now we check that every default trait implementation // has an implementation of itself. Basically, a case like: // // `impl Trait for T {}` // // has a requirement of `T: Trait` which was required for default // method implementations. Although this could be improved now that // there's a better infrastructure in place for this, it's being left // for a follow-up work. // // Since there's such a requirement, we need to check *just* positive // implementations, otherwise things like: // // impl !Send for T {} // // won't be allowed unless there's an *explicit* implementation of `Send` // for `T` hir::ItemKind::Impl(_, polarity, defaultness, _, ref trait_ref, ref self_ty, _) => { let is_auto = tcx.impl_trait_ref(tcx.hir.local_def_id(item.id)) .map_or(false, |trait_ref| tcx.trait_is_auto(trait_ref.def_id)); if let (hir::Defaultness::Default { .. }, true) = (defaultness, is_auto) { tcx.sess.span_err(item.span, "impls of auto traits cannot be default"); } if polarity == hir::ImplPolarity::Positive { check_impl(tcx, item, self_ty, trait_ref); } else { // FIXME(#27579) what amount of WF checking do we need for neg impls? if trait_ref.is_some() && !is_auto { span_err!(tcx.sess, item.span, E0192, "negative impls are only allowed for \ auto traits (e.g., `Send` and `Sync`)") } } } hir::ItemKind::Fn(..) => { check_item_fn(tcx, item); } hir::ItemKind::Static(ref ty, ..) => { check_item_type(tcx, item.id, ty.span, false); } hir::ItemKind::Const(ref ty, ..) => { check_item_type(tcx, item.id, ty.span, false); } hir::ItemKind::ForeignMod(ref module) => for it in module.items.iter() { if let hir::ForeignItemKind::Static(ref ty, ..) = it.node { check_item_type(tcx, it.id, ty.span, true); } }, hir::ItemKind::Struct(ref struct_def, ref ast_generics) => { check_type_defn(tcx, item, false, |fcx| { vec![fcx.non_enum_variant(struct_def)] }); check_variances_for_type_defn(tcx, item, ast_generics); } hir::ItemKind::Union(ref struct_def, ref ast_generics) => { check_type_defn(tcx, item, true, |fcx| { vec![fcx.non_enum_variant(struct_def)] }); check_variances_for_type_defn(tcx, item, ast_generics); } hir::ItemKind::Enum(ref enum_def, ref ast_generics) => { check_type_defn(tcx, item, true, |fcx| { fcx.enum_variants(enum_def) }); check_variances_for_type_defn(tcx, item, ast_generics); } hir::ItemKind::Trait(..) => { check_trait(tcx, item); } hir::ItemKind::TraitAlias(..) => { check_trait(tcx, item); } _ => {} } } pub fn check_trait_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) { let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); let trait_item = tcx.hir.expect_trait_item(node_id); let method_sig = match trait_item.node { hir::TraitItemKind::Method(ref sig, _) => Some(sig), _ => None }; check_associated_item(tcx, trait_item.id, trait_item.span, method_sig); } pub fn check_impl_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) { let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); let impl_item = tcx.hir.expect_impl_item(node_id); let method_sig = match impl_item.node { hir::ImplItemKind::Method(ref sig, _) => Some(sig), _ => None }; check_associated_item(tcx, impl_item.id, impl_item.span, method_sig); } fn check_associated_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: ast::NodeId, span: Span, sig_if_method: Option<&hir::MethodSig>) { debug!("check_associated_item: {:?}", item_id); let code = ObligationCauseCode::MiscObligation; for_id(tcx, item_id, span).with_fcx(|fcx, tcx| { let item = fcx.tcx.associated_item(fcx.tcx.hir.local_def_id(item_id)); let (mut implied_bounds, self_ty) = match item.container { ty::TraitContainer(_) => (vec![], fcx.tcx.mk_self_type()), ty::ImplContainer(def_id) => (fcx.impl_implied_bounds(def_id, span), fcx.tcx.type_of(def_id)) }; match item.kind { ty::AssociatedKind::Const => { let ty = fcx.tcx.type_of(item.def_id); let ty = fcx.normalize_associated_types_in(span, &ty); fcx.register_wf_obligation(ty, span, code.clone()); } ty::AssociatedKind::Method => { reject_shadowing_parameters(fcx.tcx, item.def_id); let sig = fcx.tcx.fn_sig(item.def_id); let sig = fcx.normalize_associated_types_in(span, &sig); check_fn_or_method(tcx, fcx, span, sig, item.def_id, &mut implied_bounds); let sig_if_method = sig_if_method.expect("bad signature for method"); check_method_receiver(fcx, sig_if_method, &item, self_ty); } ty::AssociatedKind::Type => { if item.defaultness.has_value() { let ty = fcx.tcx.type_of(item.def_id); let ty = fcx.normalize_associated_types_in(span, &ty); fcx.register_wf_obligation(ty, span, code.clone()); } } ty::AssociatedKind::Existential => { // do nothing, existential types check themselves } } implied_bounds }) } fn for_item<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>, item: &hir::Item) -> CheckWfFcxBuilder<'a, 'gcx, 'tcx> { for_id(tcx, item.id, item.span) } fn for_id<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>, id: ast::NodeId, span: Span) -> CheckWfFcxBuilder<'a, 'gcx, 'tcx> { let def_id = tcx.hir.local_def_id(id); CheckWfFcxBuilder { inherited: Inherited::build(tcx, def_id), id, span, param_env: tcx.param_env(def_id), } } /// In a type definition, we check that to ensure that the types of the fields are well-formed. fn check_type_defn<'a, 'tcx, F>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item: &hir::Item, all_sized: bool, mut lookup_fields: F) where F: for<'fcx, 'gcx, 'tcx2> FnMut(&FnCtxt<'fcx, 'gcx, 'tcx2>) -> Vec> { for_item(tcx, item).with_fcx(|fcx, fcx_tcx| { let variants = lookup_fields(fcx); let def_id = fcx.tcx.hir.local_def_id(item.id); let packed = fcx.tcx.adt_def(def_id).repr.packed(); for variant in &variants { // For DST, or when drop needs to copy things around, all // intermediate types must be sized. let needs_drop_copy = || { packed && { let ty = variant.fields.last().unwrap().ty; let ty = fcx.tcx.erase_regions(&ty).lift_to_tcx(fcx_tcx) .unwrap_or_else(|| { span_bug!(item.span, "inference variables in {:?}", ty) }); ty.needs_drop(fcx_tcx, fcx_tcx.param_env(def_id)) } }; let all_sized = all_sized || variant.fields.is_empty() || needs_drop_copy(); let unsized_len = if all_sized { 0 } else { 1 }; for (idx, field) in variant.fields[..variant.fields.len() - unsized_len] .iter() .enumerate() { let last = idx == variant.fields.len() - 1; fcx.register_bound( field.ty, fcx.tcx.require_lang_item(lang_items::SizedTraitLangItem), traits::ObligationCause::new( field.span, fcx.body_id, traits::FieldSized { adt_kind: match item.node.adt_kind() { Some(i) => i, None => bug!(), }, last } ) ); } // All field types must be well-formed. for field in &variant.fields { fcx.register_wf_obligation(field.ty, field.span, ObligationCauseCode::MiscObligation) } } check_where_clauses(tcx, fcx, item.span, def_id, None); vec![] // no implied bounds in a struct def'n }); } fn check_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item: &hir::Item) { debug!("check_trait: {:?}", item.id); let trait_def_id = tcx.hir.local_def_id(item.id); let trait_def = tcx.trait_def(trait_def_id); if trait_def.is_marker { for associated_def_id in &*tcx.associated_item_def_ids(trait_def_id) { struct_span_err!( tcx.sess, tcx.def_span(*associated_def_id), E0714, "marker traits cannot have associated items", ).emit(); } } for_item(tcx, item).with_fcx(|fcx, _| { check_where_clauses(tcx, fcx, item.span, trait_def_id, None); vec![] }); } fn check_item_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item: &hir::Item) { for_item(tcx, item).with_fcx(|fcx, tcx| { let def_id = fcx.tcx.hir.local_def_id(item.id); let sig = fcx.tcx.fn_sig(def_id); let sig = fcx.normalize_associated_types_in(item.span, &sig); let mut implied_bounds = vec![]; check_fn_or_method(tcx, fcx, item.span, sig, def_id, &mut implied_bounds); implied_bounds }) } fn check_item_type<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: ast::NodeId, ty_span: Span, allow_foreign_ty: bool, ) { debug!("check_item_type: {:?}", item_id); for_id(tcx, item_id, ty_span).with_fcx(|fcx, _this| { let ty = fcx.tcx.type_of(fcx.tcx.hir.local_def_id(item_id)); let item_ty = fcx.normalize_associated_types_in(ty_span, &ty); let mut forbid_unsized = true; if allow_foreign_ty { if let TyKind::Foreign(_) = tcx.struct_tail(item_ty).sty { forbid_unsized = false; } } fcx.register_wf_obligation(item_ty, ty_span, ObligationCauseCode::MiscObligation); if forbid_unsized { fcx.register_bound( item_ty, fcx.tcx.require_lang_item(lang_items::SizedTraitLangItem), traits::ObligationCause::new(ty_span, fcx.body_id, traits::MiscObligation), ); } vec![] // no implied bounds in a const etc }); } fn check_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item: &hir::Item, ast_self_ty: &hir::Ty, ast_trait_ref: &Option) { debug!("check_impl: {:?}", item); for_item(tcx, item).with_fcx(|fcx, tcx| { let item_def_id = fcx.tcx.hir.local_def_id(item.id); match *ast_trait_ref { Some(ref ast_trait_ref) => { let trait_ref = fcx.tcx.impl_trait_ref(item_def_id).unwrap(); let trait_ref = fcx.normalize_associated_types_in( ast_trait_ref.path.span, &trait_ref); let obligations = ty::wf::trait_obligations(fcx, fcx.param_env, fcx.body_id, &trait_ref, ast_trait_ref.path.span); for obligation in obligations { fcx.register_predicate(obligation); } } None => { let self_ty = fcx.tcx.type_of(item_def_id); let self_ty = fcx.normalize_associated_types_in(item.span, &self_ty); fcx.register_wf_obligation(self_ty, ast_self_ty.span, ObligationCauseCode::MiscObligation); } } check_where_clauses(tcx, fcx, item.span, item_def_id, None); fcx.impl_implied_bounds(item_def_id, item.span) }); } /// Checks where clauses and inline bounds that are declared on def_id. fn check_where_clauses<'a, 'gcx, 'fcx, 'tcx>( tcx: TyCtxt<'a, 'gcx, 'gcx>, fcx: &FnCtxt<'fcx, 'gcx, 'tcx>, span: Span, def_id: DefId, return_ty: Option>, ) { use ty::subst::Subst; use rustc::ty::TypeFoldable; let predicates = fcx.tcx.predicates_of(def_id); let generics = tcx.generics_of(def_id); let is_our_default = |def: &ty::GenericParamDef| { match def.kind { GenericParamDefKind::Type { has_default, .. } => { has_default && def.index >= generics.parent_count as u32 } _ => unreachable!() } }; // Check that concrete defaults are well-formed. See test `type-check-defaults.rs`. // For example this forbids the declaration: // struct Foo> { .. } // Here the default `Vec<[u32]>` is not WF because `[u32]: Sized` does not hold. for param in &generics.params { if let GenericParamDefKind::Type {..} = param.kind { if is_our_default(¶m) { let ty = fcx.tcx.type_of(param.def_id); // ignore dependent defaults -- that is, where the default of one type // parameter includes another (e.g., ). In those cases, we can't // be sure if it will error or not as user might always specify the other. if !ty.needs_subst() { fcx.register_wf_obligation(ty, fcx.tcx.def_span(param.def_id), ObligationCauseCode::MiscObligation); } } } } // Check that trait predicates are WF when params are substituted by their defaults. // We don't want to overly constrain the predicates that may be written but we want to // catch cases where a default my never be applied such as `struct Foo`. // Therefore we check if a predicate which contains a single type param // with a concrete default is WF with that default substituted. // For more examples see tests `defaults-well-formedness.rs` and `type-check-defaults.rs`. // // First we build the defaulted substitution. let substs = Substs::for_item(fcx.tcx, def_id, |param, _| { match param.kind { GenericParamDefKind::Lifetime => { // All regions are identity. fcx.tcx.mk_param_from_def(param) } GenericParamDefKind::Type {..} => { // If the param has a default, if is_our_default(param) { let default_ty = fcx.tcx.type_of(param.def_id); // and it's not a dependent default if !default_ty.needs_subst() { // then substitute with the default. return default_ty.into(); } } // Mark unwanted params as err. fcx.tcx.types.err.into() } } }); // Now we build the substituted predicates. let default_obligations = predicates.predicates.iter().flat_map(|&(pred, _)| { #[derive(Default)] struct CountParams { params: FxHashSet } impl<'tcx> ty::fold::TypeVisitor<'tcx> for CountParams { fn visit_ty(&mut self, t: Ty<'tcx>) -> bool { match t.sty { ty::Param(p) => { self.params.insert(p.idx); t.super_visit_with(self) } _ => t.super_visit_with(self) } } fn visit_region(&mut self, _: ty::Region<'tcx>) -> bool { true } } let mut param_count = CountParams::default(); let has_region = pred.visit_with(&mut param_count); let substituted_pred = pred.subst(fcx.tcx, substs); // Don't check non-defaulted params, dependent defaults (including lifetimes) // or preds with multiple params. if substituted_pred.references_error() || param_count.params.len() > 1 || has_region { None } else if predicates.predicates.iter().any(|&(p, _)| p == substituted_pred) { // Avoid duplication of predicates that contain no parameters, for example. None } else { Some(substituted_pred) } }).map(|pred| { // convert each of those into an obligation. So if you have // something like `struct Foo`, we would // take that predicate `T: Copy`, substitute to `String: Copy` // (actually that happens in the previous `flat_map` call), // and then try to prove it (in this case, we'll fail). // // Note the subtle difference from how we handle `predicates` // below: there, we are not trying to prove those predicates // to be *true* but merely *well-formed*. let pred = fcx.normalize_associated_types_in(span, &pred); let cause = traits::ObligationCause::new(span, fcx.body_id, traits::ItemObligation(def_id)); traits::Obligation::new(cause, fcx.param_env, pred) }); let mut predicates = predicates.instantiate_identity(fcx.tcx); if let Some(return_ty) = return_ty { predicates.predicates.extend(check_existential_types(tcx, fcx, def_id, span, return_ty)); } let predicates = fcx.normalize_associated_types_in(span, &predicates); debug!("check_where_clauses: predicates={:?}", predicates.predicates); let wf_obligations = predicates.predicates .iter() .flat_map(|p| ty::wf::predicate_obligations(fcx, fcx.param_env, fcx.body_id, p, span)); for obligation in wf_obligations.chain(default_obligations) { debug!("next obligation cause: {:?}", obligation.cause); fcx.register_predicate(obligation); } } fn check_fn_or_method<'a, 'fcx, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>, fcx: &FnCtxt<'fcx, 'gcx, 'tcx>, span: Span, sig: ty::PolyFnSig<'tcx>, def_id: DefId, implied_bounds: &mut Vec>) { let sig = fcx.normalize_associated_types_in(span, &sig); let sig = fcx.tcx.liberate_late_bound_regions(def_id, &sig); for input_ty in sig.inputs() { fcx.register_wf_obligation(&input_ty, span, ObligationCauseCode::MiscObligation); } implied_bounds.extend(sig.inputs()); fcx.register_wf_obligation(sig.output(), span, ObligationCauseCode::MiscObligation); // FIXME(#25759) return types should not be implied bounds implied_bounds.push(sig.output()); check_where_clauses(tcx, fcx, span, def_id, Some(sig.output())); } /// Checks "defining uses" of existential types to ensure that they meet the restrictions laid for /// "higher-order pattern unification". /// This ensures that inference is tractable. /// In particular, definitions of existential types can only use other generics as arguments, /// and they cannot repeat an argument. Example: /// /// ```rust /// existential type Foo; /// /// // ok -- `Foo` is applied to two distinct, generic types. /// fn a() -> Foo { .. } /// /// // not ok -- `Foo` is applied to `T` twice. /// fn b() -> Foo { .. } /// /// /// // not ok -- `Foo` is applied to a non-generic type. /// fn b() -> Foo { .. } /// ``` /// fn check_existential_types<'a, 'fcx, 'gcx, 'tcx>( tcx: TyCtxt<'a, 'gcx, 'gcx>, fcx: &FnCtxt<'fcx, 'gcx, 'tcx>, fn_def_id: DefId, span: Span, ty: Ty<'tcx>, ) -> Vec> { trace!("check_existential_types: {:?}, {:?}", ty, ty.sty); let mut substituted_predicates = Vec::new(); ty.fold_with(&mut ty::fold::BottomUpFolder { tcx: fcx.tcx, fldop: |ty| { if let ty::Opaque(def_id, substs) = ty.sty { trace!("check_existential_types: opaque_ty, {:?}, {:?}", def_id, substs); let generics = tcx.generics_of(def_id); // only check named existential types if generics.parent.is_none() { let opaque_node_id = tcx.hir.as_local_node_id(def_id).unwrap(); if may_define_existential_type(tcx, fn_def_id, opaque_node_id) { trace!("check_existential_types may define. Generics: {:#?}", generics); let mut seen: FxHashMap<_, Vec<_>> = FxHashMap::default(); for (subst, param) in substs.iter().zip(&generics.params) { match subst.unpack() { ty::subst::UnpackedKind::Type(ty) => match ty.sty { ty::Param(..) => {}, // prevent `fn foo() -> Foo` from being defining _ => { tcx .sess .struct_span_err( span, "non-defining existential type use \ in defining scope", ) .span_note( tcx.def_span(param.def_id), &format!( "used non-generic type {} for \ generic parameter", ty, ), ) .emit(); }, }, // match ty ty::subst::UnpackedKind::Lifetime(region) => { let param_span = tcx.def_span(param.def_id); if let ty::ReStatic = region { tcx .sess .struct_span_err( span, "non-defining existential type use \ in defining scope", ) .span_label( param_span, "cannot use static lifetime, use a bound lifetime \ instead or remove the lifetime parameter from the \ existential type", ) .emit(); } else { seen.entry(region).or_default().push(param_span); } }, } // match subst } // for (subst, param) for (_, spans) in seen { if spans.len() > 1 { tcx .sess .struct_span_err( span, "non-defining existential type use \ in defining scope", ). span_note( spans, "lifetime used multiple times", ) .emit(); } } } // if may_define_existential_type // now register the bounds on the parameters of the existential type // so the parameters given by the function need to fulfill them // ```rust // existential type Foo: 'static; // fn foo() -> Foo { .. *} // ``` // becomes // ```rust // existential type Foo: 'static; // fn foo() -> Foo { .. *} // ``` let predicates = tcx.predicates_of(def_id); trace!( "check_existential_types may define. adding predicates: {:#?}", predicates, ); for &(pred, _) in predicates.predicates.iter() { let substituted_pred = pred.subst(fcx.tcx, substs); // Avoid duplication of predicates that contain no parameters, for example. if !predicates.predicates.iter().any(|&(p, _)| p == substituted_pred) { substituted_predicates.push(substituted_pred); } } } // if is_named_existential_type } // if let Opaque ty }, reg_op: |reg| reg, }); substituted_predicates } fn check_method_receiver<'fcx, 'gcx, 'tcx>(fcx: &FnCtxt<'fcx, 'gcx, 'tcx>, method_sig: &hir::MethodSig, method: &ty::AssociatedItem, self_ty: Ty<'tcx>) { // check that the method has a valid receiver type, given the type `Self` debug!("check_method_receiver({:?}, self_ty={:?})", method, self_ty); if !method.method_has_self_argument { return; } let span = method_sig.decl.inputs[0].span; let sig = fcx.tcx.fn_sig(method.def_id); let sig = fcx.normalize_associated_types_in(span, &sig); let sig = fcx.tcx.liberate_late_bound_regions(method.def_id, &sig); debug!("check_method_receiver: sig={:?}", sig); let self_ty = fcx.normalize_associated_types_in(span, &self_ty); let self_ty = fcx.tcx.liberate_late_bound_regions( method.def_id, &ty::Binder::bind(self_ty) ); let self_arg_ty = sig.inputs()[0]; let cause = fcx.cause(span, ObligationCauseCode::MethodReceiver); let self_arg_ty = fcx.normalize_associated_types_in(span, &self_arg_ty); let self_arg_ty = fcx.tcx.liberate_late_bound_regions( method.def_id, &ty::Binder::bind(self_arg_ty) ); let mut autoderef = fcx.autoderef(span, self_arg_ty).include_raw_pointers(); loop { if let Some((potential_self_ty, _)) = autoderef.next() { debug!("check_method_receiver: potential self type `{:?}` to match `{:?}`", potential_self_ty, self_ty); if fcx.infcx.can_eq(fcx.param_env, self_ty, potential_self_ty).is_ok() { autoderef.finalize(); if let Some(mut err) = fcx.demand_eqtype_with_origin( &cause, self_ty, potential_self_ty) { err.emit(); } break } } else { fcx.tcx.sess.diagnostic().mut_span_err( span, &format!("invalid `self` type: {:?}", self_arg_ty)) .note(&format!("type must be `{:?}` or a type that dereferences to it", self_ty)) .help("consider changing to `self`, `&self`, `&mut self`, or `self: Box`") .code(DiagnosticId::Error("E0307".into())) .emit(); return } } let is_self_ty = |ty| fcx.infcx.can_eq(fcx.param_env, self_ty, ty).is_ok(); let self_kind = ExplicitSelf::determine(self_arg_ty, is_self_ty); if !fcx.tcx.features().arbitrary_self_types { match self_kind { ExplicitSelf::ByValue | ExplicitSelf::ByReference(_, _) | ExplicitSelf::ByBox => (), ExplicitSelf::ByRawPointer(_) => { feature_gate::feature_err( &fcx.tcx.sess.parse_sess, "arbitrary_self_types", span, GateIssue::Language, "raw pointer `self` is unstable") .help("consider changing to `self`, `&self`, `&mut self`, or `self: Box`") .emit(); } ExplicitSelf::Other => { feature_gate::feature_err( &fcx.tcx.sess.parse_sess, "arbitrary_self_types", span, GateIssue::Language,"arbitrary `self` types are unstable") .help("consider changing to `self`, `&self`, `&mut self`, or `self: Box`") .emit(); } } } } fn check_variances_for_type_defn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item: &hir::Item, hir_generics: &hir::Generics) { let item_def_id = tcx.hir.local_def_id(item.id); let ty = tcx.type_of(item_def_id); if tcx.has_error_field(ty) { return; } let ty_predicates = tcx.predicates_of(item_def_id); assert_eq!(ty_predicates.parent, None); let variances = tcx.variances_of(item_def_id); let mut constrained_parameters: FxHashSet<_> = variances.iter().enumerate() .filter(|&(_, &variance)| variance != ty::Bivariant) .map(|(index, _)| Parameter(index as u32)) .collect(); identify_constrained_type_params(tcx, &ty_predicates, None, &mut constrained_parameters); for (index, _) in variances.iter().enumerate() { if constrained_parameters.contains(&Parameter(index as u32)) { continue; } let param = &hir_generics.params[index]; match param.name { hir::ParamName::Error => { } _ => report_bivariance(tcx, param.span, param.name.ident().name), } } } fn report_bivariance<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, span: Span, param_name: ast::Name) { let mut err = error_392(tcx, span, param_name); let suggested_marker_id = tcx.lang_items().phantom_data(); // help is available only in presence of lang items if let Some(def_id) = suggested_marker_id { err.help(&format!("consider removing `{}` or using a marker such as `{}`", param_name, tcx.item_path_str(def_id))); } err.emit(); } fn reject_shadowing_parameters(tcx: TyCtxt, def_id: DefId) { let generics = tcx.generics_of(def_id); let parent = tcx.generics_of(generics.parent.unwrap()); let impl_params: FxHashMap<_, _> = parent.params.iter().flat_map(|param| match param.kind { GenericParamDefKind::Lifetime => None, GenericParamDefKind::Type {..} => Some((param.name, param.def_id)), }).collect(); for method_param in &generics.params { // Shadowing is checked in resolve_lifetime. if let GenericParamDefKind::Lifetime = method_param.kind { continue } if impl_params.contains_key(&method_param.name) { // Tighten up the span to focus on only the shadowing type let type_span = tcx.def_span(method_param.def_id); // The expectation here is that the original trait declaration is // local so it should be okay to just unwrap everything. let trait_def_id = impl_params[&method_param.name]; let trait_decl_span = tcx.def_span(trait_def_id); error_194(tcx, type_span, trait_decl_span, &method_param.name.as_str()[..]); } } } /// Feature gates RFC 2056 - trivial bounds, checking for global bounds that /// aren't true. fn check_false_global_bounds<'a, 'gcx, 'tcx>( fcx: &FnCtxt<'a, 'gcx, 'tcx>, span: Span, id: ast::NodeId) { use rustc::ty::TypeFoldable; let empty_env = ty::ParamEnv::empty(); let def_id = fcx.tcx.hir.local_def_id(id); let predicates = fcx.tcx.predicates_of(def_id).predicates .iter() .map(|(p, _)| *p) .collect(); // Check elaborated bounds let implied_obligations = traits::elaborate_predicates(fcx.tcx, predicates); for pred in implied_obligations { // Match the existing behavior. if pred.is_global() && !pred.has_late_bound_regions() { let pred = fcx.normalize_associated_types_in(span, &pred); let obligation = traits::Obligation::new( traits::ObligationCause::new( span, id, traits::TrivialBound, ), empty_env, pred, ); fcx.register_predicate(obligation); } } fcx.select_all_obligations_or_error(); } pub struct CheckTypeWellFormedVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, } impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> { pub fn new(tcx: TyCtxt<'a, 'gcx, 'gcx>) -> CheckTypeWellFormedVisitor<'a, 'gcx> { CheckTypeWellFormedVisitor { tcx, } } } impl<'a, 'tcx, 'v> Visitor<'v> for CheckTypeWellFormedVisitor<'a, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'v> { NestedVisitorMap::None } fn visit_item(&mut self, i: &hir::Item) { debug!("visit_item: {:?}", i); let def_id = self.tcx.hir.local_def_id(i.id); ty::query::queries::check_item_well_formed::ensure(self.tcx, def_id); intravisit::walk_item(self, i); } fn visit_trait_item(&mut self, trait_item: &'v hir::TraitItem) { debug!("visit_trait_item: {:?}", trait_item); let def_id = self.tcx.hir.local_def_id(trait_item.id); ty::query::queries::check_trait_item_well_formed::ensure(self.tcx, def_id); intravisit::walk_trait_item(self, trait_item) } fn visit_impl_item(&mut self, impl_item: &'v hir::ImplItem) { debug!("visit_impl_item: {:?}", impl_item); let def_id = self.tcx.hir.local_def_id(impl_item.id); ty::query::queries::check_impl_item_well_formed::ensure(self.tcx, def_id); intravisit::walk_impl_item(self, impl_item) } } /////////////////////////////////////////////////////////////////////////// // ADT struct AdtVariant<'tcx> { fields: Vec>, } struct AdtField<'tcx> { ty: Ty<'tcx>, span: Span, } impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn non_enum_variant(&self, struct_def: &hir::VariantData) -> AdtVariant<'tcx> { let fields = struct_def.fields().iter().map(|field| { let field_ty = self.tcx.type_of(self.tcx.hir.local_def_id(field.id)); let field_ty = self.normalize_associated_types_in(field.span, &field_ty); AdtField { ty: field_ty, span: field.span } }) .collect(); AdtVariant { fields } } fn enum_variants(&self, enum_def: &hir::EnumDef) -> Vec> { enum_def.variants.iter() .map(|variant| self.non_enum_variant(&variant.node.data)) .collect() } fn impl_implied_bounds(&self, impl_def_id: DefId, span: Span) -> Vec> { match self.tcx.impl_trait_ref(impl_def_id) { Some(ref trait_ref) => { // Trait impl: take implied bounds from all types that // appear in the trait reference. let trait_ref = self.normalize_associated_types_in(span, trait_ref); trait_ref.substs.types().collect() } None => { // Inherent impl: take implied bounds from the `self` type. let self_ty = self.tcx.type_of(impl_def_id); let self_ty = self.normalize_associated_types_in(span, &self_ty); vec![self_ty] } } } } fn error_392<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, span: Span, param_name: ast::Name) -> DiagnosticBuilder<'tcx> { let mut err = struct_span_err!(tcx.sess, span, E0392, "parameter `{}` is never used", param_name); err.span_label(span, "unused type parameter"); err } fn error_194(tcx: TyCtxt, span: Span, trait_decl_span: Span, name: &str) { struct_span_err!(tcx.sess, span, E0194, "type parameter `{}` shadows another type parameter of the same name", name) .span_label(span, "shadows another type parameter") .span_label(trait_decl_span, format!("first `{}` declared here", name)) .emit(); }