diff --git a/src/librustc/middle/ty/mod.rs b/src/librustc/middle/ty/mod.rs index 308883cf063df..50c9a1a31f220 100644 --- a/src/librustc/middle/ty/mod.rs +++ b/src/librustc/middle/ty/mod.rs @@ -633,7 +633,6 @@ pub struct RegionParameterDef { impl RegionParameterDef { pub fn to_early_bound_region(&self) -> ty::Region { ty::ReEarlyBound(ty::EarlyBoundRegion { - def_id: self.def_id, space: self.space, index: self.index, name: self.name, diff --git a/src/librustc/middle/ty/sty.rs b/src/librustc/middle/ty/sty.rs index 66b2a9d3ad0bf..6f72d3df07e37 100644 --- a/src/librustc/middle/ty/sty.rs +++ b/src/librustc/middle/ty/sty.rs @@ -695,7 +695,6 @@ pub enum Region { #[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)] pub struct EarlyBoundRegion { - pub def_id: DefId, pub space: subst::ParamSpace, pub index: u32, pub name: Name, diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 3c0a395f57ccb..0b362be215dfe 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -462,8 +462,7 @@ impl fmt::Debug for ty::Region { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { ty::ReEarlyBound(ref data) => { - write!(f, "ReEarlyBound({:?}, {:?}, {}, {})", - data.def_id, + write!(f, "ReEarlyBound({:?}, {}, {})", data.space, data.index, data.name) diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index df9294a9d5bfb..50a672a4b69e7 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -289,7 +289,6 @@ impl<'a, 'tcx> Env<'a, 'tcx> { -> ty::Region { let name = token::intern(name); ty::ReEarlyBound(ty::EarlyBoundRegion { - def_id: self.infcx.tcx.map.local_def_id(ast::DUMMY_NODE_ID), space: space, index: index, name: name, diff --git a/src/librustc_metadata/tydecode.rs b/src/librustc_metadata/tydecode.rs index 4d4db062329e0..b99431d265618 100644 --- a/src/librustc_metadata/tydecode.rs +++ b/src/librustc_metadata/tydecode.rs @@ -192,14 +192,12 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { } 'B' => { assert_eq!(self.next(), '['); - let def_id = self.parse_def(); let space = self.parse_param_space(); assert_eq!(self.next(), '|'); let index = self.parse_u32(); assert_eq!(self.next(), '|'); let name = token::intern(&self.parse_str(']')); ty::ReEarlyBound(ty::EarlyBoundRegion { - def_id: def_id, space: space, index: index, name: name diff --git a/src/librustc_metadata/tyencode.rs b/src/librustc_metadata/tyencode.rs index 0119f1d5cc109..6d42871201b8e 100644 --- a/src/librustc_metadata/tyencode.rs +++ b/src/librustc_metadata/tyencode.rs @@ -253,8 +253,7 @@ pub fn enc_region(w: &mut Encoder, cx: &ctxt, r: ty::Region) { mywrite!(w, "]"); } ty::ReEarlyBound(ref data) => { - mywrite!(w, "B[{}|{}|{}|{}]", - (cx.ds)(data.def_id), + mywrite!(w, "B[{}|{}|{}]", data.space.to_uint(), data.index, data.name); diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 98ae3071b87d2..95d85964044da 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -57,7 +57,7 @@ use middle::resolve_lifetime as rl; use middle::privacy::{AllPublic, LastMod}; use middle::subst::{FnSpace, TypeSpace, SelfSpace, Subst, Substs, ParamSpace}; use middle::traits; -use middle::ty::{self, RegionEscape, Ty, ToPredicate, HasTypeFlags}; +use middle::ty::{self, Ty, ToPredicate, HasTypeFlags}; use middle::ty::wf::object_region_bounds; use require_c_abi_if_variadic; use rscope::{self, UnelidableRscope, RegionScope, ElidableRscope, @@ -169,10 +169,8 @@ pub fn ast_region_to_region(tcx: &ty::ctxt, lifetime: &hir::Lifetime) ty::ReLateBound(debruijn, ty::BrNamed(tcx.map.local_def_id(id), lifetime.name)) } - Some(&rl::DefEarlyBoundRegion(space, index, id)) => { - let def_id = tcx.map.local_def_id(id); + Some(&rl::DefEarlyBoundRegion(space, index, _)) => { ty::ReEarlyBound(ty::EarlyBoundRegion { - def_id: def_id, space: space, index: index, name: lifetime.name @@ -1797,75 +1795,31 @@ fn ty_of_method_or_bare_fn<'a, 'tcx>(this: &AstConv<'tcx>, // lifetime elision, we can determine it in two ways. First (determined // here), if self is by-reference, then the implied output region is the // region of the self parameter. - let mut explicit_self_category_result = None; - let (self_ty, implied_output_region) = match opt_self_info { + let (self_ty, explicit_self_category) = match opt_self_info { None => (None, None), - Some(self_info) => { - // This type comes from an impl or trait; no late-bound - // regions should be present. - assert!(!self_info.untransformed_self_ty.has_escaping_regions()); - - // Figure out and record the explicit self category. - let explicit_self_category = - determine_explicit_self_category(this, &rb, &self_info); - explicit_self_category_result = Some(explicit_self_category); - match explicit_self_category { - ty::StaticExplicitSelfCategory => { - (None, None) - } - ty::ByValueExplicitSelfCategory => { - (Some(self_info.untransformed_self_ty), None) - } - ty::ByReferenceExplicitSelfCategory(region, mutability) => { - (Some(this.tcx().mk_ref( - this.tcx().mk_region(region), - ty::TypeAndMut { - ty: self_info.untransformed_self_ty, - mutbl: mutability - })), - Some(region)) - } - ty::ByBoxExplicitSelfCategory => { - (Some(this.tcx().mk_box(self_info.untransformed_self_ty)), None) - } - } - } + Some(self_info) => determine_self_type(this, &rb, self_info) }; // HACK(eddyb) replace the fake self type in the AST with the actual type. - let input_params = if self_ty.is_some() { + let arg_params = if self_ty.is_some() { &decl.inputs[1..] } else { &decl.inputs[..] }; - let input_tys = input_params.iter().map(|a| ty_of_arg(this, &rb, a, None)); - let input_pats: Vec = input_params.iter() - .map(|a| pprust::pat_to_string(&*a.pat)) - .collect(); - let self_and_input_tys: Vec = - self_ty.into_iter().chain(input_tys).collect(); - + let arg_tys: Vec = + arg_params.iter().map(|a| ty_of_arg(this, &rb, a, None)).collect(); + let arg_pats: Vec = + arg_params.iter().map(|a| pprust::pat_to_string(&*a.pat)).collect(); // Second, if there was exactly one lifetime (either a substitution or a // reference) in the arguments, then any anonymous regions in the output // have that lifetime. - let implied_output_region = match implied_output_region { - Some(r) => Ok(r), - None => { - let input_tys = if self_ty.is_some() { - // Skip the first argument if `self` is present. - &self_and_input_tys[1..] - } else { - &self_and_input_tys[..] - }; - - find_implied_output_region(this.tcx(), input_tys, input_pats) - } + let implied_output_region = match explicit_self_category { + Some(ty::ByReferenceExplicitSelfCategory(region, _)) => Ok(region), + _ => find_implied_output_region(this.tcx(), &arg_tys, arg_pats) }; let output_ty = match decl.output { - hir::Return(ref output) if output.node == hir::TyInfer => - ty::FnConverging(this.ty_infer(None, None, None, output.span)), hir::Return(ref output) => ty::FnConverging(convert_ty_with_lifetime_elision(this, implied_output_region, @@ -1878,28 +1832,37 @@ fn ty_of_method_or_bare_fn<'a, 'tcx>(this: &AstConv<'tcx>, unsafety: unsafety, abi: abi, sig: ty::Binder(ty::FnSig { - inputs: self_and_input_tys, + inputs: self_ty.into_iter().chain(arg_tys).collect(), output: output_ty, variadic: decl.variadic }), - }, explicit_self_category_result) + }, explicit_self_category) } -fn determine_explicit_self_category<'a, 'tcx>(this: &AstConv<'tcx>, - rscope: &RegionScope, - self_info: &SelfInfo<'a, 'tcx>) - -> ty::ExplicitSelfCategory +fn determine_self_type<'a, 'tcx>(this: &AstConv<'tcx>, + rscope: &RegionScope, + self_info: SelfInfo<'a, 'tcx>) + -> (Option>, Option) { + let self_ty = self_info.untransformed_self_ty; return match self_info.explicit_self.node { - hir::SelfStatic => ty::StaticExplicitSelfCategory, - hir::SelfValue(_) => ty::ByValueExplicitSelfCategory, + hir::SelfStatic => (None, Some(ty::StaticExplicitSelfCategory)), + hir::SelfValue(_) => { + (Some(self_ty), Some(ty::ByValueExplicitSelfCategory)) + } hir::SelfRegion(ref lifetime, mutability, _) => { let region = opt_ast_region_to_region(this, rscope, self_info.explicit_self.span, lifetime); - ty::ByReferenceExplicitSelfCategory(region, mutability) + (Some(this.tcx().mk_ref( + this.tcx().mk_region(region), + ty::TypeAndMut { + ty: self_ty, + mutbl: mutability + })), + Some(ty::ByReferenceExplicitSelfCategory(region, mutability))) } hir::SelfExplicit(ref ast_type, _) => { let explicit_type = ast_ty_to_ty(this, rscope, &**ast_type); @@ -1944,7 +1907,7 @@ fn determine_explicit_self_category<'a, 'tcx>(this: &AstConv<'tcx>, impl_modifiers, method_modifiers); - if impl_modifiers >= method_modifiers { + let category = if impl_modifiers >= method_modifiers { ty::ByValueExplicitSelfCategory } else { match explicit_type.sty { @@ -1952,7 +1915,9 @@ fn determine_explicit_self_category<'a, 'tcx>(this: &AstConv<'tcx>, ty::TyBox(_) => ty::ByBoxExplicitSelfCategory, _ => ty::ByValueExplicitSelfCategory, } - } + }; + + (Some(explicit_type), Some(category)) } }; diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 5d0e713012f2a..230422b7044cd 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -136,9 +136,10 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { let item = fcx.tcx().impl_or_trait_item(fcx.tcx().map.local_def_id(item_id)); - let mut implied_bounds = match item.container() { - ty::TraitContainer(_) => vec![], - ty::ImplContainer(def_id) => impl_implied_bounds(fcx, def_id, span) + let (mut implied_bounds, self_ty) = match item.container() { + ty::TraitContainer(_) => (vec![], fcx.tcx().mk_self_type()), + ty::ImplContainer(def_id) => (impl_implied_bounds(fcx, def_id, span), + fcx.tcx().lookup_item_type(def_id).ty) }; match item { @@ -152,6 +153,8 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { let predicates = fcx.instantiate_bounds(span, free_substs, &method.predicates); this.check_fn_or_method(fcx, span, &method_ty, &predicates, free_id_outlive, &mut implied_bounds); + this.check_method_receiver(fcx, span, &method, + free_id_outlive, self_ty); } ty::TypeTraitItem(assoc_type) => { if let Some(ref ty) = assoc_type.ty { @@ -377,6 +380,47 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { self.check_where_clauses(fcx, span, predicates); } + fn check_method_receiver<'fcx>(&mut self, + fcx: &FnCtxt<'fcx,'tcx>, + span: Span, + method: &ty::Method<'tcx>, + free_id_outlive: CodeExtent, + self_ty: ty::Ty<'tcx>) + { + // check that the type of the method's receiver matches the + // method's first parameter. + + let free_substs = &fcx.inh.infcx.parameter_environment.free_substs; + let fty = fcx.instantiate_type_scheme(span, free_substs, &method.fty); + let sig = fcx.tcx().liberate_late_bound_regions(free_id_outlive, &fty.sig); + + debug!("check_method_receiver({:?},cat={:?},self_ty={:?},sig={:?})", + method.name, method.explicit_self, self_ty, sig); + + let rcvr_ty = match method.explicit_self { + ty::StaticExplicitSelfCategory => return, + ty::ByValueExplicitSelfCategory => self_ty, + ty::ByReferenceExplicitSelfCategory(region, mutability) => { + fcx.tcx().mk_ref(fcx.tcx().mk_region(region), ty::TypeAndMut { + ty: self_ty, + mutbl: mutability + }) + } + ty::ByBoxExplicitSelfCategory => fcx.tcx().mk_box(self_ty) + }; + let rcvr_ty = fcx.instantiate_type_scheme(span, free_substs, &rcvr_ty); + let rcvr_ty = fcx.tcx().liberate_late_bound_regions(free_id_outlive, + &ty::Binder(rcvr_ty)); + + debug!("check_method_receiver: receiver ty = {:?}", rcvr_ty); + + let _ = ::require_same_types( + fcx.tcx(), Some(fcx.infcx()), false, span, + sig.inputs[0], rcvr_ty, + || "mismatched method receiver".to_owned() + ); + } + fn check_variances_for_type_defn(&self, item: &hir::Item, ast_generics: &hir::Generics) diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index bfe4151da5c91..b7ce91d331723 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -69,18 +69,15 @@ use middle::def; use middle::def_id::DefId; use constrained_type_params as ctp; use middle::lang_items::SizedTraitLangItem; -use middle::free_region::FreeRegionMap; -use middle::region; use middle::resolve_lifetime; use middle::const_eval::{self, ConstVal}; use middle::const_eval::EvalHint::UncheckedExprHint; use middle::subst::{Substs, FnSpace, ParamSpace, SelfSpace, TypeSpace, VecPerParamSpace}; use middle::ty::{ToPredicate, ImplContainer, ImplOrTraitItemContainer, TraitContainer}; -use middle::ty::{self, RegionEscape, ToPolyTraitRef, Ty, TypeScheme}; +use middle::ty::{self, ToPolyTraitRef, Ty, TypeScheme}; use middle::ty::{VariantKind}; -use middle::ty::fold::{TypeFolder, TypeFoldable}; +use middle::ty::fold::{TypeFolder}; use middle::ty::util::IntTypeExt; -use middle::infer; use rscope::*; use rustc::front::map as hir_map; use util::common::{ErrorReported, memoized}; @@ -195,16 +192,6 @@ impl<'a,'tcx> CrateCtxt<'a,'tcx> { ItemCtxt { ccx: self, param_bounds: param_bounds } } - fn method_ty(&self, method_id: ast::NodeId) -> Rc> { - let def_id = self.tcx.map.local_def_id(method_id); - match *self.tcx.impl_or_trait_items.borrow().get(&def_id).unwrap() { - ty::MethodTraitItem(ref mty) => mty.clone(), - _ => { - self.tcx.sess.bug(&format!("method with id {} has the wrong type", method_id)); - } - } - } - fn cycle_check(&self, span: Span, request: AstConvRequest, @@ -573,10 +560,10 @@ fn is_param<'tcx>(tcx: &ty::ctxt<'tcx>, fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, container: ImplOrTraitItemContainer, - sig: &hir::MethodSig, - id: ast::NodeId, name: ast::Name, + id: ast::NodeId, vis: hir::Visibility, + sig: &hir::MethodSig, untransformed_rcvr_ty: Ty<'tcx>, rcvr_ty_generics: &ty::Generics<'tcx>, rcvr_ty_predicates: &ty::GenericPredicates<'tcx>) { @@ -681,33 +668,6 @@ fn convert_associated_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, .insert(ccx.tcx.map.local_def_id(id), ty::TypeTraitItem(associated_type)); } -fn convert_methods<'a,'tcx,'i,I>(ccx: &CrateCtxt<'a, 'tcx>, - container: ImplOrTraitItemContainer, - methods: I, - untransformed_rcvr_ty: Ty<'tcx>, - rcvr_ty_generics: &ty::Generics<'tcx>, - rcvr_ty_predicates: &ty::GenericPredicates<'tcx>) - where I: Iterator -{ - debug!("convert_methods(untransformed_rcvr_ty={:?}, rcvr_ty_generics={:?}, \ - rcvr_ty_predicates={:?})", - untransformed_rcvr_ty, - rcvr_ty_generics, - rcvr_ty_predicates); - - for (sig, id, name, vis, _span) in methods { - convert_method(ccx, - container, - sig, - id, - name, - vis, - untransformed_rcvr_ty, - rcvr_ty_generics, - rcvr_ty_predicates); - } -} - fn ensure_no_ty_param_bounds(ccx: &CrateCtxt, span: Span, generics: &hir::Generics, @@ -867,36 +827,17 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { } } - let methods = impl_items.iter().filter_map(|ii| { - if let hir::ImplItemKind::Method(ref sig, _) = ii.node { + for impl_item in impl_items { + if let hir::ImplItemKind::Method(ref sig, _) = impl_item.node { // if the method specifies a visibility, use that, otherwise // inherit the visibility from the impl (so `foo` in `pub impl // { fn foo(); }` is public, but private in `impl { fn // foo(); }`). - let method_vis = ii.vis.inherit_from(parent_visibility); - Some((sig, ii.id, ii.name, method_vis, ii.span)) - } else { - None - } - }); - convert_methods(ccx, - ImplContainer(def_id), - methods, - selfty, - &ty_generics, - &ty_predicates); + let method_vis = impl_item.vis.inherit_from(parent_visibility); - for impl_item in impl_items { - if let hir::ImplItemKind::Method(ref sig, ref body) = impl_item.node { - let body_id = body.id; - let body_scope = ccx.tcx.region_maps.call_site_extent(impl_item.id, body_id); - check_method_self_type(ccx, - &BindingRscope::new(), - ccx.method_ty(impl_item.id), - selfty, - &sig.explicit_self, - body_scope, - body_id); + convert_method(ccx, ImplContainer(def_id), + impl_item.name, impl_item.id, method_vis, + sig, selfty, &ty_generics, &ty_predicates); } } @@ -904,112 +845,80 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { }, hir::ItemTrait(_, _, _, ref trait_items) => { let trait_def = trait_def_of_item(ccx, it); + let def_id = trait_def.trait_ref.def_id; let _: Result<(), ErrorReported> = // any error is already reported, can ignore - ccx.ensure_super_predicates(it.span, ccx.tcx.map.local_def_id(it.id)); + ccx.ensure_super_predicates(it.span, def_id); convert_trait_predicates(ccx, it); - let trait_predicates = tcx.lookup_predicates(ccx.tcx.map.local_def_id(it.id)); + let trait_predicates = tcx.lookup_predicates(def_id); debug!("convert: trait_bounds={:?}", trait_predicates); - // Convert all the associated types. + // FIXME: is the ordering here important? I think it is. + let container = TraitContainer(def_id); + + // Convert all the associated constants. for trait_item in trait_items { - match trait_item.node { - hir::ConstTraitItem(ref ty, ref default) => { - let ty = ccx.icx(&trait_predicates) - .to_ty(&ExplicitRscope, ty); - tcx.register_item_type(ccx.tcx.map.local_def_id(trait_item.id), - TypeScheme { - generics: trait_def.generics.clone(), - ty: ty, - }); - convert_associated_const(ccx, - TraitContainer(ccx.tcx.map.local_def_id(it.id)), - trait_item.name, - trait_item.id, - hir::Public, - ty, - default.is_some()) - } - _ => {} + if let hir::ConstTraitItem(ref ty, ref default) = trait_item.node { + let ty = ccx.icx(&trait_predicates) + .to_ty(&ExplicitRscope, ty); + tcx.register_item_type(ccx.tcx.map.local_def_id(trait_item.id), + TypeScheme { + generics: trait_def.generics.clone(), + ty: ty, + }); + convert_associated_const(ccx, + container, + trait_item.name, + trait_item.id, + hir::Public, + ty, + default.is_some()) } - }; + } // Convert all the associated types. for trait_item in trait_items { - match trait_item.node { - hir::TypeTraitItem(_, ref opt_ty) => { - let typ = opt_ty.as_ref().map({ - |ty| ccx.icx(&trait_predicates).to_ty(&ExplicitRscope, &ty) - }); - - convert_associated_type(ccx, - TraitContainer(ccx.tcx.map.local_def_id(it.id)), - trait_item.name, - trait_item.id, - hir::Public, - typ); - } - _ => {} + if let hir::TypeTraitItem(_, ref opt_ty) = trait_item.node { + let typ = opt_ty.as_ref().map({ + |ty| ccx.icx(&trait_predicates).to_ty(&ExplicitRscope, &ty) + }); + + convert_associated_type(ccx, + container, + trait_item.name, + trait_item.id, + hir::Public, + typ); } - }; + } - let methods = trait_items.iter().filter_map(|ti| { - let sig = match ti.node { - hir::MethodTraitItem(ref sig, _) => sig, - _ => return None, - }; - Some((sig, ti.id, ti.name, hir::Inherited, ti.span)) - }); + // Convert all the methods + for trait_item in trait_items { + if let hir::MethodTraitItem(ref sig, _) = trait_item.node { + convert_method(ccx, + container, + trait_item.name, + trait_item.id, + hir::Inherited, + sig, + tcx.mk_self_type(), + &trait_def.generics, + &trait_predicates); - // Run convert_methods on the trait methods. - convert_methods(ccx, - TraitContainer(ccx.tcx.map.local_def_id(it.id)), - methods, - tcx.mk_self_type(), - &trait_def.generics, - &trait_predicates); + } + } // Add an entry mapping let trait_item_def_ids = Rc::new(trait_items.iter().map(|trait_item| { let def_id = ccx.tcx.map.local_def_id(trait_item.id); match trait_item.node { - hir::ConstTraitItem(..) => { - ty::ConstTraitItemId(def_id) - } - hir::MethodTraitItem(..) => { - ty::MethodTraitItemId(def_id) - } - hir::TypeTraitItem(..) => { - ty::TypeTraitItemId(def_id) - } + hir::ConstTraitItem(..) => ty::ConstTraitItemId(def_id), + hir::MethodTraitItem(..) => ty::MethodTraitItemId(def_id), + hir::TypeTraitItem(..) => ty::TypeTraitItemId(def_id) } }).collect()); tcx.trait_item_def_ids.borrow_mut().insert(ccx.tcx.map.local_def_id(it.id), trait_item_def_ids); - - // This must be done after `collect_trait_methods` so that - // we have a method type stored for every method. - for trait_item in trait_items { - let (sig, the_scope, the_id) = match trait_item.node { - hir::MethodTraitItem(ref sig, Some(ref body)) => { - let body_scope = - ccx.tcx.region_maps.call_site_extent(trait_item.id, body.id); - (sig, body_scope, body.id) - } - hir::MethodTraitItem(ref sig, None) => { - let item_scope = ccx.tcx.region_maps.item_extent(trait_item.id); - (sig, item_scope, it.id) - } - _ => continue - }; - check_method_self_type(ccx, - &BindingRscope::new(), - ccx.method_ty(trait_item.id), - tcx.mk_self_type(), - &sig.explicit_self, - the_scope, - the_id) - } }, hir::ItemStruct(ref struct_def, _) => { let (scheme, predicates) = convert_typed_item(ccx, it); @@ -1395,7 +1304,6 @@ fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, .iter() .enumerate() .map(|(i, def)| ty::ReEarlyBound(ty::EarlyBoundRegion { - def_id: tcx.map.local_def_id(def.lifetime.id), space: TypeSpace, index: i as u32, name: def.lifetime.name @@ -1870,10 +1778,8 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, let early_lifetimes = early_bound_lifetimes_from_generics(space, ast_generics); for (index, param) in early_lifetimes.iter().enumerate() { let index = index as u32; - let def_id = tcx.map.local_def_id(param.lifetime.id); let region = ty::ReEarlyBound(ty::EarlyBoundRegion { - def_id: def_id, space: space, index: index, name: param.lifetime.name @@ -2281,106 +2187,6 @@ fn mk_item_substs<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, Substs::new(types, regions) } -/// Verifies that the explicit self type of a method matches the impl -/// or trait. This is a bit weird but basically because right now we -/// don't handle the general case, but instead map it to one of -/// several pre-defined options using various heuristics, this method -/// comes back to check after the fact that explicit type the user -/// wrote actually matches what the pre-defined option said. -fn check_method_self_type<'a, 'tcx, RS:RegionScope>( - ccx: &CrateCtxt<'a, 'tcx>, - rs: &RS, - method_type: Rc>, - required_type: Ty<'tcx>, - explicit_self: &hir::ExplicitSelf, - body_scope: region::CodeExtent, - body_id: ast::NodeId) -{ - let tcx = ccx.tcx; - if let hir::SelfExplicit(ref ast_type, _) = explicit_self.node { - let typ = ccx.icx(&method_type.predicates).to_ty(rs, &**ast_type); - let base_type = match typ.sty { - ty::TyRef(_, tm) => tm.ty, - ty::TyBox(typ) => typ, - _ => typ, - }; - - // "Required type" comes from the trait definition. It may - // contain late-bound regions from the method, but not the - // trait (since traits only have early-bound region - // parameters). - assert!(!base_type.has_regions_escaping_depth(1)); - let required_type_free = - liberate_early_bound_regions( - tcx, body_scope, - &tcx.liberate_late_bound_regions(body_scope, &ty::Binder(required_type))); - - // The "base type" comes from the impl. It too may have late-bound - // regions from the method. - assert!(!base_type.has_regions_escaping_depth(1)); - let base_type_free = - liberate_early_bound_regions( - tcx, body_scope, - &tcx.liberate_late_bound_regions(body_scope, &ty::Binder(base_type))); - - debug!("required_type={:?} required_type_free={:?} \ - base_type={:?} base_type_free={:?}", - required_type, - required_type_free, - base_type, - base_type_free); - - let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, false); - drop(::require_same_types(tcx, - Some(&infcx), - false, - explicit_self.span, - base_type_free, - required_type_free, - || { - format!("mismatched self type: expected `{}`", - required_type) - })); - - // We could conceviably add more free-region relations here, - // but since this code is just concerned with checking that - // the `&Self` types etc match up, it's not really necessary. - // It would just allow people to be more approximate in some - // cases. In any case, we can do it later as we feel the need; - // I'd like this function to go away eventually. - let free_regions = FreeRegionMap::new(); - - infcx.resolve_regions_and_report_errors(&free_regions, body_id); - } - - fn liberate_early_bound_regions<'tcx,T>( - tcx: &ty::ctxt<'tcx>, - scope: region::CodeExtent, - value: &T) - -> T - where T : TypeFoldable<'tcx> - { - /*! - * Convert early-bound regions into free regions; normally this is done by - * applying the `free_substs` from the `ParameterEnvironment`, but this particular - * method-self-type check is kind of hacky and done very early in the process, - * before we really have a `ParameterEnvironment` to check. - */ - - tcx.fold_regions(value, &mut false, |region, _| { - match region { - ty::ReEarlyBound(data) => { - ty::ReFree(ty::FreeRegion { - scope: scope, - bound_region: ty::BrNamed(data.def_id, data.name) - }) - } - _ => region - } - }) - } -} - /// Checks that all the type parameters on an impl fn enforce_impl_params_are_constrained<'tcx>(tcx: &ty::ctxt<'tcx>, ast_generics: &hir::Generics, @@ -2450,9 +2256,7 @@ fn enforce_impl_lifetimes_are_constrained<'tcx>(tcx: &ty::ctxt<'tcx>, .collect(); for (index, lifetime_def) in ast_generics.lifetimes.iter().enumerate() { - let def_id = tcx.map.local_def_id(lifetime_def.lifetime.id); - let region = ty::EarlyBoundRegion { def_id: def_id, - space: TypeSpace, + let region = ty::EarlyBoundRegion { space: TypeSpace, index: index as u32, name: lifetime_def.lifetime.name }; if diff --git a/src/librustc_typeck/variance.rs b/src/librustc_typeck/variance.rs index 1fafe3484f0f2..8c7967c707807 100644 --- a/src/librustc_typeck/variance.rs +++ b/src/librustc_typeck/variance.rs @@ -1002,12 +1002,14 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { /// Adds constraints appropriate for a region appearing in a /// context with ambient variance `variance` fn add_constraints_from_region(&mut self, - _generics: &ty::Generics<'tcx>, + generics: &ty::Generics<'tcx>, region: ty::Region, variance: VarianceTermPtr<'a>) { match region { ty::ReEarlyBound(ref data) => { - let node_id = self.tcx().map.as_local_node_id(data.def_id).unwrap(); + let def_id = + generics.regions.get(data.space, data.index as usize).def_id; + let node_id = self.tcx().map.as_local_node_id(def_id).unwrap(); if self.is_to_be_inferred(node_id) { let index = self.inferred_index(node_id); self.add_constraint(index, variance); diff --git a/src/test/compile-fail/issue-17740.rs b/src/test/compile-fail/issue-17740.rs index b4791eba76e26..4381bf22e2ace 100644 --- a/src/test/compile-fail/issue-17740.rs +++ b/src/test/compile-fail/issue-17740.rs @@ -15,12 +15,12 @@ struct Foo<'a> { impl <'a> Foo<'a>{ fn bar(self: &mut Foo) { //~^ mismatched types - //~| expected `Foo<'a>` - //~| found `Foo<'_>` + //~| expected `&mut Foo<'a>` + //~| found `&mut Foo<'_>` //~| lifetime mismatch //~| mismatched types - //~| expected `Foo<'a>` - //~| found `Foo<'_>` + //~| expected `&mut Foo<'a>` + //~| found `&mut Foo<'_>` //~| lifetime mismatch } } diff --git a/src/test/compile-fail/issue-17905.rs b/src/test/compile-fail/issue-17905.rs index eabdb36a7efc6..f11d482ea16db 100644 --- a/src/test/compile-fail/issue-17905.rs +++ b/src/test/compile-fail/issue-17905.rs @@ -16,10 +16,6 @@ impl Pair< isize > { fn say(self: &Pair<&str, isize>) { -//~^ ERROR mismatched types -//~| expected `Pair<&'static str, isize>` -//~| found `Pair<&str, isize>` -//~| lifetime mismatch println!("{}", self); } } diff --git a/src/test/compile-fail/issue-26194.rs b/src/test/compile-fail/issue-26194.rs index b5c875cc4cbd2..ef91188c5d166 100644 --- a/src/test/compile-fail/issue-26194.rs +++ b/src/test/compile-fail/issue-26194.rs @@ -12,7 +12,7 @@ struct S(String); impl S { fn f(self: *mut S) -> String { self.0 } - //~^ ERROR mismatched self type + //~^ ERROR mismatched method receiver } fn main() { S("".to_owned()).f(); } diff --git a/src/test/compile-fail/ufcs-explicit-self-bad.rs b/src/test/compile-fail/ufcs-explicit-self-bad.rs index 5d2b5fa52db41..e54a7623cb0c3 100644 --- a/src/test/compile-fail/ufcs-explicit-self-bad.rs +++ b/src/test/compile-fail/ufcs-explicit-self-bad.rs @@ -15,7 +15,7 @@ struct Foo { } impl Foo { - fn foo(self: isize, x: isize) -> isize { //~ ERROR mismatched self type + fn foo(self: isize, x: isize) -> isize { //~ ERROR mismatched method receiver self.f + x } } @@ -25,10 +25,10 @@ struct Bar { } impl Bar { - fn foo(self: Bar, x: isize) -> isize { //~ ERROR mismatched self type + fn foo(self: Bar, x: isize) -> isize { //~ ERROR mismatched method receiver x } - fn bar(self: &Bar, x: isize) -> isize { //~ ERROR mismatched self type + fn bar(self: &Bar, x: isize) -> isize { //~ ERROR mismatched method receiver x } } @@ -41,15 +41,16 @@ trait SomeTrait { impl<'a, T> SomeTrait for &'a Bar { fn dummy1(self: &&'a Bar) { } - fn dummy2(self: &Bar) {} //~ ERROR mismatched self type + fn dummy2(self: &Bar) {} //~ ERROR mismatched types + //~^ ERROR mismatched types fn dummy3(self: &&Bar) {} //~^ ERROR mismatched types - //~| expected `&'a Bar` - //~| found `&Bar` + //~| expected `&&'a Bar` + //~| found `&&Bar` //~| lifetime mismatch //~| ERROR mismatched types - //~| expected `&'a Bar` - //~| found `&Bar` + //~| expected `&&'a Bar` + //~| found `&&Bar` //~| lifetime mismatch }