Skip to content

Commit 2f3eab2

Browse files
committed
Fix two bugs in HRTB: 1. Categorize early-vs-late bindings on impls when constructing generics, so that we don't add unnecessary region parameters. 2. Correct the DeBruijn indices when substituting the self type into the method signature.
Previously, the DeBruijn index for the self type was not being adjusted to account for the fn binder. This mean that when late-bound regions were instantiated, you sometimes wind up with two distinct lifetimes. Fixes #19537.
1 parent 82fc1aa commit 2f3eab2

File tree

3 files changed

+58
-7
lines changed

3 files changed

+58
-7
lines changed

src/librustc/middle/typeck/astconv.rs

+11-6
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ use middle::resolve_lifetime as rl;
5252
use middle::subst::{FnSpace, TypeSpace, AssocSpace, SelfSpace, Subst, Substs};
5353
use middle::subst::{VecPerParamSpace};
5454
use middle::ty::{mod, Ty};
55+
use middle::ty_fold;
5556
use middle::typeck::lookup_def_tcx;
5657
use middle::typeck::rscope::{UnelidableRscope, RegionScope, SpecificRscope,
5758
ShiftedRscope, BindingRscope};
@@ -1069,7 +1070,8 @@ fn ty_of_method_or_bare_fn<'a, 'tcx, AC: AstConv<'tcx>>(
10691070
opt_self_info: Option<SelfInfo<'a, 'tcx>>,
10701071
decl: &ast::FnDecl)
10711072
-> (ty::BareFnTy<'tcx>,
1072-
Option<ty::ExplicitSelfCategory>) {
1073+
Option<ty::ExplicitSelfCategory>)
1074+
{
10731075
debug!("ty_of_method_or_bare_fn");
10741076

10751077
// 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>>(
10851087
let (self_ty, mut implied_output_region) = match opt_self_info {
10861088
None => (None, None),
10871089
Some(self_info) => {
1090+
// Shift regions in the self type by 1 to account for the binding
1091+
// level introduced by the function itself.
1092+
let untransformed_self_ty =
1093+
ty_fold::shift_regions(this.tcx(), 1, &self_info.untransformed_self_ty);
1094+
10881095
// Figure out and record the explicit self category.
10891096
let explicit_self_category =
10901097
determine_explicit_self_category(this, &rb, &self_info);
@@ -1094,21 +1101,19 @@ fn ty_of_method_or_bare_fn<'a, 'tcx, AC: AstConv<'tcx>>(
10941101
(None, None)
10951102
}
10961103
ty::ByValueExplicitSelfCategory => {
1097-
(Some(self_info.untransformed_self_ty), None)
1104+
(Some(untransformed_self_ty), None)
10981105
}
10991106
ty::ByReferenceExplicitSelfCategory(region, mutability) => {
11001107
(Some(ty::mk_rptr(this.tcx(),
11011108
region,
11021109
ty::mt {
1103-
ty: self_info.untransformed_self_ty,
1110+
ty: untransformed_self_ty,
11041111
mutbl: mutability
11051112
})),
11061113
Some(region))
11071114
}
11081115
ty::ByBoxExplicitSelfCategory => {
1109-
(Some(ty::mk_uniq(this.tcx(),
1110-
self_info.untransformed_self_ty)),
1111-
None)
1116+
(Some(ty::mk_uniq(this.tcx(), untransformed_self_ty)), None)
11121117
}
11131118
}
11141119
}

src/librustc/middle/typeck/collect.rs

+19-1
Original file line numberDiff line numberDiff line change
@@ -1074,7 +1074,7 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
10741074
ref selfty,
10751075
ref impl_items) => {
10761076
// Create generics from the generics specified in the impl head.
1077-
let ty_generics = ty_generics_for_type(
1077+
let ty_generics = ty_generics_for_impl(
10781078
ccx,
10791079
generics,
10801080
CreateTypeParametersForAssociatedTypes);
@@ -1676,6 +1676,24 @@ fn ty_generics_for_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
16761676
generics
16771677
}
16781678

1679+
fn ty_generics_for_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
1680+
generics: &ast::Generics,
1681+
create_type_parameters_for_associated_types:
1682+
CreateTypeParametersForAssociatedTypesFlag)
1683+
-> ty::Generics<'tcx>
1684+
{
1685+
let early_lifetimes = resolve_lifetime::early_bound_lifetimes(generics);
1686+
debug!("ty_generics_for_impl: early_lifetimes={}",
1687+
early_lifetimes);
1688+
ty_generics(ccx,
1689+
subst::TypeSpace,
1690+
early_lifetimes.as_slice(),
1691+
generics.ty_params.as_slice(),
1692+
ty::Generics::empty(),
1693+
&generics.where_clause,
1694+
create_type_parameters_for_associated_types)
1695+
}
1696+
16791697
fn ty_generics_for_fn_or_method<'tcx,AC>(
16801698
this: &AC,
16811699
generics: &ast::Generics,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright 2014 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 the case where the `Self` type has a bound lifetime that must
12+
// be adjusted in the fn signature. Issue #19537.
13+
14+
use std::collections::HashMap;
15+
16+
struct Foo<'a> {
17+
map: HashMap<uint, &'a str>
18+
}
19+
20+
impl<'a> Foo<'a> {
21+
fn new() -> Foo<'a> { panic!() }
22+
fn insert(&'a mut self) { }
23+
}
24+
fn main() {
25+
let mut foo = Foo::new();
26+
foo.insert();
27+
foo.insert(); //~ ERROR cannot borrow
28+
}

0 commit comments

Comments
 (0)