Skip to content

Commit 23d95f6

Browse files
committed
Make trait lifetime parameters early bound in static fn type. This is related
to #5121. Fixes #10391.
1 parent 69186ef commit 23d95f6

File tree

3 files changed

+64
-12
lines changed

3 files changed

+64
-12
lines changed

src/librustc/middle/typeck/check/vtable.rs

-1
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,6 @@ fn lookup_vtables(vcx: &VtableContext,
9494
location_info,
9595
type_param_defs.repr(vcx.tcx()),
9696
substs.repr(vcx.tcx()));
97-
let _i = indenter();
9897

9998
// We do this backwards for reasons discussed above.
10099
assert_eq!(substs.tps.len(), type_param_defs.len());

src/librustc/middle/typeck/collect.rs

+25-11
Original file line numberDiff line numberDiff line change
@@ -236,21 +236,31 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt,
236236
trait_ty_generics: &ty::Generics) {
237237
// If declaration is
238238
//
239-
// trait<'a,'b,'c,A,B,C> {
240-
// fn foo<'d,'e,'f,D,E,F>(...) -> Self;
239+
// trait Trait<'a,'b,'c,a,b,c> {
240+
// fn foo<'d,'e,'f,d,e,f>(...) -> Self;
241241
// }
242242
//
243243
// and we will create a function like
244244
//
245-
// fn foo<'a,'b,'c,'d,'e,'f,A',B',C',D',E',F',G'>(...) -> D' {}
245+
// fn foo<'a,'b,'c, // First the lifetime params from trait
246+
// 'd,'e,'f, // Then lifetime params from `foo()`
247+
// a,b,c, // Then type params from trait
248+
// D:Trait<'a,'b,'c,a,b,c>, // Then this sucker
249+
// E,F,G // Then type params from `foo()`, offset by 1
250+
// >(...) -> D' {}
246251
//
247252
// Note that `Self` is replaced with an explicit type
248-
// parameter D' that is sandwiched in between the trait params
253+
// parameter D that is sandwiched in between the trait params
249254
// and the method params, and thus the indices of the method
250255
// type parameters are offset by 1 (that is, the method
251-
// parameters are mapped from D, E, F to E', F', and G'). The
256+
// parameters are mapped from d, e, f to E, F, and G). The
252257
// choice of this ordering is somewhat arbitrary.
253258
//
259+
// Note also that the bound for `D` is `Trait<'a,'b,'c,a,b,c>`.
260+
// This implies that the lifetime parameters that were inherited
261+
// from the trait (i.e., `'a`, `'b`, and `'c`) all must be early
262+
// bound, since they appear in a trait bound.
263+
//
254264
// Also, this system is rather a hack that should be replaced
255265
// with a more uniform treatment of Self (which is partly
256266
// underway).
@@ -280,13 +290,17 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt,
280290
});
281291

282292
// Convert the regions 'a, 'b, 'c defined on the trait into
283-
// bound regions on the fn.
284-
let rps_from_trait = trait_ty_generics.region_param_defs.iter().map(|d| {
285-
ty::ReLateBound(m.fty.sig.binder_id,
286-
ty::BrNamed(d.def_id, d.ident))
287-
}).collect();
293+
// bound regions on the fn. Note that because these appear in the
294+
// bound for `Self` they must be early bound.
295+
let new_early_region_param_defs = trait_ty_generics.region_param_defs;
296+
let rps_from_trait =
297+
trait_ty_generics.region_param_defs.iter().
298+
enumerate().
299+
map(|(index,d)| ty::ReEarlyBound(d.def_id.node, index, d.ident)).
300+
collect();
288301

289302
// build up the substitution from
303+
// 'a,'b,'c => 'a,'b,'c
290304
// A,B,C => A',B',C'
291305
// Self => D'
292306
// D,E,F => E',F',G'
@@ -336,7 +350,7 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt,
336350
ty_param_bounds_and_ty {
337351
generics: ty::Generics {
338352
type_param_defs: @new_type_param_defs,
339-
region_param_defs: @[], // fn items
353+
region_param_defs: new_early_region_param_defs
340354
},
341355
ty: ty
342356
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Copyright 2013 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.
4+
//
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.
10+
11+
// Test that we are able to compile calls to associated fns like
12+
// `decode()` where the bound on the `Self` parameter references a
13+
// lifetime parameter of the trait. This example indicates why trait
14+
// lifetime parameters must be early bound in the type of the
15+
// associated item.
16+
17+
pub enum Value<'v> {
18+
A(&'v str),
19+
B,
20+
}
21+
22+
pub trait Decoder<'v> {
23+
fn read(&mut self) -> Value<'v>;
24+
}
25+
26+
pub trait Decodable<'v, D: Decoder<'v>> {
27+
fn decode(d: &mut D) -> Self;
28+
}
29+
30+
impl<'v, D: Decoder<'v>> Decodable<'v, D> for () {
31+
fn decode(d: &mut D) -> () {
32+
match d.read() {
33+
A(..) => (),
34+
B => Decodable::decode(d),
35+
}
36+
}
37+
}
38+
39+
fn main() { }

0 commit comments

Comments
 (0)