Skip to content

Commit

Permalink
rollup merge of rust-lang#21107: nikomatsakis/assoc-type-ice-hunt-take-1
Browse files Browse the repository at this point in the history
  • Loading branch information
alexcrichton committed Jan 15, 2015
2 parents d7009e6 + 2479dfc commit 692d942
Show file tree
Hide file tree
Showing 9 changed files with 226 additions and 108 deletions.
16 changes: 15 additions & 1 deletion src/librustc/middle/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2605,12 +2605,17 @@ impl FlagComputation {

&ty_projection(ref data) => {
self.add_flags(HAS_PROJECTION);
self.add_substs(data.trait_ref.substs);
self.add_projection_ty(data);
}

&ty_trait(box TyTrait { ref principal, ref bounds }) => {
let mut computation = FlagComputation::new();
computation.add_substs(principal.0.substs);
for projection_bound in bounds.projection_bounds.iter() {
let mut proj_computation = FlagComputation::new();
proj_computation.add_projection_predicate(&projection_bound.0);
computation.add_bound_computation(&proj_computation);
}
self.add_bound_computation(&computation);

self.add_bounds(bounds);
Expand Down Expand Up @@ -2674,6 +2679,15 @@ impl FlagComputation {
}
}

fn add_projection_predicate(&mut self, projection_predicate: &ProjectionPredicate) {
self.add_projection_ty(&projection_predicate.projection_ty);
self.add_ty(projection_predicate.ty);
}

fn add_projection_ty(&mut self, projection_ty: &ProjectionTy) {
self.add_substs(projection_ty.trait_ref.substs);
}

fn add_substs(&mut self, substs: &Substs) {
self.add_tys(substs.types.as_slice());
match substs.regions {
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/util/ppaux.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1430,7 +1430,7 @@ impl<'tcx> UserString<'tcx> for ty::ProjectionPredicate<'tcx> {
impl<'tcx> Repr<'tcx> for ty::ProjectionTy<'tcx> {
fn repr(&self, tcx: &ctxt<'tcx>) -> String {
format!("<{} as {}>::{}",
self.trait_ref.self_ty().repr(tcx),
self.trait_ref.substs.self_ty().repr(tcx),
self.trait_ref.repr(tcx),
self.item_name.repr(tcx))
}
Expand Down
11 changes: 7 additions & 4 deletions src/librustc_trans/trans/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,12 +217,15 @@ pub fn type_needs_drop<'tcx>(cx: &ty::ctxt<'tcx>,
ty::type_contents(cx, ty).needs_drop(cx)
}

fn type_is_newtype_immediate<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
ty: Ty<'tcx>) -> bool {
fn type_is_newtype_immediate<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool {
match ty.sty {
ty::ty_struct(def_id, substs) => {
let fields = ty::struct_fields(ccx.tcx(), def_id, substs);
fields.len() == 1 && type_is_immediate(ccx, fields[0].mt.ty)
let fields = ty::lookup_struct_fields(ccx.tcx(), def_id);
fields.len() == 1 && {
let ty = ty::lookup_field_type(ccx.tcx(), def_id, fields[0].id, substs);
let ty = monomorphize::normalize_associated_type(ccx.tcx(), &ty);
type_is_immediate(ccx, ty)
}
}
_ => false
}
Expand Down
80 changes: 22 additions & 58 deletions src/librustc_trans/trans/debuginfo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -323,28 +323,26 @@ impl<'tcx> TypeMap<'tcx> {
fn get_unique_type_id_of_type<'a>(&mut self, cx: &CrateContext<'a, 'tcx>,
type_: Ty<'tcx>) -> UniqueTypeId {

// basic type -> {:name of the type:}
// tuple -> {tuple_(:param-uid:)*}
// struct -> {struct_:svh: / :node-id:_<(:param-uid:),*> }
// enum -> {enum_:svh: / :node-id:_<(:param-uid:),*> }
// enum variant -> {variant_:variant-name:_:enum-uid:}
// reference (&) -> {& :pointee-uid:}
// mut reference (&mut) -> {&mut :pointee-uid:}
// ptr (*) -> {* :pointee-uid:}
// mut ptr (*mut) -> {*mut :pointee-uid:}
// unique ptr (~) -> {~ :pointee-uid:}
// @-ptr (@) -> {@ :pointee-uid:}
// sized vec ([T; x]) -> {[:size:] :element-uid:}
// unsized vec ([T]) -> {[] :element-uid:}
// trait (T) -> {trait_:svh: / :node-id:_<(:param-uid:),*> }
// closure -> {<unsafe_> <once_> :store-sigil:
// |(:param-uid:),* <,_...>| -> \
// :return-type-uid: : (:bounds:)*}
// function -> {<unsafe_> <abi_> fn( (:param-uid:)* <,_...> ) -> \
// :return-type-uid:}
// unique vec box (~[]) -> {HEAP_VEC_BOX<:pointee-uid:>}
// gc box -> {GC_BOX<:pointee-uid:>}
// projection (<T as U>::V) -> {<:ty-uid: as :trait-uid:> :: :name-uid: }
// basic type -> {:name of the type:}
// tuple -> {tuple_(:param-uid:)*}
// struct -> {struct_:svh: / :node-id:_<(:param-uid:),*> }
// enum -> {enum_:svh: / :node-id:_<(:param-uid:),*> }
// enum variant -> {variant_:variant-name:_:enum-uid:}
// reference (&) -> {& :pointee-uid:}
// mut reference (&mut) -> {&mut :pointee-uid:}
// ptr (*) -> {* :pointee-uid:}
// mut ptr (*mut) -> {*mut :pointee-uid:}
// unique ptr (~) -> {~ :pointee-uid:}
// @-ptr (@) -> {@ :pointee-uid:}
// sized vec ([T; x]) -> {[:size:] :element-uid:}
// unsized vec ([T]) -> {[] :element-uid:}
// trait (T) -> {trait_:svh: / :node-id:_<(:param-uid:),*> }
// closure -> {<unsafe_> <once_> :store-sigil: |(:param-uid:),* <,_...>| -> \
// :return-type-uid: : (:bounds:)*}
// function -> {<unsafe_> <abi_> fn( (:param-uid:)* <,_...> ) -> \
// :return-type-uid:}
// unique vec box (~[]) -> {HEAP_VEC_BOX<:pointee-uid:>}
// gc box -> {GC_BOX<:pointee-uid:>}

match self.type_to_unique_id.get(&type_).cloned() {
Some(unique_type_id) => return unique_type_id,
Expand Down Expand Up @@ -437,25 +435,6 @@ impl<'tcx> TypeMap<'tcx> {
principal.substs,
&mut unique_type_id);
},
ty::ty_projection(ref projection) => {
unique_type_id.push_str("<");

let self_ty = projection.trait_ref.self_ty();
let self_type_id = self.get_unique_type_id_of_type(cx, self_ty);
let self_type_id = self.get_unique_type_id_as_string(self_type_id);
unique_type_id.push_str(&self_type_id[]);

unique_type_id.push_str(" as ");

from_def_id_and_substs(self,
cx,
projection.trait_ref.def_id,
projection.trait_ref.substs,
&mut unique_type_id);

unique_type_id.push_str(">::");
unique_type_id.push_str(token::get_name(projection.item_name).get());
},
ty::ty_bare_fn(_, &ty::BareFnTy{ unsafety, abi, ref sig } ) => {
if unsafety == ast::Unsafety::Unsafe {
unique_type_id.push_str("unsafe ");
Expand Down Expand Up @@ -499,10 +478,7 @@ impl<'tcx> TypeMap<'tcx> {
closure_ty,
&mut unique_type_id);
},
ty::ty_err |
ty::ty_infer(_) |
ty::ty_open(_) |
ty::ty_param(_) => {
_ => {
cx.sess().bug(&format!("get_unique_type_id_of_type() - unexpected type: {}, {:?}",
&ppaux::ty_to_string(cx.tcx(), type_)[],
type_.sty)[])
Expand Down Expand Up @@ -3880,22 +3856,10 @@ fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
ty::ty_unboxed_closure(..) => {
output.push_str("closure");
}
ty::ty_projection(ref projection) => {
output.push_str("<");
let self_ty = projection.trait_ref.self_ty();
push_debuginfo_type_name(cx, self_ty, true, output);

output.push_str(" as ");

push_item_name(cx, projection.trait_ref.def_id, false, output);
push_type_params(cx, projection.trait_ref.substs, output);

output.push_str(">::");
output.push_str(token::get_name(projection.item_name).get());
}
ty::ty_err |
ty::ty_infer(_) |
ty::ty_open(_) |
ty::ty_projection(..) |
ty::ty_param(_) => {
cx.sess().bug(&format!("debuginfo: Trying to create type name for \
unexpected type: {}", ppaux::ty_to_string(cx.tcx(), t))[]);
Expand Down
74 changes: 45 additions & 29 deletions src/librustc_typeck/astconv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -516,8 +516,15 @@ pub fn instantiate_poly_trait_ref<'tcx>(
{
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 =
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));

for projection in projections.into_iter() {
Expand Down Expand Up @@ -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>(
this: &AstConv<'tcx>,
rscope: &RegionScope,
Expand All @@ -573,13 +603,6 @@ fn ast_path_to_trait_ref<'a,'tcx>(
debug!("ast_path_to_trait_ref {:?}", path);
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 {
ast::AngleBracketedParameters(ref data) => {
// For now, require that parenthetical notation be used
Expand All @@ -595,7 +618,7 @@ fn ast_path_to_trait_ref<'a,'tcx>(
the crate attributes to enable");
}

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

let substs = create_substs_for_ast_path(this,
&shifted_rscope,
rscope,
path.span,
&trait_def.generics,
self_ty,
Expand Down Expand Up @@ -851,15 +874,11 @@ fn ast_ty_to_trait_ref<'tcx>(this: &AstConv<'tcx>,
match this.tcx().def_map.borrow().get(&id) {
Some(&def::DefTrait(trait_def_id)) => {
let mut projection_bounds = Vec::new();
let trait_ref = ty::Binder(ast_path_to_trait_ref(this,
rscope,
trait_def_id,
None,
path,
Some(&mut projection_bounds)));
let projection_bounds = projection_bounds.into_iter()
.map(ty::Binder)
.collect();
let trait_ref = object_path_to_poly_trait_ref(this,
rscope,
trait_def_id,
path,
&mut projection_bounds);
Ok((trait_ref, projection_bounds))
}
_ => {
Expand Down Expand Up @@ -1098,16 +1117,13 @@ pub fn ast_ty_to_ty<'tcx>(
// N.B. this case overlaps somewhat with
// TyObjectSum, see that fn for details
let mut projection_bounds = Vec::new();
let trait_ref = ast_path_to_trait_ref(this,
rscope,
trait_def_id,
None,
path,
Some(&mut projection_bounds));
let trait_ref = ty::Binder(trait_ref);
let projection_bounds = projection_bounds.into_iter()
.map(ty::Binder)
.collect();

let trait_ref = object_path_to_poly_trait_ref(this,
rscope,
trait_def_id,
path,
&mut projection_bounds);

trait_ref_to_object_type(this, rscope, path.span,
trait_ref, projection_bounds, &[])
}
Expand Down
49 changes: 49 additions & 0 deletions src/test/compile-fail/issue-20831-debruijn.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// 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() {}
32 changes: 32 additions & 0 deletions src/test/run-pass/associated-types-normalize-unifield-struct.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// 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 issue #21010: Normalize associated types in
// various special paths in the `type_is_immediate` function.

#![allow(unstable)]

pub trait OffsetState: Sized {}
pub trait Offset { type State: OffsetState; }

#[derive(Copy)] pub struct X;
impl Offset for X { type State = Y; }

#[derive(Copy)] pub struct Y;
impl OffsetState for Y {}

pub fn now() -> DateTime<X> { from_utc(Y) }

pub struct DateTime<Off: Offset> { pub offset: Off::State }
pub fn from_utc<Off: Offset>(offset: Off::State) -> DateTime<Off> { DateTime { offset: offset } }

pub fn main() {
let _x = now();
}
Loading

0 comments on commit 692d942

Please sign in to comment.