提交 02aacaba 编写于 作者: N Niko Matsakis

Fix DeBruijn accounting. It used to be that all trait-refs were binders,

but now only poly-trait-refs are binders. Fixes #20831.
上级 e94a9f03
...@@ -516,8 +516,15 @@ pub fn instantiate_poly_trait_ref<'tcx>( ...@@ -516,8 +516,15 @@ pub fn instantiate_poly_trait_ref<'tcx>(
{ {
let mut projections = Vec::new(); let mut projections = Vec::new();
// the trait reference introduces a binding level here, so
// we need to shift the `rscope`. It'd be nice if we could
// do away with this rscope stuff and work this knowledge
// into resolve_lifetimes, as we do with non-omitted
// lifetimes. Oh well, not there yet.
let shifted_rscope = ShiftedRscope::new(rscope);
let trait_ref = let trait_ref =
instantiate_trait_ref(this, rscope, &ast_trait_ref.trait_ref, instantiate_trait_ref(this, &shifted_rscope, &ast_trait_ref.trait_ref,
self_ty, Some(&mut projections)); self_ty, Some(&mut projections));
for projection in projections.into_iter() { for projection in projections.into_iter() {
...@@ -561,6 +568,29 @@ pub fn instantiate_trait_ref<'tcx>( ...@@ -561,6 +568,29 @@ pub fn instantiate_trait_ref<'tcx>(
} }
} }
fn object_path_to_poly_trait_ref<'a,'tcx>(
this: &AstConv<'tcx>,
rscope: &RegionScope,
trait_def_id: ast::DefId,
path: &ast::Path,
mut projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
-> ty::PolyTraitRef<'tcx>
{
// we are introducing a binder here, so shift the
// anonymous regions depth to account for that
let shifted_rscope = ShiftedRscope::new(rscope);
let mut tmp = Vec::new();
let trait_ref = ty::Binder(ast_path_to_trait_ref(this,
&shifted_rscope,
trait_def_id,
None,
path,
Some(&mut tmp)));
projections.extend(tmp.into_iter().map(ty::Binder));
trait_ref
}
fn ast_path_to_trait_ref<'a,'tcx>( fn ast_path_to_trait_ref<'a,'tcx>(
this: &AstConv<'tcx>, this: &AstConv<'tcx>,
rscope: &RegionScope, rscope: &RegionScope,
...@@ -573,13 +603,6 @@ fn ast_path_to_trait_ref<'a,'tcx>( ...@@ -573,13 +603,6 @@ fn ast_path_to_trait_ref<'a,'tcx>(
debug!("ast_path_to_trait_ref {:?}", path); debug!("ast_path_to_trait_ref {:?}", path);
let trait_def = this.get_trait_def(trait_def_id); let trait_def = this.get_trait_def(trait_def_id);
// the trait reference introduces a binding level here, so
// we need to shift the `rscope`. It'd be nice if we could
// do away with this rscope stuff and work this knowledge
// into resolve_lifetimes, as we do with non-omitted
// lifetimes. Oh well, not there yet.
let shifted_rscope = ShiftedRscope::new(rscope);
let (regions, types, assoc_bindings) = match path.segments.last().unwrap().parameters { let (regions, types, assoc_bindings) = match path.segments.last().unwrap().parameters {
ast::AngleBracketedParameters(ref data) => { ast::AngleBracketedParameters(ref data) => {
// For now, require that parenthetical notation be used // For now, require that parenthetical notation be used
...@@ -595,7 +618,7 @@ fn ast_path_to_trait_ref<'a,'tcx>( ...@@ -595,7 +618,7 @@ fn ast_path_to_trait_ref<'a,'tcx>(
the crate attributes to enable"); the crate attributes to enable");
} }
convert_angle_bracketed_parameters(this, &shifted_rscope, data) convert_angle_bracketed_parameters(this, rscope, data)
} }
ast::ParenthesizedParameters(ref data) => { ast::ParenthesizedParameters(ref data) => {
// For now, require that parenthetical notation be used // For now, require that parenthetical notation be used
...@@ -616,7 +639,7 @@ fn ast_path_to_trait_ref<'a,'tcx>( ...@@ -616,7 +639,7 @@ fn ast_path_to_trait_ref<'a,'tcx>(
}; };
let substs = create_substs_for_ast_path(this, let substs = create_substs_for_ast_path(this,
&shifted_rscope, rscope,
path.span, path.span,
&trait_def.generics, &trait_def.generics,
self_ty, self_ty,
...@@ -851,15 +874,11 @@ fn ast_ty_to_trait_ref<'tcx>(this: &AstConv<'tcx>, ...@@ -851,15 +874,11 @@ fn ast_ty_to_trait_ref<'tcx>(this: &AstConv<'tcx>,
match this.tcx().def_map.borrow().get(&id) { match this.tcx().def_map.borrow().get(&id) {
Some(&def::DefTrait(trait_def_id)) => { Some(&def::DefTrait(trait_def_id)) => {
let mut projection_bounds = Vec::new(); let mut projection_bounds = Vec::new();
let trait_ref = ty::Binder(ast_path_to_trait_ref(this, let trait_ref = object_path_to_poly_trait_ref(this,
rscope, rscope,
trait_def_id, trait_def_id,
None,
path, path,
Some(&mut projection_bounds))); &mut projection_bounds);
let projection_bounds = projection_bounds.into_iter()
.map(ty::Binder)
.collect();
Ok((trait_ref, projection_bounds)) Ok((trait_ref, projection_bounds))
} }
_ => { _ => {
...@@ -1095,16 +1114,13 @@ pub fn ast_ty_to_ty<'tcx>( ...@@ -1095,16 +1114,13 @@ pub fn ast_ty_to_ty<'tcx>(
// N.B. this case overlaps somewhat with // N.B. this case overlaps somewhat with
// TyObjectSum, see that fn for details // TyObjectSum, see that fn for details
let mut projection_bounds = Vec::new(); let mut projection_bounds = Vec::new();
let trait_ref = ast_path_to_trait_ref(this,
let trait_ref = object_path_to_poly_trait_ref(this,
rscope, rscope,
trait_def_id, trait_def_id,
None,
path, path,
Some(&mut projection_bounds)); &mut projection_bounds);
let trait_ref = ty::Binder(trait_ref);
let projection_bounds = projection_bounds.into_iter()
.map(ty::Binder)
.collect();
trait_ref_to_object_type(this, rscope, path.span, trait_ref_to_object_type(this, rscope, path.span,
trait_ref, projection_bounds, &[]) trait_ref, projection_bounds, &[])
} }
......
// Copyright 2015 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Regression test for #20831: debruijn index account was thrown off
// by the (anonymous) lifetime in `<Self as Publisher>::Output`
// below. Note that changing to a named lifetime made the problem go
// away.
use std::ops::{Shl, Shr};
use std::cell::RefCell;
pub trait Subscriber {
type Input;
}
pub trait Publisher<'a> {
type Output;
fn subscribe(&mut self, Box<Subscriber<Input=Self::Output> + 'a>);
}
pub trait Processor<'a> : Subscriber + Publisher<'a> { }
impl<'a, P> Processor<'a> for P where P : Subscriber + Publisher<'a> { }
struct MyStruct<'a> {
sub: Box<Subscriber<Input=u64> + 'a>
}
impl<'a> Publisher<'a> for MyStruct<'a> {
type Output = u64;
fn subscribe(&mut self, t : Box<Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
// Not obvious, but there is an implicit lifetime here -------^
//~^^ ERROR cannot infer
//
// The fact that `Publisher` is using an implicit lifetime is
// what was causing the debruijn accounting to be off, so
// leave it that way!
self.sub = t;
}
}
fn main() {}
// Copyright 2015 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
struct ctxt<'tcx> {
x: &'tcx i32
}
trait AstConv<'tcx> {
fn tcx<'a>(&'a self) -> &'a ctxt<'tcx>;
}
fn foo(conv: &AstConv) { }
fn bar<'tcx>(conv: &AstConv<'tcx>) {
foo(conv)
}
fn main() { }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册