From 23d95f6dc63c42f8fec60bd60588a20a254fa4d7 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 15 Nov 2013 17:04:01 -0500 Subject: [PATCH] Make trait lifetime parameters early bound in static fn type. This is related to #5121. Fixes #10391. --- src/librustc/middle/typeck/check/vtable.rs | 1 - src/librustc/middle/typeck/collect.rs | 36 +++++++++++------ ...egions-early-bound-lifetime-in-assoc-fn.rs | 39 +++++++++++++++++++ 3 files changed, 64 insertions(+), 12 deletions(-) create mode 100644 src/test/run-pass/regions-early-bound-lifetime-in-assoc-fn.rs diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs index 6e588faeaf7..4a2ddf5f0f2 100644 --- a/src/librustc/middle/typeck/check/vtable.rs +++ b/src/librustc/middle/typeck/check/vtable.rs @@ -94,7 +94,6 @@ fn lookup_vtables(vcx: &VtableContext, location_info, type_param_defs.repr(vcx.tcx()), substs.repr(vcx.tcx())); - let _i = indenter(); // We do this backwards for reasons discussed above. assert_eq!(substs.tps.len(), type_param_defs.len()); diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index 967da143810..343808c2fa7 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -236,21 +236,31 @@ fn make_static_method_ty(ccx: &CrateCtxt, trait_ty_generics: &ty::Generics) { // If declaration is // - // trait<'a,'b,'c,A,B,C> { - // fn foo<'d,'e,'f,D,E,F>(...) -> Self; + // trait Trait<'a,'b,'c,a,b,c> { + // fn foo<'d,'e,'f,d,e,f>(...) -> Self; // } // // and we will create a function like // - // fn foo<'a,'b,'c,'d,'e,'f,A',B',C',D',E',F',G'>(...) -> D' {} + // fn foo<'a,'b,'c, // First the lifetime params from trait + // 'd,'e,'f, // Then lifetime params from `foo()` + // a,b,c, // Then type params from trait + // D:Trait<'a,'b,'c,a,b,c>, // Then this sucker + // E,F,G // Then type params from `foo()`, offset by 1 + // >(...) -> D' {} // // Note that `Self` is replaced with an explicit type - // parameter D' that is sandwiched in between the trait params + // parameter D that is sandwiched in between the trait params // and the method params, and thus the indices of the method // type parameters are offset by 1 (that is, the method - // parameters are mapped from D, E, F to E', F', and G'). The + // parameters are mapped from d, e, f to E, F, and G). The // choice of this ordering is somewhat arbitrary. // + // Note also that the bound for `D` is `Trait<'a,'b,'c,a,b,c>`. + // This implies that the lifetime parameters that were inherited + // from the trait (i.e., `'a`, `'b`, and `'c`) all must be early + // bound, since they appear in a trait bound. + // // Also, this system is rather a hack that should be replaced // with a more uniform treatment of Self (which is partly // underway). @@ -280,13 +290,17 @@ fn make_static_method_ty(ccx: &CrateCtxt, }); // Convert the regions 'a, 'b, 'c defined on the trait into - // bound regions on the fn. - let rps_from_trait = trait_ty_generics.region_param_defs.iter().map(|d| { - ty::ReLateBound(m.fty.sig.binder_id, - ty::BrNamed(d.def_id, d.ident)) - }).collect(); + // bound regions on the fn. Note that because these appear in the + // bound for `Self` they must be early bound. + let new_early_region_param_defs = trait_ty_generics.region_param_defs; + let rps_from_trait = + trait_ty_generics.region_param_defs.iter(). + enumerate(). + map(|(index,d)| ty::ReEarlyBound(d.def_id.node, index, d.ident)). + collect(); // build up the substitution from + // 'a,'b,'c => 'a,'b,'c // A,B,C => A',B',C' // Self => D' // D,E,F => E',F',G' @@ -336,7 +350,7 @@ fn make_static_method_ty(ccx: &CrateCtxt, ty_param_bounds_and_ty { generics: ty::Generics { type_param_defs: @new_type_param_defs, - region_param_defs: @[], // fn items + region_param_defs: new_early_region_param_defs }, ty: ty }); diff --git a/src/test/run-pass/regions-early-bound-lifetime-in-assoc-fn.rs b/src/test/run-pass/regions-early-bound-lifetime-in-assoc-fn.rs new file mode 100644 index 00000000000..5438758f4b9 --- /dev/null +++ b/src/test/run-pass/regions-early-bound-lifetime-in-assoc-fn.rs @@ -0,0 +1,39 @@ +// 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. + +// Test that we are able to compile calls to associated fns like +// `decode()` where the bound on the `Self` parameter references a +// lifetime parameter of the trait. This example indicates why trait +// lifetime parameters must be early bound in the type of the +// associated item. + +pub enum Value<'v> { + A(&'v str), + B, +} + +pub trait Decoder<'v> { + fn read(&mut self) -> Value<'v>; +} + +pub trait Decodable<'v, D: Decoder<'v>> { + fn decode(d: &mut D) -> Self; +} + +impl<'v, D: Decoder<'v>> Decodable<'v, D> for () { + fn decode(d: &mut D) -> () { + match d.read() { + A(..) => (), + B => Decodable::decode(d), + } + } +} + +fn main() { }