Skip to content

Commit 02aacab

Browse files
committed
Fix DeBruijn accounting. It used to be that all trait-refs were binders,
but now only poly-trait-refs are binders. Fixes #20831.
1 parent e94a9f0 commit 02aacab

File tree

3 files changed

+119
-29
lines changed

3 files changed

+119
-29
lines changed

src/librustc_typeck/astconv.rs

Lines changed: 45 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -516,8 +516,15 @@ pub fn instantiate_poly_trait_ref<'tcx>(
516516
{
517517
let mut projections = Vec::new();
518518

519+
// the trait reference introduces a binding level here, so
520+
// we need to shift the `rscope`. It'd be nice if we could
521+
// do away with this rscope stuff and work this knowledge
522+
// into resolve_lifetimes, as we do with non-omitted
523+
// lifetimes. Oh well, not there yet.
524+
let shifted_rscope = ShiftedRscope::new(rscope);
525+
519526
let trait_ref =
520-
instantiate_trait_ref(this, rscope, &ast_trait_ref.trait_ref,
527+
instantiate_trait_ref(this, &shifted_rscope, &ast_trait_ref.trait_ref,
521528
self_ty, Some(&mut projections));
522529

523530
for projection in projections.into_iter() {
@@ -561,6 +568,29 @@ pub fn instantiate_trait_ref<'tcx>(
561568
}
562569
}
563570

571+
fn object_path_to_poly_trait_ref<'a,'tcx>(
572+
this: &AstConv<'tcx>,
573+
rscope: &RegionScope,
574+
trait_def_id: ast::DefId,
575+
path: &ast::Path,
576+
mut projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
577+
-> ty::PolyTraitRef<'tcx>
578+
{
579+
// we are introducing a binder here, so shift the
580+
// anonymous regions depth to account for that
581+
let shifted_rscope = ShiftedRscope::new(rscope);
582+
583+
let mut tmp = Vec::new();
584+
let trait_ref = ty::Binder(ast_path_to_trait_ref(this,
585+
&shifted_rscope,
586+
trait_def_id,
587+
None,
588+
path,
589+
Some(&mut tmp)));
590+
projections.extend(tmp.into_iter().map(ty::Binder));
591+
trait_ref
592+
}
593+
564594
fn ast_path_to_trait_ref<'a,'tcx>(
565595
this: &AstConv<'tcx>,
566596
rscope: &RegionScope,
@@ -573,13 +603,6 @@ fn ast_path_to_trait_ref<'a,'tcx>(
573603
debug!("ast_path_to_trait_ref {:?}", path);
574604
let trait_def = this.get_trait_def(trait_def_id);
575605

576-
// the trait reference introduces a binding level here, so
577-
// we need to shift the `rscope`. It'd be nice if we could
578-
// do away with this rscope stuff and work this knowledge
579-
// into resolve_lifetimes, as we do with non-omitted
580-
// lifetimes. Oh well, not there yet.
581-
let shifted_rscope = ShiftedRscope::new(rscope);
582-
583606
let (regions, types, assoc_bindings) = match path.segments.last().unwrap().parameters {
584607
ast::AngleBracketedParameters(ref data) => {
585608
// For now, require that parenthetical notation be used
@@ -595,7 +618,7 @@ fn ast_path_to_trait_ref<'a,'tcx>(
595618
the crate attributes to enable");
596619
}
597620

598-
convert_angle_bracketed_parameters(this, &shifted_rscope, data)
621+
convert_angle_bracketed_parameters(this, rscope, data)
599622
}
600623
ast::ParenthesizedParameters(ref data) => {
601624
// For now, require that parenthetical notation be used
@@ -616,7 +639,7 @@ fn ast_path_to_trait_ref<'a,'tcx>(
616639
};
617640

618641
let substs = create_substs_for_ast_path(this,
619-
&shifted_rscope,
642+
rscope,
620643
path.span,
621644
&trait_def.generics,
622645
self_ty,
@@ -851,15 +874,11 @@ fn ast_ty_to_trait_ref<'tcx>(this: &AstConv<'tcx>,
851874
match this.tcx().def_map.borrow().get(&id) {
852875
Some(&def::DefTrait(trait_def_id)) => {
853876
let mut projection_bounds = Vec::new();
854-
let trait_ref = ty::Binder(ast_path_to_trait_ref(this,
855-
rscope,
856-
trait_def_id,
857-
None,
858-
path,
859-
Some(&mut projection_bounds)));
860-
let projection_bounds = projection_bounds.into_iter()
861-
.map(ty::Binder)
862-
.collect();
877+
let trait_ref = object_path_to_poly_trait_ref(this,
878+
rscope,
879+
trait_def_id,
880+
path,
881+
&mut projection_bounds);
863882
Ok((trait_ref, projection_bounds))
864883
}
865884
_ => {
@@ -1095,16 +1114,13 @@ pub fn ast_ty_to_ty<'tcx>(
10951114
// N.B. this case overlaps somewhat with
10961115
// TyObjectSum, see that fn for details
10971116
let mut projection_bounds = Vec::new();
1098-
let trait_ref = ast_path_to_trait_ref(this,
1099-
rscope,
1100-
trait_def_id,
1101-
None,
1102-
path,
1103-
Some(&mut projection_bounds));
1104-
let trait_ref = ty::Binder(trait_ref);
1105-
let projection_bounds = projection_bounds.into_iter()
1106-
.map(ty::Binder)
1107-
.collect();
1117+
1118+
let trait_ref = object_path_to_poly_trait_ref(this,
1119+
rscope,
1120+
trait_def_id,
1121+
path,
1122+
&mut projection_bounds);
1123+
11081124
trait_ref_to_object_type(this, rscope, path.span,
11091125
trait_ref, projection_bounds, &[])
11101126
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// Copyright 2015 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+
// Regression test for #20831: debruijn index account was thrown off
12+
// by the (anonymous) lifetime in `<Self as Publisher>::Output`
13+
// below. Note that changing to a named lifetime made the problem go
14+
// away.
15+
16+
use std::ops::{Shl, Shr};
17+
use std::cell::RefCell;
18+
19+
pub trait Subscriber {
20+
type Input;
21+
}
22+
23+
pub trait Publisher<'a> {
24+
type Output;
25+
fn subscribe(&mut self, Box<Subscriber<Input=Self::Output> + 'a>);
26+
}
27+
28+
pub trait Processor<'a> : Subscriber + Publisher<'a> { }
29+
30+
impl<'a, P> Processor<'a> for P where P : Subscriber + Publisher<'a> { }
31+
32+
struct MyStruct<'a> {
33+
sub: Box<Subscriber<Input=u64> + 'a>
34+
}
35+
36+
impl<'a> Publisher<'a> for MyStruct<'a> {
37+
type Output = u64;
38+
fn subscribe(&mut self, t : Box<Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
39+
// Not obvious, but there is an implicit lifetime here -------^
40+
//~^^ ERROR cannot infer
41+
//
42+
// The fact that `Publisher` is using an implicit lifetime is
43+
// what was causing the debruijn accounting to be off, so
44+
// leave it that way!
45+
self.sub = t;
46+
}
47+
}
48+
49+
fn main() {}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright 2015 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+
struct ctxt<'tcx> {
12+
x: &'tcx i32
13+
}
14+
15+
trait AstConv<'tcx> {
16+
fn tcx<'a>(&'a self) -> &'a ctxt<'tcx>;
17+
}
18+
19+
fn foo(conv: &AstConv) { }
20+
21+
fn bar<'tcx>(conv: &AstConv<'tcx>) {
22+
foo(conv)
23+
}
24+
25+
fn main() { }

0 commit comments

Comments
 (0)