diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 4514564ff1f6c..9a810dea04f58 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -115,6 +115,7 @@ use std::result; use std::util::replace; use std::vec; use extra::list::Nil; +use extra::list; use syntax::abi::AbiSet; use syntax::ast::{provided, required}; use syntax::ast; @@ -3342,19 +3343,30 @@ pub fn instantiate_path(fcx: @mut FnCtxt, } }; - // Special case: If there is a self parameter, omit it from the list of - // type parameters. - // - // Here we calculate the "user type parameter count", which is the number - // of type parameters actually manifest in the AST. This will differ from - // the internal type parameter count when there are self types involved. - let (user_type_parameter_count, self_parameter_index) = match def { + // Special case for static trait methods: omit the self parameter + // from the list of type parameters and constrain the 'self + // lifetime to be equal to the enclosing 'self lifetime. + let (user_type_parameter_count, self_parameter_index, regions) = match def { ast::DefStaticMethod(_, provenance @ ast::FromTrait(_), _) => { let generics = generics_of_static_method_container(fcx.ccx.tcx, provenance); - (ty_param_count - 1, Some(generics.type_param_defs.len())) + + // If 'self is in scope, then use the free region it is already + // associated with. If 'self is not in scope then + // `regions` won't be used anyway. + let constrained_regions = + match list::find(fcx.in_scope_regions, + |&(br, _)| br == ty::br_self) { + Some((_, r)) => opt_vec::with(r), + None => regions + }; + + (ty_param_count - 1, + Some(generics.type_param_defs.len()), + constrained_regions) } - _ => (ty_param_count, None), + _ => { + (ty_param_count, None, regions)} }; // determine values for type parameters, using the values given by diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs index 3c4ff35b768db..6522d6fe8f5e7 100644 --- a/src/librustc/middle/typeck/check/vtable.rs +++ b/src/librustc/middle/typeck/check/vtable.rs @@ -28,6 +28,7 @@ use std::result; use syntax::ast; use syntax::ast_util; use syntax::codemap::Span; +use syntax::opt_vec; use syntax::print::pprust::expr_to_str; use syntax::visit; use syntax::visit::Visitor; @@ -295,6 +296,33 @@ fn lookup_vtable_from_bounds(vcx: &VtableContext, bound_trait_ref.repr(vcx.tcx())); if bound_trait_ref.def_id == trait_ref.def_id { + + // Replace any instances of br_self with a new region + // variable in order to avoid asking region inference to + // relate a bound region to a free region. Strictly + // speaking, instead of a new region variable, we should + // use the free region associated with br_self, if it + // exists. However, bound_trait_ref does not play an + // important role in the main phase of region checking, so + // precisely what we choose here shouldn't matter. + let substs = ty::substs { + self_ty : None, + tps : ~[], + regions: ty::NonerasedRegions(opt_vec::with( + vcx.infcx.next_region_var( + infer::BoundRegionInTypeOrImpl( + location_info.span)))) + }; + + let bound_trait_ref = @ty::TraitRef { + def_id : bound_trait_ref.def_id, + substs : ty::substs { + self_ty : bound_trait_ref.substs.self_ty.clone(), + tps : bound_trait_ref.substs.tps.clone(), + regions : bound_trait_ref.substs.regions.subst(vcx.ccx.tcx, + &substs) + }}; + relate_trait_refs(vcx, location_info, bound_trait_ref, diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index 9c69e6fd85cc7..0c206b07552bf 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -268,7 +268,7 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt, // fn foo(...) -> Self; // } // - // and we will create a function like + // then we will create a function like // // fn foo(...) -> D' {} // @@ -312,7 +312,7 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt, // Self => D' // D,E,F => E',F',G' let substs = substs { - regions: ty::NonerasedRegions(opt_vec::Empty), + regions: ty::NonerasedRegions(opt_vec::with(ty::re_bound(ty::br_self))), self_ty: Some(self_param), tps: non_shifted_trait_tps + shifted_method_tps }; @@ -357,7 +357,7 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt, ty_param_bounds_and_ty { generics: ty::Generics { type_param_defs: @new_type_param_defs, - region_param: trait_ty_generics.region_param + region_param: None }, ty: ty }); diff --git a/src/test/run-pass/issue-7331.rs b/src/test/run-pass/issue-7331.rs new file mode 100644 index 0000000000000..e57aba5e23ad8 --- /dev/null +++ b/src/test/run-pass/issue-7331.rs @@ -0,0 +1,31 @@ +// Copyright 2013 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. + +pub trait Interner<'self, T> { + fn new() -> Self; + fn get(&'self self, tag: uint) -> Option<&'self T>; +} + +pub trait FromVec<'self> { + fn fromVec(&'self [u8]) -> Self; +} + +struct Reader<'self> { + v : &'self [u8] +} + +impl <'self, T : FromVec<'self>> Reader<'self> { + fn get(&self) -> T { + FromVec::fromVec(self.v) + } +} + + +fn main() {}