Skip to content

Commit ca98fef

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 c38e73f commit ca98fef

File tree

3 files changed

+58
-7
lines changed

3 files changed

+58
-7
lines changed

src/librustc_typeck/astconv.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ use middle::resolve_lifetime as rl;
5454
use middle::subst::{FnSpace, TypeSpace, AssocSpace, SelfSpace, Subst, Substs};
5555
use middle::subst::{VecPerParamSpace};
5656
use middle::ty::{mod, Ty};
57+
use middle::ty_fold;
5758
use rscope::{mod, UnelidableRscope, RegionScope, SpecificRscope,
5859
ShiftedRscope, BindingRscope};
5960
use TypeAndSubsts;
@@ -1062,7 +1063,8 @@ fn ty_of_method_or_bare_fn<'a, 'tcx, AC: AstConv<'tcx>>(
10621063
opt_self_info: Option<SelfInfo<'a, 'tcx>>,
10631064
decl: &ast::FnDecl)
10641065
-> (ty::BareFnTy<'tcx>,
1065-
Option<ty::ExplicitSelfCategory>) {
1066+
Option<ty::ExplicitSelfCategory>)
1067+
{
10661068
debug!("ty_of_method_or_bare_fn");
10671069

10681070
// New region names that appear inside of the arguments of the function
@@ -1078,6 +1080,11 @@ fn ty_of_method_or_bare_fn<'a, 'tcx, AC: AstConv<'tcx>>(
10781080
let (self_ty, mut implied_output_region) = match opt_self_info {
10791081
None => (None, None),
10801082
Some(self_info) => {
1083+
// Shift regions in the self type by 1 to account for the binding
1084+
// level introduced by the function itself.
1085+
let untransformed_self_ty =
1086+
ty_fold::shift_regions(this.tcx(), 1, &self_info.untransformed_self_ty);
1087+
10811088
// Figure out and record the explicit self category.
10821089
let explicit_self_category =
10831090
determine_explicit_self_category(this, &rb, &self_info);
@@ -1087,21 +1094,19 @@ fn ty_of_method_or_bare_fn<'a, 'tcx, AC: AstConv<'tcx>>(
10871094
(None, None)
10881095
}
10891096
ty::ByValueExplicitSelfCategory => {
1090-
(Some(self_info.untransformed_self_ty), None)
1097+
(Some(untransformed_self_ty), None)
10911098
}
10921099
ty::ByReferenceExplicitSelfCategory(region, mutability) => {
10931100
(Some(ty::mk_rptr(this.tcx(),
10941101
region,
10951102
ty::mt {
1096-
ty: self_info.untransformed_self_ty,
1103+
ty: untransformed_self_ty,
10971104
mutbl: mutability
10981105
})),
10991106
Some(region))
11001107
}
11011108
ty::ByBoxExplicitSelfCategory => {
1102-
(Some(ty::mk_uniq(this.tcx(),
1103-
self_info.untransformed_self_ty)),
1104-
None)
1109+
(Some(ty::mk_uniq(this.tcx(), untransformed_self_ty)), None)
11051110
}
11061111
}
11071112
}

src/librustc_typeck/collect.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1055,7 +1055,7 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
10551055
ref selfty,
10561056
ref impl_items) => {
10571057
// Create generics from the generics specified in the impl head.
1058-
let ty_generics = ty_generics_for_type(
1058+
let ty_generics = ty_generics_for_impl(
10591059
ccx,
10601060
generics,
10611061
CreateTypeParametersForAssociatedTypes);
@@ -1655,6 +1655,24 @@ fn ty_generics_for_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
16551655
generics
16561656
}
16571657

1658+
fn ty_generics_for_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
1659+
generics: &ast::Generics,
1660+
create_type_parameters_for_associated_types:
1661+
CreateTypeParametersForAssociatedTypesFlag)
1662+
-> ty::Generics<'tcx>
1663+
{
1664+
let early_lifetimes = resolve_lifetime::early_bound_lifetimes(generics);
1665+
debug!("ty_generics_for_impl: early_lifetimes={}",
1666+
early_lifetimes);
1667+
ty_generics(ccx,
1668+
subst::TypeSpace,
1669+
early_lifetimes.as_slice(),
1670+
generics.ty_params.as_slice(),
1671+
ty::Generics::empty(),
1672+
&generics.where_clause,
1673+
create_type_parameters_for_associated_types)
1674+
}
1675+
16581676
fn ty_generics_for_fn_or_method<'tcx,AC>(
16591677
this: &AC,
16601678
generics: &ast::Generics,
Lines changed: 28 additions & 0 deletions
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)