diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs index 89c004fc64596..3c71b3e80cf31 100644 --- a/src/librustc/middle/typeck/astconv.rs +++ b/src/librustc/middle/typeck/astconv.rs @@ -52,6 +52,7 @@ use middle::resolve_lifetime as rl; use middle::subst::{FnSpace, TypeSpace, AssocSpace, SelfSpace, Subst, Substs}; use middle::subst::{VecPerParamSpace}; use middle::ty::{mod, Ty}; +use middle::ty_fold; use middle::typeck::lookup_def_tcx; use middle::typeck::rscope::{UnelidableRscope, RegionScope, SpecificRscope, ShiftedRscope, BindingRscope}; @@ -1069,7 +1070,8 @@ fn ty_of_method_or_bare_fn<'a, 'tcx, AC: AstConv<'tcx>>( opt_self_info: Option>, decl: &ast::FnDecl) -> (ty::BareFnTy<'tcx>, - Option) { + Option) +{ debug!("ty_of_method_or_bare_fn"); // New region names that appear inside of the arguments of the function @@ -1085,6 +1087,11 @@ fn ty_of_method_or_bare_fn<'a, 'tcx, AC: AstConv<'tcx>>( let (self_ty, mut implied_output_region) = match opt_self_info { None => (None, None), Some(self_info) => { + // Shift regions in the self type by 1 to account for the binding + // level introduced by the function itself. + let untransformed_self_ty = + ty_fold::shift_regions(this.tcx(), 1, &self_info.untransformed_self_ty); + // Figure out and record the explicit self category. let explicit_self_category = determine_explicit_self_category(this, &rb, &self_info); @@ -1094,21 +1101,19 @@ fn ty_of_method_or_bare_fn<'a, 'tcx, AC: AstConv<'tcx>>( (None, None) } ty::ByValueExplicitSelfCategory => { - (Some(self_info.untransformed_self_ty), None) + (Some(untransformed_self_ty), None) } ty::ByReferenceExplicitSelfCategory(region, mutability) => { (Some(ty::mk_rptr(this.tcx(), region, ty::mt { - ty: self_info.untransformed_self_ty, + ty: untransformed_self_ty, mutbl: mutability })), Some(region)) } ty::ByBoxExplicitSelfCategory => { - (Some(ty::mk_uniq(this.tcx(), - self_info.untransformed_self_ty)), - None) + (Some(ty::mk_uniq(this.tcx(), untransformed_self_ty)), None) } } } diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index 3a62978ed007a..09456fc8999c7 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -1074,7 +1074,7 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) { ref selfty, ref impl_items) => { // Create generics from the generics specified in the impl head. - let ty_generics = ty_generics_for_type( + let ty_generics = ty_generics_for_impl( ccx, generics, CreateTypeParametersForAssociatedTypes); @@ -1676,6 +1676,24 @@ fn ty_generics_for_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, generics } +fn ty_generics_for_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, + generics: &ast::Generics, + create_type_parameters_for_associated_types: + CreateTypeParametersForAssociatedTypesFlag) + -> ty::Generics<'tcx> +{ + let early_lifetimes = resolve_lifetime::early_bound_lifetimes(generics); + debug!("ty_generics_for_impl: early_lifetimes={}", + early_lifetimes); + ty_generics(ccx, + subst::TypeSpace, + early_lifetimes.as_slice(), + generics.ty_params.as_slice(), + ty::Generics::empty(), + &generics.where_clause, + create_type_parameters_for_associated_types) +} + fn ty_generics_for_fn_or_method<'tcx,AC>( this: &AC, generics: &ast::Generics, diff --git a/src/test/compile-fail/hrtb-debruijn-in-receiver.rs b/src/test/compile-fail/hrtb-debruijn-in-receiver.rs new file mode 100644 index 0000000000000..2dbd16107b0d5 --- /dev/null +++ b/src/test/compile-fail/hrtb-debruijn-in-receiver.rs @@ -0,0 +1,28 @@ +// Copyright 2014 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 the case where the `Self` type has a bound lifetime that must +// be adjusted in the fn signature. Issue #19537. + +use std::collections::HashMap; + +struct Foo<'a> { + map: HashMap +} + +impl<'a> Foo<'a> { + fn new() -> Foo<'a> { panic!() } + fn insert(&'a mut self) { } +} +fn main() { + let mut foo = Foo::new(); + foo.insert(); + foo.insert(); //~ ERROR cannot borrow +}