Skip to content

Commit 6708c29

Browse files
committed
auto merge of rust-lang#10506 : nikomatsakis/rust/issue-10391-ICE-with-lifetimes, r=pnkfelix
Make trait lifetime parameters early bound in static fn type. Reasoning for this change is (hopefully) explained well enough in the comment, so I'll not duplicate it here. Fixes rust-lang#10391. r? @pnkfelix
2 parents 5535313 + e9d364d commit 6708c29

File tree

3 files changed

+64
-12
lines changed

3 files changed

+64
-12
lines changed

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

Lines changed: 0 additions & 1 deletion
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

Lines changed: 25 additions & 11 deletions
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
});
Lines changed: 39 additions & 0 deletions
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+
pub fn main() { }

0 commit comments

Comments
 (0)