Skip to content

Commit

Permalink
constrain 'self in static trait method to equal enclosing 'self
Browse files Browse the repository at this point in the history
  • Loading branch information
dwrensha committed Oct 23, 2013
1 parent 564835a commit dfd245d
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 11 deletions.
30 changes: 21 additions & 9 deletions src/librustc/middle/typeck/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
};

This comment has been minimized.

Copy link
@nikomatsakis

nikomatsakis Oct 24, 2013

I don't quite understand what this is trying to accomplish, but it does not feel right. I don't see why we would bind the 'self lifetime parameter for references to static methods to be whatever 'self happens to be in scope. I imagine we'd want a fresh variable.

That said, I am elbows deep in a rewrite of all this logic as part of fixing rust-lang#4846.


(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
Expand Down
28 changes: 28 additions & 0 deletions src/librustc/middle/typeck/check/vtable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/middle/typeck/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt,
// fn foo<D,E,F>(...) -> Self;
// }
//
// and we will create a function like
// then we will create a function like
//
// fn foo<A',B',C',D',E',F',G'>(...) -> D' {}
//
Expand Down Expand Up @@ -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
});
Expand Down
11 changes: 11 additions & 0 deletions src/test/run-pass/issue-7331.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,15 @@ 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() {}

0 comments on commit dfd245d

Please sign in to comment.