From c08d004545edf1bf16ee670fd27b8d3a477341a5 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 16 Dec 2014 15:00:05 -0500 Subject: [PATCH 01/36] Refactor various queries out of `ty` and into `trans/common` --- src/librustc/middle/ty.rs | 44 ---------------------- src/librustc_trans/trans/callee.rs | 2 +- src/librustc_trans/trans/cleanup.rs | 12 +++--- src/librustc_trans/trans/common.rs | 49 +++++++++++++++++++++++++ src/librustc_trans/trans/context.rs | 6 +++ src/librustc_trans/trans/controlflow.rs | 2 +- src/librustc_trans/trans/datum.rs | 4 +- src/librustc_trans/trans/expr.rs | 6 +-- src/librustc_trans/trans/glue.rs | 8 ++-- src/librustc_trans/trans/intrinsic.rs | 2 +- src/librustc_trans/trans/meth.rs | 2 +- src/librustc_trans/trans/tvec.rs | 2 +- 12 files changed, 75 insertions(+), 64 deletions(-) diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 617be82701a09..d09efb006f263 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -682,7 +682,6 @@ pub struct ctxt<'tcx> { pub tcache: RefCell>>, pub rcache: RefCell>>, pub short_names_cache: RefCell, String>>, - pub needs_unwind_cleanup_cache: RefCell, bool>>, pub tc_cache: RefCell, TypeContents>>, pub ast_ty_to_ty_cache: RefCell>>, pub enum_var_cache: RefCell>>>>>, @@ -2108,7 +2107,6 @@ pub fn mk_ctxt<'tcx>(s: Session, tcache: RefCell::new(DefIdMap::new()), rcache: RefCell::new(FnvHashMap::new()), short_names_cache: RefCell::new(FnvHashMap::new()), - needs_unwind_cleanup_cache: RefCell::new(FnvHashMap::new()), tc_cache: RefCell::new(FnvHashMap::new()), ast_ty_to_ty_cache: RefCell::new(NodeMap::new()), enum_var_cache: RefCell::new(DefIdMap::new()), @@ -2824,48 +2822,6 @@ pub fn type_is_floating_point(ty: Ty) -> bool { } } -pub fn type_needs_drop<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> bool { - type_contents(cx, ty).needs_drop(cx) -} - -// Some things don't need cleanups during unwinding because the -// task can free them all at once later. Currently only things -// that only contain scalars and shared boxes can avoid unwind -// cleanups. -pub fn type_needs_unwind_cleanup<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> bool { - return memoized(&cx.needs_unwind_cleanup_cache, ty, |ty| { - type_needs_unwind_cleanup_(cx, ty, &mut FnvHashSet::new()) - }); - - fn type_needs_unwind_cleanup_<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>, - tycache: &mut FnvHashSet>) -> bool { - // Prevent infinite recursion - if !tycache.insert(ty) { - return false; - } - - let mut needs_unwind_cleanup = false; - maybe_walk_ty(ty, |ty| { - needs_unwind_cleanup |= match ty.sty { - ty_bool | ty_int(_) | ty_uint(_) | - ty_float(_) | ty_tup(_) | ty_ptr(_) => false, - - ty_enum(did, substs) => - enum_variants(cx, did).iter().any(|v| - v.args.iter().any(|aty| { - let t = aty.subst(cx, substs); - type_needs_unwind_cleanup_(cx, t, tycache) - }) - ), - - _ => true - }; - !needs_unwind_cleanup - }); - needs_unwind_cleanup - } -} - /// Type contents is how the type checker reasons about kinds. /// They track what kinds of things are found within a type. You can /// think of them as kind of an "anti-kind". They track the kinds of values diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs index a159cda9fbaed..dab4c0273d076 100644 --- a/src/librustc_trans/trans/callee.rs +++ b/src/librustc_trans/trans/callee.rs @@ -722,7 +722,7 @@ pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, }; if !is_rust_fn || type_of::return_uses_outptr(ccx, ret_ty) || - ty::type_needs_drop(bcx.tcx(), ret_ty) { + type_needs_drop(bcx.tcx(), ret_ty) { // Push the out-pointer if we use an out-pointer for this // return type, otherwise push "undef". if type_is_zero_size(ccx, ret_ty) { diff --git a/src/librustc_trans/trans/cleanup.rs b/src/librustc_trans/trans/cleanup.rs index f96aa484ffc95..d02d6c1e8724f 100644 --- a/src/librustc_trans/trans/cleanup.rs +++ b/src/librustc_trans/trans/cleanup.rs @@ -279,10 +279,10 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> { cleanup_scope: ScopeId, val: ValueRef, ty: Ty<'tcx>) { - if !ty::type_needs_drop(self.ccx.tcx(), ty) { return; } + if !common::type_needs_drop(self.ccx.tcx(), ty) { return; } let drop = box DropValue { is_immediate: false, - must_unwind: ty::type_needs_unwind_cleanup(self.ccx.tcx(), ty), + must_unwind: common::type_needs_unwind_cleanup(self.ccx, ty), val: val, ty: ty, zero: false @@ -301,10 +301,10 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> { cleanup_scope: ScopeId, val: ValueRef, ty: Ty<'tcx>) { - if !ty::type_needs_drop(self.ccx.tcx(), ty) { return; } + if !common::type_needs_drop(self.ccx.tcx(), ty) { return; } let drop = box DropValue { is_immediate: false, - must_unwind: ty::type_needs_unwind_cleanup(self.ccx.tcx(), ty), + must_unwind: common::type_needs_unwind_cleanup(self.ccx, ty), val: val, ty: ty, zero: true @@ -325,10 +325,10 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> { val: ValueRef, ty: Ty<'tcx>) { - if !ty::type_needs_drop(self.ccx.tcx(), ty) { return; } + if !common::type_needs_drop(self.ccx.tcx(), ty) { return; } let drop = box DropValue { is_immediate: true, - must_unwind: ty::type_needs_unwind_cleanup(self.ccx.tcx(), ty), + must_unwind: common::type_needs_unwind_cleanup(self.ccx, ty), val: val, ty: ty, zero: false diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs index b15b75c6715b7..7ee4be0ae56f9 100644 --- a/src/librustc_trans/trans/common.rs +++ b/src/librustc_trans/trans/common.rs @@ -53,9 +53,58 @@ use syntax::ast_map::{PathElem, PathName}; use syntax::codemap::Span; use syntax::parse::token::InternedString; use syntax::parse::token; +use util::common::memoized; +use util::nodemap::FnvHashSet; pub use trans::context::CrateContext; +// Some things don't need cleanups during unwinding because the +// task can free them all at once later. Currently only things +// that only contain scalars and shared boxes can avoid unwind +// cleanups. +pub fn type_needs_unwind_cleanup<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool { + return memoized(ccx.needs_unwind_cleanup_cache(), ty, |ty| { + type_needs_unwind_cleanup_(ccx.tcx(), ty, &mut FnvHashSet::new()) + }); + + fn type_needs_unwind_cleanup_<'tcx>(tcx: &ty::ctxt<'tcx>, + ty: Ty<'tcx>, + tycache: &mut FnvHashSet>) + -> bool + { + // Prevent infinite recursion + if !tycache.insert(ty) { + return false; + } + + let mut needs_unwind_cleanup = false; + ty::maybe_walk_ty(ty, |ty| { + needs_unwind_cleanup |= match ty.sty { + ty::ty_bool | ty::ty_int(_) | ty::ty_uint(_) | + ty::ty_float(_) | ty::ty_tup(_) | ty::ty_ptr(_) => false, + + ty::ty_enum(did, substs) => + ty::enum_variants(tcx, did).iter().any(|v| + v.args.iter().any(|aty| { + let t = aty.subst(tcx, substs); + type_needs_unwind_cleanup_(tcx, t, tycache) + }) + ), + + _ => true + }; + !needs_unwind_cleanup + }); + needs_unwind_cleanup + } +} + +pub fn type_needs_drop<'tcx>(cx: &ty::ctxt<'tcx>, + ty: Ty<'tcx>) + -> bool { + ty::type_contents(cx, ty).needs_drop(cx) +} + fn type_is_newtype_immediate<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool { match ty.sty { diff --git a/src/librustc_trans/trans/context.rs b/src/librustc_trans/trans/context.rs index 2c71dd831fbcb..02eaef885483f 100644 --- a/src/librustc_trans/trans/context.rs +++ b/src/librustc_trans/trans/context.rs @@ -84,6 +84,7 @@ pub struct LocalCrateContext<'tcx> { tn: TypeNames, externs: RefCell, item_vals: RefCell>, + needs_unwind_cleanup_cache: RefCell, bool>>, fn_pointer_shims: RefCell, ValueRef>>, drop_glues: RefCell, ValueRef>>, tydescs: RefCell, Rc>>>, @@ -389,6 +390,7 @@ impl<'tcx> LocalCrateContext<'tcx> { tn: TypeNames::new(), externs: RefCell::new(FnvHashMap::new()), item_vals: RefCell::new(NodeMap::new()), + needs_unwind_cleanup_cache: RefCell::new(FnvHashMap::new()), fn_pointer_shims: RefCell::new(FnvHashMap::new()), drop_glues: RefCell::new(FnvHashMap::new()), tydescs: RefCell::new(FnvHashMap::new()), @@ -569,6 +571,10 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> { &self.shared.link_meta } + pub fn needs_unwind_cleanup_cache(&self) -> &RefCell, bool>> { + &self.local.needs_unwind_cleanup_cache + } + pub fn fn_pointer_shims(&self) -> &RefCell, ValueRef>> { &self.local.fn_pointer_shims } diff --git a/src/librustc_trans/trans/controlflow.rs b/src/librustc_trans/trans/controlflow.rs index 3b24ded6717cc..768de89d5935d 100644 --- a/src/librustc_trans/trans/controlflow.rs +++ b/src/librustc_trans/trans/controlflow.rs @@ -87,7 +87,7 @@ pub fn trans_stmt_semi<'blk, 'tcx>(cx: Block<'blk, 'tcx>, e: &ast::Expr) -> Block<'blk, 'tcx> { let _icx = push_ctxt("trans_stmt_semi"); let ty = expr_ty(cx, e); - if ty::type_needs_drop(cx.tcx(), ty) { + if type_needs_drop(cx.tcx(), ty) { expr::trans_to_lvalue(cx, e, "stmt").bcx } else { expr::trans_into(cx, e, expr::Ignore) diff --git a/src/librustc_trans/trans/datum.rs b/src/librustc_trans/trans/datum.rs index 9ab4e92b51131..ca274ab605e7f 100644 --- a/src/librustc_trans/trans/datum.rs +++ b/src/librustc_trans/trans/datum.rs @@ -218,7 +218,7 @@ impl KindOps for Lvalue { val: ValueRef, ty: Ty<'tcx>) -> Block<'blk, 'tcx> { - if ty::type_needs_drop(bcx.tcx(), ty) { + if type_needs_drop(bcx.tcx(), ty) { // cancel cleanup of affine values by zeroing out let () = zero_mem(bcx, val, ty); bcx @@ -567,7 +567,7 @@ impl<'tcx, K: KindOps + fmt::Show> Datum<'tcx, K> { /// scalar-ish (like an int or a pointer) which (1) does not require drop glue and (2) is /// naturally passed around by value, and not by reference. pub fn to_llscalarish<'blk>(self, bcx: Block<'blk, 'tcx>) -> ValueRef { - assert!(!ty::type_needs_drop(bcx.tcx(), self.ty)); + assert!(!type_needs_drop(bcx.tcx(), self.ty)); assert!(self.appropriate_rvalue_mode(bcx.ccx()) == ByValue); if self.kind.is_by_ref() { load_ty(bcx, self.val, self.ty) diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs index f49769ba0d9c6..ae07e094a5c61 100644 --- a/src/librustc_trans/trans/expr.rs +++ b/src/librustc_trans/trans/expr.rs @@ -976,7 +976,7 @@ fn trans_rvalue_stmt_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let src_datum = unpack_datum!(bcx, trans(bcx, &**src)); let dst_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, &**dst, "assign")); - if ty::type_needs_drop(bcx.tcx(), dst_datum.ty) { + if type_needs_drop(bcx.tcx(), dst_datum.ty) { // If there are destructors involved, make sure we // are copying from an rvalue, since that cannot possible // alias an lvalue. We are concerned about code like: @@ -1513,7 +1513,7 @@ pub fn trans_adt<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, assert_eq!(discr, 0); match ty::expr_kind(bcx.tcx(), &*base.expr) { - ty::RvalueDpsExpr | ty::RvalueDatumExpr if !ty::type_needs_drop(bcx.tcx(), ty) => { + ty::RvalueDpsExpr | ty::RvalueDatumExpr if !type_needs_drop(bcx.tcx(), ty) => { bcx = trans_into(bcx, &*base.expr, SaveIn(addr)); }, ty::RvalueStmtExpr => bcx.tcx().sess.bug("unexpected expr kind for struct base expr"), @@ -2117,7 +2117,7 @@ fn trans_assign_op<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, // Evaluate LHS (destination), which should be an lvalue let dst_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, dst, "assign_op")); - assert!(!ty::type_needs_drop(bcx.tcx(), dst_datum.ty)); + assert!(!type_needs_drop(bcx.tcx(), dst_datum.ty)); let dst_ty = dst_datum.ty; let dst = load_ty(bcx, dst_datum.val, dst_datum.ty); diff --git a/src/librustc_trans/trans/glue.rs b/src/librustc_trans/trans/glue.rs index e0a878c8261ef..4217dd4c6718b 100644 --- a/src/librustc_trans/trans/glue.rs +++ b/src/librustc_trans/trans/glue.rs @@ -84,11 +84,11 @@ pub fn get_drop_glue_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, if !ty::type_is_sized(tcx, t) { return t } - if !ty::type_needs_drop(tcx, t) { + if !type_needs_drop(tcx, t) { return ty::mk_i8(); } match t.sty { - ty::ty_uniq(typ) if !ty::type_needs_drop(tcx, typ) + ty::ty_uniq(typ) if !type_needs_drop(tcx, typ) && ty::type_is_sized(tcx, typ) => { let llty = sizing_type_of(ccx, typ); // `Box` does not allocate. @@ -110,7 +110,7 @@ pub fn drop_ty<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, // NB: v is an *alias* of type t here, not a direct value. debug!("drop_ty(t={})", t.repr(bcx.tcx())); let _icx = push_ctxt("drop_ty"); - if ty::type_needs_drop(bcx.tcx(), t) { + if type_needs_drop(bcx.tcx(), t) { let ccx = bcx.ccx(); let glue = get_drop_glue(ccx, t); let glue_type = get_drop_glue_type(ccx, t); @@ -469,7 +469,7 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, t: Ty<'tcx>) ty::ty_vec(ty, None) => tvec::make_drop_glue_unboxed(bcx, v0, ty, false), _ => { assert!(ty::type_is_sized(bcx.tcx(), t)); - if ty::type_needs_drop(bcx.tcx(), t) && + if type_needs_drop(bcx.tcx(), t) && ty::type_is_structural(t) { iter_structural_ty(bcx, v0, t, |bb, vv, tt| drop_ty(bb, vv, tt, None)) } else { diff --git a/src/librustc_trans/trans/intrinsic.rs b/src/librustc_trans/trans/intrinsic.rs index fff89999d99b5..f471a92f6c321 100644 --- a/src/librustc_trans/trans/intrinsic.rs +++ b/src/librustc_trans/trans/intrinsic.rs @@ -365,7 +365,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, } (_, "needs_drop") => { let tp_ty = *substs.types.get(FnSpace, 0); - C_bool(ccx, ty::type_needs_drop(ccx.tcx(), tp_ty)) + C_bool(ccx, type_needs_drop(ccx.tcx(), tp_ty)) } (_, "owns_managed") => { let tp_ty = *substs.types.get(FnSpace, 0); diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs index 553613a8eac0e..a937f989b3ac5 100644 --- a/src/librustc_trans/trans/meth.rs +++ b/src/librustc_trans/trans/meth.rs @@ -436,7 +436,7 @@ fn trans_trait_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let self_datum = unpack_datum!( bcx, expr::trans(bcx, self_expr)); - let llval = if ty::type_needs_drop(bcx.tcx(), self_datum.ty) { + let llval = if type_needs_drop(bcx.tcx(), self_datum.ty) { let self_datum = unpack_datum!( bcx, self_datum.to_rvalue_datum(bcx, "trait_callee")); diff --git a/src/librustc_trans/trans/tvec.rs b/src/librustc_trans/trans/tvec.rs index e09032ac2d04f..688a0d0725058 100644 --- a/src/librustc_trans/trans/tvec.rs +++ b/src/librustc_trans/trans/tvec.rs @@ -62,7 +62,7 @@ pub fn make_drop_glue_unboxed<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let _icx = push_ctxt("tvec::make_drop_glue_unboxed"); let dataptr = get_dataptr(bcx, vptr); - let bcx = if ty::type_needs_drop(tcx, unit_ty) { + let bcx = if type_needs_drop(tcx, unit_ty) { let len = get_len(bcx, vptr); iter_vec_raw(bcx, dataptr, unit_ty, len, |bb, vv, tt| glue::drop_ty(bb, vv, tt, None)) } else { From 0b64e5796ba3f501042f02d416a7a625802e9e44 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 16 Dec 2014 15:18:23 -0500 Subject: [PATCH 02/36] Make ExprUseVisitor<..> use inherited parameter environments. --- src/librustc/middle/check_match.rs | 2 +- src/librustc/middle/check_rvalues.rs | 2 +- src/librustc/middle/check_static.rs | 2 +- src/librustc/middle/expr_use_visitor.rs | 15 +++++++-------- src/librustc_borrowck/borrowck/check_loans.rs | 2 +- .../borrowck/gather_loans/mod.rs | 2 +- src/librustc_trans/trans/_match.rs | 2 +- 7 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs index c2992a81d2083..b7e67ea469059 100644 --- a/src/librustc/middle/check_match.rs +++ b/src/librustc/middle/check_match.rs @@ -1065,7 +1065,7 @@ fn check_for_mutation_in_guard<'a, 'tcx>(cx: &'a MatchCheckCtxt<'a, 'tcx>, }; let mut visitor = ExprUseVisitor::new(&mut checker, checker.cx.tcx, - cx.param_env.clone()); + &cx.param_env); visitor.walk_expr(guard); } diff --git a/src/librustc/middle/check_rvalues.rs b/src/librustc/middle/check_rvalues.rs index a14307b90ee83..494d85f7ba56d 100644 --- a/src/librustc/middle/check_rvalues.rs +++ b/src/librustc/middle/check_rvalues.rs @@ -40,7 +40,7 @@ impl<'a, 'tcx, 'v> visit::Visitor<'v> for RvalueContext<'a, 'tcx> { fn_id: ast::NodeId) { { let param_env = ParameterEnvironment::for_item(self.tcx, fn_id); - let mut euv = euv::ExprUseVisitor::new(self, self.tcx, param_env); + let mut euv = euv::ExprUseVisitor::new(self, self.tcx, ¶m_env); euv.walk_fn(fd, b); } visit::walk_fn(self, fk, fd, b, s) diff --git a/src/librustc/middle/check_static.rs b/src/librustc/middle/check_static.rs index 14f927f5b1ecb..e8df8e8402964 100644 --- a/src/librustc/middle/check_static.rs +++ b/src/librustc/middle/check_static.rs @@ -72,7 +72,7 @@ pub fn check_crate(tcx: &ty::ctxt) { }; { let param_env = ty::empty_parameter_environment(); - let visitor = euv::ExprUseVisitor::new(&mut checker, tcx, param_env); + let visitor = euv::ExprUseVisitor::new(&mut checker, tcx, ¶m_env); visit::walk_crate(&mut GlobalVisitor(visitor), tcx.map.krate()); } visit::walk_crate(&mut CheckStaticVisitor { diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index b7cfb22b85f8c..059f38f0930d1 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -295,11 +295,11 @@ impl OverloadedCallType { // supplies types from the tree. After type checking is complete, you // can just use the tcx as the typer. -pub struct ExprUseVisitor<'d,'t,'tcx,TYPER:'t> { +pub struct ExprUseVisitor<'d,'t,'tcx:'t,TYPER:'t> { typer: &'t TYPER, mc: mc::MemCategorizationContext<'t,TYPER>, delegate: &'d mut (Delegate<'tcx>+'d), - param_env: ParameterEnvironment<'tcx>, + param_env: &'t ParameterEnvironment<'tcx>, } /// Whether the elements of an overloaded operation are passed by value or by reference @@ -311,7 +311,7 @@ enum PassArgs { impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { pub fn new(delegate: &'d mut Delegate<'tcx>, typer: &'t TYPER, - param_env: ParameterEnvironment<'tcx>) + param_env: &'t ParameterEnvironment<'tcx>) -> ExprUseVisitor<'d,'t,'tcx,TYPER> { ExprUseVisitor { typer: typer, @@ -355,7 +355,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { cmt: mc::cmt<'tcx>) { let mode = copy_or_move(self.tcx(), cmt.ty, - &self.param_env, + self.param_env, DirectRefMove); self.delegate.consume(consume_id, consume_span, cmt, mode); } @@ -998,7 +998,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { ast::PatIdent(ast::BindByValue(_), _, _) => { match copy_or_move(tcx, cmt_pat.ty, - &self.param_env, + self.param_env, PatBindingMove) { Copy => mode.lub(CopyingMatch), Move(_) => mode.lub(MovingMatch), @@ -1028,8 +1028,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { let typer = self.typer; let def_map = &self.typer.tcx().def_map; let delegate = &mut self.delegate; - let param_env = &mut self.param_env; - + let param_env = self.param_env; mc.cat_pattern(cmt_discr.clone(), pat, |mc, cmt_pat, pat| { if pat_util::pat_is_binding(def_map, pat) { let tcx = typer.tcx(); @@ -1249,7 +1248,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { closure_expr.span, freevar.def); let mode = copy_or_move(self.tcx(), cmt_var.ty, - &self.param_env, CaptureMove); + self.param_env, CaptureMove); self.delegate.consume(closure_expr.id, freevar.span, cmt_var, mode); } } diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs index fdb13ecabde81..2062685f4c866 100644 --- a/src/librustc_borrowck/borrowck/check_loans.rs +++ b/src/librustc_borrowck/borrowck/check_loans.rs @@ -210,7 +210,7 @@ pub fn check_loans<'a, 'b, 'c, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, { let mut euv = euv::ExprUseVisitor::new(&mut clcx, bccx.tcx, - param_env.clone()); + ¶m_env); euv.walk_fn(decl, body); } } diff --git a/src/librustc_borrowck/borrowck/gather_loans/mod.rs b/src/librustc_borrowck/borrowck/gather_loans/mod.rs index c0e892cdd2798..7854c8acb4796 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/mod.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/mod.rs @@ -53,7 +53,7 @@ pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, { let mut euv = euv::ExprUseVisitor::new(&mut glcx, bccx.tcx, - param_env); + ¶m_env); euv.walk_fn(decl, body); } diff --git a/src/librustc_trans/trans/_match.rs b/src/librustc_trans/trans/_match.rs index a798d09872ca2..db0536869351f 100644 --- a/src/librustc_trans/trans/_match.rs +++ b/src/librustc_trans/trans/_match.rs @@ -1263,7 +1263,7 @@ fn is_discr_reassigned(bcx: Block, discr: &ast::Expr, body: &ast::Expr) -> bool }; { let param_env = ty::empty_parameter_environment(); - let mut visitor = euv::ExprUseVisitor::new(&mut rc, bcx, param_env); + let mut visitor = euv::ExprUseVisitor::new(&mut rc, bcx, ¶m_env); visitor.walk_expr(body); } rc.reassigned From 4946e1a46317a890b3e8d0157e045adf80b535d3 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 18 Dec 2014 09:26:10 -0500 Subject: [PATCH 03/36] Move the TypeContents-based "Sized" queries into trans, where the full types are always known and hence the ParameterEnvironment is not necessary. For other `Sized` queries, use the trait infrastructure just like `Copy`. --- src/librustc/middle/check_rvalues.rs | 14 ++- src/librustc/middle/traits/mod.rs | 38 ++++++++ src/librustc/middle/ty.rs | 120 +++++++++++--------------- src/librustc_trans/trans/adt.rs | 8 +- src/librustc_trans/trans/base.rs | 10 +-- src/librustc_trans/trans/common.rs | 56 +++++++++++- src/librustc_trans/trans/consts.rs | 2 +- src/librustc_trans/trans/datum.rs | 4 +- src/librustc_trans/trans/expr.rs | 16 ++-- src/librustc_trans/trans/glue.rs | 26 +++--- src/librustc_trans/trans/intrinsic.rs | 4 +- src/librustc_trans/trans/type_of.rs | 10 +-- src/librustc_typeck/check/mod.rs | 18 +++- 13 files changed, 207 insertions(+), 119 deletions(-) diff --git a/src/librustc/middle/check_rvalues.rs b/src/librustc/middle/check_rvalues.rs index 494d85f7ba56d..3b4ea5234f43f 100644 --- a/src/librustc/middle/check_rvalues.rs +++ b/src/librustc/middle/check_rvalues.rs @@ -28,7 +28,7 @@ pub fn check_crate(tcx: &ty::ctxt, } struct RvalueContext<'a, 'tcx: 'a> { - tcx: &'a ty::ctxt<'tcx> + tcx: &'a ty::ctxt<'tcx>, } impl<'a, 'tcx, 'v> visit::Visitor<'v> for RvalueContext<'a, 'tcx> { @@ -40,21 +40,27 @@ impl<'a, 'tcx, 'v> visit::Visitor<'v> for RvalueContext<'a, 'tcx> { fn_id: ast::NodeId) { { let param_env = ParameterEnvironment::for_item(self.tcx, fn_id); - let mut euv = euv::ExprUseVisitor::new(self, self.tcx, ¶m_env); + let mut delegate = RvalueContextDelegate { tcx: self.tcx, param_env: ¶m_env }; + let mut euv = euv::ExprUseVisitor::new(&mut delegate, self.tcx, ¶m_env); euv.walk_fn(fd, b); } visit::walk_fn(self, fk, fd, b, s) } } -impl<'a, 'tcx> euv::Delegate<'tcx> for RvalueContext<'a, 'tcx> { +struct RvalueContextDelegate<'a, 'tcx: 'a> { + tcx: &'a ty::ctxt<'tcx>, + param_env: &'a ty::ParameterEnvironment<'tcx>, +} + +impl<'a, 'tcx> euv::Delegate<'tcx> for RvalueContextDelegate<'a, 'tcx> { fn consume(&mut self, _: ast::NodeId, span: Span, cmt: mc::cmt<'tcx>, _: euv::ConsumeMode) { debug!("consume; cmt: {}; type: {}", *cmt, ty_to_string(self.tcx, cmt.ty)); - if !ty::type_is_sized(self.tcx, cmt.ty) { + if !ty::type_is_sized(self.tcx, cmt.ty, self.param_env) { span_err!(self.tcx.sess, span, E0161, "cannot move a value of type {0}: the size of {0} cannot be statically determined", ty_to_string(self.tcx, cmt.ty)); diff --git a/src/librustc/middle/traits/mod.rs b/src/librustc/middle/traits/mod.rs index 6597730846ded..5676ba6f6652b 100644 --- a/src/librustc/middle/traits/mod.rs +++ b/src/librustc/middle/traits/mod.rs @@ -22,6 +22,7 @@ use std::rc::Rc; use std::slice::Iter; use syntax::ast; use syntax::codemap::{Span, DUMMY_SP}; +use util::ppaux::Repr; pub use self::error_reporting::report_fulfillment_errors; pub use self::fulfill::{FulfillmentContext, RegionObligation}; @@ -265,6 +266,43 @@ pub fn predicates_for_generics<'tcx>(tcx: &ty::ctxt<'tcx>, util::predicates_for_generics(tcx, cause, 0, generic_bounds) } +/// Determines whether the type `ty` is known to meet `bound` and +/// returns true if so. Returns false if `ty` either does not meet +/// `bound` or is not known to meet bound (note that this is +/// conservative towards *no impl*, which is the opposite of the +/// `evaluate` methods). +pub fn type_known_to_meet_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>, + param_env: &ty::ParameterEnvironment<'tcx>, + ty: Ty<'tcx>, + bound: ty::BuiltinBound) + -> bool +{ + debug!("type_known_to_meet_builtin_bound(ty={}, bound={})", + ty.repr(infcx.tcx), + bound); + + let mut fulfill_cx = FulfillmentContext::new(); + + // We can use dummy values here because we won't report any errors + // that result nor will we pay any mind to region obligations that arise + // (there shouldn't really be any anyhow). + let cause = ObligationCause::misc(DUMMY_SP, ast::DUMMY_NODE_ID); + + fulfill_cx.register_builtin_bound(infcx.tcx, ty, bound, cause); + + // Note: we only assume something is `Copy` if we can + // *definitively* show that it implements `Copy`. Otherwise, + // assume it is move; linear is always ok. + let result = fulfill_cx.select_all_or_error(infcx, param_env, infcx.tcx).is_ok(); + + debug!("type_known_to_meet_builtin_bound: ty={} bound={} result={}", + ty.repr(infcx.tcx), + bound, + result); + + result +} + impl<'tcx,O> Obligation<'tcx,O> { pub fn new(cause: ObligationCause<'tcx>, trait_ref: O) diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index d09efb006f263..731ad64799e3a 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -56,7 +56,6 @@ use middle::resolve_lifetime; use middle::infer; use middle::stability; use middle::subst::{mod, Subst, Substs, VecPerParamSpace}; -use middle::traits::ObligationCause; use middle::traits; use middle::ty; use middle::ty_fold::{mod, TypeFoldable, TypeFolder}; @@ -65,7 +64,7 @@ use util::ppaux::{trait_store_to_string, ty_to_string}; use util::ppaux::{Repr, UserString}; use util::common::{indenter, memoized, ErrorReported}; use util::nodemap::{NodeMap, NodeSet, DefIdMap, DefIdSet}; -use util::nodemap::{FnvHashMap, FnvHashSet}; +use util::nodemap::{FnvHashMap}; use arena::TypedArena; use std::borrow::BorrowFrom; @@ -80,13 +79,13 @@ use collections::enum_set::{EnumSet, CLike}; use std::collections::{HashMap, HashSet}; use std::collections::hash_map::Entry::{Occupied, Vacant}; use syntax::abi; -use syntax::ast::{CrateNum, DefId, DUMMY_NODE_ID, Ident, ItemTrait, LOCAL_CRATE}; +use syntax::ast::{CrateNum, DefId, Ident, ItemTrait, LOCAL_CRATE}; use syntax::ast::{MutImmutable, MutMutable, Name, NamedField, NodeId}; use syntax::ast::{Onceness, StmtExpr, StmtSemi, StructField, UnnamedField}; use syntax::ast::{Visibility}; use syntax::ast_util::{mod, is_local, lit_is_str, local_def, PostExpansionMethod}; use syntax::attr::{mod, AttrMetaMethods}; -use syntax::codemap::{DUMMY_SP, Span}; +use syntax::codemap::Span; use syntax::parse::token::{mod, InternedString}; use syntax::{ast, ast_map}; @@ -780,8 +779,15 @@ pub struct ctxt<'tcx> { /// Caches the representation hints for struct definitions. pub repr_hint_cache: RefCell>>>, - /// Caches whether types move by default. - pub type_moves_by_default_cache: RefCell,bool>>, + /// Caches whether types are known to impl Copy. Note that type + /// parameters are never placed into this cache, because their + /// results are dependent on the parameter environment. + pub type_impls_copy_cache: RefCell,bool>>, + + /// Caches whether types are known to impl Sized. Note that type + /// parameters are never placed into this cache, because their + /// results are dependent on the parameter environment. + pub type_impls_sized_cache: RefCell,bool>>, } // Flags that we track on types. These flags are propagated upwards @@ -2142,7 +2148,8 @@ pub fn mk_ctxt<'tcx>(s: Session, associated_types: RefCell::new(DefIdMap::new()), selection_cache: traits::SelectionCache::new(), repr_hint_cache: RefCell::new(DefIdMap::new()), - type_moves_by_default_cache: RefCell::new(HashMap::new()), + type_impls_copy_cache: RefCell::new(HashMap::new()), + type_impls_sized_cache: RefCell::new(HashMap::new()), } } @@ -2791,14 +2798,6 @@ pub fn type_is_unique(ty: Ty) -> bool { } } -pub fn type_is_fat_ptr<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> bool { - match ty.sty { - ty_ptr(mt{ty, ..}) | ty_rptr(_, mt{ty, ..}) - | ty_uniq(ty) if !type_is_sized(cx, ty) => true, - _ => false, - } -} - /* A scalar type is one that denotes an atomic datum, with no sub-components. (A ty_ptr is scalar because it represents a non-managed pointer, so its @@ -3289,17 +3288,22 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents { } } -pub fn type_moves_by_default<'tcx>(cx: &ctxt<'tcx>, - ty: Ty<'tcx>, - param_env: &ParameterEnvironment<'tcx>) - -> bool +fn type_impls_bound<'tcx>(cx: &ctxt<'tcx>, + cache: &RefCell,bool>>, + param_env: &ParameterEnvironment<'tcx>, + ty: Ty<'tcx>, + bound: ty::BuiltinBound) + -> bool { + assert!(!ty::type_needs_infer(ty)); + if !type_has_params(ty) && !type_has_self(ty) { - match cx.type_moves_by_default_cache.borrow().get(&ty) { + match cache.borrow().get(&ty) { None => {} Some(&result) => { - debug!("determined whether {} moves by default (cached): {}", + debug!("type_impls_bound({}, {}) = {} (cached)", ty_to_string(cx, ty), + bound, result); return result } @@ -3307,27 +3311,35 @@ pub fn type_moves_by_default<'tcx>(cx: &ctxt<'tcx>, } let infcx = infer::new_infer_ctxt(cx); - let mut fulfill_cx = traits::FulfillmentContext::new(); + let is_impld = traits::type_known_to_meet_builtin_bound(&infcx, param_env, ty, bound); - // we can use dummy values here because we won't report any errors - // that result nor will we pay any mind to region obligations that arise - // (there shouldn't really be any anyhow) - let cause = ObligationCause::misc(DUMMY_SP, DUMMY_NODE_ID); + debug!("type_impls_bound({}, {}) = {}", + ty_to_string(cx, ty), + bound, + is_impld); - fulfill_cx.register_builtin_bound(cx, ty, ty::BoundCopy, cause); + if !type_has_params(ty) && !type_has_self(ty) { + let old_value = cache.borrow_mut().insert(ty, is_impld); + assert!(old_value.is_none()); + } - // Note: we only assuming something is `Copy` if we can - // *definitively* show that it implements `Copy`. Otherwise, - // assume it is move; linear is always ok. - let is_copy = fulfill_cx.select_all_or_error(&infcx, param_env, cx).is_ok(); - let is_move = !is_copy; + is_impld +} - debug!("determined whether {} moves by default: {}", - ty_to_string(cx, ty), - is_move); +pub fn type_moves_by_default<'tcx>(cx: &ctxt<'tcx>, + ty: Ty<'tcx>, + param_env: &ParameterEnvironment<'tcx>) + -> bool +{ + !type_impls_bound(cx, &cx.type_impls_copy_cache, param_env, ty, ty::BoundCopy) +} - cx.type_moves_by_default_cache.borrow_mut().insert(ty, is_move); - is_move +pub fn type_is_sized<'tcx>(cx: &ctxt<'tcx>, + ty: Ty<'tcx>, + param_env: &ParameterEnvironment<'tcx>) + -> bool +{ + type_impls_bound(cx, &cx.type_impls_sized_cache, param_env, ty, ty::BoundSized) } pub fn is_ffi_safe<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> bool { @@ -3699,40 +3711,6 @@ pub fn type_is_machine(ty: Ty) -> bool { } } -// Is the type's representation size known at compile time? -pub fn type_is_sized<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> bool { - type_contents(cx, ty).is_sized(cx) -} - -pub fn lltype_is_sized<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> bool { - match ty.sty { - ty_open(_) => true, - _ => type_contents(cx, ty).is_sized(cx) - } -} - -// Return the smallest part of `ty` which is unsized. Fails if `ty` is sized. -// 'Smallest' here means component of the static representation of the type; not -// the size of an object at runtime. -pub fn unsized_part_of_type<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { - match ty.sty { - ty_str | ty_trait(..) | ty_vec(..) => ty, - ty_struct(def_id, substs) => { - let unsized_fields: Vec<_> = struct_fields(cx, def_id, substs).iter() - .map(|f| f.mt.ty).filter(|ty| !type_is_sized(cx, *ty)).collect(); - // Exactly one of the fields must be unsized. - assert!(unsized_fields.len() == 1); - - unsized_part_of_type(cx, unsized_fields[0]) - } - _ => { - assert!(type_is_sized(cx, ty), - "unsized_part_of_type failed even though ty is unsized"); - panic!("called unsized_part_of_type with sized ty"); - } - } -} - // Whether a type is enum like, that is an enum type with only nullary // constructors pub fn type_is_c_like_enum(cx: &ctxt, ty: Ty) -> bool { diff --git a/src/librustc_trans/trans/adt.rs b/src/librustc_trans/trans/adt.rs index 595d252a0b1a0..717c2af2beb96 100644 --- a/src/librustc_trans/trans/adt.rs +++ b/src/librustc_trans/trans/adt.rs @@ -343,7 +343,7 @@ fn find_discr_field_candidate<'tcx>(tcx: &ty::ctxt<'tcx>, mut path: DiscrField) -> Option { match ty.sty { // Fat &T/&mut T/Box i.e. T is [T], str, or Trait - ty::ty_rptr(_, ty::mt { ty, .. }) | ty::ty_uniq(ty) if !ty::type_is_sized(tcx, ty) => { + ty::ty_rptr(_, ty::mt { ty, .. }) | ty::ty_uniq(ty) if !type_is_sized(tcx, ty) => { path.push(FAT_PTR_ADDR); Some(path) }, @@ -447,12 +447,12 @@ fn mk_struct<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, tys: &[Ty<'tcx>], packed: bool, scapegoat: Ty<'tcx>) -> Struct<'tcx> { - let sized = tys.iter().all(|&ty| ty::type_is_sized(cx.tcx(), ty)); + let sized = tys.iter().all(|&ty| type_is_sized(cx.tcx(), ty)); let lltys : Vec = if sized { tys.iter() .map(|&ty| type_of::sizing_type_of(cx, ty)).collect() } else { - tys.iter().filter(|&ty| ty::type_is_sized(cx.tcx(), *ty)) + tys.iter().filter(|&ty| type_is_sized(cx.tcx(), *ty)) .map(|&ty| type_of::sizing_type_of(cx, ty)).collect() }; @@ -704,7 +704,7 @@ fn generic_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, fn struct_llfields<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, st: &Struct<'tcx>, sizing: bool, dst: bool) -> Vec { if sizing { - st.fields.iter().filter(|&ty| !dst || ty::type_is_sized(cx.tcx(), *ty)) + st.fields.iter().filter(|&ty| !dst || type_is_sized(cx.tcx(), *ty)) .map(|&ty| type_of::sizing_type_of(cx, ty)).collect() } else { st.fields.iter().map(|&ty| type_of::type_of(cx, ty)).collect() diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index f0d738d839d7a..397baac960d24 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -581,7 +581,7 @@ pub fn compare_scalar_types<'blk, 'tcx>(cx: Block<'blk, 'tcx>, match t.sty { ty::ty_tup(ref tys) if tys.is_empty() => f(nil_type), ty::ty_bool | ty::ty_uint(_) | ty::ty_char => f(unsigned_int), - ty::ty_ptr(mt) if ty::type_is_sized(cx.tcx(), mt.ty) => f(unsigned_int), + ty::ty_ptr(mt) if common::type_is_sized(cx.tcx(), mt.ty) => f(unsigned_int), ty::ty_int(_) => f(signed_int), ty::ty_float(_) => f(floating_point), // Should never get here, because t is scalar. @@ -719,7 +719,7 @@ pub fn iter_structural_ty<'a, 'blk, 'tcx>(cx: Block<'blk, 'tcx>, return cx; } - let (data_ptr, info) = if ty::type_is_sized(cx.tcx(), t) { + let (data_ptr, info) = if common::type_is_sized(cx.tcx(), t) { (av, None) } else { let data = GEPi(cx, av, &[0, abi::FAT_PTR_ADDR]); @@ -736,7 +736,7 @@ pub fn iter_structural_ty<'a, 'blk, 'tcx>(cx: Block<'blk, 'tcx>, let field_ty = field_ty.mt.ty; let llfld_a = adt::trans_field_ptr(cx, &*repr, data_ptr, discr, i); - let val = if ty::type_is_sized(cx.tcx(), field_ty) { + let val = if common::type_is_sized(cx.tcx(), field_ty) { llfld_a } else { let boxed_ty = ty::mk_open(cx.tcx(), field_ty); @@ -2522,7 +2522,7 @@ pub fn get_fn_llvm_attributes<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_ty: Ty< match ret_ty.sty { // `~` pointer return values never alias because ownership // is transferred - ty::ty_uniq(it) if !ty::type_is_sized(ccx.tcx(), it) => {} + ty::ty_uniq(it) if !common::type_is_sized(ccx.tcx(), it) => {} ty::ty_uniq(_) => { attrs.ret(llvm::NoAliasAttribute); } @@ -2533,7 +2533,7 @@ pub fn get_fn_llvm_attributes<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_ty: Ty< match ret_ty.sty { // These are not really pointers but pairs, (pointer, len) ty::ty_uniq(it) | - ty::ty_rptr(_, ty::mt { ty: it, .. }) if !ty::type_is_sized(ccx.tcx(), it) => {} + ty::ty_rptr(_, ty::mt { ty: it, .. }) if !common::type_is_sized(ccx.tcx(), it) => {} ty::ty_uniq(inner) | ty::ty_rptr(_, ty::mt { ty: inner, .. }) => { let llret_sz = llsize_of_real(ccx, type_of::type_of(ccx, inner)); attrs.ret(llvm::DereferenceableAttribute(llret_sz)); diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs index 7ee4be0ae56f9..f052a20bc89eb 100644 --- a/src/librustc_trans/trans/common.rs +++ b/src/librustc_trans/trans/common.rs @@ -58,6 +58,58 @@ use util::nodemap::FnvHashSet; pub use trans::context::CrateContext; +// Is the type's representation size known at compile time? +pub fn type_is_sized<'tcx>(cx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool { + ty::type_contents(cx, ty).is_sized(cx) +} + +pub fn lltype_is_sized<'tcx>(cx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool { + match ty.sty { + ty::ty_open(_) => true, + _ => type_is_sized(cx, ty), + } +} + +pub fn type_is_fat_ptr<'tcx>(cx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool { + match ty.sty { + ty::ty_ptr(ty::mt{ty, ..}) | + ty::ty_rptr(_, ty::mt{ty, ..}) | + ty::ty_uniq(ty) => { + !type_is_sized(cx, ty) + } + _ => { + false + } + } +} + +// Return the smallest part of `ty` which is unsized. Fails if `ty` is sized. +// 'Smallest' here means component of the static representation of the type; not +// the size of an object at runtime. +pub fn unsized_part_of_type<'tcx>(cx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { + match ty.sty { + ty::ty_str | ty::ty_trait(..) | ty::ty_vec(..) => ty, + ty::ty_struct(def_id, substs) => { + let unsized_fields: Vec<_> = + ty::struct_fields(cx, def_id, substs) + .iter() + .map(|f| f.mt.ty) + .filter(|ty| !type_is_sized(cx, *ty)) + .collect(); + + // Exactly one of the fields must be unsized. + assert!(unsized_fields.len() == 1); + + unsized_part_of_type(cx, unsized_fields[0]) + } + _ => { + assert!(type_is_sized(cx, ty), + "unsized_part_of_type failed even though ty is unsized"); + panic!("called unsized_part_of_type with sized ty"); + } + } +} + // Some things don't need cleanups during unwinding because the // task can free them all at once later. Currently only things // that only contain scalars and shared boxes can avoid unwind @@ -128,10 +180,10 @@ pub fn type_is_immediate<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) - ty::type_is_unique(ty) || ty::type_is_region_ptr(ty) || type_is_newtype_immediate(ccx, ty) || ty::type_is_simd(tcx, ty); - if simple && !ty::type_is_fat_ptr(tcx, ty) { + if simple && !type_is_fat_ptr(tcx, ty) { return true; } - if !ty::type_is_sized(tcx, ty) { + if !type_is_sized(tcx, ty) { return false; } match ty.sty { diff --git a/src/librustc_trans/trans/consts.rs b/src/librustc_trans/trans/consts.rs index bc386dc96a469..0fd6d286e8b2d 100644 --- a/src/librustc_trans/trans/consts.rs +++ b/src/librustc_trans/trans/consts.rs @@ -138,7 +138,7 @@ fn const_deref<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, v: ValueRef, Some(ref mt) => { match t.sty { ty::ty_ptr(mt) | ty::ty_rptr(_, mt) => { - if ty::type_is_sized(cx.tcx(), mt.ty) { + if type_is_sized(cx.tcx(), mt.ty) { (const_deref_ptr(cx, v), mt.ty) } else { // Derefing a fat pointer does not change the representation, diff --git a/src/librustc_trans/trans/datum.rs b/src/librustc_trans/trans/datum.rs index ca274ab605e7f..83bf06383a89c 100644 --- a/src/librustc_trans/trans/datum.rs +++ b/src/librustc_trans/trans/datum.rs @@ -398,7 +398,7 @@ impl<'tcx> Datum<'tcx, Expr> { -> DatumBlock<'blk, 'tcx, Lvalue> { debug!("to_lvalue_datum self: {}", self.to_string(bcx.ccx())); - assert!(ty::lltype_is_sized(bcx.tcx(), self.ty), + assert!(lltype_is_sized(bcx.tcx(), self.ty), "Trying to convert unsized value to lval"); self.match_kind( |l| DatumBlock::new(bcx, l), @@ -456,7 +456,7 @@ impl<'tcx> Datum<'tcx, Lvalue> { F: FnOnce(ValueRef) -> ValueRef, { let val = match self.ty.sty { - _ if ty::type_is_sized(bcx.tcx(), self.ty) => gep(self.val), + _ if type_is_sized(bcx.tcx(), self.ty) => gep(self.val), ty::ty_open(_) => { let base = Load(bcx, expr::get_dataptr(bcx, self.val)); gep(base) diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs index ae07e094a5c61..fc2e6c7b7fddb 100644 --- a/src/librustc_trans/trans/expr.rs +++ b/src/librustc_trans/trans/expr.rs @@ -280,7 +280,7 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr.repr(bcx.tcx()), datum.to_string(bcx.ccx())); - if !ty::type_is_sized(bcx.tcx(), datum.ty) { + if !type_is_sized(bcx.tcx(), datum.ty) { debug!("Taking address of unsized type {}", bcx.ty_to_string(datum.ty)); ref_fat_ptr(bcx, expr, datum) @@ -693,7 +693,7 @@ fn trans_field<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, field_tys[ix].mt.ty, |srcval| adt::trans_field_ptr(bcx, &*repr, srcval, discr, ix)); - if ty::type_is_sized(bcx.tcx(), d.ty) { + if type_is_sized(bcx.tcx(), d.ty) { DatumBlock { datum: d.to_expr_datum(), bcx: bcx } } else { let scratch = rvalue_scratch_datum(bcx, ty::mk_open(bcx.tcx(), d.ty), ""); @@ -773,7 +773,7 @@ fn trans_index<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, Some(SaveIn(scratch.val)), true)); let datum = scratch.to_expr_datum(); - if ty::type_is_sized(bcx.tcx(), elt_ty) { + if type_is_sized(bcx.tcx(), elt_ty) { Datum::new(datum.to_llscalarish(bcx), elt_ty, LvalueExpr) } else { Datum::new(datum.val, ty::mk_open(bcx.tcx(), elt_ty), LvalueExpr) @@ -1522,7 +1522,7 @@ pub fn trans_adt<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, for &(i, t) in base.fields.iter() { let datum = base_datum.get_element( bcx, t, |srcval| adt::trans_field_ptr(bcx, &*repr, srcval, discr, i)); - assert!(ty::type_is_sized(bcx.tcx(), datum.ty)); + assert!(type_is_sized(bcx.tcx(), datum.ty)); let dest = adt::trans_field_ptr(bcx, &*repr, addr, discr, i); bcx = datum.store_to(bcx, dest); } @@ -1650,7 +1650,7 @@ fn trans_uniq_expr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, -> DatumBlock<'blk, 'tcx, Expr> { let _icx = push_ctxt("trans_uniq_expr"); let fcx = bcx.fcx; - assert!(ty::type_is_sized(bcx.tcx(), contents_ty)); + assert!(type_is_sized(bcx.tcx(), contents_ty)); let llty = type_of::type_of(bcx.ccx(), contents_ty); let size = llsize_of(bcx.ccx(), llty); let align = C_uint(bcx.ccx(), type_of::align_of(bcx.ccx(), contents_ty)); @@ -1985,7 +1985,7 @@ pub fn cast_type_kind<'tcx>(tcx: &ty::ctxt<'tcx>, t: Ty<'tcx>) -> cast_kind { ty::ty_char => cast_integral, ty::ty_float(..) => cast_float, ty::ty_rptr(_, mt) | ty::ty_ptr(mt) => { - if ty::type_is_sized(tcx, mt.ty) { + if type_is_sized(tcx, mt.ty) { cast_pointer } else { cast_other @@ -2217,7 +2217,7 @@ fn deref_once<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let r = match datum.ty.sty { ty::ty_uniq(content_ty) => { - if ty::type_is_sized(bcx.tcx(), content_ty) { + if type_is_sized(bcx.tcx(), content_ty) { deref_owned_pointer(bcx, expr, datum, content_ty) } else { // A fat pointer and an opened DST value have the same @@ -2236,7 +2236,7 @@ fn deref_once<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ty::ty_ptr(ty::mt { ty: content_ty, .. }) | ty::ty_rptr(_, ty::mt { ty: content_ty, .. }) => { - if ty::type_is_sized(bcx.tcx(), content_ty) { + if type_is_sized(bcx.tcx(), content_ty) { let ptr = datum.to_llscalarish(bcx); // Always generate an lvalue datum, even if datum.mode is diff --git a/src/librustc_trans/trans/glue.rs b/src/librustc_trans/trans/glue.rs index 4217dd4c6718b..31455920c1097 100644 --- a/src/librustc_trans/trans/glue.rs +++ b/src/librustc_trans/trans/glue.rs @@ -63,7 +63,7 @@ pub fn trans_exchange_free<'blk, 'tcx>(cx: Block<'blk, 'tcx>, v: ValueRef, pub fn trans_exchange_free_ty<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ptr: ValueRef, content_ty: Ty<'tcx>) -> Block<'blk, 'tcx> { - assert!(ty::type_is_sized(bcx.ccx().tcx(), content_ty)); + assert!(type_is_sized(bcx.ccx().tcx(), content_ty)); let sizing_type = sizing_type_of(bcx.ccx(), content_ty); let content_size = llsize_of_alloc(bcx.ccx(), sizing_type); @@ -81,7 +81,7 @@ pub fn get_drop_glue_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, let tcx = ccx.tcx(); // Even if there is no dtor for t, there might be one deeper down and we // might need to pass in the vtable ptr. - if !ty::type_is_sized(tcx, t) { + if !type_is_sized(tcx, t) { return t } if !type_needs_drop(tcx, t) { @@ -89,7 +89,7 @@ pub fn get_drop_glue_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, } match t.sty { ty::ty_uniq(typ) if !type_needs_drop(tcx, typ) - && ty::type_is_sized(tcx, typ) => { + && type_is_sized(tcx, typ) => { let llty = sizing_type_of(ccx, typ); // `Box` does not allocate. if llsize_of_alloc(ccx, llty) == 0 { @@ -150,7 +150,7 @@ pub fn get_drop_glue<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Val _ => { } } - let llty = if ty::type_is_sized(ccx.tcx(), t) { + let llty = if type_is_sized(ccx.tcx(), t) { type_of(ccx, t).ptr_to() } else { type_of(ccx, ty::mk_uniq(ccx.tcx(), t)).ptr_to() @@ -193,7 +193,7 @@ fn trans_struct_drop_flag<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, substs: &subst::Substs<'tcx>) -> Block<'blk, 'tcx> { let repr = adt::represent_type(bcx.ccx(), t); - let struct_data = if ty::type_is_sized(bcx.tcx(), t) { + let struct_data = if type_is_sized(bcx.tcx(), t) { v0 } else { let llval = GEPi(bcx, v0, &[0, abi::FAT_PTR_ADDR]); @@ -234,7 +234,7 @@ fn trans_struct_drop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, bcx.ty_to_string(fty))[]) }; - let (struct_data, info) = if ty::type_is_sized(bcx.tcx(), t) { + let (struct_data, info) = if type_is_sized(bcx.tcx(), t) { (v0, None) } else { let data = GEPi(bcx, v0, &[0, abi::FAT_PTR_ADDR]); @@ -251,7 +251,7 @@ fn trans_struct_drop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, // Class dtors have no explicit args, so the params should // just consist of the environment (self). assert_eq!(params.len(), 1); - let self_arg = if ty::type_is_fat_ptr(bcx.tcx(), self_ty) { + let self_arg = if type_is_fat_ptr(bcx.tcx(), self_ty) { // The dtor expects a fat pointer, so make one, even if we have to fake it. let boxed_ty = ty::mk_open(bcx.tcx(), t); let scratch = datum::rvalue_scratch_datum(bcx, boxed_ty, "__fat_ptr_drop_self"); @@ -275,7 +275,7 @@ fn trans_struct_drop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, for (i, ty) in st.fields.iter().enumerate().rev() { let llfld_a = adt::struct_field_ptr(variant_cx, &*st, value, i, false); - let val = if ty::type_is_sized(bcx.tcx(), *ty) { + let val = if type_is_sized(bcx.tcx(), *ty) { llfld_a } else { let boxed_ty = ty::mk_open(bcx.tcx(), *ty); @@ -303,7 +303,7 @@ fn size_and_align_of_dst<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, t: Ty<'tcx>, info: -> (ValueRef, ValueRef) { debug!("calculate size of DST: {}; with lost info: {}", bcx.ty_to_string(t), bcx.val_to_string(info)); - if ty::type_is_sized(bcx.tcx(), t) { + if type_is_sized(bcx.tcx(), t) { let sizing_type = sizing_type_of(bcx.ccx(), t); let size = C_uint(bcx.ccx(), llsize_of_alloc(bcx.ccx(), sizing_type)); let align = C_uint(bcx.ccx(), align_of(bcx.ccx(), t)); @@ -383,7 +383,7 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, t: Ty<'tcx>) bcx }) } - ty::ty_struct(..) if !ty::type_is_sized(bcx.tcx(), content_ty) => { + ty::ty_struct(..) if !type_is_sized(bcx.tcx(), content_ty) => { let llval = GEPi(bcx, v0, &[0, abi::FAT_PTR_ADDR]); let llbox = Load(bcx, llval); let not_null = IsNotNull(bcx, llbox); @@ -396,7 +396,7 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, t: Ty<'tcx>) }) } _ => { - assert!(ty::type_is_sized(bcx.tcx(), content_ty)); + assert!(type_is_sized(bcx.tcx(), content_ty)); let llval = v0; let llbox = Load(bcx, llval); let not_null = IsNotNull(bcx, llbox); @@ -415,7 +415,7 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, t: Ty<'tcx>) // find the drop flag (which is at the end of the struct). // Lets just ignore the flag and pretend everything will be // OK. - if ty::type_is_sized(bcx.tcx(), t) { + if type_is_sized(bcx.tcx(), t) { trans_struct_drop_flag(bcx, t, v0, dtor, did, substs) } else { // Give the user a heads up that we are doing something @@ -468,7 +468,7 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, t: Ty<'tcx>) } ty::ty_vec(ty, None) => tvec::make_drop_glue_unboxed(bcx, v0, ty, false), _ => { - assert!(ty::type_is_sized(bcx.tcx(), t)); + assert!(type_is_sized(bcx.tcx(), t)); if type_needs_drop(bcx.tcx(), t) && ty::type_is_structural(t) { iter_structural_ty(bcx, v0, t, |bb, vv, tt| drop_ty(bb, vv, tt, None)) diff --git a/src/librustc_trans/trans/intrinsic.rs b/src/librustc_trans/trans/intrinsic.rs index f471a92f6c321..6b0baa5d05e29 100644 --- a/src/librustc_trans/trans/intrinsic.rs +++ b/src/librustc_trans/trans/intrinsic.rs @@ -120,8 +120,8 @@ pub fn check_intrinsics(ccx: &CrateContext) { "s" })[]); } - if ty::type_is_fat_ptr(ccx.tcx(), transmute_restriction.to) || - ty::type_is_fat_ptr(ccx.tcx(), transmute_restriction.from) { + if type_is_fat_ptr(ccx.tcx(), transmute_restriction.to) || + type_is_fat_ptr(ccx.tcx(), transmute_restriction.from) { ccx.sess() .add_lint(::lint::builtin::FAT_PTR_TRANSMUTES, transmute_restriction.id, diff --git a/src/librustc_trans/trans/type_of.rs b/src/librustc_trans/trans/type_of.rs index 499195b51b9ce..aaec82bb1771d 100644 --- a/src/librustc_trans/trans/type_of.rs +++ b/src/librustc_trans/trans/type_of.rs @@ -187,7 +187,7 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ } let llsizingty = match t.sty { - _ if !ty::lltype_is_sized(cx.tcx(), t) => { + _ if !lltype_is_sized(cx.tcx(), t) => { cx.sess().bug(format!("trying to take the sizing type of {}, an unsized type", ppaux::ty_to_string(cx.tcx(), t))[]) } @@ -199,7 +199,7 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ ty::ty_float(t) => Type::float_from_ty(cx, t), ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) | ty::ty_ptr(ty::mt{ty, ..}) => { - if ty::type_is_sized(cx.tcx(), ty) { + if type_is_sized(cx.tcx(), ty) { Type::i8p(cx) } else { Type::struct_(cx, &[Type::i8p(cx), Type::i8p(cx)], false) @@ -267,11 +267,11 @@ pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type { // struct which might be unsized, but is monomorphised to a sized type. // In this case we'll fake a fat pointer with no unsize info (we use 0). // However, its still a fat pointer, so we need some type use. - if ty::type_is_sized(cx.tcx(), t) { + if type_is_sized(cx.tcx(), t) { return Type::i8p(cx); } - match ty::unsized_part_of_type(cx.tcx(), t).sty { + match unsized_part_of_type(cx.tcx(), t).sty { ty::ty_str | ty::ty_vec(..) => Type::uint_from_ty(cx, ast::TyU), ty::ty_trait(_) => Type::vtable_ptr(cx), _ => panic!("Unexpected type returned from unsized_part_of_type : {}", @@ -342,7 +342,7 @@ pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type { cx.tn().find_type("str_slice").unwrap() } ty::ty_trait(..) => Type::opaque_trait(cx), - _ if !ty::type_is_sized(cx.tcx(), ty) => { + _ if !type_is_sized(cx.tcx(), ty) => { let p_ty = type_of(cx, ty).ptr_to(); Type::struct_(cx, &[p_ty, type_of_unsize_info(cx, ty)], false) } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index c8c8211f29253..dfa41c2707e8e 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1356,7 +1356,7 @@ fn check_cast(fcx: &FnCtxt, return } - if !ty::type_is_sized(fcx.tcx(), t_1) { + if !fcx.type_is_known_to_be_sized(t_1) { let tstr = fcx.infcx().ty_to_string(t_1); fcx.type_error_message(span, |actual| { format!("cast to unsized type: `{}` as `{}`", actual, tstr) @@ -1545,10 +1545,14 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> { impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn tcx(&self) -> &ty::ctxt<'tcx> { self.ccx.tcx } - pub fn infcx<'b>(&'b self) -> &'b infer::InferCtxt<'a, 'tcx> { + pub fn infcx(&self) -> &infer::InferCtxt<'a, 'tcx> { &self.inh.infcx } + pub fn param_env(&self) -> &ty::ParameterEnvironment<'tcx> { + &self.inh.param_env + } + pub fn sess(&self) -> &Session { &self.tcx().sess } @@ -1792,6 +1796,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.require_type_is_sized(self.expr_ty(expr), expr.span, code); } + pub fn type_is_known_to_be_sized(&self, + ty: Ty<'tcx>) + -> bool + { + traits::type_known_to_meet_builtin_bound(self.infcx(), + self.param_env(), + ty, + ty::BoundSized) + } + pub fn register_builtin_bound(&self, ty: Ty<'tcx>, builtin_bound: ty::BuiltinBound, From c5edd22646fcde05b39490558371c7ea9d525a0f Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 22 Dec 2014 20:57:14 -0500 Subject: [PATCH 04/36] Rewrite the intrinsicck to take the parameter environment into account. Also fixes #20116. --- src/librustc/middle/intrinsicck.rs | 249 ++++++++++++++---- src/librustc/middle/subst.rs | 1 + src/librustc/middle/ty.rs | 107 +++----- src/librustc_trans/trans/intrinsic.rs | 79 +++--- .../compile-fail/transmute-different-sizes.rs | 2 +- .../compile-fail/transmute-fat-pointers.rs | 41 +++ src/test/compile-fail/transmute-impl.rs | 33 +++ 7 files changed, 352 insertions(+), 160 deletions(-) create mode 100644 src/test/compile-fail/transmute-fat-pointers.rs create mode 100644 src/test/compile-fail/transmute-impl.rs diff --git a/src/librustc/middle/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs index ba18c02f52dc1..1f4ddd1a5d641 100644 --- a/src/librustc/middle/intrinsicck.rs +++ b/src/librustc/middle/intrinsicck.rs @@ -10,9 +10,10 @@ use metadata::csearch; use middle::def::DefFn; -use middle::subst::Subst; +use middle::subst::{Subst, Substs, EnumeratedItems}; use middle::ty::{TransmuteRestriction, ctxt, ty_bare_fn}; use middle::ty::{mod, Ty}; +use util::ppaux::Repr; use syntax::abi::RustIntrinsic; use syntax::ast::DefId; @@ -23,52 +24,31 @@ use syntax::parse::token; use syntax::visit::Visitor; use syntax::visit; -fn type_size_is_affected_by_type_parameters<'tcx>(tcx: &ty::ctxt<'tcx>, typ: Ty<'tcx>) - -> bool { - let mut result = false; - ty::maybe_walk_ty(typ, |typ| { - match typ.sty { - ty::ty_uniq(_) | ty::ty_ptr(_) | ty::ty_rptr(..) | - ty::ty_bare_fn(..) | ty::ty_closure(..) => { - false - } - ty::ty_param(_) => { - result = true; - // No need to continue; we now know the result. - false - } - ty::ty_enum(did, substs) => { - for enum_variant in (*ty::enum_variants(tcx, did)).iter() { - for argument_type in enum_variant.args.iter() { - let argument_type = argument_type.subst(tcx, substs); - result = result || - type_size_is_affected_by_type_parameters( - tcx, - argument_type); - } - } - - // Don't traverse substitutions. - false - } - ty::ty_struct(did, substs) => { - for field in ty::struct_fields(tcx, did, substs).iter() { - result = result || - type_size_is_affected_by_type_parameters(tcx, - field.mt.ty); - } - - // Don't traverse substitutions. - false - } - _ => true, - } - }); - result +pub fn check_crate(tcx: &ctxt) { + let mut visitor = IntrinsicCheckingVisitor { + tcx: tcx, + param_envs: Vec::new(), + dummy_sized_ty: ty::mk_int(), + dummy_unsized_ty: ty::mk_vec(tcx, ty::mk_int(), None), + }; + visit::walk_crate(&mut visitor, tcx.map.krate()); } struct IntrinsicCheckingVisitor<'a, 'tcx: 'a> { tcx: &'a ctxt<'tcx>, + + // As we traverse the AST, we keep a stack of the parameter + // environments for each function we encounter. When we find a + // call to `transmute`, we can check it in the context of the top + // of the stack (which ought not to be empty). + param_envs: Vec>, + + // Dummy sized/unsized types that use to substitute for type + // parameters in order to estimate how big a type will be for any + // possible instantiation of the type parameters in scope. See + // `check_transmute` for more details. + dummy_sized_ty: Ty<'tcx>, + dummy_unsized_ty: Ty<'tcx>, } impl<'a, 'tcx> IntrinsicCheckingVisitor<'a, 'tcx> { @@ -97,26 +77,175 @@ impl<'a, 'tcx> IntrinsicCheckingVisitor<'a, 'tcx> { } fn check_transmute(&self, span: Span, from: Ty<'tcx>, to: Ty<'tcx>, id: ast::NodeId) { - if type_size_is_affected_by_type_parameters(self.tcx, from) { + // Find the parameter environment for the most recent function that + // we entered. + + let param_env = match self.param_envs.last() { + Some(p) => p, + None => { + self.tcx.sess.span_bug( + span, + "transmute encountered outside of any fn"); + } + }; + + // Simple case: no type parameters involved. + if + !ty::type_has_params(from) && !ty::type_has_self(from) && + !ty::type_has_params(to) && !ty::type_has_self(to) + { + let restriction = TransmuteRestriction { + span: span, + original_from: from, + original_to: to, + substituted_from: from, + substituted_to: to, + id: id, + }; + self.push_transmute_restriction(restriction); + return; + } + + // The rules around type parameters are a bit subtle. We are + // checking these rules before monomorphization, so there may + // be unsubstituted type parameters present in the + // types. Obviously we cannot create LLVM types for those. + // However, if a type parameter appears only indirectly (i.e., + // through a pointer), it does not necessarily affect the + // size, so that should be allowed. The only catch is that we + // DO want to be careful around unsized type parameters, since + // fat pointers have a different size than a thin pointer, and + // hence `&T` and `&U` have different sizes if `T : Sized` but + // `U : Sized` does not hold. + // + // However, it's not as simple as checking whether `T : + // Sized`, because even if `T : Sized` does not hold, that + // just means that `T` *may* not be sized. After all, even a + // type parameter `Sized? T` could be bound to a sized + // type. (Issue #20116) + // + // To handle this, we first check for "interior" type + // parameters, which are always illegal. If there are none of + // those, then we know that the only way that all type + // parameters `T` are referenced indirectly, e.g. via a + // pointer type like `&T`. In that case, we only care whether + // `T` is sized or not, because that influences whether `&T` + // is a thin or fat pointer. + // + // One could imagine establishing a sophisticated constraint + // system to ensure that the transmute is legal, but instead + // we do something brutally dumb. We just substitute dummy + // sized or unsized types for every type parameter in scope, + // exhaustively checking all possible combinations. Here are some examples: + // + // ``` + // fn foo() { + // // T=int, U=int + // } + // + // fn bar() { + // // T=int, U=int + // // T=[int], U=int + // } + // + // fn baz() { + // // T=int, U=int + // // T=[int], U=int + // // T=int, U=[int] + // // T=[int], U=[int] + // } + // ``` + // + // In all cases, we keep the original unsubstituted types + // around for error reporting. + + let from_tc = ty::type_contents(self.tcx, from); + let to_tc = ty::type_contents(self.tcx, to); + if from_tc.interior_param() || to_tc.interior_param() { span_err!(self.tcx.sess, span, E0139, - "cannot transmute from a type that contains type parameters"); + "cannot transmute to or from a type that contains \ + type parameters in its interior"); + return; } - if type_size_is_affected_by_type_parameters(self.tcx, to) { - span_err!(self.tcx.sess, span, E0140, - "cannot transmute to a type that contains type parameters"); + + let mut substs = param_env.free_substs.clone(); + self.with_each_combination( + param_env, + param_env.free_substs.types.iter_enumerated(), + &mut substs, + &mut |substs| { + let restriction = TransmuteRestriction { + span: span, + original_from: from, + original_to: to, + substituted_from: from.subst(self.tcx, substs), + substituted_to: to.subst(self.tcx, substs), + id: id, + }; + self.push_transmute_restriction(restriction); + }); + } + + fn with_each_combination(&self, + param_env: &ty::ParameterEnvironment<'tcx>, + mut types_in_scope: EnumeratedItems>, + substs: &mut Substs<'tcx>, + callback: &mut FnMut(&Substs<'tcx>)) + { + // This parameter invokes `callback` many times with different + // substitutions that replace all the parameters in scope with + // either `int` or `[int]`, depending on whether the type + // parameter is known to be sized. See big comment above for + // an explanation of why this is a reasonable thing to do. + + match types_in_scope.next() { + None => { + debug!("with_each_combination(substs={})", + substs.repr(self.tcx)); + + callback.call_mut((substs,)); + } + + Some((space, index, ¶m_ty)) => { + debug!("with_each_combination: space={}, index={}, param_ty={}", + space, index, param_ty.repr(self.tcx)); + + if !ty::type_is_sized(self.tcx, param_ty, param_env) { + debug!("with_each_combination: param_ty is not known to be sized"); + + substs.types.get_mut_slice(space)[index] = self.dummy_unsized_ty; + self.with_each_combination(param_env, types_in_scope.clone(), substs, callback); + } + + substs.types.get_mut_slice(space)[index] = self.dummy_sized_ty; + self.with_each_combination(param_env, types_in_scope, substs, callback); + } } + } - let restriction = TransmuteRestriction { - span: span, - from: from, - to: to, - id: id, - }; + fn push_transmute_restriction(&self, restriction: TransmuteRestriction<'tcx>) { + debug!("Pushing transmute restriction: {}", restriction.repr(self.tcx)); self.tcx.transmute_restrictions.borrow_mut().push(restriction); } } impl<'a, 'tcx, 'v> Visitor<'v> for IntrinsicCheckingVisitor<'a, 'tcx> { + fn visit_fn(&mut self, fk: visit::FnKind<'v>, fd: &'v ast::FnDecl, + b: &'v ast::Block, s: Span, id: ast::NodeId) { + match fk { + visit::FkItemFn(..) | visit::FkMethod(..) => { + let param_env = ty::ParameterEnvironment::for_item(self.tcx, id); + self.param_envs.push(param_env); + visit::walk_fn(self, fk, fd, b, s); + self.param_envs.pop(); + } + visit::FkFnBlock(..) => { + visit::walk_fn(self, fk, fd, b, s); + } + } + + } + fn visit_expr(&mut self, expr: &ast::Expr) { if let ast::ExprPath(..) = expr.node { match ty::resolve_expr(self.tcx, expr) { @@ -144,7 +273,13 @@ impl<'a, 'tcx, 'v> Visitor<'v> for IntrinsicCheckingVisitor<'a, 'tcx> { } } -pub fn check_crate(tcx: &ctxt) { - visit::walk_crate(&mut IntrinsicCheckingVisitor { tcx: tcx }, - tcx.map.krate()); +impl<'tcx> Repr<'tcx> for TransmuteRestriction<'tcx> { + fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String { + format!("TransmuteRestriction(id={}, original=({},{}), substituted=({},{}))", + self.id, + self.original_from.repr(tcx), + self.original_to.repr(tcx), + self.substituted_from.repr(tcx), + self.substituted_to.repr(tcx)) + } } diff --git a/src/librustc/middle/subst.rs b/src/librustc/middle/subst.rs index abacad7d37c90..8d920e0a8211f 100644 --- a/src/librustc/middle/subst.rs +++ b/src/librustc/middle/subst.rs @@ -487,6 +487,7 @@ impl VecPerParamSpace { } } +#[deriving(Clone)] pub struct EnumeratedItems<'a,T:'a> { vec: &'a VecPerParamSpace, space_index: uint, diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 731ad64799e3a..b3e9f85c69c78 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -62,7 +62,7 @@ use middle::ty_fold::{mod, TypeFoldable, TypeFolder}; use util::ppaux::{note_and_explain_region, bound_region_ptr_to_string}; use util::ppaux::{trait_store_to_string, ty_to_string}; use util::ppaux::{Repr, UserString}; -use util::common::{indenter, memoized, ErrorReported}; +use util::common::{memoized, ErrorReported}; use util::nodemap::{NodeMap, NodeSet, DefIdMap, DefIdSet}; use util::nodemap::{FnvHashMap}; @@ -590,16 +590,33 @@ pub enum vtable_origin<'tcx> { pub type ObjectCastMap<'tcx> = RefCell>>>; /// A restriction that certain types must be the same size. The use of -/// `transmute` gives rise to these restrictions. +/// `transmute` gives rise to these restrictions. These generally +/// cannot be checked until trans; therefore, each call to `transmute` +/// will push one or more such restriction into the +/// `transmute_restrictions` vector during `intrinsicck`. They are +/// then checked during `trans` by the fn `check_intrinsics`. #[deriving(Copy)] pub struct TransmuteRestriction<'tcx> { - /// The span from whence the restriction comes. + /// The span whence the restriction comes. pub span: Span, + /// The type being transmuted from. - pub from: Ty<'tcx>, + pub original_from: Ty<'tcx>, + /// The type being transmuted to. - pub to: Ty<'tcx>, - /// NodeIf of the transmute intrinsic. + pub original_to: Ty<'tcx>, + + /// The type being transmuted from, with all type parameters + /// substituted for an arbitrary representative. Not to be shown + /// to the end user. + pub substituted_from: Ty<'tcx>, + + /// The type being transmuted to, with all type parameters + /// substituted for an arbitrary representative. Not to be shown + /// to the end user. + pub substituted_to: Ty<'tcx>, + + /// NodeId of the transmute intrinsic. pub id: ast::NodeId, } @@ -2856,6 +2873,7 @@ def_type_content_sets! { // Things that are interior to the value (first nibble): InteriorUnsized = 0b0000_0000__0000_0000__0001, InteriorUnsafe = 0b0000_0000__0000_0000__0010, + InteriorParam = 0b0000_0000__0000_0000__0100, // InteriorAll = 0b00000000__00000000__1111, // Things that are owned by the value (second and third nibbles): @@ -2910,6 +2928,10 @@ impl TypeContents { !self.intersects(TC::Nonsized) } + pub fn interior_param(&self) -> bool { + self.intersects(TC::InteriorParam) + } + pub fn interior_unsafe(&self) -> bool { self.intersects(TC::InteriorUnsafe) } @@ -3038,7 +3060,7 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents { } ty_closure(ref c) => { - closure_contents(cx, &**c) | TC::ReachesFfiUnsafe + closure_contents(&**c) | TC::ReachesFfiUnsafe } ty_uniq(typ) => { @@ -3049,7 +3071,7 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents { } ty_trait(box TyTrait { bounds, .. }) => { - object_contents(cx, bounds) | TC::ReachesFfiUnsafe | TC::Nonsized + object_contents(bounds) | TC::ReachesFfiUnsafe | TC::Nonsized } ty_ptr(ref mt) => { @@ -3159,26 +3181,7 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents { apply_lang_items(cx, did, res) } - ty_param(p) => { - // We only ever ask for the kind of types that are defined in - // the current crate; therefore, the only type parameters that - // could be in scope are those defined in the current crate. - // If this assertion fails, it is likely because of a - // failure of the cross-crate inlining code to translate a - // def-id. - assert_eq!(p.def_id.krate, ast::LOCAL_CRATE); - - let ty_param_defs = cx.ty_param_defs.borrow(); - let tp_def = &(*ty_param_defs)[p.def_id.node]; - kind_bounds_to_contents( - cx, - tp_def.bounds.builtin_bounds, - tp_def.bounds.trait_bounds[]) - } - - ty_infer(_) => { - // This occurs during coherence, but shouldn't occur at other - // times. + ty_param(_) => { TC::All } @@ -3188,6 +3191,7 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents { result.unsafe_pointer() | TC::Nonsized } + ty_infer(_) | ty_err => { cx.sess.bug("asked to compute contents of error type"); } @@ -3227,10 +3231,10 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents { b | (TC::ReachesBorrowed).when(region != ty::ReStatic) } - fn closure_contents(cx: &ctxt, cty: &ClosureTy) -> TypeContents { + fn closure_contents(cty: &ClosureTy) -> TypeContents { // Closure contents are just like trait contents, but with potentially // even more stuff. - let st = object_contents(cx, cty.bounds); + let st = object_contents(cty.bounds); let st = match cty.store { UniqTraitStore => { @@ -3244,47 +3248,18 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents { st } - fn object_contents(cx: &ctxt, - bounds: ExistentialBounds) - -> TypeContents { - // These are the type contents of the (opaque) interior - kind_bounds_to_contents(cx, bounds.builtin_bounds, &[]) - } - - fn kind_bounds_to_contents<'tcx>(cx: &ctxt<'tcx>, - bounds: BuiltinBounds, - traits: &[Rc>]) - -> TypeContents { - let _i = indenter(); - let mut tc = TC::All; - each_inherited_builtin_bound(cx, bounds, traits, |bound| { + fn object_contents(bounds: ExistentialBounds) -> TypeContents { + // These are the type contents of the (opaque) interior. We + // make no assumptions (other than that it cannot have an + // in-scope type parameter within, which makes no sense). + let mut tc = TC::All - TC::InteriorParam; + for bound in bounds.builtin_bounds.iter() { tc = tc - match bound { BoundSync | BoundSend | BoundCopy => TC::None, BoundSized => TC::Nonsized, }; - }); - return tc; - - // Iterates over all builtin bounds on the type parameter def, including - // those inherited from traits with builtin-kind-supertraits. - fn each_inherited_builtin_bound<'tcx, F>(cx: &ctxt<'tcx>, - bounds: BuiltinBounds, - traits: &[Rc>], - mut f: F) where - F: FnMut(BuiltinBound), - { - for bound in bounds.iter() { - f(bound); - } - - each_bound_trait_and_supertraits(cx, traits, |trait_ref| { - let trait_def = lookup_trait_def(cx, trait_ref.def_id()); - for bound in trait_def.bounds.builtin_bounds.iter() { - f(bound); - } - true - }); } + return tc; } } diff --git a/src/librustc_trans/trans/intrinsic.rs b/src/librustc_trans/trans/intrinsic.rs index 6b0baa5d05e29..d49018e00c1cb 100644 --- a/src/librustc_trans/trans/intrinsic.rs +++ b/src/librustc_trans/trans/intrinsic.rs @@ -32,7 +32,7 @@ use middle::ty::{mod, Ty}; use syntax::abi::RustIntrinsic; use syntax::ast; use syntax::parse::token; -use util::ppaux::ty_to_string; +use util::ppaux::{Repr, ty_to_string}; pub fn get_simple_intrinsic(ccx: &CrateContext, item: &ast::ForeignItem) -> Option { let name = match token::get_ident(item.ident).get() { @@ -90,46 +90,53 @@ pub fn get_simple_intrinsic(ccx: &CrateContext, item: &ast::ForeignItem) -> Opti /// Performs late verification that intrinsics are used correctly. At present, /// the only intrinsic that needs such verification is `transmute`. pub fn check_intrinsics(ccx: &CrateContext) { - for transmute_restriction in ccx.tcx() - .transmute_restrictions - .borrow() - .iter() { + let mut last_failing_id = None; + for transmute_restriction in ccx.tcx().transmute_restrictions.borrow().iter() { + // Sometimes, a single call to transmute will push multiple + // type pairs to test in order to exhaustively test the + // possibility around a type parameter. If one of those fails, + // there is no sense reporting errors on the others. + if last_failing_id == Some(transmute_restriction.id) { + continue; + } + + debug!("transmute_restriction: {}", transmute_restriction.repr(ccx.tcx())); + + assert!(!ty::type_has_params(transmute_restriction.substituted_from)); + assert!(!ty::type_has_params(transmute_restriction.substituted_to)); + let llfromtype = type_of::sizing_type_of(ccx, - transmute_restriction.from); + transmute_restriction.substituted_from); let lltotype = type_of::sizing_type_of(ccx, - transmute_restriction.to); + transmute_restriction.substituted_to); let from_type_size = machine::llbitsize_of_real(ccx, llfromtype); let to_type_size = machine::llbitsize_of_real(ccx, lltotype); if from_type_size != to_type_size { - ccx.sess() - .span_err(transmute_restriction.span, - format!("transmute called on types with different sizes: \ - {} ({} bit{}) to {} ({} bit{})", - ty_to_string(ccx.tcx(), transmute_restriction.from), - from_type_size as uint, - if from_type_size == 1 { - "" - } else { - "s" - }, - ty_to_string(ccx.tcx(), transmute_restriction.to), - to_type_size as uint, - if to_type_size == 1 { - "" - } else { - "s" - })[]); - } - if type_is_fat_ptr(ccx.tcx(), transmute_restriction.to) || - type_is_fat_ptr(ccx.tcx(), transmute_restriction.from) { - ccx.sess() - .add_lint(::lint::builtin::FAT_PTR_TRANSMUTES, - transmute_restriction.id, - transmute_restriction.span, - format!("Transmuting fat pointer types; {} to {}.\ - Beware of relying on the compiler's representation", - ty_to_string(ccx.tcx(), transmute_restriction.from), - ty_to_string(ccx.tcx(), transmute_restriction.to))); + last_failing_id = Some(transmute_restriction.id); + + if transmute_restriction.original_from != transmute_restriction.substituted_from { + ccx.sess().span_err( + transmute_restriction.span, + format!("transmute called on types with potentially different sizes: \ + {} (could be {} bit{}) to {} (could be {} bit{})", + ty_to_string(ccx.tcx(), transmute_restriction.original_from), + from_type_size as uint, + if from_type_size == 1 {""} else {"s"}, + ty_to_string(ccx.tcx(), transmute_restriction.original_to), + to_type_size as uint, + if to_type_size == 1 {""} else {"s"}).as_slice()); + } else { + ccx.sess().span_err( + transmute_restriction.span, + format!("transmute called on types with different sizes: \ + {} ({} bit{}) to {} ({} bit{})", + ty_to_string(ccx.tcx(), transmute_restriction.original_from), + from_type_size as uint, + if from_type_size == 1 {""} else {"s"}, + ty_to_string(ccx.tcx(), transmute_restriction.original_to), + to_type_size as uint, + if to_type_size == 1 {""} else {"s"}).as_slice()); + } } } ccx.sess().abort_if_errors(); diff --git a/src/test/compile-fail/transmute-different-sizes.rs b/src/test/compile-fail/transmute-different-sizes.rs index abdfe983e3a8f..5c61212a7f5a5 100644 --- a/src/test/compile-fail/transmute-different-sizes.rs +++ b/src/test/compile-fail/transmute-different-sizes.rs @@ -21,7 +21,7 @@ unsafe fn f() { unsafe fn g(x: &T) { let _: i8 = transmute(x); - //~^ ERROR transmute called on types with different sizes + //~^ ERROR transmute called on types with potentially different sizes } fn main() {} diff --git a/src/test/compile-fail/transmute-fat-pointers.rs b/src/test/compile-fail/transmute-fat-pointers.rs new file mode 100644 index 0000000000000..5e81a4cec2284 --- /dev/null +++ b/src/test/compile-fail/transmute-fat-pointers.rs @@ -0,0 +1,41 @@ +// Copyright 2012 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Tests that are conservative around thin/fat pointer mismatches. + +#![allow(dead_code)] + +use std::mem::transmute; + +fn a(x: &[T]) -> &U { + unsafe { transmute(x) } //~ ERROR transmute called on types with potentially different sizes +} + +fn b(x: &T) -> &U { + unsafe { transmute(x) } //~ ERROR transmute called on types with potentially different sizes +} + +fn c(x: &T) -> &U { + unsafe { transmute(x) } +} + +fn d(x: &[T]) -> &[U] { + unsafe { transmute(x) } +} + +fn e(x: &T) -> &U { + unsafe { transmute(x) } //~ ERROR transmute called on types with potentially different sizes +} + +fn f(x: &T) -> &U { + unsafe { transmute(x) } //~ ERROR transmute called on types with potentially different sizes +} + +fn main() { } diff --git a/src/test/compile-fail/transmute-impl.rs b/src/test/compile-fail/transmute-impl.rs new file mode 100644 index 0000000000000..8b5a8c679b245 --- /dev/null +++ b/src/test/compile-fail/transmute-impl.rs @@ -0,0 +1,33 @@ +// Copyright 2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Tests that are conservative around thin/fat pointer mismatches. + +#![allow(dead_code)] + +use std::mem::transmute; + +struct Foo { + t: Box +} + +impl Foo { + fn m(x: &T) -> &int where T : Sized { + // OK here, because T : Sized is in scope. + unsafe { transmute(x) } + } + + fn n(x: &T) -> &int { + // Not OK here, because T : Sized is not in scope. + unsafe { transmute(x) } //~ ERROR transmute called on types with potentially different sizes + } +} + +fn main() { } From 986f654f3b087809fbf9b1168708e46b4211da84 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 17 Dec 2014 16:00:34 -0500 Subject: [PATCH 05/36] Rename `trait_ref` field to `predicate`, since `trait_ref` is really overly general, and the value is always *some* sort of predicate. --- src/librustc/middle/traits/fulfill.rs | 36 ++++++++++---------- src/librustc/middle/traits/mod.rs | 8 ++--- src/librustc/middle/traits/select.rs | 47 ++++++++++++++------------- src/librustc/middle/traits/util.rs | 14 +++++--- src/librustc/middle/ty_fold.rs | 2 +- 5 files changed, 56 insertions(+), 51 deletions(-) diff --git a/src/librustc/middle/traits/fulfill.rs b/src/librustc/middle/traits/fulfill.rs index e9e80ed8c18c9..6c80a22536a34 100644 --- a/src/librustc/middle/traits/fulfill.rs +++ b/src/librustc/middle/traits/fulfill.rs @@ -126,7 +126,7 @@ impl<'tcx> FulfillmentContext<'tcx> { let trait_obligation = Obligation { cause: cause, recursion_depth: 0, - trait_ref: ty::Predicate::Trait(trait_ref) }; + predicate: ty::Predicate::Trait(trait_ref) }; self.register_predicate(tcx, trait_obligation) } @@ -141,15 +141,15 @@ impl<'tcx> FulfillmentContext<'tcx> { pub fn register_predicate<'a>(&mut self, tcx: &ty::ctxt<'tcx>, - predicate: PredicateObligation<'tcx>) + obligation: PredicateObligation<'tcx>) { - if !self.duplicate_set.insert(predicate.trait_ref.clone()) { - debug!("register_predicate({}) -- already seen, skip", predicate.repr(tcx)); + if !self.duplicate_set.insert(obligation.predicate.clone()) { + debug!("register_predicate({}) -- already seen, skip", obligation.repr(tcx)); return; } - debug!("register_predicate({})", predicate.repr(tcx)); - self.predicates.push(predicate); + debug!("register_predicate({})", obligation.repr(tcx)); + self.predicates.push(obligation); } pub fn region_obligations(&self, @@ -289,7 +289,7 @@ impl<'tcx> FulfillmentContext<'tcx> { } fn process_predicate<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>, - predicate: &PredicateObligation<'tcx>, + obligation: &PredicateObligation<'tcx>, selections: &mut Vec>, errors: &mut Vec>, region_obligations: &mut NodeMap>>) @@ -303,11 +303,9 @@ fn process_predicate<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>, */ let tcx = selcx.tcx(); - match predicate.trait_ref { + match obligation.predicate { ty::Predicate::Trait(ref trait_ref) => { - let trait_obligation = Obligation { cause: predicate.cause.clone(), - recursion_depth: predicate.recursion_depth, - trait_ref: trait_ref.clone() }; + let trait_obligation = obligation.with(trait_ref.clone()); match selcx.select(&trait_obligation) { Ok(None) => { false @@ -318,11 +316,11 @@ fn process_predicate<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>, } Err(selection_err) => { debug!("predicate: {} error: {}", - predicate.repr(tcx), + obligation.repr(tcx), selection_err.repr(tcx)); errors.push( FulfillmentError::new( - predicate.clone(), + obligation.clone(), CodeSelectionError(selection_err))); true } @@ -330,12 +328,12 @@ fn process_predicate<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>, } ty::Predicate::Equate(ref binder) => { - match selcx.infcx().equality_predicate(predicate.cause.span, binder) { + match selcx.infcx().equality_predicate(obligation.cause.span, binder) { Ok(()) => { } Err(_) => { errors.push( FulfillmentError::new( - predicate.clone(), + obligation.clone(), CodeSelectionError(Unimplemented))); } } @@ -343,12 +341,12 @@ fn process_predicate<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>, } ty::Predicate::RegionOutlives(ref binder) => { - match selcx.infcx().region_outlives_predicate(predicate.cause.span, binder) { + match selcx.infcx().region_outlives_predicate(obligation.cause.span, binder) { Ok(()) => { } Err(_) => { errors.push( FulfillmentError::new( - predicate.clone(), + obligation.clone(), CodeSelectionError(Unimplemented))); } } @@ -364,12 +362,12 @@ fn process_predicate<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>, if ty::count_late_bound_regions(selcx.tcx(), binder) != 0 { errors.push( FulfillmentError::new( - predicate.clone(), + obligation.clone(), CodeSelectionError(Unimplemented))); } else { let ty::OutlivesPredicate(t_a, r_b) = binder.0; register_region_obligation(tcx, t_a, r_b, - predicate.cause.clone(), + obligation.cause.clone(), region_obligations); } true diff --git a/src/librustc/middle/traits/mod.rs b/src/librustc/middle/traits/mod.rs index 5676ba6f6652b..41c55abc9ae0f 100644 --- a/src/librustc/middle/traits/mod.rs +++ b/src/librustc/middle/traits/mod.rs @@ -53,7 +53,7 @@ mod util; pub struct Obligation<'tcx, T> { pub cause: ObligationCause<'tcx>, pub recursion_depth: uint, - pub trait_ref: T, + pub predicate: T, } pub type PredicateObligation<'tcx> = Obligation<'tcx, ty::Predicate<'tcx>>; @@ -310,7 +310,7 @@ impl<'tcx,O> Obligation<'tcx,O> { { Obligation { cause: cause, recursion_depth: 0, - trait_ref: trait_ref } + predicate: trait_ref } } pub fn misc(span: Span, body_id: ast::NodeId, trait_ref: O) -> Obligation<'tcx, O> { @@ -320,13 +320,13 @@ impl<'tcx,O> Obligation<'tcx,O> { pub fn with

(&self, value: P) -> Obligation<'tcx,P> { Obligation { cause: self.cause.clone(), recursion_depth: self.recursion_depth, - trait_ref: value } + predicate: value } } } impl<'tcx> TraitObligation<'tcx> { pub fn self_ty(&self) -> Ty<'tcx> { - self.trait_ref.self_ty() + self.predicate.self_ty() } } diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index b10b1ce35c436..6b56bbac20101 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -218,7 +218,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { pub fn select(&mut self, obligation: &TraitObligation<'tcx>) -> SelectionResult<'tcx, Selection<'tcx>> { debug!("select({})", obligation.repr(self.tcx())); - assert!(!obligation.trait_ref.has_escaping_regions()); + assert!(!obligation.predicate.has_escaping_regions()); let stack = self.push_stack(None, obligation); match try!(self.candidate_from_obligation(&stack)) { @@ -280,7 +280,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { debug!("evaluate_predicate_recursively({})", obligation.repr(self.tcx())); - match obligation.trait_ref { + match obligation.predicate { ty::Predicate::Trait(ref t) => { assert!(!t.has_escaping_regions()); let obligation = obligation.with(t.clone()); @@ -411,7 +411,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.infcx.probe(|snapshot| { let (skol_obligation_trait_ref, skol_map) = - self.infcx().skolemize_late_bound_regions(&*obligation.trait_ref, snapshot); + self.infcx().skolemize_late_bound_regions(&*obligation.predicate, snapshot); match self.match_impl(impl_def_id, obligation, snapshot, &skol_map, Rc::new(skol_obligation_trait_ref)) { Ok(substs) => { @@ -456,11 +456,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // is because we want the unbound variables to be replaced // with fresh skolemized types starting from index 0. let cache_fresh_trait_ref = - self.infcx.freshen(stack.obligation.trait_ref.clone()); + self.infcx.freshen(stack.obligation.predicate.clone()); debug!("candidate_from_obligation(cache_fresh_trait_ref={}, obligation={})", cache_fresh_trait_ref.repr(self.tcx()), stack.repr(self.tcx())); - assert!(!stack.obligation.trait_ref.has_escaping_regions()); + assert!(!stack.obligation.predicate.has_escaping_regions()); match self.check_candidate_cache(cache_fresh_trait_ref.clone()) { Some(c) => { @@ -655,7 +655,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Other bounds. Consider both in-scope bounds from fn decl // and applicable impls. There is a certain set of precedence rules here. - match self.tcx().lang_items.to_builtin_kind(obligation.trait_ref.def_id()) { + match self.tcx().lang_items.to_builtin_kind(obligation.predicate.def_id()) { Some(ty::BoundCopy) => { debug!("obligation self ty is {}", obligation.self_ty().repr(self.tcx())); @@ -747,7 +747,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { candidates: &mut CandidateSet<'tcx>) -> Result<(),SelectionError<'tcx>> { - let kind = match self.fn_family_trait_kind(obligation.trait_ref.def_id()) { + let kind = match self.fn_family_trait_kind(obligation.predicate.def_id()) { Some(k) => k, None => { return Ok(()); } }; @@ -795,7 +795,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // We provide a `Fn` impl for fn pointers. There is no need to provide // the other traits (e.g. `FnMut`) since those are provided by blanket // impls. - if Some(obligation.trait_ref.def_id()) != self.tcx().lang_items.fn_trait() { + if Some(obligation.predicate.def_id()) != self.tcx().lang_items.fn_trait() { return Ok(()); } @@ -830,11 +830,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { candidate_vec: &mut Vec>) -> Result<(), SelectionError<'tcx>> { - let all_impls = self.all_impls(obligation.trait_ref.def_id()); + let all_impls = self.all_impls(obligation.predicate.def_id()); for &impl_def_id in all_impls.iter() { self.infcx.probe(|snapshot| { let (skol_obligation_trait_ref, skol_map) = - self.infcx().skolemize_late_bound_regions(&*obligation.trait_ref, snapshot); + self.infcx().skolemize_late_bound_regions(&*obligation.predicate, snapshot); match self.match_impl(impl_def_id, obligation, snapshot, &skol_map, Rc::new(skol_obligation_trait_ref)) { Ok(_) => { @@ -931,7 +931,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.infcx.probe(|snapshot| { let (skol_obligation_trait_ref, skol_map) = self.infcx().skolemize_late_bound_regions( - &*stack.obligation.trait_ref, snapshot); + &*stack.obligation.predicate, snapshot); let impl_substs = self.rematch_impl(impl_def_id, stack.obligation, snapshot, &skol_map, Rc::new(skol_obligation_trait_ref)); @@ -987,7 +987,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &TraitObligation<'tcx>) -> Result,SelectionError<'tcx>> { - let self_ty = self.infcx.shallow_resolve(obligation.trait_ref.self_ty()); + let self_ty = self.infcx.shallow_resolve(obligation.predicate.self_ty()); return match self_ty.sty { ty::ty_infer(ty::IntVar(_)) | ty::ty_infer(ty::FloatVar(_)) | @@ -1415,7 +1415,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // trait-ref. Repeat that unification now without any // transactional boundary; it should not fail. match self.confirm_poly_trait_refs(obligation.cause.clone(), - obligation.trait_ref.clone(), + obligation.predicate.clone(), param.bound.clone()) { Ok(()) => Ok(param), Err(_) => { @@ -1472,7 +1472,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligations.push(Obligation { cause: obligation.cause.clone(), recursion_depth: obligation.recursion_depth+1, - trait_ref: ty::Binder(ty::OutlivesPredicate(obligation.self_ty(), + predicate: ty::Binder(ty::OutlivesPredicate(obligation.self_ty(), ty::ReStatic)).as_predicate(), }); } @@ -1500,7 +1500,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // this time not in a probe. self.infcx.try(|snapshot| { let (skol_obligation_trait_ref, skol_map) = - self.infcx().skolemize_late_bound_regions(&*obligation.trait_ref, snapshot); + self.infcx().skolemize_late_bound_regions(&*obligation.predicate, snapshot); let substs = self.rematch_impl(impl_def_id, obligation, snapshot, &skol_map, Rc::new(skol_obligation_trait_ref)); debug!("confirm_impl_candidate substs={}", substs); @@ -1574,12 +1574,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { vec![], self_ty); let trait_ref = Rc::new(ty::Binder(ty::TraitRef { - def_id: obligation.trait_ref.def_id(), + def_id: obligation.predicate.def_id(), substs: self.tcx().mk_substs(substs), })); try!(self.confirm_poly_trait_refs(obligation.cause.clone(), - obligation.trait_ref.clone(), + obligation.predicate.clone(), trait_ref)); Ok(self_ty) } @@ -1615,7 +1615,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { vec![], obligation.self_ty()); let trait_ref = Rc::new(ty::Binder(ty::TraitRef { - def_id: obligation.trait_ref.def_id(), + def_id: obligation.predicate.def_id(), substs: self.tcx().mk_substs(substs), })); @@ -1624,7 +1624,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { trait_ref.repr(self.tcx())); self.confirm_poly_trait_refs(obligation.cause.clone(), - obligation.trait_ref.clone(), + obligation.predicate.clone(), trait_ref) } @@ -1769,7 +1769,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // substitution if we find that any of the input types, when // simplified, do not match. - obligation.trait_ref.input_types().iter() + obligation.predicate.input_types().iter() .zip(impl_trait_ref.input_types().iter()) .any(|(&obligation_ty, &impl_ty)| { let simplified_obligation_ty = @@ -1796,7 +1796,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { match self.infcx.sub_poly_trait_refs(false, origin, where_clause_trait_ref, - obligation.trait_ref.clone()) { + obligation.predicate.clone()) { Ok(()) => Ok(()), Err(_) => Err(()), } @@ -1878,7 +1878,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &'o TraitObligation<'tcx>) -> TraitObligationStack<'o, 'tcx> { - let fresh_trait_ref = obligation.trait_ref.fold_with(&mut self.freshener); + let fresh_trait_ref = obligation.predicate.fold_with(&mut self.freshener); TraitObligationStack { obligation: obligation, @@ -2020,7 +2020,8 @@ impl<'tcx> EvaluationResult<'tcx> { EvaluatedToOk | EvaluatedToAmbig | EvaluatedToErr(Overflow) | - EvaluatedToErr(OutputTypeParameterMismatch(..)) => { + EvaluatedToErr(OutputTypeParameterMismatch(..)) | + EvaluatedToErr(ProjectionMismatch(..)) => { true } EvaluatedToErr(Unimplemented) => { diff --git a/src/librustc/middle/traits/util.rs b/src/librustc/middle/traits/util.rs index e75478b32438f..6b95e983e8891 100644 --- a/src/librustc/middle/traits/util.rs +++ b/src/librustc/middle/traits/util.rs @@ -261,7 +261,7 @@ pub fn predicates_for_generics<'tcx>(tcx: &ty::ctxt<'tcx>, generic_bounds.predicates.map(|predicate| { Obligation { cause: cause.clone(), recursion_depth: recursion_depth, - trait_ref: predicate.clone() } + predicate: predicate.clone() } }) } @@ -297,7 +297,7 @@ pub fn predicate_for_builtin_bound<'tcx>( Ok(Obligation { cause: cause, recursion_depth: recursion_depth, - trait_ref: ty::Predicate::Trait(trait_ref), + predicate: ty::Predicate::Trait(trait_ref), }) } @@ -323,8 +323,8 @@ pub fn search_trait_and_supertraits_from_bound<'tcx,F>(tcx: &ty::ctxt<'tcx>, impl<'tcx,O:Repr<'tcx>> Repr<'tcx> for super::Obligation<'tcx, O> { fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String { - format!("Obligation(trait_ref={},depth={})", - self.trait_ref.repr(tcx), + format!("Obligation(predicate={},depth={})", + self.predicate.repr(tcx), self.recursion_depth) } } @@ -390,6 +390,12 @@ impl<'tcx> Repr<'tcx> for super::SelectionError<'tcx> { a.repr(tcx), b.repr(tcx), c.repr(tcx)), + + super::ProjectionMismatch(ref a, ref b, ref c) => + format!("PrjectionMismatch({},{},{})", + a.repr(tcx), + b.repr(tcx), + c.repr(tcx)), } } } diff --git a/src/librustc/middle/ty_fold.rs b/src/librustc/middle/ty_fold.rs index 782b464ed96d5..11a130f0c5407 100644 --- a/src/librustc/middle/ty_fold.rs +++ b/src/librustc/middle/ty_fold.rs @@ -441,7 +441,7 @@ impl<'tcx,O> TypeFoldable<'tcx> for traits::Obligation<'tcx,O> traits::Obligation { cause: self.cause.clone(), recursion_depth: self.recursion_depth, - trait_ref: self.trait_ref.fold_with(folder), + predicate: self.predicate.fold_with(folder), } } } From 771dd54ea6c09ac32093a46a0d9ed80502ce3b02 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 23 Dec 2014 05:52:47 -0500 Subject: [PATCH 06/36] Rename `Polytype` to `TypeScheme` to differentiate type schemes (early bound) from higher-ranked things (late-bound), which also use the `Poly` prefix. --- src/librustc/metadata/csearch.rs | 6 +- src/librustc/metadata/decoder.rs | 4 +- src/librustc/metadata/encoder.rs | 2 +- src/librustc/middle/astencode.rs | 40 ++++---- src/librustc/middle/ty.rs | 15 ++- src/librustc/util/ppaux.rs | 4 +- src/librustc_trans/trans/callee.rs | 8 +- src/librustc_typeck/astconv.rs | 14 +-- src/librustc_typeck/check/_match.rs | 20 ++-- src/librustc_typeck/check/mod.rs | 36 ++++---- src/librustc_typeck/check/wf.rs | 10 +- src/librustc_typeck/coherence/mod.rs | 16 ++-- src/librustc_typeck/collect.rs | 132 +++++++++++++-------------- src/librustc_typeck/lib.rs | 4 +- 14 files changed, 158 insertions(+), 153 deletions(-) diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs index 51cebbfb52c58..0cbc94f379d80 100644 --- a/src/librustc/metadata/csearch.rs +++ b/src/librustc/metadata/csearch.rs @@ -226,7 +226,7 @@ pub fn get_struct_field_attrs(cstore: &cstore::CStore, def: ast::DefId) -> HashM pub fn get_type<'tcx>(tcx: &ty::ctxt<'tcx>, def: ast::DefId) - -> ty::Polytype<'tcx> { + -> ty::TypeScheme<'tcx> { let cstore = &tcx.sess.cstore; let cdata = cstore.get_crate_data(def.krate); decoder::get_type(&*cdata, def.node, tcx) @@ -239,7 +239,7 @@ pub fn get_trait_def<'tcx>(tcx: &ty::ctxt<'tcx>, def: ast::DefId) -> ty::TraitDe } pub fn get_field_type<'tcx>(tcx: &ty::ctxt<'tcx>, class_id: ast::DefId, - def: ast::DefId) -> ty::Polytype<'tcx> { + def: ast::DefId) -> ty::TypeScheme<'tcx> { let cstore = &tcx.sess.cstore; let cdata = cstore.get_crate_data(class_id.krate); let all_items = reader::get_doc(rbml::Doc::new(cdata.data()), tag_items); @@ -257,7 +257,7 @@ pub fn get_field_type<'tcx>(tcx: &ty::ctxt<'tcx>, class_id: ast::DefId, def)).to_string() }); let ty = decoder::item_type(def, the_field, tcx, &*cdata); - ty::Polytype { + ty::TypeScheme { generics: ty::Generics::empty(), ty: ty, } diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index 4447af809e4b2..ce04a9029929d 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -387,7 +387,7 @@ pub fn get_trait_def<'tcx>(cdata: Cmd, } pub fn get_type<'tcx>(cdata: Cmd, id: ast::NodeId, tcx: &ty::ctxt<'tcx>) - -> ty::Polytype<'tcx> { + -> ty::TypeScheme<'tcx> { let item = lookup_item(id, cdata.data()); @@ -396,7 +396,7 @@ pub fn get_type<'tcx>(cdata: Cmd, id: ast::NodeId, tcx: &ty::ctxt<'tcx>) let generics = doc_generics(item, tcx, cdata, tag_item_generics); - ty::Polytype { + ty::TypeScheme { generics: generics, ty: t } diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 2a670b308b6b2..6d79419b38634 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -142,7 +142,7 @@ fn encode_item_variances(rbml_w: &mut Encoder, fn encode_bounds_and_type<'a, 'tcx>(rbml_w: &mut Encoder, ecx: &EncodeContext<'a, 'tcx>, - pty: &ty::Polytype<'tcx>) { + pty: &ty::TypeScheme<'tcx>) { encode_generics(rbml_w, ecx, &pty.generics, tag_item_generics); encode_type(ecx, rbml_w, pty.ty); } diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index e8627dfa64b0b..a135701a9c435 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -838,8 +838,8 @@ trait rbml_writer_helpers<'tcx> { predicate: &ty::Predicate<'tcx>); fn emit_trait_ref<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>, ty: &ty::TraitRef<'tcx>); - fn emit_polytype<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>, - pty: ty::Polytype<'tcx>); + fn emit_type_scheme<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>, + type_scheme: ty::TypeScheme<'tcx>); fn emit_substs<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>, substs: &subst::Substs<'tcx>); fn emit_existential_bounds(&mut self, ecx: &e::EncodeContext, bounds: &ty::ExistentialBounds); @@ -951,33 +951,33 @@ impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> { }); } - fn emit_polytype<'b>(&mut self, - ecx: &e::EncodeContext<'b, 'tcx>, - pty: ty::Polytype<'tcx>) { + fn emit_type_scheme<'b>(&mut self, + ecx: &e::EncodeContext<'b, 'tcx>, + type_scheme: ty::TypeScheme<'tcx>) { use serialize::Encoder; - self.emit_struct("Polytype", 2, |this| { + self.emit_struct("TypeScheme", 2, |this| { this.emit_struct_field("generics", 0, |this| { this.emit_struct("Generics", 2, |this| { this.emit_struct_field("types", 0, |this| { Ok(encode_vec_per_param_space( - this, &pty.generics.types, + this, &type_scheme.generics.types, |this, def| this.emit_type_param_def(ecx, def))) }); this.emit_struct_field("regions", 1, |this| { Ok(encode_vec_per_param_space( - this, &pty.generics.regions, + this, &type_scheme.generics.regions, |this, def| def.encode(this).unwrap())) }); this.emit_struct_field("predicates", 2, |this| { Ok(encode_vec_per_param_space( - this, &pty.generics.predicates, + this, &type_scheme.generics.predicates, |this, def| this.emit_predicate(ecx, def))) }) }) }); this.emit_struct_field("ty", 1, |this| { - Ok(this.emit_ty(ecx, pty.ty)) + Ok(this.emit_ty(ecx, type_scheme.ty)) }) }); } @@ -1252,11 +1252,11 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext, } let lid = ast::DefId { krate: ast::LOCAL_CRATE, node: id }; - for &pty in tcx.tcache.borrow().get(&lid).iter() { + for &type_scheme in tcx.tcache.borrow().get(&lid).iter() { rbml_w.tag(c::tag_table_tcache, |rbml_w| { rbml_w.id(id); rbml_w.tag(c::tag_table_val, |rbml_w| { - rbml_w.emit_polytype(ecx, pty.clone()); + rbml_w.emit_type_scheme(ecx, type_scheme.clone()); }) }) } @@ -1369,8 +1369,8 @@ trait rbml_decoder_decoder_helpers<'tcx> { -> ty::TypeParameterDef<'tcx>; fn read_predicate<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>) -> ty::Predicate<'tcx>; - fn read_polytype<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>) - -> ty::Polytype<'tcx>; + fn read_type_scheme<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>) + -> ty::TypeScheme<'tcx>; fn read_existential_bounds<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>) -> ty::ExistentialBounds; fn read_substs<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>) @@ -1591,10 +1591,10 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> { }).unwrap() } - fn read_polytype<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>) - -> ty::Polytype<'tcx> { - self.read_struct("Polytype", 2, |this| { - Ok(ty::Polytype { + fn read_type_scheme<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>) + -> ty::TypeScheme<'tcx> { + self.read_struct("TypeScheme", 2, |this| { + Ok(ty::TypeScheme { generics: this.read_struct_field("generics", 0, |this| { this.read_struct("Generics", 2, |this| { Ok(ty::Generics { @@ -1939,9 +1939,9 @@ fn decode_side_tables(dcx: &DecodeContext, .insert(id, capture_mode); } c::tag_table_tcache => { - let pty = val_dsr.read_polytype(dcx); + let type_scheme = val_dsr.read_type_scheme(dcx); let lid = ast::DefId { krate: ast::LOCAL_CRATE, node: id }; - dcx.tcx.tcache.borrow_mut().insert(lid, pty); + dcx.tcx.tcache.borrow_mut().insert(lid, type_scheme); } c::tag_table_param_defs => { let bounds = val_dsr.read_type_param_def(dcx); diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index b3e9f85c69c78..c082c12da5bfa 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -695,7 +695,7 @@ pub struct ctxt<'tcx> { pub map: ast_map::Map<'tcx>, pub intrinsic_defs: RefCell>>, pub freevars: RefCell, - pub tcache: RefCell>>, + pub tcache: RefCell>>, pub rcache: RefCell>>, pub short_names_cache: RefCell, String>>, pub tc_cache: RefCell, TypeContents>>, @@ -2029,18 +2029,23 @@ impl<'tcx> ParameterEnvironment<'tcx> { } } -/// A polytype. +/// A "type scheme", in ML terminology, is a type combined with some +/// set of generic types that the type is, well, generic over. In Rust +/// terms, it is the "type" of a fn item or struct -- this type will +/// include various generic parameters that must be substituted when +/// the item/struct is referenced. That is called converting the type +/// scheme to a monotype. /// /// - `generics`: the set of type parameters and their bounds /// - `ty`: the base types, which may reference the parameters defined /// in `generics` #[deriving(Clone, Show)] -pub struct Polytype<'tcx> { +pub struct TypeScheme<'tcx> { pub generics: Generics<'tcx>, pub ty: Ty<'tcx> } -/// As `Polytype` but for a trait ref. +/// As `TypeScheme` but for a trait ref. pub struct TraitDef<'tcx> { pub unsafety: ast::Unsafety, @@ -5102,7 +5107,7 @@ pub fn enum_variant_with_id<'tcx>(cx: &ctxt<'tcx>, // the type cache. Returns the type parameters and type. pub fn lookup_item_type<'tcx>(cx: &ctxt<'tcx>, did: ast::DefId) - -> Polytype<'tcx> { + -> TypeScheme<'tcx> { lookup_locally_or_in_crate_store( "tcache", did, &mut *cx.tcache.borrow_mut(), || csearch::get_type(cx, did)) diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 3a383dd5a3b7c..ae8324d9a4f15 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -929,9 +929,9 @@ impl<'tcx> Repr<'tcx> for ast::DefId { } } -impl<'tcx> Repr<'tcx> for ty::Polytype<'tcx> { +impl<'tcx> Repr<'tcx> for ty::TypeScheme<'tcx> { fn repr(&self, tcx: &ctxt<'tcx>) -> String { - format!("Polytype {{generics: {}, ty: {}}}", + format!("TypeScheme {{generics: {}, ty: {}}}", self.generics.repr(tcx), self.ty.repr(tcx)) } diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs index dab4c0273d076..c0697c2a238df 100644 --- a/src/librustc_trans/trans/callee.rs +++ b/src/librustc_trans/trans/callee.rs @@ -514,8 +514,8 @@ pub fn trans_fn_ref_with_substs<'blk, 'tcx>( return val; } - // Polytype of the function item (may have type params) - let fn_tpt = ty::lookup_item_type(tcx, def_id); + // Type scheme of the function item (may have type params) + let fn_type_scheme = ty::lookup_item_type(tcx, def_id); // Find the actual function pointer. let mut val = { @@ -524,7 +524,7 @@ pub fn trans_fn_ref_with_substs<'blk, 'tcx>( get_item_val(ccx, def_id.node) } else { // External reference. - trans_external_path(ccx, def_id, fn_tpt.ty) + trans_external_path(ccx, def_id, fn_type_scheme.ty) } }; @@ -551,7 +551,7 @@ pub fn trans_fn_ref_with_substs<'blk, 'tcx>( // This can occur on either a crate-local or crate-external // reference. It also occurs when testing libcore and in some // other weird situations. Annoying. - let llty = type_of::type_of_fn_from_ty(ccx, fn_tpt.ty); + let llty = type_of::type_of_fn_from_ty(ccx, fn_type_scheme.ty); let llptrty = llty.ptr_to(); if val_ty(val) != llptrty { debug!("trans_fn_ref_with_vtables(): casting pointer!"); diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index d6f1f5fedc581..859cb88ea9a1c 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -16,11 +16,11 @@ //! somewhat differently during the collect and check phases, //! particularly with respect to looking up the types of top-level //! items. In the collect phase, the crate context is used as the -//! `AstConv` instance; in this phase, the `get_item_ty()` function +//! `AstConv` instance; in this phase, the `get_item_type_scheme()` function //! triggers a recursive call to `ty_of_item()` (note that //! `ast_ty_to_ty()` will detect recursive types and report an error). //! In the check phase, when the FnCtxt is used as the `AstConv`, -//! `get_item_ty()` just looks up the item type in `tcx.tcache`. +//! `get_item_type_scheme()` just looks up the item type in `tcx.tcache`. //! //! The `RegionScope` trait controls what happens when the user does //! not specify a region in some location where a region is required @@ -70,7 +70,7 @@ use syntax::print::pprust; pub trait AstConv<'tcx> { fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx>; - fn get_item_ty(&self, id: ast::DefId) -> ty::Polytype<'tcx>; + fn get_item_type_scheme(&self, id: ast::DefId) -> ty::TypeScheme<'tcx>; fn get_trait_def(&self, id: ast::DefId) -> Rc>; /// Return an (optional) substitution to convert bound type parameters that @@ -650,10 +650,10 @@ pub fn ast_path_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( -> TypeAndSubsts<'tcx> { let tcx = this.tcx(); - let ty::Polytype { + let ty::TypeScheme { generics, ty: decl_ty - } = this.get_item_ty(did); + } = this.get_item_type_scheme(did); let substs = ast_path_substs_for_ty(this, rscope, @@ -678,10 +678,10 @@ pub fn ast_path_to_ty_relaxed<'tcx,AC,RS>( where AC : AstConv<'tcx>, RS : RegionScope { let tcx = this.tcx(); - let ty::Polytype { + let ty::TypeScheme { generics, ty: decl_ty - } = this.get_item_ty(did); + } = this.get_item_type_scheme(did); let wants_params = generics.has_type_params(TypeSpace) || generics.has_region_params(TypeSpace); diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 09a5dd521f882..4fbae63780068 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -79,9 +79,9 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, } ast::PatEnum(..) | ast::PatIdent(..) if pat_is_const(&tcx.def_map, pat) => { let const_did = tcx.def_map.borrow()[pat.id].clone().def_id(); - let const_pty = ty::lookup_item_type(tcx, const_did); - fcx.write_ty(pat.id, const_pty.ty); - demand::suptype(fcx, pat.span, expected, const_pty.ty); + let const_scheme = ty::lookup_item_type(tcx, const_did); + fcx.write_ty(pat.id, const_scheme.ty); + demand::suptype(fcx, pat.span, expected, const_scheme.ty); } ast::PatIdent(bm, ref path, ref sub) if pat_is_binding(&tcx.def_map, pat) => { let typ = fcx.local_ty(pat.span, pat.id); @@ -395,16 +395,16 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &ast::Pat, let enum_def = def.variant_def_ids() .map_or_else(|| def.def_id(), |(enum_def, _)| enum_def); - let ctor_pty = ty::lookup_item_type(tcx, enum_def); - let path_ty = if ty::is_fn_ty(ctor_pty.ty) { - ty::Polytype { - ty: ty::ty_fn_ret(ctor_pty.ty).unwrap(), - ..ctor_pty + let ctor_scheme = ty::lookup_item_type(tcx, enum_def); + let path_scheme = if ty::is_fn_ty(ctor_scheme.ty) { + ty::TypeScheme { + ty: ty::ty_fn_ret(ctor_scheme.ty).unwrap(), + ..ctor_scheme } } else { - ctor_pty + ctor_scheme }; - instantiate_path(pcx.fcx, path, path_ty, def, pat.span, pat.id); + instantiate_path(pcx.fcx, path, path_scheme, def, pat.span, pat.id); let pat_ty = fcx.node_ty(pat.id); demand::eqtype(fcx, pat.span, expected, pat_ty); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index dfa41c2707e8e..bb1b24f4b487a 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -91,7 +91,7 @@ use middle::pat_util::{mod, pat_id_map}; use middle::region::CodeExtent; use middle::subst::{mod, Subst, Substs, VecPerParamSpace, ParamSpace}; use middle::traits; -use middle::ty::{FnSig, VariantInfo, Polytype}; +use middle::ty::{FnSig, VariantInfo, TypeScheme}; use middle::ty::{Disr, ParamTy, ParameterEnvironment}; use middle::ty::{mod, Ty}; use middle::ty::liberate_late_bound_regions; @@ -1510,7 +1510,7 @@ fn check_cast(fcx: &FnCtxt, impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> { fn tcx(&self) -> &ty::ctxt<'tcx> { self.ccx.tcx } - fn get_item_ty(&self, id: ast::DefId) -> ty::Polytype<'tcx> { + fn get_item_type_scheme(&self, id: ast::DefId) -> ty::TypeScheme<'tcx> { ty::lookup_item_type(self.tcx(), id) } @@ -1739,14 +1739,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { def_id: ast::DefId) -> TypeAndSubsts<'tcx> { - let polytype = + let type_scheme = ty::lookup_item_type(self.tcx(), def_id); let substs = self.infcx().fresh_substs_for_generics( span, - &polytype.generics); + &type_scheme.generics); let bounds = - polytype.generics.to_bounds(self.tcx(), &substs); + type_scheme.generics.to_bounds(self.tcx(), &substs); self.add_obligations_for_parameters( traits::ObligationCause::new( span, @@ -1754,7 +1754,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { traits::ItemObligation(def_id)), &bounds); let monotype = - polytype.ty.subst(self.tcx(), &substs); + type_scheme.ty.subst(self.tcx(), &substs); TypeAndSubsts { ty: monotype, @@ -3829,7 +3829,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, } ast::ExprPath(ref pth) => { let defn = lookup_def(fcx, pth.span, id); - let pty = polytype_for_def(fcx, expr.span, defn); + let pty = type_scheme_for_def(fcx, expr.span, defn); instantiate_path(fcx, pth, pty, defn, expr.span, expr.id); // We always require that the type provided as the value for @@ -4922,10 +4922,10 @@ pub fn lookup_def(fcx: &FnCtxt, sp: Span, id: ast::NodeId) -> def::Def { } // Returns the type parameter count and the type for the given definition. -pub fn polytype_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, - sp: Span, - defn: def::Def) - -> Polytype<'tcx> { +pub fn type_scheme_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, + sp: Span, + defn: def::Def) + -> TypeScheme<'tcx> { match defn { def::DefLocal(nid) | def::DefUpvar(nid, _, _) => { let typ = fcx.local_ty(sp, nid); @@ -4969,15 +4969,15 @@ pub fn polytype_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, // number of type parameters and type. pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, path: &ast::Path, - polytype: Polytype<'tcx>, + type_scheme: TypeScheme<'tcx>, def: def::Def, span: Span, node_id: ast::NodeId) { - debug!("instantiate_path(path={}, def={}, node_id={}, polytype={})", + debug!("instantiate_path(path={}, def={}, node_id={}, type_scheme={})", path.repr(fcx.tcx()), def.repr(fcx.tcx()), node_id, - polytype.repr(fcx.tcx())); + type_scheme.repr(fcx.tcx())); // We need to extract the type parameters supplied by the user in // the path `path`. Due to the current setup, this is a bit of a @@ -5102,8 +5102,8 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, // Next, examine the definition, and determine how many type // parameters we expect from each space. - let type_defs = &polytype.generics.types; - let region_defs = &polytype.generics.regions; + let type_defs = &type_scheme.generics.types; + let region_defs = &type_scheme.generics.regions; // Now that we have categorized what space the parameters for each // segment belong to, let's sort out the parameters that the user @@ -5151,12 +5151,12 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, // the fn itself). Those should be replaced with fresh variables // now. These can appear either on the type being referenced, or // on the associated bounds. - let bounds = polytype.generics.to_bounds(fcx.tcx(), &substs); + let bounds = type_scheme.generics.to_bounds(fcx.tcx(), &substs); let (ty_late_bound, bounds) = fcx.infcx().replace_late_bound_regions_with_fresh_var( span, infer::FnCall, - &ty::Binder((polytype.ty, bounds))).0; + &ty::Binder((type_scheme.ty, bounds))).0; debug!("after late-bounds have been replaced: ty_late_bound={}", ty_late_bound.repr(fcx.tcx())); debug!("after late-bounds have been replaced: bounds={}", bounds.repr(fcx.tcx())); diff --git a/src/librustc_typeck/check/wf.rs b/src/librustc_typeck/check/wf.rs index 258177bb72096..3ddc81d40a5da 100644 --- a/src/librustc_typeck/check/wf.rs +++ b/src/librustc_typeck/check/wf.rs @@ -147,8 +147,8 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { item.span, region::CodeExtent::from_node_id(item.id), Some(&mut this.cache)); - let polytype = ty::lookup_item_type(fcx.tcx(), local_def(item.id)); - let item_ty = polytype.ty.subst(fcx.tcx(), &fcx.inh.param_env.free_substs); + let type_scheme = ty::lookup_item_type(fcx.tcx(), local_def(item.id)); + let item_ty = type_scheme.ty.subst(fcx.tcx(), &fcx.inh.param_env.free_substs); bounds_checker.check_traits_in_ty(item_ty); }); } @@ -313,14 +313,14 @@ impl<'cx,'tcx> TypeFolder<'tcx> for BoundsChecker<'cx,'tcx> { match t.sty{ ty::ty_struct(type_id, substs) | ty::ty_enum(type_id, substs) => { - let polytype = ty::lookup_item_type(self.fcx.tcx(), type_id); + let type_scheme = ty::lookup_item_type(self.fcx.tcx(), type_id); if self.binding_count == 0 { self.fcx.add_obligations_for_parameters( traits::ObligationCause::new(self.span, self.fcx.body_id, traits::ItemObligation(type_id)), - &polytype.generics.to_bounds(self.tcx(), substs)); + &type_scheme.generics.to_bounds(self.tcx(), substs)); } else { // There are two circumstances in which we ignore // region obligations. @@ -344,7 +344,7 @@ impl<'cx,'tcx> TypeFolder<'tcx> for BoundsChecker<'cx,'tcx> { // // (I believe we should do the same for traits, but // that will require an RFC. -nmatsakis) - let bounds = polytype.generics.to_bounds(self.tcx(), substs); + let bounds = type_scheme.generics.to_bounds(self.tcx(), substs); let bounds = filter_to_trait_obligations(bounds); self.fcx.add_obligations_for_parameters( traits::ObligationCause::new(self.span, diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index f92c7764a69b0..30039f2ecc1cf 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -23,7 +23,7 @@ use middle::ty::RegionEscape; use middle::ty::{ImplContainer, ImplOrTraitItemId, MethodTraitItemId}; use middle::ty::{ParameterEnvironment, TypeTraitItemId, lookup_item_type}; use middle::ty::{Ty, ty_bool, ty_char, ty_closure, ty_enum, ty_err}; -use middle::ty::{ty_param, Polytype, ty_ptr}; +use middle::ty::{ty_param, TypeScheme, ty_ptr}; use middle::ty::{ty_rptr, ty_struct, ty_trait, ty_tup}; use middle::ty::{ty_str, ty_vec, ty_float, ty_infer, ty_int, ty_open}; use middle::ty::{ty_uint, ty_unboxed_closure, ty_uniq, ty_bare_fn}; @@ -206,7 +206,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> { debug!("instantiate_default_methods(impl_id={}, trait_ref={})", impl_id, trait_ref.repr(tcx)); - let impl_poly_type = ty::lookup_item_type(tcx, impl_id); + let impl_type_scheme = ty::lookup_item_type(tcx, impl_id); let prov = ty::provided_trait_methods(tcx, trait_ref.def_id); for trait_method in prov.iter() { @@ -221,7 +221,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> { Rc::new(subst_receiver_types_in_method_ty( tcx, impl_id, - &impl_poly_type, + &impl_type_scheme, trait_ref, new_did, &**trait_method, @@ -233,7 +233,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> { // construct the polytype for the method based on the // method_ty. it will have all the generics from the // impl, plus its own. - let new_polytype = ty::Polytype { + let new_polytype = ty::TypeScheme { generics: new_method_ty.generics.clone(), ty: ty::mk_bare_fn(tcx, Some(new_did), tcx.mk_bare_fn(new_method_ty.fty.clone())) @@ -275,7 +275,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> { } fn get_self_type_for_implementation(&self, impl_did: DefId) - -> Polytype<'tcx> { + -> TypeScheme<'tcx> { self.crate_context.tcx.tcache.borrow()[impl_did].clone() } @@ -535,7 +535,7 @@ fn enforce_trait_manually_implementable(tcx: &ty::ctxt, sp: Span, trait_def_id: fn subst_receiver_types_in_method_ty<'tcx>(tcx: &ty::ctxt<'tcx>, impl_id: ast::DefId, - impl_poly_type: &ty::Polytype<'tcx>, + impl_type_scheme: &ty::TypeScheme<'tcx>, trait_ref: &ty::TraitRef<'tcx>, new_def_id: ast::DefId, method: &ty::Method<'tcx>, @@ -554,10 +554,10 @@ fn subst_receiver_types_in_method_ty<'tcx>(tcx: &ty::ctxt<'tcx>, for &space in [subst::TypeSpace, subst::SelfSpace].iter() { method_generics.types.replace( space, - impl_poly_type.generics.types.get_slice(space).to_vec()); + impl_type_scheme.generics.types.get_slice(space).to_vec()); method_generics.regions.replace( space, - impl_poly_type.generics.regions.get_slice(space).to_vec()); + impl_type_scheme.generics.regions.get_slice(space).to_vec()); } debug!("subst_receiver_types_in_method_ty: method_generics={}", diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 8d07f1e435503..74cfbb117e9a3 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -23,8 +23,8 @@ Unlike most of the types that are present in Rust, the types computed for each item are in fact polytypes. In "layman's terms", this means that they are generic types that may have type parameters (more mathematically phrased, they are universally quantified over a set of -type parameters). Polytypes are represented by an instance of -`ty::Polytype`. This combines the core type along with a list of the +type parameters). TypeSchemes are represented by an instance of +`ty::TypeScheme`. This combines the core type along with a list of the bounds for each parameter. Type parameters themselves are represented as `ty_param()` instances. @@ -43,7 +43,7 @@ use middle::resolve_lifetime; use middle::subst; use middle::subst::{Substs}; use middle::ty::{AsPredicate, ImplContainer, ImplOrTraitItemContainer, TraitContainer}; -use middle::ty::{mod, RegionEscape, Ty, Polytype}; +use middle::ty::{mod, RegionEscape, Ty, TypeScheme}; use middle::ty_fold::{mod, TypeFolder, TypeFoldable}; use middle::infer; use rscope::*; @@ -70,8 +70,8 @@ use syntax::visit; pub fn collect_item_types(ccx: &CrateCtxt) { fn collect_intrinsic_type(ccx: &CrateCtxt, lang_item: ast::DefId) { - let ty::Polytype { ty, .. } = - ccx.get_item_ty(lang_item); + let ty::TypeScheme { ty, .. } = + ccx.get_item_type_scheme(lang_item); ccx.tcx.intrinsic_defs.borrow_mut().insert(lang_item, ty); } @@ -154,7 +154,7 @@ impl<'a,'tcx> ToTy<'tcx> for CrateCtxt<'a,'tcx> { impl<'a, 'tcx> AstConv<'tcx> for CrateCtxt<'a, 'tcx> { fn tcx(&self) -> &ty::ctxt<'tcx> { self.tcx } - fn get_item_ty(&self, id: ast::DefId) -> ty::Polytype<'tcx> { + fn get_item_type_scheme(&self, id: ast::DefId) -> ty::TypeScheme<'tcx> { if id.krate != ast::LOCAL_CRATE { return csearch::get_type(self.tcx, id) } @@ -170,8 +170,8 @@ impl<'a, 'tcx> AstConv<'tcx> for CrateCtxt<'a, 'tcx> { } x => { self.tcx.sess.bug(format!("unexpected sort of node \ - in get_item_ty(): {}", - x)[]); + in get_item_type_scheme(): {}", + x).as_slice()); } } } @@ -227,7 +227,7 @@ pub fn get_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, } ast::StructVariantKind(ref struct_def) => { - let pty = Polytype { + let scheme = TypeScheme { generics: ty_generics_for_type_or_impl( ccx, generics, @@ -235,12 +235,12 @@ pub fn get_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, ty: enum_ty }; - convert_struct(ccx, &**struct_def, pty, variant.node.id); + convert_struct(ccx, &**struct_def, scheme, variant.node.id); enum_ty } }; - let pty = Polytype { + let scheme = TypeScheme { generics: ty_generics_for_type_or_impl( ccx, generics, @@ -248,7 +248,7 @@ pub fn get_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, ty: result_ty }; - tcx.tcache.borrow_mut().insert(variant_def_id, pty); + tcx.tcache.borrow_mut().insert(variant_def_id, scheme); write_ty_to_tcx(tcx, variant.node.id, result_ty); } @@ -353,7 +353,7 @@ fn collect_trait_methods<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, fn make_method_ty<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, m: &ty::Method<'tcx>) { ccx.tcx.tcache.borrow_mut().insert( m.def_id, - Polytype { + TypeScheme { generics: m.generics.clone(), ty: ty::mk_bare_fn(ccx.tcx, Some(m.def_id), ccx.tcx.mk_bare_fn(m.fty.clone())) }); } @@ -416,7 +416,7 @@ pub fn convert_field<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, write_ty_to_tcx(ccx.tcx, v.node.id, tt); /* add the field to the tcache */ ccx.tcx.tcache.borrow_mut().insert(local_def(v.node.id), - ty::Polytype { + ty::TypeScheme { generics: struct_generics.clone(), ty: tt }); @@ -536,7 +536,7 @@ fn convert_methods<'a,'tcx,'i,I>(ccx: &CrateCtxt<'a, 'tcx>, fty.repr(tcx)); tcx.tcache.borrow_mut().insert( m_def_id, - Polytype { + TypeScheme { generics: mty.generics.clone(), ty: fty }); @@ -1034,11 +1034,11 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) { // These don't define types. ast::ItemForeignMod(_) | ast::ItemMod(_) | ast::ItemMac(_) => {} ast::ItemEnum(ref enum_definition, ref generics) => { - let pty = ty_of_item(ccx, it); - write_ty_to_tcx(tcx, it.id, pty.ty); + let scheme = ty_of_item(ccx, it); + write_ty_to_tcx(tcx, it.id, scheme.ty); get_enum_variant_types(ccx, - pty.ty, - enum_definition.variants[], + scheme.ty, + enum_definition.variants.as_slice(), generics); }, ast::ItemImpl(_, @@ -1058,7 +1058,7 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) { tcx.tcache .borrow_mut() .insert(local_def(it.id), - Polytype { + TypeScheme { generics: ty_generics.clone(), ty: selfty, }); @@ -1105,7 +1105,7 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) { tcx.tcache .borrow_mut() .insert(local_def(typedef.id), - Polytype { + TypeScheme { generics: ty::Generics::empty(), ty: typ, }); @@ -1202,12 +1202,12 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) { }, ast::ItemStruct(ref struct_def, _) => { // Write the class type. - let pty = ty_of_item(ccx, it); - write_ty_to_tcx(tcx, it.id, pty.ty); + let scheme = ty_of_item(ccx, it); + write_ty_to_tcx(tcx, it.id, scheme.ty); - tcx.tcache.borrow_mut().insert(local_def(it.id), pty.clone()); + tcx.tcache.borrow_mut().insert(local_def(it.id), scheme.clone()); - convert_struct(ccx, &**struct_def, pty, it.id); + convert_struct(ccx, &**struct_def, scheme, it.id); }, ast::ItemTy(_, ref generics) => { ensure_no_ty_param_bounds(ccx, it.span, generics, "type"); @@ -1218,22 +1218,22 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) { // This call populates the type cache with the converted type // of the item in passing. All we have to do here is to write // it into the node type table. - let pty = ty_of_item(ccx, it); - write_ty_to_tcx(tcx, it.id, pty.ty); + let scheme = ty_of_item(ccx, it); + write_ty_to_tcx(tcx, it.id, scheme.ty); }, } } pub fn convert_struct<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, struct_def: &ast::StructDef, - pty: ty::Polytype<'tcx>, + scheme: ty::TypeScheme<'tcx>, id: ast::NodeId) { let tcx = ccx.tcx; // Write the type of each of the members and check for duplicate fields. let mut seen_fields: FnvHashMap = FnvHashMap::new(); let field_tys = struct_def.fields.iter().map(|f| { - let result = convert_field(ccx, &pty.generics, f, local_def(id)); + let result = convert_field(ccx, &scheme.generics, f, local_def(id)); if result.name != special_idents::unnamed_field.name { let dup = match seen_fields.get(&result.name) { @@ -1258,7 +1258,7 @@ pub fn convert_struct<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, tcx.struct_fields.borrow_mut().insert(local_def(id), Rc::new(field_tys)); - let substs = mk_item_substs(ccx, &pty.generics); + let substs = mk_item_substs(ccx, &scheme.generics); let selfty = ty::mk_struct(tcx, local_def(id), tcx.mk_substs(substs)); // If this struct is enum-like or tuple-like, create the type of its @@ -1270,7 +1270,7 @@ pub fn convert_struct<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, // Enum-like. write_ty_to_tcx(tcx, ctor_id, selfty); - tcx.tcache.borrow_mut().insert(local_def(ctor_id), pty); + tcx.tcache.borrow_mut().insert(local_def(ctor_id), scheme); } else if struct_def.fields[0].node.kind.is_unnamed() { // Tuple-like. let inputs: Vec<_> = struct_def.fields.iter().map( @@ -1282,8 +1282,8 @@ pub fn convert_struct<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, selfty); write_ty_to_tcx(tcx, ctor_id, ctor_fn_ty); tcx.tcache.borrow_mut().insert(local_def(ctor_id), - Polytype { - generics: pty.generics, + TypeScheme { + generics: scheme.generics, ty: ctor_fn_ty }); } @@ -1302,10 +1302,10 @@ pub fn convert_foreign(ccx: &CrateCtxt, i: &ast::ForeignItem) { // convenient way to extract the ABI. - ndm let abi = ccx.tcx.map.get_foreign_abi(i.id); - let pty = ty_of_foreign_item(ccx, i, abi); - write_ty_to_tcx(ccx.tcx, i.id, pty.ty); + let scheme = ty_of_foreign_item(ccx, i, abi); + write_ty_to_tcx(ccx.tcx, i.id, scheme.ty); - ccx.tcx.tcache.borrow_mut().insert(local_def(i.id), pty); + ccx.tcx.tcache.borrow_mut().insert(local_def(i.id), scheme); } fn get_trait_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, @@ -1429,19 +1429,19 @@ pub fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, } pub fn ty_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &ast::Item) - -> ty::Polytype<'tcx> { + -> ty::TypeScheme<'tcx> { let def_id = local_def(it.id); let tcx = ccx.tcx; - if let Some(pty) = tcx.tcache.borrow().get(&def_id) { - return pty.clone(); + if let Some(scheme) = tcx.tcache.borrow().get(&def_id) { + return scheme.clone(); } match it.node { ast::ItemStatic(ref t, _, _) | ast::ItemConst(ref t, _) => { let typ = ccx.to_ty(&ExplicitRscope, &**t); - let pty = no_params(typ); + let scheme = no_params(typ); - tcx.tcache.borrow_mut().insert(local_def(it.id), pty.clone()); - return pty; + tcx.tcache.borrow_mut().insert(local_def(it.id), scheme.clone()); + return scheme; } ast::ItemFn(ref decl, unsafety, abi, ref generics, _) => { let ty_generics = ty_generics_for_fn_or_method( @@ -1456,27 +1456,27 @@ pub fn ty_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &ast::Item) }; astconv::ty_of_bare_fn(&fcx, unsafety, abi, &**decl) }; - let pty = Polytype { + let scheme = TypeScheme { generics: ty_generics, ty: ty::mk_bare_fn(ccx.tcx, Some(local_def(it.id)), ccx.tcx.mk_bare_fn(tofd)) }; debug!("type of {} (id {}) is {}", token::get_ident(it.ident), it.id, - pty.repr(tcx)); + scheme.repr(tcx)); - ccx.tcx.tcache.borrow_mut().insert(local_def(it.id), pty.clone()); - return pty; + ccx.tcx.tcache.borrow_mut().insert(local_def(it.id), scheme.clone()); + return scheme; } ast::ItemTy(ref t, ref generics) => { match tcx.tcache.borrow_mut().get(&local_def(it.id)) { - Some(pty) => return pty.clone(), + Some(scheme) => return scheme.clone(), None => { } } - let pty = { + let scheme = { let ty = ccx.to_ty(&ExplicitRscope, &**t); - Polytype { + TypeScheme { generics: ty_generics_for_type_or_impl( ccx, generics, @@ -1485,8 +1485,8 @@ pub fn ty_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &ast::Item) } }; - tcx.tcache.borrow_mut().insert(local_def(it.id), pty.clone()); - return pty; + tcx.tcache.borrow_mut().insert(local_def(it.id), scheme.clone()); + return scheme; } ast::ItemEnum(_, ref generics) => { // Create a new generic polytype. @@ -1496,13 +1496,13 @@ pub fn ty_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &ast::Item) DontCreateTypeParametersForAssociatedTypes); let substs = mk_item_substs(ccx, &ty_generics); let t = ty::mk_enum(tcx, local_def(it.id), tcx.mk_substs(substs)); - let pty = Polytype { + let scheme = TypeScheme { generics: ty_generics, ty: t }; - tcx.tcache.borrow_mut().insert(local_def(it.id), pty.clone()); - return pty; + tcx.tcache.borrow_mut().insert(local_def(it.id), scheme.clone()); + return scheme; } ast::ItemTrait(..) => { tcx.sess.span_bug(it.span, "invoked ty_of_item on trait"); @@ -1514,13 +1514,13 @@ pub fn ty_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &ast::Item) DontCreateTypeParametersForAssociatedTypes); let substs = mk_item_substs(ccx, &ty_generics); let t = ty::mk_struct(tcx, local_def(it.id), tcx.mk_substs(substs)); - let pty = Polytype { + let scheme = TypeScheme { generics: ty_generics, ty: t }; - tcx.tcache.borrow_mut().insert(local_def(it.id), pty.clone()); - return pty; + tcx.tcache.borrow_mut().insert(local_def(it.id), scheme.clone()); + return scheme; } ast::ItemImpl(..) | ast::ItemMod(_) | ast::ItemForeignMod(_) | ast::ItemMac(_) => panic!(), @@ -1529,7 +1529,7 @@ pub fn ty_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &ast::Item) pub fn ty_of_foreign_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &ast::ForeignItem, - abi: abi::Abi) -> ty::Polytype<'tcx> + abi: abi::Abi) -> ty::TypeScheme<'tcx> { match it.node { ast::ForeignItemFn(ref fn_decl, ref generics) => { @@ -1540,7 +1540,7 @@ pub fn ty_of_foreign_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, abi) } ast::ForeignItemStatic(ref t, _) => { - ty::Polytype { + ty::TypeScheme { generics: ty::Generics::empty(), ty: ast_ty_to_ty(ccx, &ExplicitRscope, &**t) } @@ -2107,7 +2107,7 @@ pub fn ty_of_foreign_fn_decl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, def_id: ast::DefId, ast_generics: &ast::Generics, abi: abi::Abi) - -> ty::Polytype<'tcx> { + -> ty::TypeScheme<'tcx> { for i in decl.inputs.iter() { match (*i).pat.node { ast::PatIdent(_, _, _) => (), @@ -2144,16 +2144,16 @@ pub fn ty_of_foreign_fn_decl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, abi: abi, unsafety: ast::Unsafety::Unsafe, sig: ty::Binder(ty::FnSig {inputs: input_tys, - output: output, - variadic: decl.variadic}) - })); - let pty = Polytype { + output: output, + variadic: decl.variadic}), + }); + let scheme = TypeScheme { generics: ty_generics_for_fn_or_method, ty: t_fn }; - ccx.tcx.tcache.borrow_mut().insert(def_id, pty.clone()); - return pty; + ccx.tcx.tcache.borrow_mut().insert(def_id, scheme.clone()); + return scheme; } pub fn mk_item_substs<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 3418cded022c9..a903c8b0d55aa 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -159,8 +159,8 @@ fn lookup_def_ccx(ccx: &CrateCtxt, sp: Span, id: ast::NodeId) lookup_def_tcx(ccx.tcx, sp, id) } -fn no_params<'tcx>(t: Ty<'tcx>) -> ty::Polytype<'tcx> { - ty::Polytype { +fn no_params<'tcx>(t: Ty<'tcx>) -> ty::TypeScheme<'tcx> { + ty::TypeScheme { generics: ty::Generics { types: VecPerParamSpace::empty(), regions: VecPerParamSpace::empty(), From f95bb55a1c4cb258ac8e6adde99cf1aadc5d776b Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 25 Dec 2014 07:20:48 -0500 Subject: [PATCH 07/36] Move the scalar types out of static data so that we can put `Rc` into sty. --- src/librustc/metadata/tydecode.rs | 63 ++-- src/librustc/middle/astconv_util.rs | 10 +- src/librustc/middle/infer/combine.rs | 14 +- src/librustc/middle/infer/mod.rs | 8 +- src/librustc/middle/infer/resolve.rs | 6 +- src/librustc/middle/infer/sub.rs | 2 +- src/librustc/middle/infer/unify.rs | 14 +- src/librustc/middle/intrinsicck.rs | 4 +- src/librustc/middle/mem_categorization.rs | 8 +- src/librustc/middle/traits/select.rs | 5 +- src/librustc/middle/ty.rs | 165 +++++----- src/librustc_driver/test.rs | 103 +++--- src/librustc_trans/trans/_match.rs | 2 +- src/librustc_trans/trans/adt.rs | 29 +- src/librustc_trans/trans/base.rs | 4 +- src/librustc_trans/trans/cleanup.rs | 2 +- src/librustc_trans/trans/closure.rs | 4 +- src/librustc_trans/trans/debuginfo.rs | 13 +- src/librustc_trans/trans/glue.rs | 6 +- src/librustc_typeck/astconv.rs | 8 +- src/librustc_typeck/check/_match.rs | 22 +- src/librustc_typeck/check/method/confirm.rs | 4 +- src/librustc_typeck/check/mod.rs | 342 +++++++++++--------- src/librustc_typeck/check/vtable.rs | 3 +- src/librustc_typeck/check/writeback.rs | 4 +- src/librustc_typeck/collect.rs | 2 +- src/librustc_typeck/lib.rs | 8 +- 27 files changed, 464 insertions(+), 391 deletions(-) diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs index 9b008f36a9646..01cde5138c533 100644 --- a/src/librustc/metadata/tydecode.rs +++ b/src/librustc/metadata/tydecode.rs @@ -384,39 +384,40 @@ fn parse_trait_ref<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did) } fn parse_ty<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did) -> Ty<'tcx> { + let tcx = st.tcx; match next(st) { - 'b' => return ty::mk_bool(), - 'i' => return ty::mk_int(), - 'u' => return ty::mk_uint(), + 'b' => return tcx.types.bool, + 'i' => return tcx.types.int, + 'u' => return tcx.types.uint, 'M' => { match next(st) { - 'b' => return ty::mk_mach_uint(ast::TyU8), - 'w' => return ty::mk_mach_uint(ast::TyU16), - 'l' => return ty::mk_mach_uint(ast::TyU32), - 'd' => return ty::mk_mach_uint(ast::TyU64), - 'B' => return ty::mk_mach_int(ast::TyI8), - 'W' => return ty::mk_mach_int(ast::TyI16), - 'L' => return ty::mk_mach_int(ast::TyI32), - 'D' => return ty::mk_mach_int(ast::TyI64), - 'f' => return ty::mk_mach_float(ast::TyF32), - 'F' => return ty::mk_mach_float(ast::TyF64), + 'b' => return tcx.types.u8, + 'w' => return tcx.types.u16, + 'l' => return tcx.types.u32, + 'd' => return tcx.types.u64, + 'B' => return tcx.types.i8, + 'W' => return tcx.types.i16, + 'L' => return tcx.types.i32, + 'D' => return tcx.types.i64, + 'f' => return tcx.types.f32, + 'F' => return tcx.types.f64, _ => panic!("parse_ty: bad numeric type") } } - 'c' => return ty::mk_char(), + 'c' => return tcx.types.char, 't' => { assert_eq!(next(st), '['); let def = parse_def(st, NominalType, |x,y| conv(x,y)); let substs = parse_substs(st, |x,y| conv(x,y)); assert_eq!(next(st), ']'); - return ty::mk_enum(st.tcx, def, st.tcx.mk_substs(substs)); + return ty::mk_enum(tcx, def, st.tcx.mk_substs(substs)); } 'x' => { assert_eq!(next(st), '['); let trait_ref = ty::Binder(parse_trait_ref(st, |x,y| conv(x,y))); let bounds = parse_existential_bounds(st, |x,y| conv(x,y)); assert_eq!(next(st), ']'); - return ty::mk_trait(st.tcx, trait_ref, bounds); + return ty::mk_trait(tcx, trait_ref, bounds); } 'p' => { let did = parse_def(st, TypeParameter, |x,y| conv(x,y)); @@ -425,41 +426,41 @@ fn parse_ty<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did) -> Ty<'tcx> { assert_eq!(next(st), '|'); let space = parse_param_space(st); assert_eq!(next(st), '|'); - return ty::mk_param(st.tcx, space, index, did); + return ty::mk_param(tcx, space, index, did); } - '~' => return ty::mk_uniq(st.tcx, parse_ty(st, |x,y| conv(x,y))), - '*' => return ty::mk_ptr(st.tcx, parse_mt(st, |x,y| conv(x,y))), + '~' => return ty::mk_uniq(tcx, parse_ty(st, |x,y| conv(x,y))), + '*' => return ty::mk_ptr(tcx, parse_mt(st, |x,y| conv(x,y))), '&' => { let r = parse_region(st, |x,y| conv(x,y)); let mt = parse_mt(st, |x,y| conv(x,y)); - return ty::mk_rptr(st.tcx, st.tcx.mk_region(r), mt); + return ty::mk_rptr(tcx, tcx.mk_region(r), mt); } 'V' => { let t = parse_ty(st, |x,y| conv(x,y)); let sz = parse_size(st); - return ty::mk_vec(st.tcx, t, sz); + return ty::mk_vec(tcx, t, sz); } 'v' => { - return ty::mk_str(st.tcx); + return ty::mk_str(tcx); } 'T' => { assert_eq!(next(st), '['); let mut params = Vec::new(); while peek(st) != ']' { params.push(parse_ty(st, |x,y| conv(x,y))); } st.pos = st.pos + 1u; - return ty::mk_tup(st.tcx, params); + return ty::mk_tup(tcx, params); } 'f' => { - return ty::mk_closure(st.tcx, parse_closure_ty(st, |x,y| conv(x,y))); + return ty::mk_closure(tcx, parse_closure_ty(st, |x,y| conv(x,y))); } 'F' => { let def_id = parse_def(st, NominalType, |x,y| conv(x,y)); - return ty::mk_bare_fn(st.tcx, Some(def_id), - st.tcx.mk_bare_fn(parse_bare_fn_ty(st, |x,y| conv(x,y)))); + return ty::mk_bare_fn(tcx, Some(def_id), + tcx.mk_bare_fn(parse_bare_fn_ty(st, |x,y| conv(x,y)))); } 'G' => { - return ty::mk_bare_fn(st.tcx, None, - st.tcx.mk_bare_fn(parse_bare_fn_ty(st, |x,y| conv(x,y)))); + return ty::mk_bare_fn(tcx, None, + tcx.mk_bare_fn(parse_bare_fn_ty(st, |x,y| conv(x,y)))); } '#' => { let pos = parse_hex(st); @@ -470,7 +471,7 @@ fn parse_ty<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did) -> Ty<'tcx> { pos: pos, len: len }; - match st.tcx.rcache.borrow().get(&key).cloned() { + match tcx.rcache.borrow().get(&key).cloned() { Some(tt) => return tt, None => {} } @@ -479,7 +480,7 @@ fn parse_ty<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did) -> Ty<'tcx> { .. *st }; let tt = parse_ty(&mut ps, |x,y| conv(x,y)); - st.tcx.rcache.borrow_mut().insert(key, tt); + tcx.rcache.borrow_mut().insert(key, tt); return tt; } '\"' => { @@ -504,7 +505,7 @@ fn parse_ty<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did) -> Ty<'tcx> { st.tcx.mk_region(region), st.tcx.mk_substs(substs)); } 'e' => { - return ty::mk_err(); + return tcx.types.err; } c => { panic!("unexpected char in type string: {}", c);} } diff --git a/src/librustc/middle/astconv_util.rs b/src/librustc/middle/astconv_util.rs index 060e2f67faf98..b1b4fd831a0fa 100644 --- a/src/librustc/middle/astconv_util.rs +++ b/src/librustc/middle/astconv_util.rs @@ -57,23 +57,23 @@ pub fn ast_ty_to_prim_ty<'tcx>(tcx: &ty::ctxt<'tcx>, ast_ty: &ast::Ty) match nty { ast::TyBool => { check_path_args(tcx, path, NO_TPS | NO_REGIONS); - Some(ty::mk_bool()) + Some(tcx.types.bool) } ast::TyChar => { check_path_args(tcx, path, NO_TPS | NO_REGIONS); - Some(ty::mk_char()) + Some(tcx.types.char) } ast::TyInt(it) => { check_path_args(tcx, path, NO_TPS | NO_REGIONS); - Some(ty::mk_mach_int(it)) + Some(ty::mk_mach_int(tcx, it)) } ast::TyUint(uit) => { check_path_args(tcx, path, NO_TPS | NO_REGIONS); - Some(ty::mk_mach_uint(uit)) + Some(ty::mk_mach_uint(tcx, uit)) } ast::TyFloat(ft) => { check_path_args(tcx, path, NO_TPS | NO_REGIONS); - Some(ty::mk_mach_float(ft)) + Some(ty::mk_mach_float(tcx, ft)) } ast::TyStr => { Some(ty::mk_str(tcx)) diff --git a/src/librustc/middle/infer/combine.rs b/src/librustc/middle/infer/combine.rs index 04ae0a5a60432..9f5eca142c36c 100644 --- a/src/librustc/middle/infer/combine.rs +++ b/src/librustc/middle/infer/combine.rs @@ -397,8 +397,8 @@ pub fn expected_found<'tcx, C: Combine<'tcx>, T>( pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C, a: Ty<'tcx>, b: Ty<'tcx>) - -> cres<'tcx, Ty<'tcx>> { - + -> cres<'tcx, Ty<'tcx>> +{ let tcx = this.infcx().tcx; let a_sty = &a.sty; let b_sty = &b.sty; @@ -415,7 +415,7 @@ pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C, } (&ty::ty_err, _) | (_, &ty::ty_err) => { - Ok(ty::mk_err()) + Ok(tcx.types.err) } // Relate integral variables to other types @@ -592,8 +592,8 @@ pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C, { try!(this.infcx().simple_var_t(vid_is_expected, vid, val)); match val { - IntType(v) => Ok(ty::mk_mach_int(v)), - UintType(v) => Ok(ty::mk_mach_uint(v)) + IntType(v) => Ok(ty::mk_mach_int(this.tcx(), v)), + UintType(v) => Ok(ty::mk_mach_uint(this.tcx(), v)) } } @@ -604,7 +604,7 @@ pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C, val: ast::FloatTy) -> cres<'tcx, Ty<'tcx>> { try!(this.infcx().simple_var_t(vid_is_expected, vid, val)); - Ok(ty::mk_mach_float(val)) + Ok(ty::mk_mach_float(this.tcx(), val)) } } @@ -763,7 +763,7 @@ impl<'cx, 'tcx> ty_fold::TypeFolder<'tcx> for Generalizer<'cx, 'tcx> { ty::ty_infer(ty::TyVar(vid)) => { if vid == self.for_vid { self.cycle_detected = true; - ty::mk_err() + self.tcx().types.err } else { match self.infcx.type_variables.borrow().probe(vid) { Some(u) => self.fold_ty(u), diff --git a/src/librustc/middle/infer/mod.rs b/src/librustc/middle/infer/mod.rs index 07823779216d9..2231c0088e725 100644 --- a/src/librustc/middle/infer/mod.rs +++ b/src/librustc/middle/infer/mod.rs @@ -324,7 +324,7 @@ pub fn common_supertype<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>, Ok(t) => t, Err(ref err) => { cx.report_and_explain_type_error(trace, err); - ty::mk_err() + cx.tcx.types.err } } } @@ -1058,12 +1058,12 @@ impl<'tcx> TypeTrace<'tcx> { self.origin.span() } - pub fn dummy() -> TypeTrace<'tcx> { + pub fn dummy(tcx: &ty::ctxt<'tcx>) -> TypeTrace<'tcx> { TypeTrace { origin: Misc(codemap::DUMMY_SP), values: Types(ty::expected_found { - expected: ty::mk_err(), - found: ty::mk_err(), + expected: tcx.types.err, + found: tcx.types.err, }) } } diff --git a/src/librustc/middle/infer/resolve.rs b/src/librustc/middle/infer/resolve.rs index 12400de31ed9e..ca2ae25e6c63a 100644 --- a/src/librustc/middle/infer/resolve.rs +++ b/src/librustc/middle/infer/resolve.rs @@ -83,15 +83,15 @@ impl<'a, 'tcx> ty_fold::TypeFolder<'tcx> for FullTypeResolver<'a, 'tcx> { match t.sty { ty::ty_infer(ty::TyVar(vid)) => { self.err = Some(unresolved_ty(vid)); - ty::mk_err() + self.tcx().types.err } ty::ty_infer(ty::IntVar(vid)) => { self.err = Some(unresolved_int_ty(vid)); - ty::mk_err() + self.tcx().types.err } ty::ty_infer(ty::FloatVar(vid)) => { self.err = Some(unresolved_float_ty(vid)); - ty::mk_err() + self.tcx().types.err } ty::ty_infer(_) => { self.infcx.tcx.sess.bug( diff --git a/src/librustc/middle/infer/sub.rs b/src/librustc/middle/infer/sub.rs index 2b8adfb7c1eeb..4bd3308728c10 100644 --- a/src/librustc/middle/infer/sub.rs +++ b/src/librustc/middle/infer/sub.rs @@ -146,7 +146,7 @@ impl<'f, 'tcx> Combine<'tcx> for Sub<'f, 'tcx> { } (&ty::ty_err, _) | (_, &ty::ty_err) => { - Ok(ty::mk_err()) + Ok(self.tcx().types.err) } _ => { diff --git a/src/librustc/middle/infer/unify.rs b/src/librustc/middle/infer/unify.rs index dcf70263c0a43..3127ef5d8a5f5 100644 --- a/src/librustc/middle/infer/unify.rs +++ b/src/librustc/middle/infer/unify.rs @@ -225,7 +225,7 @@ impl sv::SnapshotVecDelegate,()> for Delegate { /// Indicates a type that does not have any kind of subtyping /// relationship. pub trait SimplyUnifiable<'tcx> : Clone + PartialEq + Repr<'tcx> { - fn to_type(&self) -> Ty<'tcx>; + fn to_type(&self, tcx: &ty::ctxt<'tcx>) -> Ty<'tcx>; fn to_type_err(expected_found) -> ty::type_err<'tcx>; } @@ -337,7 +337,7 @@ impl<'a,'tcx,V:SimplyUnifiable<'tcx>,K:UnifyKey<'tcx, Option>> let node_a = table.borrow_mut().get(tcx, a_id); match node_a.value { None => None, - Some(ref a_t) => Some(a_t.to_type()) + Some(ref a_t) => Some(a_t.to_type(tcx)) } } } @@ -363,10 +363,10 @@ impl<'tcx> UnifyKey<'tcx, Option> for ty::IntVid { } impl<'tcx> SimplyUnifiable<'tcx> for IntVarValue { - fn to_type(&self) -> Ty<'tcx> { + fn to_type(&self, tcx: &ty::ctxt<'tcx>) -> Ty<'tcx> { match *self { - ty::IntType(i) => ty::mk_mach_int(i), - ty::UintType(i) => ty::mk_mach_uint(i), + ty::IntType(i) => ty::mk_mach_int(tcx, i), + ty::UintType(i) => ty::mk_mach_uint(tcx, i), } } @@ -399,8 +399,8 @@ impl<'tcx> UnifyValue<'tcx> for Option { } impl<'tcx> SimplyUnifiable<'tcx> for ast::FloatTy { - fn to_type(&self) -> Ty<'tcx> { - ty::mk_mach_float(*self) + fn to_type(&self, tcx: &ty::ctxt<'tcx>) -> Ty<'tcx> { + ty::mk_mach_float(tcx, *self) } fn to_type_err(err: expected_found) -> ty::type_err<'tcx> { diff --git a/src/librustc/middle/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs index 1f4ddd1a5d641..df06b3b7789c9 100644 --- a/src/librustc/middle/intrinsicck.rs +++ b/src/librustc/middle/intrinsicck.rs @@ -28,8 +28,8 @@ pub fn check_crate(tcx: &ctxt) { let mut visitor = IntrinsicCheckingVisitor { tcx: tcx, param_envs: Vec::new(), - dummy_sized_ty: ty::mk_int(), - dummy_unsized_ty: ty::mk_vec(tcx, ty::mk_int(), None), + dummy_sized_ty: tcx.types.int, + dummy_unsized_ty: ty::mk_vec(tcx, tcx.types.int, None), }; visit::walk_crate(&mut visitor, tcx.map.krate()); } diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 5d3134b9629b2..c15001af68d96 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -755,7 +755,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { // instead of bothering to construct a proper // one. base.mutbl = McImmutable; - base.ty = ty::mk_err(); + base.ty = self.tcx().types.err; Rc::new(cmt_ { id: id, span: span, @@ -781,7 +781,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { is_unboxed: is_unboxed }), mutbl: McImmutable, - ty: ty::mk_err(), + ty: self.tcx().types.err, note: NoteNone }; @@ -792,7 +792,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { span: span, cat: cat_deref(Rc::new(base), 0, env_ptr), mutbl: env_mutbl, - ty: ty::mk_err(), + ty: self.tcx().types.err, note: NoteClosureEnv(upvar_id) }; } @@ -987,7 +987,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { ty::ty_fn_args(method_ty)[0] } None => { - match ty::array_element_ty(base_cmt.ty) { + match ty::array_element_ty(self.tcx(), base_cmt.ty) { Some(ty) => ty, None => { self.tcx().sess.span_bug( diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index 6b56bbac20101..a22a602ddff25 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -1100,8 +1100,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } else { // Recursively check all supertraits to find out if any further // bounds are required and thus we must fulfill. - let tmp_tr = data.principal_trait_ref_with_self_ty(self.tcx(), - ty::mk_err()); + let tmp_tr = + data.principal_trait_ref_with_self_ty(self.tcx(), + self.tcx().types.err); for tr in util::supertraits(self.tcx(), tmp_tr) { let td = ty::lookup_trait_def(self.tcx(), tr.def_id()); diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index c082c12da5bfa..8a0e5ea0bb314 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -639,6 +639,24 @@ impl<'tcx> CtxtArenas<'tcx> { } } +pub struct CommonTypes<'tcx> { + pub bool: Ty<'tcx>, + pub char: Ty<'tcx>, + pub int: Ty<'tcx>, + pub i8: Ty<'tcx>, + pub i16: Ty<'tcx>, + pub i32: Ty<'tcx>, + pub i64: Ty<'tcx>, + pub uint: Ty<'tcx>, + pub u8: Ty<'tcx>, + pub u16: Ty<'tcx>, + pub u32: Ty<'tcx>, + pub u64: Ty<'tcx>, + pub f32: Ty<'tcx>, + pub f64: Ty<'tcx>, + pub err: Ty<'tcx>, +} + /// The data structure to keep track of all the information that typechecker /// generates so that so that it can be reused and doesn't have to be redone /// later on. @@ -651,11 +669,15 @@ pub struct ctxt<'tcx> { // FIXME(eddyb) use a FnvHashSet> when equivalent keys can // queried from a HashSet. interner: RefCell, Ty<'tcx>>>, + // FIXME as above, use a hashset if equivalent elements can be queried. substs_interner: RefCell, &'tcx Substs<'tcx>>>, bare_fn_interner: RefCell, &'tcx BareFnTy<'tcx>>>, region_interner: RefCell>, + /// Common types, pre-interned for your convenience. + pub types: CommonTypes<'tcx>, + pub sess: Session, pub def_map: DefMap, @@ -1297,54 +1319,6 @@ pub enum BoundRegion { BrEnv } -#[inline] -pub fn mk_prim_t<'tcx>(primitive: &'tcx TyS<'static>) -> Ty<'tcx> { - // FIXME(#17596) Ty<'tcx> is incorrectly invariant w.r.t 'tcx. - unsafe { &*(primitive as *const _ as *const TyS<'tcx>) } -} - -// Do not change these from static to const, interning types requires -// the primitives to have a significant address. -macro_rules! def_prim_tys { - ($($name:ident -> $sty:expr;)*) => ( - $(#[inline] pub fn $name<'tcx>() -> Ty<'tcx> { - static PRIM_TY: TyS<'static> = TyS { - sty: $sty, - flags: NO_TYPE_FLAGS, - region_depth: 0, - }; - mk_prim_t(&PRIM_TY) - })* - ) -} - -def_prim_tys!{ - mk_bool -> ty_bool; - mk_char -> ty_char; - mk_int -> ty_int(ast::TyI); - mk_i8 -> ty_int(ast::TyI8); - mk_i16 -> ty_int(ast::TyI16); - mk_i32 -> ty_int(ast::TyI32); - mk_i64 -> ty_int(ast::TyI64); - mk_uint -> ty_uint(ast::TyU); - mk_u8 -> ty_uint(ast::TyU8); - mk_u16 -> ty_uint(ast::TyU16); - mk_u32 -> ty_uint(ast::TyU32); - mk_u64 -> ty_uint(ast::TyU64); - mk_f32 -> ty_float(ast::TyF32); - mk_f64 -> ty_float(ast::TyF64); -} - -#[inline] -pub fn mk_err<'tcx>() -> Ty<'tcx> { - static TY_ERR: TyS<'static> = TyS { - sty: ty_err, - flags: HAS_TY_ERR, - region_depth: 0, - }; - mk_prim_t(&TY_ERR) -} - // NB: If you change this, you'll probably want to change the corresponding // AST structure in libsyntax/ast.rs as well. #[deriving(Clone, PartialEq, Eq, Hash, Show)] @@ -2102,6 +2076,31 @@ impl UnboxedClosureKind { } } +impl<'tcx> CommonTypes<'tcx> { + fn new(arena: &'tcx TypedArena>, + interner: &mut FnvHashMap, Ty<'tcx>>) + -> CommonTypes<'tcx> + { + CommonTypes { + bool: intern_ty(arena, interner, ty_bool), + char: intern_ty(arena, interner, ty_char), + err: intern_ty(arena, interner, ty_err), + int: intern_ty(arena, interner, ty_int(ast::TyI)), + i8: intern_ty(arena, interner, ty_int(ast::TyI8)), + i16: intern_ty(arena, interner, ty_int(ast::TyI16)), + i32: intern_ty(arena, interner, ty_int(ast::TyI32)), + i64: intern_ty(arena, interner, ty_int(ast::TyI64)), + uint: intern_ty(arena, interner, ty_uint(ast::TyU)), + u8: intern_ty(arena, interner, ty_uint(ast::TyU8)), + u16: intern_ty(arena, interner, ty_uint(ast::TyU16)), + u32: intern_ty(arena, interner, ty_uint(ast::TyU32)), + u64: intern_ty(arena, interner, ty_uint(ast::TyU64)), + f32: intern_ty(arena, interner, ty_float(ast::TyF32)), + f64: intern_ty(arena, interner, ty_float(ast::TyF64)), + } + } +} + pub fn mk_ctxt<'tcx>(s: Session, arenas: &'tcx CtxtArenas<'tcx>, dm: DefMap, @@ -2111,13 +2110,18 @@ pub fn mk_ctxt<'tcx>(s: Session, capture_modes: RefCell, region_maps: middle::region::RegionMaps, lang_items: middle::lang_items::LanguageItems, - stability: stability::Index) -> ctxt<'tcx> { + stability: stability::Index) -> ctxt<'tcx> +{ + let mut interner = FnvHashMap::new(); + let common_types = CommonTypes::new(&arenas.type_, &mut interner); + ctxt { arenas: arenas, interner: RefCell::new(FnvHashMap::new()), substs_interner: RefCell::new(FnvHashMap::new()), bare_fn_interner: RefCell::new(FnvHashMap::new()), region_interner: RefCell::new(FnvHashMap::new()), + types: common_types, named_region_map: named_region_map, item_variance_map: RefCell::new(DefIdMap::new()), variance_computed: Cell::new(false), @@ -2212,31 +2216,32 @@ impl<'tcx> ctxt<'tcx> { // Interns a type/name combination, stores the resulting box in cx.interner, // and returns the box as cast to an unsafe ptr (see comments for Ty above). pub fn mk_t<'tcx>(cx: &ctxt<'tcx>, st: sty<'tcx>) -> Ty<'tcx> { - // Check for primitive types. - match st { - ty_err => return mk_err(), - ty_bool => return mk_bool(), - ty_int(i) => return mk_mach_int(i), - ty_uint(u) => return mk_mach_uint(u), - ty_float(f) => return mk_mach_float(f), - ty_char => return mk_char(), - _ => {} - }; + let mut interner = cx.interner.borrow_mut(); + intern_ty(cx.type_arena, &mut *interner, st) +} - match cx.interner.borrow().get(&st) { +fn intern_ty<'tcx>(type_arena: &'tcx TypedArena>, + interner: &mut FnvHashMap, Ty<'tcx>>, + st: sty<'tcx>) + -> Ty<'tcx> +{ + match interner.get(&st) { Some(ty) => return *ty, _ => () } let flags = FlagComputation::for_sty(&st); - let ty = cx.arenas.type_.alloc(TyS { + let ty = type_arena.alloc(TyS { sty: st, flags: flags.flags, region_depth: flags.depth, }); - cx.interner.borrow_mut().insert(InternedTy { ty: ty }, ty); + debug!("Interned type: {} Pointer: {}", + ty, ty as *const _); + + interner.insert(InternedTy { ty: ty }, ty); ty } @@ -2416,30 +2421,30 @@ impl FlagComputation { } } -pub fn mk_mach_int<'tcx>(tm: ast::IntTy) -> Ty<'tcx> { +pub fn mk_mach_int<'tcx>(tcx: &ctxt<'tcx>, tm: ast::IntTy) -> Ty<'tcx> { match tm { - ast::TyI => mk_int(), - ast::TyI8 => mk_i8(), - ast::TyI16 => mk_i16(), - ast::TyI32 => mk_i32(), - ast::TyI64 => mk_i64(), + ast::TyI => tcx.types.int, + ast::TyI8 => tcx.types.i8, + ast::TyI16 => tcx.types.i16, + ast::TyI32 => tcx.types.i32, + ast::TyI64 => tcx.types.i64, } } -pub fn mk_mach_uint<'tcx>(tm: ast::UintTy) -> Ty<'tcx> { +pub fn mk_mach_uint<'tcx>(tcx: &ctxt<'tcx>, tm: ast::UintTy) -> Ty<'tcx> { match tm { - ast::TyU => mk_uint(), - ast::TyU8 => mk_u8(), - ast::TyU16 => mk_u16(), - ast::TyU32 => mk_u32(), - ast::TyU64 => mk_u64(), + ast::TyU => tcx.types.uint, + ast::TyU8 => tcx.types.u8, + ast::TyU16 => tcx.types.u16, + ast::TyU32 => tcx.types.u32, + ast::TyU64 => tcx.types.u64, } } -pub fn mk_mach_float<'tcx>(tm: ast::FloatTy) -> Ty<'tcx> { +pub fn mk_mach_float<'tcx>(tcx: &ctxt<'tcx>, tm: ast::FloatTy) -> Ty<'tcx> { match tm { - ast::TyF32 => mk_f32(), - ast::TyF64 => mk_f64(), + ast::TyF32 => tcx.types.f32, + ast::TyF64 => tcx.types.f64, } } @@ -2769,7 +2774,7 @@ pub fn type_is_simd(cx: &ctxt, ty: Ty) -> bool { pub fn sequence_element_type<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { match ty.sty { ty_vec(ty, _) => ty, - ty_str => mk_mach_uint(ast::TyU8), + ty_str => mk_mach_uint(cx, ast::TyU8), ty_open(ty) => sequence_element_type(cx, ty), _ => cx.sess.bug(format!("sequence_element_type called on non-sequence value: {}", ty_to_string(cx, ty))[]), @@ -3760,10 +3765,10 @@ pub fn index<'tcx>(ty: Ty<'tcx>) -> Option> { // Returns the type of elements contained within an 'array-like' type. // This is exactly the same as the above, except it supports strings, // which can't actually be indexed. -pub fn array_element_ty<'tcx>(ty: Ty<'tcx>) -> Option> { +pub fn array_element_ty<'tcx>(tcx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Option> { match ty.sty { ty_vec(ty, _) => Some(ty), - ty_str => Some(mk_u8()), + ty_str => Some(tcx.types.u8), _ => None } } diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index 941155ac5e7e3..6329acfb57805 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -28,7 +28,7 @@ use rustc_typeck::middle::infer::glb::Glb; use rustc_typeck::middle::infer::sub::Sub; use rustc_typeck::util::ppaux::{ty_to_string, Repr, UserString}; use rustc::session::{mod,config}; -use syntax::{abi, ast, ast_map, ast_util}; +use syntax::{abi, ast, ast_map}; use syntax::codemap; use syntax::codemap::{Span, CodeMap, DUMMY_SP}; use syntax::diagnostic::{Level, RenderSpan, Bug, Fatal, Error, Warning, Note, Help}; @@ -145,6 +145,10 @@ fn test_env(source_string: &str, } impl<'a, 'tcx> Env<'a, 'tcx> { + pub fn tcx(&self) -> &ty::ctxt<'tcx> { + self.infcx.tcx + } + pub fn create_region_hierarchy(&self, rh: &RH) { for child_rh in rh.sub.iter() { self.create_region_hierarchy(child_rh); @@ -296,7 +300,8 @@ impl<'a, 'tcx> Env<'a, 'tcx> { } pub fn t_param(&self, space: subst::ParamSpace, index: u32) -> Ty<'tcx> { - ty::mk_param(self.infcx.tcx, space, index, ast_util::local_def(ast::DUMMY_NODE_ID)) + let name = format!("T{}", index); + ty::mk_param(self.infcx.tcx, space, index, token::intern(name[])) } pub fn re_early_bound(&self, @@ -314,14 +319,16 @@ impl<'a, 'tcx> Env<'a, 'tcx> { } pub fn t_rptr(&self, r: ty::Region) -> Ty<'tcx> { - ty::mk_imm_rptr(self.infcx.tcx, self.infcx.tcx.mk_region(r), ty::mk_int()) + ty::mk_imm_rptr(self.infcx.tcx, + self.infcx.tcx.mk_region(r), + self.tcx().types.int) } pub fn t_rptr_late_bound(&self, id: u32) -> Ty<'tcx> { let r = self.re_late_bound_with_debruijn(id, ty::DebruijnIndex::new(1)); ty::mk_imm_rptr(self.infcx.tcx, self.infcx.tcx.mk_region(r), - ty::mk_int()) + self.tcx().types.int) } pub fn t_rptr_late_bound_with_debruijn(&self, @@ -331,12 +338,13 @@ impl<'a, 'tcx> Env<'a, 'tcx> { let r = self.re_late_bound_with_debruijn(id, debruijn); ty::mk_imm_rptr(self.infcx.tcx, self.infcx.tcx.mk_region(r), - ty::mk_int()) + self.tcx().types.int) } pub fn t_rptr_scope(&self, id: ast::NodeId) -> Ty<'tcx> { let r = ty::ReScope(CodeExtent::from_node_id(id)); - ty::mk_imm_rptr(self.infcx.tcx, self.infcx.tcx.mk_region(r), ty::mk_int()) + ty::mk_imm_rptr(self.infcx.tcx, self.infcx.tcx.mk_region(r), + self.tcx().types.int) } pub fn re_free(&self, nid: ast::NodeId, id: u32) -> ty::Region { @@ -346,15 +354,19 @@ impl<'a, 'tcx> Env<'a, 'tcx> { pub fn t_rptr_free(&self, nid: ast::NodeId, id: u32) -> Ty<'tcx> { let r = self.re_free(nid, id); - ty::mk_imm_rptr(self.infcx.tcx, self.infcx.tcx.mk_region(r), ty::mk_int()) + ty::mk_imm_rptr(self.infcx.tcx, + self.infcx.tcx.mk_region(r), + self.tcx().types.int) } pub fn t_rptr_static(&self) -> Ty<'tcx> { - ty::mk_imm_rptr(self.infcx.tcx, self.infcx.tcx.mk_region(ty::ReStatic), ty::mk_int()) + ty::mk_imm_rptr(self.infcx.tcx, + self.infcx.tcx.mk_region(ty::ReStatic), + self.tcx().types.int) } pub fn dummy_type_trace(&self) -> infer::TypeTrace<'tcx> { - infer::TypeTrace::dummy() + infer::TypeTrace::dummy(self.tcx()) } pub fn sub(&self) -> Sub<'a, 'tcx> { @@ -480,8 +492,8 @@ fn sub_free_bound_false() { test_env(EMPTY_SOURCE_STR, errors(&[]), |env| { let t_rptr_free1 = env.t_rptr_free(0, 1); let t_rptr_bound1 = env.t_rptr_late_bound(1); - env.check_not_sub(env.t_fn(&[t_rptr_free1], ty::mk_int()), - env.t_fn(&[t_rptr_bound1], ty::mk_int())); + env.check_not_sub(env.t_fn(&[t_rptr_free1], env.tcx().types.int), + env.t_fn(&[t_rptr_bound1], env.tcx().types.int)); }) } @@ -496,8 +508,8 @@ fn sub_bound_free_true() { test_env(EMPTY_SOURCE_STR, errors(&[]), |env| { let t_rptr_bound1 = env.t_rptr_late_bound(1); let t_rptr_free1 = env.t_rptr_free(0, 1); - env.check_sub(env.t_fn(&[t_rptr_bound1], ty::mk_int()), - env.t_fn(&[t_rptr_free1], ty::mk_int())); + env.check_sub(env.t_fn(&[t_rptr_bound1], env.tcx().types.int), + env.t_fn(&[t_rptr_free1], env.tcx().types.int)); }) } @@ -512,8 +524,8 @@ fn sub_free_bound_false_infer() { test_env(EMPTY_SOURCE_STR, errors(&[]), |env| { let t_infer1 = env.infcx.next_ty_var(); let t_rptr_bound1 = env.t_rptr_late_bound(1); - env.check_not_sub(env.t_fn(&[t_infer1], ty::mk_int()), - env.t_fn(&[t_rptr_bound1], ty::mk_int())); + env.check_not_sub(env.t_fn(&[t_infer1], env.tcx().types.int), + env.t_fn(&[t_rptr_bound1], env.tcx().types.int)); }) } @@ -531,9 +543,9 @@ fn lub_free_bound_infer() { let t_infer1 = env.infcx.next_ty_var(); let t_rptr_bound1 = env.t_rptr_late_bound(1); let t_rptr_free1 = env.t_rptr_free(0, 1); - env.check_lub(env.t_fn(&[t_infer1], ty::mk_int()), - env.t_fn(&[t_rptr_bound1], ty::mk_int()), - env.t_fn(&[t_rptr_free1], ty::mk_int())); + env.check_lub(env.t_fn(&[t_infer1], env.tcx().types.int), + env.t_fn(&[t_rptr_bound1], env.tcx().types.int), + env.t_fn(&[t_rptr_free1], env.tcx().types.int)); }); } @@ -542,9 +554,9 @@ fn lub_bound_bound() { test_env(EMPTY_SOURCE_STR, errors(&[]), |env| { let t_rptr_bound1 = env.t_rptr_late_bound(1); let t_rptr_bound2 = env.t_rptr_late_bound(2); - env.check_lub(env.t_fn(&[t_rptr_bound1], ty::mk_int()), - env.t_fn(&[t_rptr_bound2], ty::mk_int()), - env.t_fn(&[t_rptr_bound1], ty::mk_int())); + env.check_lub(env.t_fn(&[t_rptr_bound1], env.tcx().types.int), + env.t_fn(&[t_rptr_bound2], env.tcx().types.int), + env.t_fn(&[t_rptr_bound1], env.tcx().types.int)); }) } @@ -553,9 +565,9 @@ fn lub_bound_free() { test_env(EMPTY_SOURCE_STR, errors(&[]), |env| { let t_rptr_bound1 = env.t_rptr_late_bound(1); let t_rptr_free1 = env.t_rptr_free(0, 1); - env.check_lub(env.t_fn(&[t_rptr_bound1], ty::mk_int()), - env.t_fn(&[t_rptr_free1], ty::mk_int()), - env.t_fn(&[t_rptr_free1], ty::mk_int())); + env.check_lub(env.t_fn(&[t_rptr_bound1], env.tcx().types.int), + env.t_fn(&[t_rptr_free1], env.tcx().types.int), + env.t_fn(&[t_rptr_free1], env.tcx().types.int)); }) } @@ -564,9 +576,9 @@ fn lub_bound_static() { test_env(EMPTY_SOURCE_STR, errors(&[]), |env| { let t_rptr_bound1 = env.t_rptr_late_bound(1); let t_rptr_static = env.t_rptr_static(); - env.check_lub(env.t_fn(&[t_rptr_bound1], ty::mk_int()), - env.t_fn(&[t_rptr_static], ty::mk_int()), - env.t_fn(&[t_rptr_static], ty::mk_int())); + env.check_lub(env.t_fn(&[t_rptr_bound1], env.tcx().types.int), + env.t_fn(&[t_rptr_static], env.tcx().types.int), + env.t_fn(&[t_rptr_static], env.tcx().types.int)); }) } @@ -587,9 +599,9 @@ fn lub_free_free() { let t_rptr_free1 = env.t_rptr_free(0, 1); let t_rptr_free2 = env.t_rptr_free(0, 2); let t_rptr_static = env.t_rptr_static(); - env.check_lub(env.t_fn(&[t_rptr_free1], ty::mk_int()), - env.t_fn(&[t_rptr_free2], ty::mk_int()), - env.t_fn(&[t_rptr_static], ty::mk_int())); + env.check_lub(env.t_fn(&[t_rptr_free1], env.tcx().types.int), + env.t_fn(&[t_rptr_free2], env.tcx().types.int), + env.t_fn(&[t_rptr_static], env.tcx().types.int)); }) } @@ -612,9 +624,9 @@ fn glb_free_free_with_common_scope() { let t_rptr_free1 = env.t_rptr_free(0, 1); let t_rptr_free2 = env.t_rptr_free(0, 2); let t_rptr_scope = env.t_rptr_scope(0); - env.check_glb(env.t_fn(&[t_rptr_free1], ty::mk_int()), - env.t_fn(&[t_rptr_free2], ty::mk_int()), - env.t_fn(&[t_rptr_scope], ty::mk_int())); + env.check_glb(env.t_fn(&[t_rptr_free1], env.tcx().types.int), + env.t_fn(&[t_rptr_free2], env.tcx().types.int), + env.t_fn(&[t_rptr_scope], env.tcx().types.int)); }) } @@ -623,9 +635,9 @@ fn glb_bound_bound() { test_env(EMPTY_SOURCE_STR, errors(&[]), |env| { let t_rptr_bound1 = env.t_rptr_late_bound(1); let t_rptr_bound2 = env.t_rptr_late_bound(2); - env.check_glb(env.t_fn(&[t_rptr_bound1], ty::mk_int()), - env.t_fn(&[t_rptr_bound2], ty::mk_int()), - env.t_fn(&[t_rptr_bound1], ty::mk_int())); + env.check_glb(env.t_fn(&[t_rptr_bound1], env.tcx().types.int), + env.t_fn(&[t_rptr_bound2], env.tcx().types.int), + env.t_fn(&[t_rptr_bound1], env.tcx().types.int)); }) } @@ -634,9 +646,9 @@ fn glb_bound_free() { test_env(EMPTY_SOURCE_STR, errors(&[]), |env| { let t_rptr_bound1 = env.t_rptr_late_bound(1); let t_rptr_free1 = env.t_rptr_free(0, 1); - env.check_glb(env.t_fn(&[t_rptr_bound1], ty::mk_int()), - env.t_fn(&[t_rptr_free1], ty::mk_int()), - env.t_fn(&[t_rptr_bound1], ty::mk_int())); + env.check_glb(env.t_fn(&[t_rptr_bound1], env.tcx().types.int), + env.t_fn(&[t_rptr_free1], env.tcx().types.int), + env.t_fn(&[t_rptr_bound1], env.tcx().types.int)); }) } @@ -648,9 +660,9 @@ fn glb_bound_free_infer() { // compute GLB(fn(_) -> int, for<'b> fn(&'b int) -> int), // which should yield for<'b> fn(&'b int) -> int - env.check_glb(env.t_fn(&[t_rptr_bound1], ty::mk_int()), - env.t_fn(&[t_infer1], ty::mk_int()), - env.t_fn(&[t_rptr_bound1], ty::mk_int())); + env.check_glb(env.t_fn(&[t_rptr_bound1], env.tcx().types.int), + env.t_fn(&[t_infer1], env.tcx().types.int), + env.t_fn(&[t_rptr_bound1], env.tcx().types.int)); // as a side-effect, computing GLB should unify `_` with // `&'_ int` @@ -667,9 +679,9 @@ fn glb_bound_static() { test_env(EMPTY_SOURCE_STR, errors(&[]), |env| { let t_rptr_bound1 = env.t_rptr_late_bound(1); let t_rptr_static = env.t_rptr_static(); - env.check_glb(env.t_fn(&[t_rptr_bound1], ty::mk_int()), - env.t_fn(&[t_rptr_static], ty::mk_int()), - env.t_fn(&[t_rptr_bound1], ty::mk_int())); + env.check_glb(env.t_fn(&[t_rptr_bound1], env.tcx().types.int), + env.t_fn(&[t_rptr_static], env.tcx().types.int), + env.t_fn(&[t_rptr_bound1], env.tcx().types.int)); }) } @@ -790,7 +802,6 @@ fn escaping() { /// late-bound region. #[test] fn subst_region_renumber_region() { - test_env(EMPTY_SOURCE_STR, errors(&[]), |env| { let re_bound1 = env.re_late_bound_with_debruijn(1, ty::DebruijnIndex::new(1)); diff --git a/src/librustc_trans/trans/_match.rs b/src/librustc_trans/trans/_match.rs index db0536869351f..0e37cd0f3b8d6 100644 --- a/src/librustc_trans/trans/_match.rs +++ b/src/librustc_trans/trans/_match.rs @@ -1122,7 +1122,7 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, let t = if kind == Compare { left_ty } else { - ty::mk_uint() // vector length + tcx.types.uint // vector length }; let Result { bcx: after_cx, val: matches } = { match opt.trans(bcx) { diff --git a/src/librustc_trans/trans/adt.rs b/src/librustc_trans/trans/adt.rs index 717c2af2beb96..d01047c53b955 100644 --- a/src/librustc_trans/trans/adt.rs +++ b/src/librustc_trans/trans/adt.rs @@ -163,7 +163,7 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, }).collect::>(); let packed = ty::lookup_packed(cx.tcx(), def_id); let dtor = ty::ty_dtor(cx.tcx(), def_id).has_drop_flag(); - if dtor { ftys.push(ty::mk_bool()); } + if dtor { ftys.push(cx.tcx().types.bool); } Univariant(mk_struct(cx, ftys[], packed, t), dtor) } @@ -183,7 +183,7 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, // Uninhabitable; represent as unit // (Typechecking will reject discriminant-sizing attrs.) assert_eq!(hint, attr::ReprAny); - let ftys = if dtor { vec!(ty::mk_bool()) } else { vec!() }; + let ftys = if dtor { vec!(cx.tcx().types.bool) } else { vec!() }; return Univariant(mk_struct(cx, ftys[], false, t), dtor); } @@ -215,7 +215,7 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, // (Typechecking will reject discriminant-sizing attrs.) assert_eq!(hint, attr::ReprAny); let mut ftys = cases[0].tys.clone(); - if dtor { ftys.push(ty::mk_bool()); } + if dtor { ftys.push(cx.tcx().types.bool); } return Univariant(mk_struct(cx, ftys[], false, t), dtor); } @@ -261,9 +261,9 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, // Create the set of structs that represent each variant // Use the minimum integer type we figured out above let fields : Vec<_> = cases.iter().map(|c| { - let mut ftys = vec!(ty_of_inttype(min_ity)); + let mut ftys = vec!(ty_of_inttype(cx.tcx(), min_ity)); ftys.push_all(c.tys.as_slice()); - if dtor { ftys.push(ty::mk_bool()); } + if dtor { ftys.push(cx.tcx().types.bool); } mk_struct(cx, ftys.as_slice(), false, t) }).collect(); @@ -314,9 +314,9 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, }; let fields : Vec<_> = cases.iter().map(|c| { - let mut ftys = vec!(ty_of_inttype(ity)); + let mut ftys = vec!(ty_of_inttype(cx.tcx(), ity)); ftys.push_all(c.tys[]); - if dtor { ftys.push(ty::mk_bool()); } + if dtor { ftys.push(cx.tcx().types.bool); } mk_struct(cx, ftys[], false, t) }).collect(); @@ -553,11 +553,10 @@ fn bounds_usable(cx: &CrateContext, ity: IntType, bounds: &IntBounds) -> bool { } } -// FIXME(#17596) Ty<'tcx> is incorrectly invariant w.r.t 'tcx. -pub fn ty_of_inttype<'tcx>(ity: IntType) -> Ty<'tcx> { +pub fn ty_of_inttype<'tcx>(tcx: &ty::ctxt<'tcx>, ity: IntType) -> Ty<'tcx> { match ity { - attr::SignedInt(t) => ty::mk_mach_int(t), - attr::UnsignedInt(t) => ty::mk_mach_uint(t) + attr::SignedInt(t) => ty::mk_mach_int(tcx, t), + attr::UnsignedInt(t) => ty::mk_mach_uint(tcx, t) } } @@ -995,8 +994,10 @@ pub fn fold_variants<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, /// Access the struct drop flag, if present. pub fn trans_drop_flag_ptr<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>, val: ValueRef) - -> datum::DatumBlock<'blk, 'tcx, datum::Expr> { - let ptr_ty = ty::mk_imm_ptr(bcx.tcx(), ty::mk_bool()); + -> datum::DatumBlock<'blk, 'tcx, datum::Expr> +{ + let tcx = bcx.tcx(); + let ptr_ty = ty::mk_imm_ptr(bcx.tcx(), tcx.types.bool); match *r { Univariant(ref st, true) => { let flag_ptr = GEPi(bcx, val, &[0, st.fields.len() - 1]); @@ -1006,7 +1007,7 @@ pub fn trans_drop_flag_ptr<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, r: &Repr<'tcx let fcx = bcx.fcx; let custom_cleanup_scope = fcx.push_custom_cleanup_scope(); let scratch = unpack_datum!(bcx, datum::lvalue_scratch_datum( - bcx, ty::mk_bool(), "drop_flag", false, + bcx, tcx.types.bool, "drop_flag", false, cleanup::CustomScope(custom_cleanup_scope), (), |_, bcx, _| bcx )); bcx = fold_variants(bcx, r, val, |variant_cx, st, value| { diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index 397baac960d24..e0a717d8073c9 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -786,7 +786,7 @@ pub fn iter_structural_ty<'a, 'blk, 'tcx>(cx: Block<'blk, 'tcx>, substs, f); } (_match::Switch, Some(lldiscrim_a)) => { - cx = f(cx, lldiscrim_a, ty::mk_int()); + cx = f(cx, lldiscrim_a, cx.tcx().types.int); let unr_cx = fcx.new_temp_block("enum-iter-unr"); Unreachable(unr_cx); let llswitch = Switch(cx, lldiscrim_a, unr_cx.llbb, @@ -1765,7 +1765,7 @@ pub fn build_return_block<'blk, 'tcx>(fcx: &FunctionContext<'blk, 'tcx>, retptr.erase_from_parent(); } - let retval = if retty == ty::FnConverging(ty::mk_bool()) { + let retval = if retty == ty::FnConverging(fcx.ccx.tcx().types.bool) { Trunc(ret_cx, retval, Type::i1(fcx.ccx)) } else { retval diff --git a/src/librustc_trans/trans/cleanup.rs b/src/librustc_trans/trans/cleanup.rs index d02d6c1e8724f..b4deea4c72fc8 100644 --- a/src/librustc_trans/trans/cleanup.rs +++ b/src/librustc_trans/trans/cleanup.rs @@ -736,7 +736,7 @@ impl<'blk, 'tcx> CleanupHelperMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx let f = base::decl_cdecl_fn(self.ccx, "rust_eh_personality", fty, - ty::mk_i32()); + self.ccx.tcx().types.i32); *personality = Some(f); f } diff --git a/src/librustc_trans/trans/closure.rs b/src/librustc_trans/trans/closure.rs index 0ae9de8c89183..ed3c820f2faf4 100644 --- a/src/librustc_trans/trans/closure.rs +++ b/src/librustc_trans/trans/closure.rs @@ -133,8 +133,8 @@ pub fn mk_closure_tys<'tcx>(tcx: &ty::ctxt<'tcx>, } fn tuplify_box_ty<'tcx>(tcx: &ty::ctxt<'tcx>, t: Ty<'tcx>) -> Ty<'tcx> { - let ptr = ty::mk_imm_ptr(tcx, ty::mk_i8()); - ty::mk_tup(tcx, vec!(ty::mk_uint(), ty::mk_nil_ptr(tcx), ptr, ptr, t)) + let ptr = ty::mk_imm_ptr(tcx, tcx.types.i8); + ty::mk_tup(tcx, vec!(tcx.types.uint, ty::mk_nil_ptr(tcx), ptr, ptr, t)) } fn allocate_cbox<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, diff --git a/src/librustc_trans/trans/debuginfo.rs b/src/librustc_trans/trans/debuginfo.rs index 56c42c7afdeb8..98f87b273852d 100644 --- a/src/librustc_trans/trans/debuginfo.rs +++ b/src/librustc_trans/trans/debuginfo.rs @@ -2487,9 +2487,10 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, let discriminant_llvm_type = adt::ll_inttype(cx, inttype); let (discriminant_size, discriminant_align) = size_and_align_of(cx, discriminant_llvm_type); - let discriminant_base_type_metadata = type_metadata(cx, - adt::ty_of_inttype(inttype), - codemap::DUMMY_SP); + let discriminant_base_type_metadata = + type_metadata(cx, + adt::ty_of_inttype(cx.tcx(), inttype), + codemap::DUMMY_SP); let discriminant_name = get_enum_discriminant_name(cx, enum_def_id); let discriminant_type_metadata = discriminant_name.get().with_c_str(|name| { @@ -2797,7 +2798,7 @@ fn vec_slice_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, MemberDescription { name: "length".to_string(), llvm_type: member_llvm_types[1], - type_metadata: type_metadata(cx, ty::mk_uint(), span), + type_metadata: type_metadata(cx, cx.tcx().types.uint, span), offset: ComputedMemberOffset, flags: FLAGS_NONE }, @@ -2963,7 +2964,7 @@ fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, } // FIXME Can we do better than this for unsized vec/str fields? ty::ty_vec(typ, None) => fixed_vec_metadata(cx, unique_type_id, typ, 0, usage_site_span), - ty::ty_str => fixed_vec_metadata(cx, unique_type_id, ty::mk_i8(), 0, usage_site_span), + ty::ty_str => fixed_vec_metadata(cx, unique_type_id, cx.tcx().types.i8, 0, usage_site_span), ty::ty_trait(..) => { MetadataCreationResult::new( trait_pointer_metadata(cx, t, None, unique_type_id), @@ -2975,7 +2976,7 @@ fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, vec_slice_metadata(cx, t, typ, unique_type_id, usage_site_span) } ty::ty_str => { - vec_slice_metadata(cx, t, ty::mk_u8(), unique_type_id, usage_site_span) + vec_slice_metadata(cx, t, cx.tcx().types.u8, unique_type_id, usage_site_span) } ty::ty_trait(..) => { MetadataCreationResult::new( diff --git a/src/librustc_trans/trans/glue.rs b/src/librustc_trans/trans/glue.rs index 31455920c1097..ab5c670ef5a2d 100644 --- a/src/librustc_trans/trans/glue.rs +++ b/src/librustc_trans/trans/glue.rs @@ -85,7 +85,7 @@ pub fn get_drop_glue_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, return t } if !type_needs_drop(tcx, t) { - return ty::mk_i8(); + return tcx.types.i8; } match t.sty { ty::ty_uniq(typ) if !type_needs_drop(tcx, typ) @@ -93,7 +93,7 @@ pub fn get_drop_glue_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, let llty = sizing_type_of(ccx, typ); // `Box` does not allocate. if llsize_of_alloc(ccx, llty) == 0 { - ty::mk_i8() + tcx.types.i8 } else { t } @@ -200,7 +200,7 @@ fn trans_struct_drop_flag<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, Load(bcx, llval) }; let drop_flag = unpack_datum!(bcx, adt::trans_drop_flag_ptr(bcx, &*repr, struct_data)); - with_cond(bcx, load_ty(bcx, drop_flag.val, ty::mk_bool()), |cx| { + with_cond(bcx, load_ty(bcx, drop_flag.val, bcx.tcx().types.bool), |cx| { trans_struct_drop(cx, t, v0, dtor_did, class_did, substs) }) } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 859cb88ea9a1c..0ba528ad0303d 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -932,7 +932,7 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( trait_ref, bounds[]) } Err(ErrorReported) => { - ty::mk_err() + this.tcx().types.err } } } @@ -1046,7 +1046,7 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( .unwrap() .identifier) .get())[]); - ty::mk_err() + this.tcx().types.err } def::DefAssociatedPath(typ, assoc_ident) => { // FIXME(#19541): in both branches we should consider @@ -1485,8 +1485,8 @@ fn conv_ty_poly_trait_ref<'tcx, AC, RS>( partitioned_bounds); match main_trait_bound { - None => ty::mk_err(), - Some(principal) => ty::mk_trait(this.tcx(), (*principal).clone(), bounds) + None => this.tcx().types.err, + Some(principal) => ty::mk_trait(this.tcx(), principal, bounds) } } diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 4fbae63780068..dc77a1e782bba 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -142,7 +142,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, check_pat(pcx, &**inner, inner_ty); } else { fcx.write_error(pat.id); - check_pat(pcx, &**inner, ty::mk_err()); + check_pat(pcx, &**inner, tcx.types.err); } } ast::PatRegion(ref inner) => { @@ -162,7 +162,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, check_pat(pcx, &**inner, inner_ty); } else { fcx.write_error(pat.id); - check_pat(pcx, &**inner, ty::mk_err()); + check_pat(pcx, &**inner, tcx.types.err); } } ast::PatVec(ref before, ref slice, ref after) => { @@ -285,11 +285,11 @@ pub fn check_match<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, }; if let Some(ref e) = arm.guard { - check_expr_has_type(fcx, &**e, ty::mk_bool()); + check_expr_has_type(fcx, &**e, tcx.types.bool); } if ty::type_is_error(result_ty) || ty::type_is_error(bty) { - ty::mk_err() + tcx.types.err } else { let (origin, expected, found) = match match_src { /* if-let construct without an else block */ @@ -339,7 +339,7 @@ pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &ast::Pat, fcx.write_error(pat.id); for field in fields.iter() { - check_pat(pcx, &*field.node.pat, ty::mk_err()); + check_pat(pcx, &*field.node.pat, tcx.types.err); } return; }, @@ -358,7 +358,7 @@ pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &ast::Pat, fcx.write_error(pat.id); for field in fields.iter() { - check_pat(pcx, &*field.node.pat, ty::mk_err()); + check_pat(pcx, &*field.node.pat, tcx.types.err); } return; } @@ -430,7 +430,7 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &ast::Pat, if let Some(ref subpats) = *subpats { for pat in subpats.iter() { - check_pat(pcx, &**pat, ty::mk_err()); + check_pat(pcx, &**pat, tcx.types.err); } } return; @@ -448,7 +448,7 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &ast::Pat, subpats.len(), if subpats.len() == 1 {""} else {"s"}, kind_name); for pat in subpats.iter() { - check_pat(pcx, &**pat, ty::mk_err()); + check_pat(pcx, &**pat, tcx.types.err); } } else { span_err!(tcx.sess, pat.span, E0023, @@ -458,7 +458,7 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &ast::Pat, arg_tys.len(), if arg_tys.len() == 1 {""} else {"s"}); for pat in subpats.iter() { - check_pat(pcx, &**pat, ty::mk_err()); + check_pat(pcx, &**pat, tcx.types.err); } } } @@ -496,7 +496,7 @@ pub fn check_struct_pat_fields<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, span_note!(tcx.sess, *occupied.get(), "field `{}` previously bound here", token::get_ident(field.ident)); - ty::mk_err() + tcx.types.err } Vacant(vacant) => { vacant.set(span); @@ -506,7 +506,7 @@ pub fn check_struct_pat_fields<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, "struct `{}` does not have a field named `{}`", ty::item_path_str(tcx, struct_id), token::get_ident(field.ident)); - ty::mk_err() + tcx.types.err }) } }; diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index cf6715e2d7320..791ebc5d0ea80 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -342,7 +342,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { } else if num_supplied_types != num_method_types { span_err!(self.tcx().sess, self.span, E0036, "incorrect number of type parameters given for this method"); - Vec::from_elem(num_method_types, ty::mk_err()) + Vec::from_elem(num_method_types, self.tcx().types.err) } else { supplied_method_types } @@ -410,7 +410,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { let method_bounds_substs = match pick.kind { probe::ObjectPick(..) => { let mut temp_substs = all_substs.clone(); - temp_substs.types.get_mut_slice(subst::SelfSpace)[0] = ty::mk_err(); + temp_substs.types.get_mut_slice(subst::SelfSpace)[0] = self.tcx().types.err; temp_substs } _ => { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index bb1b24f4b487a..7a6b2d54dc167 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -386,7 +386,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckItemTypesVisitor<'a, 'tcx> { fn visit_ty(&mut self, t: &ast::Ty) { match t.node { ast::TyFixedLengthVec(_, ref expr) => { - check_const_in_type(self.ccx, &**expr, ty::mk_uint()); + check_const_in_type(self.ccx, &**expr, self.ccx.tcx.types.uint); } _ => {} } @@ -505,7 +505,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for GatherLocalsVisitor<'a, 'tcx> { match t.node { ast::TyFixedLengthVec(ref ty, ref count_expr) => { self.visit_ty(&**ty); - check_expr_with_hint(self.fcx, &**count_expr, ty::mk_uint()); + check_expr_with_hint(self.fcx, &**count_expr, self.fcx.tcx().types.uint); } _ => visit::walk_ty(self, t) } @@ -1766,7 +1766,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.write_ty(node_id, ty::mk_nil(self.tcx())); } pub fn write_error(&self, node_id: ast::NodeId) { - self.write_ty(node_id, ty::mk_err()); + self.write_ty(node_id, self.tcx().types.err); } pub fn require_type_meets(&self, @@ -2072,7 +2072,7 @@ pub fn autoderef<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>, sp: Span, span_err!(fcx.tcx().sess, sp, E0055, "reached the recursion limit while auto-dereferencing {}", base_ty.repr(fcx.tcx())); - (ty::mk_err(), 0, None) + (fcx.tcx().types.err, 0, None) } /// Attempts to resolve a call expression as an overloaded call. @@ -2228,6 +2228,57 @@ fn autoderef_for_index<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>, } } +/// Autoderefs `base_expr`, looking for a `Slice` impl. If it finds one, installs the relevant +/// method info and returns the result type (else None). +fn try_overloaded_slice<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, + method_call: MethodCall, + expr: &ast::Expr, + base_expr: &ast::Expr, + base_ty: Ty<'tcx>, + start_expr: &Option>, + end_expr: &Option>, + mutbl: ast::Mutability) + -> Option> // return type is result of slice +{ + let lvalue_pref = match mutbl { + ast::MutMutable => PreferMutLvalue, + ast::MutImmutable => NoPreference + }; + + let opt_method_ty = + autoderef_for_index(fcx, base_expr, base_ty, lvalue_pref, |adjusted_ty, autoderefref| { + try_overloaded_slice_step(fcx, method_call, expr, base_expr, + adjusted_ty, autoderefref, mutbl, + start_expr, end_expr) + }); + + // Regardless of whether the lookup succeeds, check the method arguments + // so that we have *some* type for each argument. + let method_ty_or_err = opt_method_ty.unwrap_or(fcx.tcx().types.err); + + let mut args = vec![]; + start_expr.as_ref().map(|x| args.push(x)); + end_expr.as_ref().map(|x| args.push(x)); + + check_method_argument_types(fcx, + expr.span, + method_ty_or_err, + expr, + args.as_slice(), + AutorefArgs::Yes, + DontTupleArguments); + + opt_method_ty.map(|method_ty| { + let result_ty = ty::ty_fn_ret(method_ty); + match result_ty { + ty::FnConverging(result_ty) => result_ty, + ty::FnDiverging => { + fcx.tcx().sess.span_bug(expr.span, + "slice trait does not define a `!` return") + } + } + }) +} /// Checks for a `Slice` (or `SliceMut`) impl at the relevant level of autoderef. If it finds one, /// installs method info and returns type of method (else None). @@ -2336,7 +2387,7 @@ fn try_index_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, match ty::index(adjusted_ty) { Some(ty) => { fcx.write_adjustment(base_expr.id, base_expr.span, ty::AdjustDerefRef(adjustment)); - return Some((ty::mk_uint(), ty)); + return Some((fcx.tcx().types.uint, ty)); } None => { } @@ -2398,7 +2449,7 @@ fn lookup_method_for_for_loop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, Err(ref err_string) => { fcx.tcx().sess.span_err(iterator_expr.span, err_string[]); - return ty::mk_err() + return fcx.tcx().types.err } }; @@ -2426,7 +2477,7 @@ fn lookup_method_for_for_loop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, maybe try .iter()", ty_string)[]); } - ty::mk_err() + fcx.tcx().types.err } }; let return_type = check_method_argument_types(fcx, @@ -2447,7 +2498,7 @@ fn lookup_method_for_for_loop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, let return_type = match return_type { ty::FnConverging(return_type) => structurally_resolved_type(fcx, iterator_expr.span, return_type), - ty::FnDiverging => ty::mk_err() + ty::FnDiverging => fcx.tcx().types.err }; match return_type.sty { ty::ty_enum(_, ref substs) @@ -2455,7 +2506,7 @@ fn lookup_method_for_for_loop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, *substs.types.get(subst::TypeSpace, 0) } ty::ty_err => { - ty::mk_err() + fcx.tcx().types.err } _ => { fcx.tcx().sess.span_err(iterator_expr.span, @@ -2463,11 +2514,11 @@ fn lookup_method_for_for_loop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, trait has an unexpected type `{}`", fcx.infcx().ty_to_string(return_type)) []); - ty::mk_err() + fcx.tcx().types.err } } } - None => ty::mk_err() + None => fcx.tcx().types.err } } @@ -2480,7 +2531,7 @@ fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, tuple_arguments: TupleArgumentsFlag) -> ty::FnOutput<'tcx> { if ty::type_is_error(method_fn_ty) { - let err_inputs = err_args(args_no_rcvr.len()); + let err_inputs = err_args(fcx.tcx(), args_no_rcvr.len()); let err_inputs = match tuple_arguments { DontTupleArguments => err_inputs, @@ -2495,7 +2546,7 @@ fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, autoref_args, false, tuple_arguments); - ty::FnConverging(ty::mk_err()) + ty::FnConverging(fcx.tcx().types.err) } else { match method_fn_ty.sty { ty::ty_bare_fn(_, ref fty) => { @@ -2550,7 +2601,7 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, if arg_types.len() == 1 {""} else {"s"}, args.len(), if args.len() == 1 {" was"} else {"s were"}); - err_args(args.len()) + err_args(fcx.tcx(), args.len()) } else { (*arg_types).clone() } @@ -2559,7 +2610,7 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, span_err!(tcx.sess, sp, E0059, "cannot use call notation; the first type parameter \ for the function trait is neither a tuple nor unit"); - err_args(args.len()) + err_args(fcx.tcx(), args.len()) } } } else if expected_arg_count == supplied_arg_count { @@ -2575,7 +2626,7 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, if expected_arg_count == 1 {""} else {"s"}, supplied_arg_count, if supplied_arg_count == 1 {" was"} else {"s were"}); - err_args(supplied_arg_count) + err_args(fcx.tcx(), supplied_arg_count) } } else { span_err!(tcx.sess, sp, E0061, @@ -2584,7 +2635,7 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, if expected_arg_count == 1 {""} else {"s"}, supplied_arg_count, if supplied_arg_count == 1 {" was"} else {"s were"}); - err_args(supplied_arg_count) + err_args(fcx.tcx(), supplied_arg_count) }; debug!("check_argument_types: formal_tys={}", @@ -2640,7 +2691,7 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, // mismatch impl/trait method phase no need to // ICE here. // See: #11450 - formal_ty = ty::mk_err(); + formal_ty = tcx.types.err; } } } @@ -2691,8 +2742,8 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, } // FIXME(#17596) Ty<'tcx> is incorrectly invariant w.r.t 'tcx. -fn err_args<'tcx>(len: uint) -> Vec> { - Vec::from_fn(len, |_| ty::mk_err()) +fn err_args<'tcx>(tcx: &ty::ctxt<'tcx>, len: uint) -> Vec> { + Vec::from_fn(len, |_| tcx.types.err) } fn write_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, @@ -2715,27 +2766,28 @@ fn check_lit<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, match lit.node { ast::LitStr(..) => ty::mk_str_slice(tcx, tcx.mk_region(ty::ReStatic), ast::MutImmutable), ast::LitBinary(..) => { - ty::mk_slice(tcx, tcx.mk_region(ty::ReStatic), - ty::mt{ ty: ty::mk_u8(), mutbl: ast::MutImmutable }) - } - ast::LitByte(_) => ty::mk_u8(), - ast::LitChar(_) => ty::mk_char(), - ast::LitInt(_, ast::SignedIntLit(t, _)) => ty::mk_mach_int(t), - ast::LitInt(_, ast::UnsignedIntLit(t)) => ty::mk_mach_uint(t), + ty::mk_slice(tcx, + tcx.mk_region(ty::ReStatic), + ty::mt{ ty: tcx.types.u8, mutbl: ast::MutImmutable }) + } + ast::LitByte(_) => tcx.types.u8, + ast::LitChar(_) => tcx.types.char, + ast::LitInt(_, ast::SignedIntLit(t, _)) => ty::mk_mach_int(tcx, t), + ast::LitInt(_, ast::UnsignedIntLit(t)) => ty::mk_mach_uint(tcx, t), ast::LitInt(_, ast::UnsuffixedIntLit(_)) => { let opt_ty = expected.map_to_option(fcx, |ty| { match ty.sty { ty::ty_int(_) | ty::ty_uint(_) => Some(ty), - ty::ty_char => Some(ty::mk_mach_uint(ast::TyU8)), - ty::ty_ptr(..) => Some(ty::mk_mach_uint(ast::TyU)), - ty::ty_bare_fn(..) => Some(ty::mk_mach_uint(ast::TyU)), + ty::ty_char => Some(tcx.types.u8), + ty::ty_ptr(..) => Some(tcx.types.uint), + ty::ty_bare_fn(..) => Some(tcx.types.uint), _ => None } }); opt_ty.unwrap_or_else( || ty::mk_int_var(tcx, fcx.infcx().next_int_var_id())) } - ast::LitFloat(_, t) => ty::mk_mach_float(t), + ast::LitFloat(_, t) => ty::mk_mach_float(tcx, t), ast::LitFloatUnsuffixed(_) => { let opt_ty = expected.map_to_option(fcx, |ty| { match ty.sty { @@ -2746,7 +2798,7 @@ fn check_lit<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, opt_ty.unwrap_or_else( || ty::mk_float_var(tcx, fcx.infcx().next_float_var_id())) } - ast::LitBool(_) => ty::mk_bool() + ast::LitBool(_) => tcx.types.bool } } @@ -2921,8 +2973,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, // In that case, we check each argument against "error" in order to // set up all the node type bindings. let error_fn_sig = ty::Binder(FnSig { - inputs: err_args(args.len()), - output: ty::FnConverging(ty::mk_err()), + inputs: err_args(fcx.tcx(), args.len()), + output: ty::FnConverging(fcx.tcx().types.err), variadic: false }); @@ -2989,7 +3041,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, Err(error) => { method::report_error(fcx, method_name.span, expr_t, method_name.node.name, error); fcx.write_error(expr.id); - ty::mk_err() + fcx.tcx().types.err } }; @@ -3015,7 +3067,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, id: ast::NodeId, sp: Span, expected: Expectation<'tcx>) { - check_expr_has_type(fcx, cond_expr, ty::mk_bool()); + check_expr_has_type(fcx, cond_expr, fcx.tcx().types.bool); let expected = expected.adjust_for_branches(fcx); check_block_with_expected(fcx, then_blk, expected); @@ -3042,7 +3094,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, let cond_ty = fcx.expr_ty(cond_expr); let if_ty = if ty::type_is_error(cond_ty) { - ty::mk_err() + fcx.tcx().types.err } else { branches_ty }; @@ -3114,14 +3166,14 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, autoref_args, DontTupleArguments) { ty::FnConverging(result_type) => result_type, - ty::FnDiverging => ty::mk_err() + ty::FnDiverging => fcx.tcx().types.err } } None => { unbound_method(); // Check the args anyway // so we get all the error messages - let expected_ty = ty::mk_err(); + let expected_ty = fcx.tcx().types.err; check_method_argument_types(fcx, op_ex.span, expected_ty, @@ -3129,7 +3181,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, args.as_slice(), autoref_args, DontTupleArguments); - ty::mk_err() + fcx.tcx().types.err } } } @@ -3155,7 +3207,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, if ty::type_is_integral(lhs_t) && ast_util::is_shift_binop(op) { // Shift is a special case: rhs must be uint, no matter what lhs is - check_expr_has_type(fcx, &**rhs, ty::mk_uint()); + check_expr_has_type(fcx, &**rhs, fcx.tcx().types.uint); fcx.write_ty(expr.id, lhs_t); return; } @@ -3182,12 +3234,12 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, lhs_t, None ); - ty::mk_err() + fcx.tcx().types.err } else { lhs_t } } else { - ty::mk_bool() + fcx.tcx().types.bool } }, _ => lhs_t, @@ -3229,7 +3281,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, lhs_t, None); check_expr(fcx, &**rhs); - ty::mk_err() + fcx.tcx().types.err }; fcx.write_ty(expr.id, result_t); @@ -3265,7 +3317,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, ast::BiNe => ("ne", lang.eq_trait()), ast::BiAnd | ast::BiOr => { check_expr(fcx, &**rhs); - return ty::mk_err(); + return tcx.types.err; } }; lookup_op_method(fcx, ex, lhs_resolved_t, token::intern(name), @@ -3438,7 +3490,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, // Typecheck each field. for field in ast_fields.iter() { - let mut expected_field_type = ty::mk_err(); + let mut expected_field_type = tcx.types.err; let pair = class_field_map.get(&field.ident.node.name).map(|x| *x); match pair { @@ -3545,7 +3597,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, base_expr.is_none(), None); if ty::type_is_error(fcx.node_ty(id)) { - struct_type = ty::mk_err(); + struct_type = tcx.types.err; } // Check the base expression if necessary. @@ -3634,7 +3686,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, if !checked { span_err!(tcx.sess, expr.span, E0066, "only the managed heap and exchange heap are currently supported"); - fcx.write_ty(id, ty::mk_err()); + fcx.write_ty(id, tcx.types.err); } } @@ -3734,7 +3786,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, dereferenced", actual) }, oprnd_t, None); } - ty::mk_err() + tcx.types.err } } }; @@ -3791,7 +3843,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, let tm = ty::mt { ty: fcx.expr_ty(&**oprnd), mutbl: mutbl }; let oprnd_t = if ty::type_is_error(tm.ty) { - ty::mk_err() + tcx.types.err } else { // Note: at this point, we cannot say what the best lifetime // is to use for resulting pointer. We want to use the @@ -3909,7 +3961,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, tcx.sess.span_bug(expr.span, "non-desugared ExprIfLet"); } ast::ExprWhile(ref cond, ref body, _) => { - check_expr_has_type(fcx, &**cond, ty::mk_bool()); + check_expr_has_type(fcx, &**cond, tcx.types.bool); check_block_no_value(fcx, &**body); let cond_ty = fcx.expr_ty(&**cond); let body_ty = fcx.node_ty(body.id); @@ -3989,7 +4041,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, } ast::ExprCast(ref e, ref t) => { if let ast::TyFixedLengthVec(_, ref count_expr) = t.node { - check_expr_with_hint(fcx, &**count_expr, ty::mk_uint()); + check_expr_with_hint(fcx, &**count_expr, tcx.types.uint); } check_cast(fcx, expr, &**e, &**t); } @@ -4020,7 +4072,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, fcx.write_ty(id, typ); } ast::ExprRepeat(ref element, ref count_expr) => { - check_expr_has_type(fcx, &**count_expr, ty::mk_uint()); + check_expr_has_type(fcx, &**count_expr, tcx.types.uint); let count = ty::eval_repeat_count(fcx.tcx(), &**count_expr); let uty = match expected { @@ -4824,12 +4876,12 @@ pub fn check_enum_variants(ccx: &CrateCtxt, let inh = static_inherited_fields(ccx); let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), e.id); let declty = match hint { - attr::ReprAny | attr::ReprPacked | attr::ReprExtern => ty::mk_int(), + attr::ReprAny | attr::ReprPacked | attr::ReprExtern => fcx.tcx().types.int, attr::ReprInt(_, attr::SignedInt(ity)) => { - ty::mk_mach_int(ity) + ty::mk_mach_int(fcx.tcx(), ity) } attr::ReprInt(_, attr::UnsignedInt(ity)) => { - ty::mk_mach_uint(ity) + ty::mk_mach_uint(fcx.tcx(), ity) }, }; check_const_with_ty(&fcx, e.span, &**e, declty); @@ -5366,7 +5418,7 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, , found {} parameter(s)", qualifier, required_len, provided_len); substs.types.replace(space, - Vec::from_elem(desired.len(), ty::mk_err())); + Vec::from_elem(desired.len(), fcx.tcx().types.err)); return; } @@ -5450,8 +5502,8 @@ pub fn structurally_resolved_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span, "the type of this value must be known in this \ context".to_string() }, ty, None); - demand::suptype(fcx, sp, ty::mk_err(), ty); - ty = ty::mk_err(); + demand::suptype(fcx, sp, fcx.tcx().types.err, ty); + ty = fcx.tcx().types.err; } ty @@ -5554,7 +5606,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) { let (n_tps, inputs, output) = match name.get() { "breakpoint" => (0, Vec::new(), ty::mk_nil(tcx)), "size_of" | - "pref_align_of" | "min_align_of" => (1u, Vec::new(), ty::mk_uint()), + "pref_align_of" | "min_align_of" => (1u, Vec::new(), ccx.tcx.types.uint), "init" => (1u, Vec::new(), param(ccx, 0)), "uninit" => (1u, Vec::new(), param(ccx, 0)), "forget" => (1u, vec!( param(ccx, 0) ), ty::mk_nil(tcx)), @@ -5570,8 +5622,8 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) { ), ty::mk_nil(tcx)) } - "needs_drop" => (1u, Vec::new(), ty::mk_bool()), - "owns_managed" => (1u, Vec::new(), ty::mk_bool()), + "needs_drop" => (1u, Vec::new(), ccx.tcx.types.bool), + "owns_managed" => (1u, Vec::new(), ccx.tcx.types.bool), "get_tydesc" => { let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) { @@ -5603,7 +5655,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) { ty: param(ccx, 0), mutbl: ast::MutImmutable }), - ty::mk_int() + ccx.tcx.types.int ), ty::mk_ptr(tcx, ty::mt { ty: param(ccx, 0), @@ -5622,7 +5674,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) { ty: param(ccx, 0), mutbl: ast::MutImmutable }), - ty::mk_uint() + tcx.types.uint, ), ty::mk_nil(tcx)) } @@ -5633,88 +5685,88 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) { ty: param(ccx, 0), mutbl: ast::MutMutable }), - ty::mk_u8(), - ty::mk_uint() + tcx.types.u8, + tcx.types.uint, ), ty::mk_nil(tcx)) } - "sqrtf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()), - "sqrtf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()), + "sqrtf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32), + "sqrtf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64), "powif32" => { (0, - vec!( ty::mk_f32(), ty::mk_i32() ), - ty::mk_f32()) + vec!( tcx.types.f32, tcx.types.i32 ), + tcx.types.f32) } "powif64" => { (0, - vec!( ty::mk_f64(), ty::mk_i32() ), - ty::mk_f64()) + vec!( tcx.types.f64, tcx.types.i32 ), + tcx.types.f64) } - "sinf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()), - "sinf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()), - "cosf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()), - "cosf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()), + "sinf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32), + "sinf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64), + "cosf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32), + "cosf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64), "powf32" => { (0, - vec!( ty::mk_f32(), ty::mk_f32() ), - ty::mk_f32()) + vec!( tcx.types.f32, tcx.types.f32 ), + tcx.types.f32) } "powf64" => { (0, - vec!( ty::mk_f64(), ty::mk_f64() ), - ty::mk_f64()) - } - "expf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()), - "expf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()), - "exp2f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()), - "exp2f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()), - "logf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()), - "logf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()), - "log10f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()), - "log10f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()), - "log2f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()), - "log2f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()), + vec!( tcx.types.f64, tcx.types.f64 ), + tcx.types.f64) + } + "expf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32), + "expf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64), + "exp2f32" => (0, vec!( tcx.types.f32 ), tcx.types.f32), + "exp2f64" => (0, vec!( tcx.types.f64 ), tcx.types.f64), + "logf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32), + "logf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64), + "log10f32" => (0, vec!( tcx.types.f32 ), tcx.types.f32), + "log10f64" => (0, vec!( tcx.types.f64 ), tcx.types.f64), + "log2f32" => (0, vec!( tcx.types.f32 ), tcx.types.f32), + "log2f64" => (0, vec!( tcx.types.f64 ), tcx.types.f64), "fmaf32" => { (0, - vec!( ty::mk_f32(), ty::mk_f32(), ty::mk_f32() ), - ty::mk_f32()) + vec!( tcx.types.f32, tcx.types.f32, tcx.types.f32 ), + tcx.types.f32) } "fmaf64" => { (0, - vec!( ty::mk_f64(), ty::mk_f64(), ty::mk_f64() ), - ty::mk_f64()) - } - "fabsf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()), - "fabsf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()), - "copysignf32" => (0, vec!( ty::mk_f32(), ty::mk_f32() ), ty::mk_f32()), - "copysignf64" => (0, vec!( ty::mk_f64(), ty::mk_f64() ), ty::mk_f64()), - "floorf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()), - "floorf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()), - "ceilf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()), - "ceilf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()), - "truncf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()), - "truncf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()), - "rintf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()), - "rintf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()), - "nearbyintf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()), - "nearbyintf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()), - "roundf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()), - "roundf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()), - "ctpop8" => (0, vec!( ty::mk_u8() ), ty::mk_u8()), - "ctpop16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()), - "ctpop32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()), - "ctpop64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()), - "ctlz8" => (0, vec!( ty::mk_u8() ), ty::mk_u8()), - "ctlz16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()), - "ctlz32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()), - "ctlz64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()), - "cttz8" => (0, vec!( ty::mk_u8() ), ty::mk_u8()), - "cttz16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()), - "cttz32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()), - "cttz64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()), - "bswap16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()), - "bswap32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()), - "bswap64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()), + vec!( tcx.types.f64, tcx.types.f64, tcx.types.f64 ), + tcx.types.f64) + } + "fabsf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32), + "fabsf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64), + "copysignf32" => (0, vec!( tcx.types.f32, tcx.types.f32 ), tcx.types.f32), + "copysignf64" => (0, vec!( tcx.types.f64, tcx.types.f64 ), tcx.types.f64), + "floorf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32), + "floorf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64), + "ceilf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32), + "ceilf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64), + "truncf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32), + "truncf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64), + "rintf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32), + "rintf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64), + "nearbyintf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32), + "nearbyintf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64), + "roundf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32), + "roundf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64), + "ctpop8" => (0, vec!( tcx.types.u8 ), tcx.types.u8), + "ctpop16" => (0, vec!( tcx.types.u16 ), tcx.types.u16), + "ctpop32" => (0, vec!( tcx.types.u32 ), tcx.types.u32), + "ctpop64" => (0, vec!( tcx.types.u64 ), tcx.types.u64), + "ctlz8" => (0, vec!( tcx.types.u8 ), tcx.types.u8), + "ctlz16" => (0, vec!( tcx.types.u16 ), tcx.types.u16), + "ctlz32" => (0, vec!( tcx.types.u32 ), tcx.types.u32), + "ctlz64" => (0, vec!( tcx.types.u64 ), tcx.types.u64), + "cttz8" => (0, vec!( tcx.types.u8 ), tcx.types.u8), + "cttz16" => (0, vec!( tcx.types.u16 ), tcx.types.u16), + "cttz32" => (0, vec!( tcx.types.u32 ), tcx.types.u32), + "cttz64" => (0, vec!( tcx.types.u64 ), tcx.types.u64), + "bswap16" => (0, vec!( tcx.types.u16 ), tcx.types.u16), + "bswap32" => (0, vec!( tcx.types.u32 ), tcx.types.u32), + "bswap64" => (0, vec!( tcx.types.u64 ), tcx.types.u64), "volatile_load" => (1, vec!( ty::mk_imm_ptr(tcx, param(ccx, 0)) ), param(ccx, 0)), @@ -5722,40 +5774,40 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) { (1, vec!( ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0) ), ty::mk_nil(tcx)), "i8_add_with_overflow" | "i8_sub_with_overflow" | "i8_mul_with_overflow" => - (0, vec!(ty::mk_i8(), ty::mk_i8()), - ty::mk_tup(tcx, vec!(ty::mk_i8(), ty::mk_bool()))), + (0, vec!(tcx.types.i8, tcx.types.i8), + ty::mk_tup(tcx, vec!(tcx.types.i8, tcx.types.bool))), "i16_add_with_overflow" | "i16_sub_with_overflow" | "i16_mul_with_overflow" => - (0, vec!(ty::mk_i16(), ty::mk_i16()), - ty::mk_tup(tcx, vec!(ty::mk_i16(), ty::mk_bool()))), + (0, vec!(tcx.types.i16, tcx.types.i16), + ty::mk_tup(tcx, vec!(tcx.types.i16, tcx.types.bool))), "i32_add_with_overflow" | "i32_sub_with_overflow" | "i32_mul_with_overflow" => - (0, vec!(ty::mk_i32(), ty::mk_i32()), - ty::mk_tup(tcx, vec!(ty::mk_i32(), ty::mk_bool()))), + (0, vec!(tcx.types.i32, tcx.types.i32), + ty::mk_tup(tcx, vec!(tcx.types.i32, tcx.types.bool))), "i64_add_with_overflow" | "i64_sub_with_overflow" | "i64_mul_with_overflow" => - (0, vec!(ty::mk_i64(), ty::mk_i64()), - ty::mk_tup(tcx, vec!(ty::mk_i64(), ty::mk_bool()))), + (0, vec!(tcx.types.i64, tcx.types.i64), + ty::mk_tup(tcx, vec!(tcx.types.i64, tcx.types.bool))), "u8_add_with_overflow" | "u8_sub_with_overflow" | "u8_mul_with_overflow" => - (0, vec!(ty::mk_u8(), ty::mk_u8()), - ty::mk_tup(tcx, vec!(ty::mk_u8(), ty::mk_bool()))), + (0, vec!(tcx.types.u8, tcx.types.u8), + ty::mk_tup(tcx, vec!(tcx.types.u8, tcx.types.bool))), "u16_add_with_overflow" | "u16_sub_with_overflow" | "u16_mul_with_overflow" => - (0, vec!(ty::mk_u16(), ty::mk_u16()), - ty::mk_tup(tcx, vec!(ty::mk_u16(), ty::mk_bool()))), + (0, vec!(tcx.types.u16, tcx.types.u16), + ty::mk_tup(tcx, vec!(tcx.types.u16, tcx.types.bool))), "u32_add_with_overflow" | "u32_sub_with_overflow" | "u32_mul_with_overflow"=> - (0, vec!(ty::mk_u32(), ty::mk_u32()), - ty::mk_tup(tcx, vec!(ty::mk_u32(), ty::mk_bool()))), + (0, vec!(tcx.types.u32, tcx.types.u32), + ty::mk_tup(tcx, vec!(tcx.types.u32, tcx.types.bool))), "u64_add_with_overflow" | "u64_sub_with_overflow" | "u64_mul_with_overflow" => - (0, vec!(ty::mk_u64(), ty::mk_u64()), - ty::mk_tup(tcx, vec!(ty::mk_u64(), ty::mk_bool()))), + (0, vec!(tcx.types.u64, tcx.types.u64), + ty::mk_tup(tcx, vec!(tcx.types.u64, tcx.types.bool))), - "return_address" => (0, vec![], ty::mk_imm_ptr(tcx, ty::mk_u8())), + "return_address" => (0, vec![], ty::mk_imm_ptr(tcx, tcx.types.u8)), - "assume" => (0, vec![ty::mk_bool()], ty::mk_nil(tcx)), + "assume" => (0, vec![tcx.types.bool], ty::mk_nil(tcx)), ref other => { span_err!(tcx.sess, it.span, E0093, diff --git a/src/librustc_typeck/check/vtable.rs b/src/librustc_typeck/check/vtable.rs index ff16568aa63fc..626845613b41a 100644 --- a/src/librustc_typeck/check/vtable.rs +++ b/src/librustc_typeck/check/vtable.rs @@ -133,7 +133,8 @@ pub fn check_object_safety<'tcx>(tcx: &ty::ctxt<'tcx>, object_trait: &ty::TyTrait<'tcx>, span: Span) { - let object_trait_ref = object_trait.principal_trait_ref_with_self_ty(tcx, ty::mk_err()); + let object_trait_ref = + object_trait.principal_trait_ref_with_self_ty(tcx, tcx.types.err); for tr in traits::supertraits(tcx, object_trait_ref) { check_object_safety_inner(tcx, &*tr, span); } diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index b123d97d8970c..5ef9757b91ac2 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -169,7 +169,7 @@ impl<'cx, 'tcx, 'v> Visitor<'v> for WritebackCx<'cx, 'tcx> { match t.node { ast::TyFixedLengthVec(ref ty, ref count_expr) => { self.visit_ty(&**ty); - write_ty_to_tcx(self.tcx(), count_expr.id, ty::mk_uint()); + write_ty_to_tcx(self.tcx(), count_expr.id, self.tcx().types.uint); } _ => visit::walk_ty(self, t) } @@ -441,7 +441,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Resolver<'cx, 'tcx> { debug!("Resolver::fold_ty: input type `{}` not fully resolvable", t.repr(self.tcx)); self.report_error(e); - ty::mk_err() + self.tcx().types.err } } } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 74cfbb117e9a3..6bbf464441460 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -183,7 +183,7 @@ impl<'a, 'tcx> AstConv<'tcx> for CrateCtxt<'a, 'tcx> { fn ty_infer(&self, span: Span) -> Ty<'tcx> { span_err!(self.tcx.sess, span, E0121, "the type placeholder `_` is not allowed within types on item signatures"); - ty::mk_err() + self.tcx().types.err } fn associated_types_of_trait_are_valid(&self, _: Ty<'tcx>, _: ast::DefId) diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index a903c8b0d55aa..353db82eb027d 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -278,11 +278,11 @@ fn check_start_fn_ty(ccx: &CrateCtxt, abi: abi::Rust, sig: ty::Binder(ty::FnSig { inputs: vec!( - ty::mk_int(), - ty::mk_imm_ptr(tcx, ty::mk_imm_ptr(tcx, ty::mk_u8())) + tcx.types.int, + ty::mk_imm_ptr(tcx, ty::mk_imm_ptr(tcx, tcx.types.u8)) ), - output: ty::FnConverging(ty::mk_int()), - variadic: false + output: ty::FnConverging(tcx.types.int), + variadic: false, }), })); From 4404592f3631233c2f160c3f9a315764a4fcfba9 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 17 Dec 2014 14:16:28 -0500 Subject: [PATCH 08/36] Implement associated type projection and normalization. --- src/librustc/metadata/common.rs | 3 + src/librustc/metadata/decoder.rs | 15 +- src/librustc/metadata/encoder.rs | 9 + src/librustc/metadata/tydecode.rs | 37 +- src/librustc/metadata/tyencode.rs | 28 +- src/librustc/middle/astencode.rs | 10 +- src/librustc/middle/fast_reject.rs | 5 +- src/librustc/middle/infer/combine.rs | 22 + src/librustc/middle/infer/error_reporting.rs | 18 +- src/librustc/middle/infer/freshen.rs | 1 + src/librustc/middle/infer/mod.rs | 17 +- src/librustc/middle/traits/coherence.rs | 11 +- src/librustc/middle/traits/error_reporting.rs | 192 ++-- src/librustc/middle/traits/fulfill.rs | 172 +++- src/librustc/middle/traits/mod.rs | 43 +- src/librustc/middle/traits/project.rs | 374 ++++++++ src/librustc/middle/traits/select.rs | 168 ++-- src/librustc/middle/traits/util.rs | 62 +- src/librustc/middle/ty.rs | 482 +++++++++- src/librustc/middle/ty_fold.rs | 51 +- src/librustc/util/ppaux.rs | 54 +- src/librustc_trans/trans/base.rs | 12 +- src/librustc_trans/trans/callee.rs | 5 +- src/librustc_trans/trans/common.rs | 38 +- src/librustc_trans/trans/context.rs | 8 +- src/librustc_trans/trans/debuginfo.rs | 26 +- src/librustc_trans/trans/expr.rs | 14 +- src/librustc_trans/trans/foreign.rs | 11 +- src/librustc_trans/trans/meth.rs | 21 +- src/librustc_trans/trans/monomorphize.rs | 94 +- src/librustc_trans/trans/type_of.rs | 3 +- src/librustc_typeck/astconv.rs | 454 +++++---- src/librustc_typeck/check/_match.rs | 21 +- src/librustc_typeck/check/assoc.rs | 73 ++ src/librustc_typeck/check/closure.rs | 17 +- src/librustc_typeck/check/method/confirm.rs | 30 +- src/librustc_typeck/check/method/mod.rs | 10 +- src/librustc_typeck/check/method/probe.rs | 25 +- src/librustc_typeck/check/mod.rs | 190 ++-- src/librustc_typeck/check/regionmanip.rs | 9 + src/librustc_typeck/check/vtable.rs | 9 +- src/librustc_typeck/check/wf.rs | 30 +- src/librustc_typeck/coherence/mod.rs | 5 +- src/librustc_typeck/coherence/orphan.rs | 4 +- src/librustc_typeck/collect.rs | 880 ++---------------- src/librustc_typeck/variance.rs | 31 +- src/librustdoc/clean/mod.rs | 12 + ...assoc-eq-1.rs => associated-types-eq-1.rs} | 0 ...assoc-eq-2.rs => associated-types-eq-2.rs} | 0 ...assoc-eq-3.rs => associated-types-eq-3.rs} | 0 ...th.rs => associated-types-eq-expr-path.rs} | 0 .../associated-types-for-unimpl-trait.rs | 25 + .../associated-types-in-wrong-context.rs | 3 - ...c-path-1.rs => associated-types-path-1.rs} | 0 ...c-path-2.rs => associated-types-path-2.rs} | 0 src/test/run-pass/associated-types-basic.rs | 26 + ...ssociated-types-binding-in-where-clause.rs | 47 + .../associated-types-constant-type.rs | 42 + src/test/run-pass/associated-types-eq-obj.rs | 34 + ...assoc-eq.rs => associated-types-return.rs} | 11 +- ...path.rs => associated-types-sugar-path.rs} | 0 61 files changed, 2478 insertions(+), 1516 deletions(-) create mode 100644 src/librustc/middle/traits/project.rs create mode 100644 src/librustc_typeck/check/assoc.rs rename src/test/compile-fail/{assoc-eq-1.rs => associated-types-eq-1.rs} (100%) rename src/test/compile-fail/{assoc-eq-2.rs => associated-types-eq-2.rs} (100%) rename src/test/compile-fail/{assoc-eq-3.rs => associated-types-eq-3.rs} (100%) rename src/test/compile-fail/{assoc-eq-expr-path.rs => associated-types-eq-expr-path.rs} (100%) create mode 100644 src/test/compile-fail/associated-types-for-unimpl-trait.rs rename src/test/compile-fail/{assoc-path-1.rs => associated-types-path-1.rs} (100%) rename src/test/compile-fail/{assoc-path-2.rs => associated-types-path-2.rs} (100%) create mode 100644 src/test/run-pass/associated-types-basic.rs create mode 100644 src/test/run-pass/associated-types-binding-in-where-clause.rs create mode 100644 src/test/run-pass/associated-types-constant-type.rs create mode 100644 src/test/run-pass/associated-types-eq-obj.rs rename src/test/run-pass/{assoc-eq.rs => associated-types-return.rs} (89%) rename src/test/run-pass/{assoc-sugar-path.rs => associated-types-sugar-path.rs} (100%) diff --git a/src/librustc/metadata/common.rs b/src/librustc/metadata/common.rs index 03e436e98df46..2a58da8cb3be7 100644 --- a/src/librustc/metadata/common.rs +++ b/src/librustc/metadata/common.rs @@ -256,3 +256,6 @@ pub const tag_predicate_space: uint = 0xa9; pub const tag_predicate_data: uint = 0xb0; pub const tag_unsafety: uint = 0xb1; + +pub const tag_associated_type_names: uint = 0xb2; +pub const tag_associated_type_name: uint = 0xb3; diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index ce04a9029929d..fe0a2beb9ab21 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -369,6 +369,17 @@ fn parse_unsafety(item_doc: rbml::Doc) -> ast::Unsafety { } } +fn parse_associated_type_names(item_doc: rbml::Doc) -> Vec { + let names_doc = reader::get_doc(item_doc, tag_associated_type_names); + let mut names = Vec::new(); + reader::tagged_docs(names_doc, tag_associated_type_name, |name_doc| { + let name = token::intern(name_doc.as_str_slice()); + names.push(name); + true + }); + names +} + pub fn get_trait_def<'tcx>(cdata: Cmd, item_id: ast::NodeId, tcx: &ty::ctxt<'tcx>) -> ty::TraitDef<'tcx> @@ -377,12 +388,14 @@ pub fn get_trait_def<'tcx>(cdata: Cmd, let generics = doc_generics(item_doc, tcx, cdata, tag_item_generics); let bounds = trait_def_bounds(item_doc, tcx, cdata); let unsafety = parse_unsafety(item_doc); + let associated_type_names = parse_associated_type_names(item_doc); ty::TraitDef { unsafety: unsafety, generics: generics, bounds: bounds, - trait_ref: Rc::new(item_trait_ref(item_doc, tcx, cdata)) + trait_ref: Rc::new(item_trait_ref(item_doc, tcx, cdata)), + associated_type_names: associated_type_names, } } diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 6d79419b38634..e541768b3578e 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -1316,6 +1316,7 @@ fn encode_info_for_item(ecx: &EncodeContext, encode_item_variances(rbml_w, ecx, item.id); let trait_def = ty::lookup_trait_def(tcx, def_id); encode_unsafety(rbml_w, trait_def.unsafety); + encode_associated_type_names(rbml_w, trait_def.associated_type_names.as_slice()); encode_generics(rbml_w, ecx, &trait_def.generics, tag_item_generics); encode_trait_ref(rbml_w, ecx, &*trait_def.trait_ref, tag_item_trait_ref); encode_name(rbml_w, item.ident.name); @@ -1689,6 +1690,14 @@ fn encode_unsafety(rbml_w: &mut Encoder, unsafety: ast::Unsafety) { rbml_w.wr_tagged_u8(tag_unsafety, byte); } +fn encode_associated_type_names(rbml_w: &mut Encoder, names: &[ast::Name]) { + rbml_w.start_tag(tag_associated_type_names); + for &name in names.iter() { + rbml_w.wr_tagged_str(tag_associated_type_name, token::get_name(name).get()); + } + rbml_w.end_tag(); +} + fn encode_crate_deps(rbml_w: &mut Encoder, cstore: &cstore::CStore) { fn get_ordered_deps(cstore: &cstore::CStore) -> Vec { // Pull the cnums and name,vers,hash out of cstore diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs index 01cde5138c533..7daef30e25325 100644 --- a/src/librustc/metadata/tydecode.rs +++ b/src/librustc/metadata/tydecode.rs @@ -504,6 +504,12 @@ fn parse_ty<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did) -> Ty<'tcx> { return ty::mk_unboxed_closure(st.tcx, did, st.tcx.mk_region(region), st.tcx.mk_substs(substs)); } + 'P' => { + assert_eq!(next(st), '['); + let trait_ref = parse_trait_ref(st, |x,y| conv(x,y)); + let name = token::str_to_ident(parse_str(st, ']').as_slice()).name; + return ty::mk_projection(tcx, trait_ref, name); + } 'e' => { return tcx.types.err; } @@ -683,17 +689,32 @@ pub fn parse_predicate<'a,'tcx>(st: &mut PState<'a, 'tcx>, -> ty::Predicate<'tcx> { match next(st) { - 't' => Rc::new(ty::Binder(parse_trait_ref(st, conv))).as_predicate(), + 't' => ty::Binder(Rc::new(parse_trait_ref(st, conv))).as_predicate(), 'e' => ty::Binder(ty::EquatePredicate(parse_ty(st, |x,y| conv(x,y)), parse_ty(st, |x,y| conv(x,y)))).as_predicate(), 'r' => ty::Binder(ty::OutlivesPredicate(parse_region(st, |x,y| conv(x,y)), parse_region(st, |x,y| conv(x,y)))).as_predicate(), 'o' => ty::Binder(ty::OutlivesPredicate(parse_ty(st, |x,y| conv(x,y)), parse_region(st, |x,y| conv(x,y)))).as_predicate(), + 'p' => ty::Binder(parse_projection_predicate(st, conv)).as_predicate(), c => panic!("Encountered invalid character in metadata: {}", c) } } +fn parse_projection_predicate<'a,'tcx>( + st: &mut PState<'a, 'tcx>, + conv: conv_did) + -> ty::ProjectionPredicate<'tcx> +{ + ty::ProjectionPredicate { + projection_ty: ty::ProjectionTy { + trait_ref: Rc::new(parse_trait_ref(st, |x,y| conv(x,y))), + item_name: token::str_to_ident(parse_str(st, '|').as_slice()).name, + }, + ty: parse_ty(st, |x,y| conv(x,y)), + } +} + pub fn parse_type_param_def_data<'tcx>(data: &[u8], start: uint, crate_num: ast::CrateNum, tcx: &ty::ctxt<'tcx>, conv: conv_did) -> ty::TypeParameterDef<'tcx> @@ -710,10 +731,6 @@ fn parse_type_param_def<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did) assert_eq!(next(st), '|'); let index = parse_u32(st); assert_eq!(next(st), '|'); - let associated_with = parse_opt(st, |st| { - parse_def(st, NominalType, |x,y| conv(x,y)) - }); - assert_eq!(next(st), '|'); let bounds = parse_bounds(st, |x,y| conv(x,y)); let default = parse_opt(st, |st| parse_ty(st, |x,y| conv(x,y))); @@ -722,7 +739,6 @@ fn parse_type_param_def<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did) def_id: def_id, space: space, index: index, - associated_with: associated_with, bounds: bounds, default: default } @@ -768,7 +784,8 @@ fn parse_bounds<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did) let mut param_bounds = ty::ParamBounds { region_bounds: Vec::new(), builtin_bounds: builtin_bounds, - trait_bounds: Vec::new() + trait_bounds: Vec::new(), + projection_bounds: Vec::new(), }; loop { match next(st) { @@ -778,7 +795,11 @@ fn parse_bounds<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did) } 'I' => { param_bounds.trait_bounds.push( - Rc::new(ty::Binder(parse_trait_ref(st, |x,y| conv(x,y))))); + ty::Binder(Rc::new(parse_trait_ref(st, |x,y| conv(x,y))))); + } + 'P' => { + param_bounds.projection_bounds.push( + ty::Binder(parse_projection_predicate(st, |x,y| conv(x,y)))); } '.' => { return param_bounds; diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs index 3e9eaf7eea207..6d2b7e0ba93f6 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -149,6 +149,11 @@ pub fn enc_ty<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>, t: Ty<'t enc_substs(w, cx, substs); mywrite!(w, "]"); } + ty::ty_projection(ref data) => { + mywrite!(w, "P["); + enc_trait_ref(w, cx, &data.trait_ref); + mywrite!(w, "{}]", token::get_name(data.item_name)); + } ty::ty_err => { mywrite!(w, "e"); } @@ -403,7 +408,12 @@ pub fn enc_bounds<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>, for tp in bs.trait_bounds.iter() { mywrite!(w, "I"); - enc_trait_ref(w, cx, &tp.0); + enc_trait_ref(w, cx, &*tp.0); + } + + for tp in bs.projection_bounds.iter() { + mywrite!(w, "P"); + enc_projection_predicate(w, cx, &tp.0); } mywrite!(w, "."); @@ -414,8 +424,6 @@ pub fn enc_type_param_def<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tc mywrite!(w, "{}:{}|{}|{}|", token::get_name(v.name), (cx.ds)(v.def_id), v.space.to_uint(), v.index); - enc_opt(w, v.associated_with, |w, did| mywrite!(w, "{}", (cx.ds)(did))); - mywrite!(w, "|"); enc_bounds(w, cx, &v.bounds); enc_opt(w, v.default, |w, t| enc_ty(w, cx, t)); } @@ -427,7 +435,7 @@ pub fn enc_predicate<'a, 'tcx>(w: &mut SeekableMemWriter, match *p { ty::Predicate::Trait(ref trait_ref) => { mywrite!(w, "t"); - enc_trait_ref(w, cx, &trait_ref.0); + enc_trait_ref(w, cx, &*trait_ref.0.trait_ref); } ty::Predicate::Equate(ty::Binder(ty::EquatePredicate(a, b))) => { mywrite!(w, "e"); @@ -444,5 +452,17 @@ pub fn enc_predicate<'a, 'tcx>(w: &mut SeekableMemWriter, enc_ty(w, cx, a); enc_region(w, cx, b); } + ty::Predicate::Projection(ty::Binder(ref data)) => { + mywrite!(w, "p"); + enc_projection_predicate(w, cx, data) + } } } + +fn enc_projection_predicate<'a, 'tcx>(w: &mut SeekableMemWriter, + cx: &ctxt<'a, 'tcx>, + data: &ty::ProjectionPredicate<'tcx>) { + enc_trait_ref(w, cx, &*data.projection_ty.trait_ref); + mywrite!(w, "{}|", token::get_name(data.projection_ty.item_name)); + enc_ty(w, cx, data.ty); +} diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index a135701a9c435..57dac607fa6b7 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -1284,7 +1284,7 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext, rbml_w.tag(c::tag_table_object_cast_map, |rbml_w| { rbml_w.id(id); rbml_w.tag(c::tag_table_val, |rbml_w| { - rbml_w.emit_trait_ref(ecx, &trait_ref.0); + rbml_w.emit_trait_ref(ecx, &*trait_ref.0); }) }) } @@ -1364,7 +1364,7 @@ trait rbml_decoder_decoder_helpers<'tcx> { fn read_trait_ref<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>) -> Rc>; fn read_poly_trait_ref<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>) - -> Rc>; + -> ty::PolyTraitRef<'tcx>; fn read_type_param_def<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>) -> ty::TypeParameterDef<'tcx>; fn read_predicate<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>) @@ -1558,8 +1558,8 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> { } fn read_poly_trait_ref<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>) - -> Rc> { - Rc::new(ty::Binder(self.read_opaque(|this, doc| { + -> ty::PolyTraitRef<'tcx> { + ty::Binder(Rc::new(self.read_opaque(|this, doc| { let ty = tydecode::parse_trait_ref_data( doc.data, dcx.cdata.cnum, @@ -1786,7 +1786,7 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> { Ok(this.read_poly_trait_ref(dcx)) })); Ok(ty::TyTrait { - principal: (*principal).clone(), + principal: ty::Binder((*principal.0).clone()), bounds: try!(this.read_struct_field("bounds", 1, |this| { Ok(this.read_existential_bounds(dcx)) })), diff --git a/src/librustc/middle/fast_reject.rs b/src/librustc/middle/fast_reject.rs index 62cf47da68701..dcbd94b8482fd 100644 --- a/src/librustc/middle/fast_reject.rs +++ b/src/librustc/middle/fast_reject.rs @@ -58,7 +58,7 @@ pub fn simplify_type(tcx: &ty::ctxt, ty::ty_vec(..) => Some(VecSimplifiedType), ty::ty_ptr(_) => Some(PtrSimplifiedType), ty::ty_trait(ref trait_info) => { - Some(TraitSimplifiedType(trait_info.principal.def_id())) + Some(TraitSimplifiedType(trait_info.principal_def_id())) } ty::ty_struct(def_id, _) => { Some(StructSimplifiedType(def_id)) @@ -86,6 +86,9 @@ pub fn simplify_type(tcx: &ty::ctxt, ty::ty_bare_fn(_, ref f) => { Some(FunctionSimplifiedType(f.sig.0.inputs.len())) } + ty::ty_projection(_) => { + None + } ty::ty_param(_) => { if can_simplify_params { Some(ParameterSimplifiedType) diff --git a/src/librustc/middle/infer/combine.rs b/src/librustc/middle/infer/combine.rs index 9f5eca142c36c..8ff2d0ba1f0d8 100644 --- a/src/librustc/middle/infer/combine.rs +++ b/src/librustc/middle/infer/combine.rs @@ -51,6 +51,7 @@ use middle::ty_fold; use middle::ty_fold::{TypeFoldable}; use util::ppaux::Repr; +use std::rc::Rc; use syntax::ast::{Onceness, Unsafety}; use syntax::ast; use syntax::abi; @@ -358,6 +359,18 @@ pub trait Combineable<'tcx> : Repr<'tcx> + TypeFoldable<'tcx> { fn combine>(combiner: &C, a: &Self, b: &Self) -> cres<'tcx, Self>; } +impl<'tcx,T> Combineable<'tcx> for Rc + where T : Combineable<'tcx> +{ + fn combine>(combiner: &C, + a: &Rc, + b: &Rc) + -> cres<'tcx, Rc> + { + Ok(Rc::new(try!(Combineable::combine(combiner, &**a, &**b)))) + } +} + impl<'tcx> Combineable<'tcx> for ty::TraitRef<'tcx> { fn combine>(combiner: &C, a: &ty::TraitRef<'tcx>, @@ -581,6 +594,15 @@ pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C, }) } + (&ty::ty_projection(ref a_data), &ty::ty_projection(ref b_data)) => { + if a_data.item_name == b_data.item_name { + let trait_ref = try!(this.trait_refs(&a_data.trait_ref, &b_data.trait_ref)); + Ok(ty::mk_projection(tcx, trait_ref, a_data.item_name)) + } else { + Err(ty::terr_sorts(expected_found(this, a, b))) + } + } + _ => Err(ty::terr_sorts(expected_found(this, a, b))) }; diff --git a/src/librustc/middle/infer/error_reporting.rs b/src/librustc/middle/infer/error_reporting.rs index 3d3eac7b6ed9f..e38b721ce2d0d 100644 --- a/src/librustc/middle/infer/error_reporting.rs +++ b/src/librustc/middle/infer/error_reporting.rs @@ -1437,6 +1437,11 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> { format!(" for {}in generic type", bound_region_to_string(self.tcx, "lifetime parameter ", true, br)) } + infer::LateBoundRegion(_, br, infer::AssocTypeProjection(type_name)) => { + format!(" for {}in trait containing associated type `{}`", + bound_region_to_string(self.tcx, "lifetime parameter ", true, br), + token::get_name(type_name)) + } infer::EarlyBoundRegion(_, name) => { format!(" for lifetime parameter `{}`", token::get_name(name).get()) @@ -1661,13 +1666,16 @@ impl<'tcx> Resolvable<'tcx> for Rc> { } } -impl<'tcx> Resolvable<'tcx> for Rc> { - fn resolve<'a>(&self, infcx: &InferCtxt<'a, 'tcx>) - -> Rc> { - Rc::new(infcx.resolve_type_vars_if_possible(&**self)) +impl<'tcx> Resolvable<'tcx> for ty::PolyTraitRef<'tcx> { + fn resolve<'a>(&self, + infcx: &InferCtxt<'a, 'tcx>) + -> ty::PolyTraitRef<'tcx> + { + infcx.resolve_type_vars_if_possible(self) } + fn contains_error(&self) -> bool { - ty::trait_ref_contains_error(&self.0) + ty::trait_ref_contains_error(&*self.0) } } diff --git a/src/librustc/middle/infer/freshen.rs b/src/librustc/middle/infer/freshen.rs index d8455b8db71ed..33174409f899b 100644 --- a/src/librustc/middle/infer/freshen.rs +++ b/src/librustc/middle/infer/freshen.rs @@ -157,6 +157,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> { ty::ty_struct(..) | ty::ty_unboxed_closure(..) | ty::ty_tup(..) | + ty::ty_projection(..) | ty::ty_param(..) => { ty_fold::super_fold_ty(self, t) } diff --git a/src/librustc/middle/infer/mod.rs b/src/librustc/middle/infer/mod.rs index 2231c0088e725..cf9520ecfbbde 100644 --- a/src/librustc/middle/infer/mod.rs +++ b/src/librustc/middle/infer/mod.rs @@ -139,7 +139,7 @@ pub enum TypeOrigin { pub enum ValuePairs<'tcx> { Types(ty::expected_found>), TraitRefs(ty::expected_found>>), - PolyTraitRefs(ty::expected_found>>), + PolyTraitRefs(ty::expected_found>), } /// The trace designates the path through inference that we took to @@ -231,6 +231,9 @@ pub enum LateBoundRegionConversionTime { /// when two higher-ranked types are compared HigherRankedType, + + /// when projecting an associated type + AssocTypeProjection(ast::Name), } /// Reasons to create a region inference variable @@ -407,8 +410,8 @@ pub fn mk_eqty<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>, pub fn mk_sub_poly_trait_refs<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>, a_is_expected: bool, origin: TypeOrigin, - a: Rc>, - b: Rc>) + a: ty::PolyTraitRef<'tcx>, + b: ty::PolyTraitRef<'tcx>) -> ures<'tcx> { debug!("mk_sub_trait_refs({} <: {})", @@ -703,8 +706,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { pub fn sub_poly_trait_refs(&self, a_is_expected: bool, origin: TypeOrigin, - a: Rc>, - b: Rc>) + a: ty::PolyTraitRef<'tcx>, + b: ty::PolyTraitRef<'tcx>) -> ures<'tcx> { debug!("sub_poly_trait_refs({} <: {})", @@ -715,7 +718,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { origin: origin, values: PolyTraitRefs(expected_found(a_is_expected, a.clone(), b.clone())) }; - self.sub(a_is_expected, trace).binders(&*a, &*b).to_ures() + self.sub(a_is_expected, trace).binders(&a, &b).to_ures() }) } @@ -750,7 +753,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { -> T where T : TypeFoldable<'tcx> + Repr<'tcx> { - /*! See `higher_ranked::leak_check` */ + /*! See `higher_ranked::plug_leaks` */ higher_ranked::plug_leaks(self, skol_map, snapshot, value) } diff --git a/src/librustc/middle/traits/coherence.rs b/src/librustc/middle/traits/coherence.rs index d48685ce27d89..d8b39d92c692f 100644 --- a/src/librustc/middle/traits/coherence.rs +++ b/src/librustc/middle/traits/coherence.rs @@ -45,7 +45,9 @@ pub fn impl_can_satisfy(infcx: &InferCtxt, let param_env = ty::empty_parameter_environment(); let mut selcx = SelectionContext::intercrate(infcx, ¶m_env, infcx.tcx); let obligation = Obligation::new(ObligationCause::dummy(), - Rc::new(ty::Binder(impl1_trait_ref))); + ty::Binder(ty::TraitPredicate { + trait_ref: Rc::new(impl1_trait_ref), + })); debug!("impl_can_satisfy(obligation={})", obligation.repr(infcx.tcx)); selcx.evaluate_impl(impl2_def_id, &obligation) } @@ -140,7 +142,7 @@ pub fn ty_is_local<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool { } ty::ty_trait(ref tt) => { - tt.principal.def_id().krate == ast::LOCAL_CRATE + tt.principal_def_id().krate == ast::LOCAL_CRATE } // Type parameters may be bound to types that are not local to @@ -149,6 +151,11 @@ pub fn ty_is_local<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool { false } + // Associated types could be anything, I guess. + ty::ty_projection(..) => { + false + } + ty::ty_infer(..) | ty::ty_open(..) | ty::ty_err => { diff --git a/src/librustc/middle/traits/error_reporting.rs b/src/librustc/middle/traits/error_reporting.rs index 462857de1d4f8..a3d92c698a2ad 100644 --- a/src/librustc/middle/traits/error_reporting.rs +++ b/src/librustc/middle/traits/error_reporting.rs @@ -8,12 +8,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use super::{FulfillmentError, FulfillmentErrorCode, - ObligationCauseCode, SelectionError, - PredicateObligation, OutputTypeParameterMismatch}; +use super::{ + FulfillmentError, + FulfillmentErrorCode, + MismatchedProjectionTypes, + ObligationCauseCode, + OutputTypeParameterMismatch, + PredicateObligation, + SelectionError, +}; use middle::infer::InferCtxt; -use middle::ty::{mod}; +use middle::ty::{mod, AsPredicate, ReferencesError, ToPolyTraitRef}; use syntax::codemap::Span; use util::ppaux::{Repr, UserString}; @@ -30,12 +36,32 @@ fn report_fulfillment_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>, FulfillmentErrorCode::CodeSelectionError(ref e) => { report_selection_error(infcx, &error.obligation, e); } + FulfillmentErrorCode::CodeProjectionError(ref e) => { + report_projection_error(infcx, &error.obligation, e); + } FulfillmentErrorCode::CodeAmbiguity => { maybe_report_ambiguity(infcx, &error.obligation); } } } +pub fn report_projection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>, + obligation: &PredicateObligation<'tcx>, + error: &MismatchedProjectionTypes<'tcx>) +{ + let predicate = + infcx.resolve_type_vars_if_possible(&obligation.predicate); + if !predicate.references_error() { + infcx.tcx.sess.span_err( + obligation.cause.span, + format!( + "type mismatch resolving `{}`: {}", + predicate.user_string(infcx.tcx), + ty::type_err_to_str(infcx.tcx, &error.err)).as_slice()); + note_obligation_cause(infcx, obligation); + } +} + pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>, obligation: &PredicateObligation<'tcx>, error: &SelectionError<'tcx>) @@ -43,38 +69,13 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>, match *error { SelectionError::Overflow => { // We could track the stack here more precisely if we wanted, I imagine. - match obligation.trait_ref { - ty::Predicate::Trait(ref trait_ref) => { - let trait_ref = - infcx.resolve_type_vars_if_possible(&**trait_ref); - infcx.tcx.sess.span_err( - obligation.cause.span, - format!( - "overflow evaluating the trait `{}` for the type `{}`", - trait_ref.user_string(infcx.tcx), - trait_ref.self_ty().user_string(infcx.tcx))[]); - } - - ty::Predicate::Equate(ref predicate) => { - let predicate = infcx.resolve_type_vars_if_possible(predicate); - let err = infcx.equality_predicate(obligation.cause.span, - &predicate).unwrap_err(); - - infcx.tcx.sess.span_err( - obligation.cause.span, - format!( - "the requirement `{}` is not satisfied (`{}`)", - predicate.user_string(infcx.tcx), - ty::type_err_to_str(infcx.tcx, &err)).as_slice()); - } - - ty::Predicate::TypeOutlives(..) | - ty::Predicate::RegionOutlives(..) => { - infcx.tcx.sess.span_err( - obligation.cause.span, - format!("overflow evaluating lifetime predicate").as_slice()); - } - } + let predicate = + infcx.resolve_type_vars_if_possible(&obligation.predicate); + infcx.tcx.sess.span_err( + obligation.cause.span, + format!( + "overflow evaluating the requirement `{}`", + predicate.user_string(infcx.tcx)).as_slice()); let current_limit = infcx.tcx.sess.recursion_limit.get(); let suggested_limit = current_limit * 2; @@ -87,27 +88,37 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>, note_obligation_cause(infcx, obligation); } SelectionError::Unimplemented => { - match obligation.trait_ref { - ty::Predicate::Trait(ref trait_ref) => { - let trait_ref = - infcx.resolve_type_vars_if_possible( - &**trait_ref); - if !ty::type_is_error(trait_ref.self_ty()) { + match obligation.predicate { + ty::Predicate::Trait(ref trait_predicate) => { + let trait_predicate = + infcx.resolve_type_vars_if_possible(trait_predicate); + if !trait_predicate.references_error() { + let trait_ref = trait_predicate.to_poly_trait_ref(); infcx.tcx.sess.span_err( obligation.cause.span, format!( "the trait `{}` is not implemented for the type `{}`", trait_ref.user_string(infcx.tcx), trait_ref.self_ty().user_string(infcx.tcx)).as_slice()); - note_obligation_cause(infcx, obligation); } } ty::Predicate::Equate(ref predicate) => { let predicate = infcx.resolve_type_vars_if_possible(predicate); let err = infcx.equality_predicate(obligation.cause.span, - &predicate).unwrap_err(); + &predicate).unwrap_err(); + infcx.tcx.sess.span_err( + obligation.cause.span, + format!( + "the requirement `{}` is not satisfied (`{}`)", + predicate.user_string(infcx.tcx), + ty::type_err_to_str(infcx.tcx, &err)).as_slice()); + } + ty::Predicate::RegionOutlives(ref predicate) => { + let predicate = infcx.resolve_type_vars_if_possible(predicate); + let err = infcx.region_outlives_predicate(obligation.cause.span, + &predicate).unwrap_err(); infcx.tcx.sess.span_err( obligation.cause.span, format!( @@ -116,9 +127,10 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>, ty::type_err_to_str(infcx.tcx, &err)).as_slice()); } - ty::Predicate::TypeOutlives(..) | - ty::Predicate::RegionOutlives(..) => { - let predicate = infcx.resolve_type_vars_if_possible(&obligation.trait_ref); + ty::Predicate::Projection(..) | + ty::Predicate::TypeOutlives(..) => { + let predicate = + infcx.resolve_type_vars_if_possible(&obligation.predicate); infcx.tcx.sess.span_err( obligation.cause.span, format!( @@ -128,12 +140,8 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>, } } OutputTypeParameterMismatch(ref expected_trait_ref, ref actual_trait_ref, ref e) => { - let expected_trait_ref = - infcx.resolve_type_vars_if_possible( - &**expected_trait_ref); - let actual_trait_ref = - infcx.resolve_type_vars_if_possible( - &**actual_trait_ref); + let expected_trait_ref = infcx.resolve_type_vars_if_possible(&*expected_trait_ref); + let actual_trait_ref = infcx.resolve_type_vars_if_possible(&*actual_trait_ref); if !ty::type_is_error(actual_trait_ref.self_ty()) { infcx.tcx.sess.span_err( obligation.cause.span, @@ -150,24 +158,26 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>, } } -fn maybe_report_ambiguity<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>, - obligation: &PredicateObligation<'tcx>) { +pub fn maybe_report_ambiguity<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>, + obligation: &PredicateObligation<'tcx>) { // Unable to successfully determine, probably means // insufficient type information, but could mean // ambiguous impls. The latter *ought* to be a // coherence violation, so we don't report it here. - let trait_ref = match obligation.trait_ref { - ty::Predicate::Trait(ref trait_ref) => { - infcx.resolve_type_vars_if_possible(&**trait_ref) + let trait_ref = match obligation.predicate { + ty::Predicate::Trait(ref trait_predicate) => { + infcx.resolve_type_vars_if_possible( + &trait_predicate.to_poly_trait_ref()) } _ => { infcx.tcx.sess.span_bug( obligation.cause.span, format!("ambiguity from something other than a trait: {}", - obligation.trait_ref.repr(infcx.tcx)).as_slice()); + obligation.predicate.repr(infcx.tcx)).as_slice()); } }; + let self_ty = trait_ref.self_ty(); debug!("maybe_report_ambiguity(trait_ref={}, self_ty={}, obligation={})", @@ -208,7 +218,7 @@ fn maybe_report_ambiguity<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>, locate the impl of the trait `{}` for \ the type `{}`; type annotations required", trait_ref.user_string(infcx.tcx), - self_ty.user_string(infcx.tcx))[]); + self_ty.user_string(infcx.tcx)).as_slice()); note_obligation_cause(infcx, obligation); } } @@ -221,56 +231,38 @@ fn maybe_report_ambiguity<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>, cannot locate the impl of the trait `{}` for \ the type `{}`", trait_ref.user_string(infcx.tcx), - self_ty.user_string(infcx.tcx))[]); + self_ty.user_string(infcx.tcx)).as_slice()); } } fn note_obligation_cause<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>, obligation: &PredicateObligation<'tcx>) { - let trait_ref = match obligation.trait_ref { - ty::Predicate::Trait(ref trait_ref) => { - infcx.resolve_type_vars_if_possible(&**trait_ref) - } - _ => { - infcx.tcx.sess.span_bug( - obligation.cause.span, - format!("ambiguity from something other than a trait: {}", - obligation.trait_ref.repr(infcx.tcx)).as_slice()); - } - }; - note_obligation_cause_code(infcx, - &trait_ref, + &obligation.predicate, obligation.cause.span, - &obligation.cause.code) + &obligation.cause.code); } fn note_obligation_cause_code<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>, - trait_ref: &ty::PolyTraitRef<'tcx>, + _predicate: &ty::Predicate<'tcx>, cause_span: Span, cause_code: &ObligationCauseCode<'tcx>) { let tcx = infcx.tcx; - let trait_name = ty::item_path_str(tcx, trait_ref.def_id()); match *cause_code { ObligationCauseCode::MiscObligation => { } ObligationCauseCode::ItemObligation(item_def_id) => { let item_name = ty::item_path_str(tcx, item_def_id); tcx.sess.span_note( cause_span, - format!( - "the trait `{}` must be implemented because it is required by `{}`", - trait_name, - item_name).as_slice()); + format!("required by `{}`", item_name).as_slice()); } ObligationCauseCode::ObjectCastObligation(object_ty) => { tcx.sess.span_note( cause_span, format!( - "the trait `{}` must be implemented for the cast \ - to the object type `{}`", - trait_name, + "required for the cast to the object type `{}`", infcx.ty_to_string(object_ty)).as_slice()); } ObligationCauseCode::RepeatVec => { @@ -323,27 +315,23 @@ fn note_obligation_cause_code<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>, span_note!(tcx.sess, cause_span, "shared static variables must have a type that implements `Sync`"); } - ObligationCauseCode::BuiltinDerivedObligation(ref root_trait_ref, ref root_cause_code) => { - let root_trait_ref = - infcx.resolve_type_vars_if_possible(&**root_trait_ref); + ObligationCauseCode::BuiltinDerivedObligation(ref data) => { + let parent_trait_ref = infcx.resolve_type_vars_if_possible(&data.parent_trait_ref); span_note!(tcx.sess, cause_span, - "the type `{}` must implement `{}` because it appears within the type `{}`", - trait_ref.self_ty().user_string(infcx.tcx), - trait_ref.user_string(infcx.tcx), - root_trait_ref.self_ty().user_string(infcx.tcx)); - note_obligation_cause_code(infcx, &root_trait_ref, cause_span, &**root_cause_code); + "required because it appears within the type `{}`", + parent_trait_ref.0.self_ty().user_string(infcx.tcx)); + let parent_predicate = parent_trait_ref.as_predicate(); + note_obligation_cause_code(infcx, &parent_predicate, cause_span, &*data.parent_code); } - ObligationCauseCode::ImplDerivedObligation(ref root_trait_ref, ref root_cause_code) => { - let root_trait_ref = - infcx.resolve_type_vars_if_possible(&**root_trait_ref); + ObligationCauseCode::ImplDerivedObligation(ref data) => { + let parent_trait_ref = infcx.resolve_type_vars_if_possible(&data.parent_trait_ref); span_note!(tcx.sess, cause_span, - "the type `{}` must implement `{}` due to the requirements \ - on the impl of `{}` for the type `{}`", - trait_ref.self_ty().user_string(infcx.tcx), - trait_ref.user_string(infcx.tcx), - root_trait_ref.user_string(infcx.tcx), - root_trait_ref.self_ty().user_string(infcx.tcx)); - note_obligation_cause_code(infcx, &root_trait_ref, cause_span, &**root_cause_code); + "required because of the requirements on the impl of `{}` for `{}`", + parent_trait_ref.user_string(infcx.tcx), + parent_trait_ref.0.self_ty().user_string(infcx.tcx)); + let parent_predicate = parent_trait_ref.as_predicate(); + note_obligation_cause_code(infcx, &parent_predicate, cause_span, &*data.parent_code); } } } + diff --git a/src/librustc/middle/traits/fulfill.rs b/src/librustc/middle/traits/fulfill.rs index 6c80a22536a34..e5024e000df0d 100644 --- a/src/librustc/middle/traits/fulfill.rs +++ b/src/librustc/middle/traits/fulfill.rs @@ -8,9 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use middle::infer::InferCtxt; +use middle::infer::{mod, InferCtxt}; use middle::mem_categorization::Typer; -use middle::ty::{mod, Ty}; +use middle::ty::{mod, AsPredicate, RegionEscape, Ty, ToPolyTraitRef}; use std::collections::HashSet; use std::collections::hash_map::Entry::{Occupied, Vacant}; use std::default::Default; @@ -21,15 +21,16 @@ use util::ppaux::Repr; use util::nodemap::NodeMap; use super::CodeAmbiguity; +use super::CodeProjectionError; use super::CodeSelectionError; use super::FulfillmentError; use super::Obligation; use super::ObligationCause; use super::PredicateObligation; -use super::Selection; +use super::project; use super::select::SelectionContext; -use super::poly_trait_ref_for_builtin_bound; use super::Unimplemented; +use super::util::predicate_for_builtin_bound; /// The fulfillment context is used to drive trait resolution. It /// consists of a list of obligations that must be (eventually) @@ -101,35 +102,41 @@ impl<'tcx> FulfillmentContext<'tcx> { } } + pub fn normalize_associated_type<'a>(&mut self, + infcx: &InferCtxt<'a,'tcx>, + trait_ref: Rc>, + item_name: ast::Name, + cause: ObligationCause<'tcx>) + -> Ty<'tcx> + { + assert!(!trait_ref.has_escaping_regions()); + + let ty_var = infcx.next_ty_var(); + let projection = + ty::Binder(ty::ProjectionPredicate { + projection_ty: ty::ProjectionTy { trait_ref: trait_ref, + item_name: item_name }, + ty: ty_var + }); + let obligation = Obligation::new(cause, projection.as_predicate()); + self.register_predicate(infcx.tcx, obligation); + ty_var + } + pub fn register_builtin_bound(&mut self, tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>, builtin_bound: ty::BuiltinBound, cause: ObligationCause<'tcx>) { - match poly_trait_ref_for_builtin_bound(tcx, builtin_bound, ty) { - Ok(trait_ref) => { - self.register_trait_ref(tcx, trait_ref, cause); + match predicate_for_builtin_bound(tcx, cause, builtin_bound, 0, ty) { + Ok(predicate) => { + self.register_predicate(tcx, predicate); } Err(ErrorReported) => { } } } - pub fn register_trait_ref<'a>(&mut self, - tcx: &ty::ctxt<'tcx>, - trait_ref: Rc>, - cause: ObligationCause<'tcx>) - { - /*! - * A convenience function for registering trait obligations. - */ - - let trait_obligation = Obligation { cause: cause, - recursion_depth: 0, - predicate: ty::Predicate::Trait(trait_ref) }; - self.register_predicate(tcx, trait_obligation) - } - pub fn register_region_obligation(&mut self, tcx: &ty::ctxt<'tcx>, t_a: Ty<'tcx>, @@ -232,7 +239,7 @@ impl<'tcx> FulfillmentContext<'tcx> { debug!("select_where_possible({} obligations) iteration", count); - let mut selections = Vec::new(); + let mut new_obligations = Vec::new(); // If we are only attempting obligations we haven't seen yet, // then set `skip` to the number of obligations we've already @@ -253,7 +260,7 @@ impl<'tcx> FulfillmentContext<'tcx> { let processed = if skip == 0 { process_predicate(selcx, predicate, - &mut selections, &mut errors, region_obligations) + &mut new_obligations, &mut errors, region_obligations) } else { skip -= 1; false @@ -271,8 +278,8 @@ impl<'tcx> FulfillmentContext<'tcx> { // Now go through all the successful ones, // registering any nested obligations for the future. - for selection in selections.into_iter() { - selection.map_move_nested(|p| self.register_predicate(tcx, p)); + for new_obligation in new_obligations.into_iter() { + self.register_predicate(tcx, new_obligation); } } @@ -290,7 +297,7 @@ impl<'tcx> FulfillmentContext<'tcx> { fn process_predicate<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>, obligation: &PredicateObligation<'tcx>, - selections: &mut Vec>, + new_obligations: &mut Vec>, errors: &mut Vec>, region_obligations: &mut NodeMap>>) -> bool @@ -304,14 +311,14 @@ fn process_predicate<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>, let tcx = selcx.tcx(); match obligation.predicate { - ty::Predicate::Trait(ref trait_ref) => { - let trait_obligation = obligation.with(trait_ref.clone()); + ty::Predicate::Trait(ref data) => { + let trait_obligation = obligation.with(data.clone()); match selcx.select(&trait_obligation) { Ok(None) => { false } Ok(Some(s)) => { - selections.push(s); + s.map_move_nested(|p| new_obligations.push(p)); true } Err(selection_err) => { @@ -372,6 +379,111 @@ fn process_predicate<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>, } true } + + ty::Predicate::Projection(ref data) => { + let project_obligation = obligation.with(data.clone()); + let result = project::poly_project_and_unify_type(selcx, &project_obligation); + debug!("poly_project_and_unify_type({}) = {}", + project_obligation.repr(tcx), + result.repr(tcx)); + match result { + Ok(()) => { + true + } + Err(project::ProjectionError::TooManyCandidates) => { + // Without more type information, we can't say much. + false + } + Err(project::ProjectionError::NoCandidate) => { + // This means that we have a type like `::name = U` but we couldn't find any more + // information. This could just be that we're in a + // function like: + // + // fn foo(...) + // + // in which case this is not an error. But it + // might also mean we're in a situation where we + // don't actually know that `T : Trait` holds, + // which would be weird (e.g., if `T` was not a + // parameter type but a normal type, like `int`). + // + // So what we do is to (1) add a requirement that + // `T : Trait` (just in case) and (2) try to unify + // `U` with `::name`. + + if !ty::binds_late_bound_regions(selcx.tcx(), data) { + // Check that `T : Trait` holds. + let trait_ref = data.to_poly_trait_ref(); + new_obligations.push(obligation.with(trait_ref.as_predicate())); + + // Fallback to `::name`. If this + // fails, then the output must be at least + // somewhat constrained, and we cannot verify + // that constraint, so yield an error. + let ty_projection = ty::mk_projection(tcx, + (*trait_ref.0).clone(), + data.0.projection_ty.item_name); + + debug!("process_predicate: falling back to projection {}", + ty_projection.repr(selcx.tcx())); + + match infer::mk_eqty(selcx.infcx(), + true, + infer::EquatePredicate(obligation.cause.span), + ty_projection, + data.0.ty) { + Ok(()) => { } + Err(_) => { + debug!("process_predicate: fallback failed to unify; error"); + errors.push( + FulfillmentError::new( + obligation.clone(), + CodeSelectionError(Unimplemented))); + } + } + + true + } else { + // If we have something like + // + // for<'a> as Trait>::name == &'a int + // + // there is no "canonical form" for us to + // make, so just report the lack of candidates + // as an error. + + debug!("process_predicate: can't fallback, higher-ranked"); + errors.push( + FulfillmentError::new( + obligation.clone(), + CodeSelectionError(Unimplemented))); + + true + } + } + Err(project::ProjectionError::MismatchedTypes(e)) => { + errors.push( + FulfillmentError::new( + obligation.clone(), + CodeProjectionError(e))); + true + } + Err(project::ProjectionError::TraitSelectionError(e)) => { + // Extract just the `T : Trait` from `::Name == U`, so that when we report an + // error to the user, it says something like "`T : + // Trait` not satisfied".5D + let trait_predicate = data.to_poly_trait_ref(); + let trait_obligation = obligation.with(trait_predicate.as_predicate()); + errors.push( + FulfillmentError::new( + trait_obligation, + CodeSelectionError(e))); + true + } + } + } } } diff --git a/src/librustc/middle/traits/mod.rs b/src/librustc/middle/traits/mod.rs index 41c55abc9ae0f..b7e2304849a14 100644 --- a/src/librustc/middle/traits/mod.rs +++ b/src/librustc/middle/traits/mod.rs @@ -18,28 +18,32 @@ pub use self::ObligationCauseCode::*; use middle::subst; use middle::ty::{mod, Ty}; use middle::infer::InferCtxt; -use std::rc::Rc; use std::slice::Iter; +use std::rc::Rc; use syntax::ast; use syntax::codemap::{Span, DUMMY_SP}; use util::ppaux::Repr; pub use self::error_reporting::report_fulfillment_errors; pub use self::fulfill::{FulfillmentContext, RegionObligation}; +pub use self::project::MismatchedProjectionTypes; +pub use self::project::project_type; +pub use self::project::ProjectionResult; pub use self::select::SelectionContext; pub use self::select::SelectionCache; pub use self::select::{MethodMatchResult, MethodMatched, MethodAmbiguous, MethodDidNotMatch}; pub use self::select::{MethodMatchedData}; // intentionally don't export variants pub use self::util::elaborate_predicates; +pub use self::util::trait_ref_for_builtin_bound; pub use self::util::supertraits; pub use self::util::Supertraits; pub use self::util::search_trait_and_supertraits_from_bound; pub use self::util::transitive_bounds; -pub use self::util::poly_trait_ref_for_builtin_bound; mod coherence; mod error_reporting; mod fulfill; +mod project; mod select; mod util; @@ -57,7 +61,7 @@ pub struct Obligation<'tcx, T> { } pub type PredicateObligation<'tcx> = Obligation<'tcx, ty::Predicate<'tcx>>; -pub type TraitObligation<'tcx> = Obligation<'tcx, Rc>>; +pub type TraitObligation<'tcx> = Obligation<'tcx, ty::PolyTraitPredicate<'tcx>>; /// Why did we incur this obligation? Used for error reporting. #[deriving(Clone)] @@ -107,9 +111,18 @@ pub enum ObligationCauseCode<'tcx> { // static items must have `Sync` type SharedStatic, - BuiltinDerivedObligation(Rc>, Rc>), + BuiltinDerivedObligation(DerivedObligationCause<'tcx>), - ImplDerivedObligation(Rc>, Rc>), + ImplDerivedObligation(DerivedObligationCause<'tcx>), +} + +#[deriving(Clone)] +pub struct DerivedObligationCause<'tcx> { + /// Resolving this trait led to the current obligation + parent_trait_ref: ty::PolyTraitRef<'tcx>, + + /// The parent trait had this cause + parent_code: Rc> } pub type Obligations<'tcx, O> = subst::VecPerParamSpace>; @@ -122,8 +135,8 @@ pub type Selection<'tcx> = Vtable<'tcx, PredicateObligation<'tcx>>; pub enum SelectionError<'tcx> { Unimplemented, Overflow, - OutputTypeParameterMismatch(Rc>, - Rc>, + OutputTypeParameterMismatch(ty::PolyTraitRef<'tcx>, + ty::PolyTraitRef<'tcx>, ty::type_err<'tcx>), } @@ -135,6 +148,7 @@ pub struct FulfillmentError<'tcx> { #[deriving(Clone)] pub enum FulfillmentErrorCode<'tcx> { CodeSelectionError(SelectionError<'tcx>), + CodeProjectionError(MismatchedProjectionTypes<'tcx>), CodeAmbiguity, } @@ -235,7 +249,7 @@ pub struct VtableBuiltinData { #[deriving(PartialEq,Eq,Clone)] pub struct VtableParamData<'tcx> { // In the above example, this would `Eq` - pub bound: Rc>, + pub bound: ty::PolyTraitRef<'tcx>, } /// True if neither the trait nor self type is local. Note that `impl_def_id` must refer to an impl @@ -324,12 +338,6 @@ impl<'tcx,O> Obligation<'tcx,O> { } } -impl<'tcx> TraitObligation<'tcx> { - pub fn self_ty(&self) -> Ty<'tcx> { - self.predicate.self_ty() - } -} - impl<'tcx> ObligationCause<'tcx> { pub fn new(span: Span, body_id: ast::NodeId, @@ -441,6 +449,13 @@ impl<'tcx> FulfillmentError<'tcx> { CodeAmbiguity => false, CodeSelectionError(Overflow) => true, CodeSelectionError(_) => false, + CodeProjectionError(_) => false, } } } + +impl<'tcx> TraitObligation<'tcx> { + fn self_ty(&self) -> Ty<'tcx> { + self.predicate.0.self_ty() + } +} diff --git a/src/librustc/middle/traits/project.rs b/src/librustc/middle/traits/project.rs new file mode 100644 index 0000000000000..083227d02bd06 --- /dev/null +++ b/src/librustc/middle/traits/project.rs @@ -0,0 +1,374 @@ +// Copyright 2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Code for projecting associated types out of trait references. + +use super::elaborate_predicates; +use super::Obligation; +use super::PredicateObligation; +use super::SelectionContext; +use super::SelectionError; +use super::VtableImplData; + +use middle::infer; +use middle::subst::Subst; +use middle::ty::{mod, ToPolyTraitRef, Ty}; +use std::fmt; +use util::ppaux::Repr; + +pub type PolyProjectionObligation<'tcx> = + Obligation<'tcx, ty::PolyProjectionPredicate<'tcx>>; + +pub type ProjectionObligation<'tcx> = + Obligation<'tcx, ty::ProjectionPredicate<'tcx>>; + +pub type ProjectionTyObligation<'tcx> = + Obligation<'tcx, ty::ProjectionTy<'tcx>>; + +/// When attempting to resolve `::Name == U`... +pub enum ProjectionError<'tcx> { + NoCandidate, + TooManyCandidates, + + /// + MismatchedTypes(MismatchedProjectionTypes<'tcx>), + + /// ...an error occurred matching `T : TraitRef` + TraitSelectionError(SelectionError<'tcx>), +} + +#[deriving(Clone)] +pub struct MismatchedProjectionTypes<'tcx> { + pub err: ty::type_err<'tcx> // TODO expected/actual/etc +} + +pub type ProjectionResult<'tcx, T> = Result>; + +enum ProjectionTyCandidate<'tcx> { + ParamEnv(ty::PolyProjectionPredicate<'tcx>), + Impl(VtableImplData<'tcx, PredicateObligation<'tcx>>), +} + +struct ProjectionTyCandidateSet<'tcx> { + vec: Vec>, + ambiguous: bool +} + +pub fn poly_project_and_unify_type<'cx,'tcx>( + selcx: &mut SelectionContext<'cx,'tcx>, + obligation: &PolyProjectionObligation<'tcx>) + -> ProjectionResult<'tcx, ()> +{ + debug!("poly_project(obligation={})", + obligation.repr(selcx.tcx())); + + let infcx = selcx.infcx(); + + infcx.try(|snapshot| { + let (skol_predicate, skol_map) = + infcx.skolemize_late_bound_regions(&obligation.predicate, snapshot); + + let skol_obligation = obligation.with(skol_predicate); + let () = try!(project_and_unify_type(selcx, &skol_obligation)); + match infcx.leak_check(&skol_map, snapshot) { + Ok(()) => Ok(()), + Err(e) => Err(ProjectionError::MismatchedTypes(MismatchedProjectionTypes{err: e})), + } + }) +} + +/// Compute result of projecting an associated type and unify it with +/// `obligation.predicate.ty` (if we can). +pub fn project_and_unify_type<'cx,'tcx>( + selcx: &mut SelectionContext<'cx,'tcx>, + obligation: &ProjectionObligation<'tcx>) + -> ProjectionResult<'tcx, ()> +{ + debug!("project_and_unify(obligation={})", + obligation.repr(selcx.tcx())); + + let ty_obligation = obligation.with(obligation.predicate.projection_ty.clone()); + let projected_ty = try!(project_type(selcx, &ty_obligation)); + let infcx = selcx.infcx(); + let origin = infer::RelateOutputImplTypes(obligation.cause.span); + debug!("project_and_unify_type: projected_ty = {}", projected_ty.repr(selcx.tcx())); + match infer::mk_eqty(infcx, true, origin, projected_ty, obligation.predicate.ty) { + Ok(()) => Ok(()), + Err(e) => Err(ProjectionError::MismatchedTypes(MismatchedProjectionTypes{err: e})), + } +} + +/// Compute the result of a projection type (if we can). +pub fn project_type<'cx,'tcx>( + selcx: &mut SelectionContext<'cx,'tcx>, + obligation: &ProjectionTyObligation<'tcx>) + -> ProjectionResult<'tcx, Ty<'tcx>> +{ + debug!("project(obligation={})", + obligation.repr(selcx.tcx())); + + let mut candidates = ProjectionTyCandidateSet { + vec: Vec::new(), + ambiguous: false, + }; + + let () = assemble_candidates_from_param_env(selcx, + obligation, + &mut candidates); + + let () = try!(assemble_candidates_from_impls(selcx, + obligation, + &mut candidates)); + + debug!("{} candidates, ambiguous={}", + candidates.vec.len(), + candidates.ambiguous); + + // We probably need some winnowing logic similar to select here. + + if candidates.ambiguous || candidates.vec.len() > 1 { + return Err(ProjectionError::TooManyCandidates); + } + + match candidates.vec.pop() { + Some(candidate) => { + Ok(try!(confirm_candidate(selcx, obligation, candidate))) + } + None => { + Err(ProjectionError::NoCandidate) + } + } +} + +/// The first thing we have to do is scan through the parameter +/// environment to see whether there are any projection predicates +/// there that can answer this question. +fn assemble_candidates_from_param_env<'cx,'tcx>( + selcx: &mut SelectionContext<'cx,'tcx>, + obligation: &ProjectionTyObligation<'tcx>, + candidate_set: &mut ProjectionTyCandidateSet<'tcx>) +{ + let infcx = selcx.infcx(); + let env_predicates = selcx.param_env().caller_bounds.predicates.clone(); + let env_predicates = env_predicates.iter().cloned().collect(); + for predicate in elaborate_predicates(selcx.tcx(), env_predicates) { + match predicate { + ty::Predicate::Projection(ref data) => { + let is_match = infcx.probe(|_| { + let origin = infer::Misc(obligation.cause.span); + let obligation_poly_trait_ref = + obligation.predicate.trait_ref.to_poly_trait_ref(); + let data_poly_trait_ref = + data.to_poly_trait_ref(); + infcx.sub_poly_trait_refs(false, + origin, + obligation_poly_trait_ref, + data_poly_trait_ref).is_ok() + }); + + if is_match { + candidate_set.vec.push( + ProjectionTyCandidate::ParamEnv(data.clone())); + } + } + _ => { } + } + } +} + +fn assemble_candidates_from_impls<'cx,'tcx>( + selcx: &mut SelectionContext<'cx,'tcx>, + obligation: &ProjectionTyObligation<'tcx>, + candidate_set: &mut ProjectionTyCandidateSet<'tcx>) + -> ProjectionResult<'tcx, ()> +{ + // If we are resolving `>::Item == Type`, + // start out by selecting the predicate `T as TraitRef<...>`: + let trait_ref = + obligation.predicate.trait_ref.to_poly_trait_ref(); + let trait_obligation = + obligation.with(trait_ref.to_poly_trait_predicate()); + let vtable = match selcx.select(&trait_obligation) { + Ok(Some(vtable)) => vtable, + Ok(None) => { + candidate_set.ambiguous = true; + return Ok(()); + } + Err(e) => { + debug!("assemble_candidates_from_impls: selection error {}", + e.repr(selcx.tcx())); + return Err(ProjectionError::TraitSelectionError(e)); + } + }; + + match vtable { + super::VtableImpl(data) => { + candidate_set.vec.push( + ProjectionTyCandidate::Impl(data)); + } + super::VtableParam(..) => { + // This case tell us nothing about the value of an + // associated type. Consider: + // + // ``` + // trait SomeTrait { type Foo; } + // fn foo(...) { } + // ``` + // + // If the user writes `::Foo`, then the `T + // : SomeTrait` binding does not help us decide what the + // type `Foo` is (at least, not more specifically than + // what we already knew). + // + // But wait, you say! What about an example like this: + // + // ``` + // fn bar>(...) { ... } + // ``` + // + // Doesn't the `T : Sometrait` predicate help + // resolve `T::Foo`? And of course it does, but in fact + // that single predicate is desugared into two predicates + // in the compiler: a trait predicate (`T : SomeTrait`) and a + // projection. And the projection where clause is handled + // in `assemble_candidates_from_param_env`. + } + super::VtableBuiltin(..) | + super::VtableUnboxedClosure(..) | + super::VtableFnPointer(..) => { + // These traits have no associated types. + selcx.tcx().sess.span_bug( + obligation.cause.span, + format!("Cannot project an associated type from `{}`", + vtable.repr(selcx.tcx())).as_slice()); + } + } + + Ok(()) +} + +fn confirm_candidate<'cx,'tcx>( + selcx: &mut SelectionContext<'cx,'tcx>, + obligation: &ProjectionTyObligation<'tcx>, + candidate: ProjectionTyCandidate<'tcx>) + -> ProjectionResult<'tcx, Ty<'tcx>> +{ + let infcx = selcx.infcx(); + + debug!("confirm_candidate(candidate={}, obligation={})", + candidate.repr(infcx.tcx), + obligation.repr(infcx.tcx)); + + let projected_ty = match candidate { + ProjectionTyCandidate::ParamEnv(poly_projection) => { + let projection = + infcx.replace_late_bound_regions_with_fresh_var( + obligation.cause.span, + infer::LateBoundRegionConversionTime::HigherRankedType, + &poly_projection).0; + + assert_eq!(projection.projection_ty.item_name, + obligation.predicate.item_name); + + let origin = infer::RelateOutputImplTypes(obligation.cause.span); + match infcx.sub_trait_refs(false, + origin, + obligation.predicate.trait_ref.clone(), + projection.projection_ty.trait_ref.clone()) { + Ok(()) => { } + Err(e) => { + selcx.tcx().sess.span_bug( + obligation.cause.span, + format!("Failed to unify `{}` and `{}` in projection: {}", + obligation.repr(selcx.tcx()), + projection.repr(selcx.tcx()), + ty::type_err_to_str(selcx.tcx(), &e)).as_slice()); + } + } + + projection.ty + } + + ProjectionTyCandidate::Impl(impl_vtable) => { + // there don't seem to be nicer accessors to these: + let impl_items_map = selcx.tcx().impl_items.borrow(); + let impl_or_trait_items_map = selcx.tcx().impl_or_trait_items.borrow(); + + let impl_items = &impl_items_map[impl_vtable.impl_def_id]; + let mut impl_ty = None; + for impl_item in impl_items.iter() { + let assoc_type = match impl_or_trait_items_map[impl_item.def_id()] { + ty::TypeTraitItem(ref assoc_type) => assoc_type.clone(), + ty::MethodTraitItem(..) => { continue; } + }; + + if assoc_type.name != obligation.predicate.item_name { + continue; + } + + let impl_poly_ty = ty::lookup_item_type(selcx.tcx(), assoc_type.def_id); + impl_ty = Some(impl_poly_ty.ty.subst(selcx.tcx(), &impl_vtable.substs)); + break; + } + + match impl_ty { + Some(ty) => ty, + None => { + selcx.tcx().sess.span_bug( + obligation.cause.span, + format!("impl `{}` did not contain projection for `{}`", + impl_vtable.repr(selcx.tcx()), + obligation.repr(selcx.tcx())).as_slice()); + } + } + } + }; + + Ok(projected_ty) +} + +impl<'tcx> Repr<'tcx> for super::MismatchedProjectionTypes<'tcx> { + fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String { + self.err.repr(tcx) + } +} + +impl<'tcx> Repr<'tcx> for ProjectionError<'tcx> { + fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String { + match *self { + ProjectionError::NoCandidate => + format!("NoCandidate"), + ProjectionError::TooManyCandidates => + format!("NoCandidate"), + ProjectionError::MismatchedTypes(ref m) => + format!("MismatchedTypes({})", m.repr(tcx)), + ProjectionError::TraitSelectionError(ref e) => + format!("TraitSelectionError({})", e.repr(tcx)), + } + } +} + +impl<'tcx> fmt::Show for super::MismatchedProjectionTypes<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "MismatchedProjectionTypes(..)") + } +} + +impl<'tcx> Repr<'tcx> for ProjectionTyCandidate<'tcx> { + fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String { + match *self { + ProjectionTyCandidate::ParamEnv(ref data) => + format!("ParamEnv({})", data.repr(tcx)), + ProjectionTyCandidate::Impl(ref data) => + format!("Impl({})", data.repr(tcx)) + } + } +} + diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index a22a602ddff25..2a3bb3c80c894 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -13,10 +13,11 @@ pub use self::MethodMatchResult::*; pub use self::MethodMatchedData::*; -use self::Candidate::*; +use self::SelectionCandidate::*; use self::BuiltinBoundConditions::*; use self::EvaluationResult::*; +use super::{DerivedObligationCause}; use super::{PredicateObligation, Obligation, TraitObligation, ObligationCause}; use super::{ObligationCauseCode, BuiltinDerivedObligation}; use super::{SelectionError, Unimplemented, Overflow, OutputTypeParameterMismatch}; @@ -29,7 +30,7 @@ use super::{util}; use middle::fast_reject; use middle::mem_categorization::Typer; use middle::subst::{Subst, Substs, VecPerParamSpace}; -use middle::ty::{mod, AsPredicate, RegionEscape, Ty}; +use middle::ty::{mod, AsPredicate, RegionEscape, ToPolyTraitRef, Ty}; use middle::infer; use middle::infer::{InferCtxt, TypeFreshener}; use middle::ty_fold::TypeFoldable; @@ -75,15 +76,15 @@ struct TraitObligationStack<'prev, 'tcx: 'prev> { /// Trait ref from `obligation` but skolemized with the /// selection-context's freshener. Used to check for recursion. - fresh_trait_ref: Rc>, + fresh_trait_ref: ty::PolyTraitRef<'tcx>, previous: Option<&'prev TraitObligationStack<'prev, 'tcx>> } #[deriving(Clone)] pub struct SelectionCache<'tcx> { - hashmap: RefCell>, - SelectionResult<'tcx, Candidate<'tcx>>>>, + hashmap: RefCell>, + SelectionResult<'tcx, SelectionCandidate<'tcx>>>>, } pub enum MethodMatchResult { @@ -128,7 +129,7 @@ pub enum MethodMatchedData { /// clauses can give additional information (like, the types of output /// parameters) that would have to be inferred from the impl. #[deriving(PartialEq,Eq,Show,Clone)] -enum Candidate<'tcx> { +enum SelectionCandidate<'tcx> { BuiltinCandidate(ty::BuiltinBound), ParamCandidate(VtableParamData<'tcx>), ImplCandidate(ast::DefId), @@ -144,8 +145,8 @@ enum Candidate<'tcx> { ErrorCandidate, } -struct CandidateSet<'tcx> { - vec: Vec>, +struct SelectionCandidateSet<'tcx> { + vec: Vec>, ambiguous: bool } @@ -193,6 +194,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.infcx } + pub fn param_env(&self) -> &'cx ty::ParameterEnvironment<'tcx> { + self.param_env + } + pub fn tcx(&self) -> &'cx ty::ctxt<'tcx> { self.infcx.tcx } @@ -302,6 +307,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // evaluating trait matches EvaluatedToOk } + + ty::Predicate::Projection(..) => { + // FIXME(#20296) -- we should be able to give a more precise answer here + EvaluatedToAmbig + } } } @@ -411,9 +421,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.infcx.probe(|snapshot| { let (skol_obligation_trait_ref, skol_map) = - self.infcx().skolemize_late_bound_regions(&*obligation.predicate, snapshot); + self.infcx().skolemize_late_bound_regions(&obligation.predicate, snapshot); match self.match_impl(impl_def_id, obligation, snapshot, - &skol_map, Rc::new(skol_obligation_trait_ref)) { + &skol_map, skol_obligation_trait_ref.trait_ref.clone()) { Ok(substs) => { let vtable_impl = self.vtable_impl(impl_def_id, substs, @@ -439,7 +449,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn candidate_from_obligation<'o>(&mut self, stack: &TraitObligationStack<'o, 'tcx>) - -> SelectionResult<'tcx, Candidate<'tcx>> + -> SelectionResult<'tcx, SelectionCandidate<'tcx>> { // Watch out for overflow. This intentionally bypasses (and does // not update) the cache. @@ -455,17 +465,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // separately rather than using `stack.fresh_trait_ref` -- this // is because we want the unbound variables to be replaced // with fresh skolemized types starting from index 0. - let cache_fresh_trait_ref = + let cache_fresh_trait_pred = self.infcx.freshen(stack.obligation.predicate.clone()); - debug!("candidate_from_obligation(cache_fresh_trait_ref={}, obligation={})", - cache_fresh_trait_ref.repr(self.tcx()), + debug!("candidate_from_obligation(cache_fresh_trait_pred={}, obligation={})", + cache_fresh_trait_pred.repr(self.tcx()), stack.repr(self.tcx())); assert!(!stack.obligation.predicate.has_escaping_regions()); - match self.check_candidate_cache(cache_fresh_trait_ref.clone()) { + match self.check_candidate_cache(&cache_fresh_trait_pred) { Some(c) => { - debug!("CACHE HIT: cache_fresh_trait_ref={}, candidate={}", - cache_fresh_trait_ref.repr(self.tcx()), + debug!("CACHE HIT: cache_fresh_trait_pred={}, candidate={}", + cache_fresh_trait_pred.repr(self.tcx()), c.repr(self.tcx())); return c; } @@ -474,17 +484,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // If no match, compute result and insert into cache. let candidate = self.candidate_from_obligation_no_cache(stack); - debug!("CACHE MISS: cache_fresh_trait_ref={}, candidate={}", - cache_fresh_trait_ref.repr(self.tcx()), candidate.repr(self.tcx())); - self.insert_candidate_cache(cache_fresh_trait_ref, candidate.clone()); + debug!("CACHE MISS: cache_fresh_trait_pred={}, candidate={}", + cache_fresh_trait_pred.repr(self.tcx()), candidate.repr(self.tcx())); + self.insert_candidate_cache(cache_fresh_trait_pred, candidate.clone()); candidate } fn candidate_from_obligation_no_cache<'o>(&mut self, stack: &TraitObligationStack<'o, 'tcx>) - -> SelectionResult<'tcx, Candidate<'tcx>> + -> SelectionResult<'tcx, SelectionCandidate<'tcx>> { - if ty::type_is_error(stack.obligation.self_ty()) { + if ty::type_is_error(stack.obligation.predicate.0.self_ty()) { return Ok(Some(ErrorCandidate)); } @@ -576,7 +586,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } fn pick_candidate_cache(&self, - cache_fresh_trait_ref: &Rc>) + cache_fresh_trait_pred: &ty::PolyTraitPredicate<'tcx>) -> &SelectionCache<'tcx> { // High-level idea: we have to decide whether to consult the @@ -598,7 +608,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // If the trait refers to any parameters in scope, then use // the cache of the param-environment. if - cache_fresh_trait_ref.0.input_types().iter().any( + cache_fresh_trait_pred.0.input_types().iter().any( |&t| ty::type_has_self(t) || ty::type_has_params(t)) { return &self.param_env.selection_cache; @@ -611,7 +621,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // See the discussion in doc.rs for more details. if !self.param_env.caller_bounds.is_empty() && - cache_fresh_trait_ref.0.input_types().iter().any( + cache_fresh_trait_pred.0.input_types().iter().any( |&t| ty::type_has_ty_infer(t)) { return &self.param_env.selection_cache; @@ -622,32 +632,32 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } fn check_candidate_cache(&mut self, - cache_fresh_trait_ref: Rc>) - -> Option>> + cache_fresh_trait_pred: &ty::PolyTraitPredicate<'tcx>) + -> Option>> { - let cache = self.pick_candidate_cache(&cache_fresh_trait_ref); + let cache = self.pick_candidate_cache(cache_fresh_trait_pred); let hashmap = cache.hashmap.borrow(); - hashmap.get(&cache_fresh_trait_ref).map(|c| (*c).clone()) + hashmap.get(&cache_fresh_trait_pred.0.trait_ref).map(|c| (*c).clone()) } fn insert_candidate_cache(&mut self, - cache_fresh_trait_ref: Rc>, - candidate: SelectionResult<'tcx, Candidate<'tcx>>) + cache_fresh_trait_pred: ty::PolyTraitPredicate<'tcx>, + candidate: SelectionResult<'tcx, SelectionCandidate<'tcx>>) { - let cache = self.pick_candidate_cache(&cache_fresh_trait_ref); + let cache = self.pick_candidate_cache(&cache_fresh_trait_pred); let mut hashmap = cache.hashmap.borrow_mut(); - hashmap.insert(cache_fresh_trait_ref, candidate); + hashmap.insert(cache_fresh_trait_pred.0.trait_ref.clone(), candidate); } fn assemble_candidates<'o>(&mut self, stack: &TraitObligationStack<'o, 'tcx>) - -> Result, SelectionError<'tcx>> + -> Result, SelectionError<'tcx>> { // Check for overflow. let TraitObligationStack { obligation, .. } = *stack; - let mut candidates = CandidateSet { + let mut candidates = SelectionCandidateSet { vec: Vec::new(), ambiguous: false }; @@ -658,7 +668,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { match self.tcx().lang_items.to_builtin_kind(obligation.predicate.def_id()) { Some(ty::BoundCopy) => { debug!("obligation self ty is {}", - obligation.self_ty().repr(self.tcx())); + obligation.predicate.0.self_ty().repr(self.tcx())); // If the user has asked for the older, compatibility // behavior, ignore user-defined impls here. This will @@ -707,7 +717,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// Never affects inference environment. fn assemble_candidates_from_caller_bounds(&mut self, obligation: &TraitObligation<'tcx>, - candidates: &mut CandidateSet<'tcx>) + candidates: &mut SelectionCandidateSet<'tcx>) -> Result<(),SelectionError<'tcx>> { debug!("assemble_candidates_from_caller_bounds({})", @@ -715,7 +725,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let caller_trait_refs: Vec<_> = self.param_env.caller_bounds.predicates.iter() - .filter_map(|o| o.to_trait()) + .filter_map(|o| o.to_opt_poly_trait_ref()) .collect(); let all_bounds = @@ -744,10 +754,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// unified during the confirmation step. fn assemble_unboxed_closure_candidates(&mut self, obligation: &TraitObligation<'tcx>, - candidates: &mut CandidateSet<'tcx>) + candidates: &mut SelectionCandidateSet<'tcx>) -> Result<(),SelectionError<'tcx>> { - let kind = match self.fn_family_trait_kind(obligation.predicate.def_id()) { + let kind = match self.fn_family_trait_kind(obligation.predicate.0.def_id()) { Some(k) => k, None => { return Ok(()); } }; @@ -789,7 +799,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// Implement one of the `Fn()` family for a fn pointer. fn assemble_fn_pointer_candidates(&mut self, obligation: &TraitObligation<'tcx>, - candidates: &mut CandidateSet<'tcx>) + candidates: &mut SelectionCandidateSet<'tcx>) -> Result<(),SelectionError<'tcx>> { // We provide a `Fn` impl for fn pointers. There is no need to provide @@ -827,16 +837,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// Search for impls that might apply to `obligation`. fn assemble_candidates_from_impls(&mut self, obligation: &TraitObligation<'tcx>, - candidate_vec: &mut Vec>) + candidate_vec: &mut Vec>) -> Result<(), SelectionError<'tcx>> { let all_impls = self.all_impls(obligation.predicate.def_id()); for &impl_def_id in all_impls.iter() { self.infcx.probe(|snapshot| { - let (skol_obligation_trait_ref, skol_map) = - self.infcx().skolemize_late_bound_regions(&*obligation.predicate, snapshot); + let (skol_obligation_trait_pred, skol_map) = + self.infcx().skolemize_late_bound_regions(&obligation.predicate, snapshot); match self.match_impl(impl_def_id, obligation, snapshot, - &skol_map, Rc::new(skol_obligation_trait_ref)) { + &skol_map, skol_obligation_trait_pred.trait_ref.clone()) { Ok(_) => { candidate_vec.push(ImplCandidate(impl_def_id)); } @@ -861,7 +871,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// scrutiny. fn winnow_candidate<'o>(&mut self, stack: &TraitObligationStack<'o, 'tcx>, - candidate: &Candidate<'tcx>) + candidate: &SelectionCandidate<'tcx>) -> EvaluationResult<'tcx> { debug!("winnow_candidate: candidate={}", candidate.repr(self.tcx())); @@ -918,8 +928,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// a case where doing the opposite caused us harm. fn candidate_should_be_dropped_in_favor_of<'o>(&mut self, stack: &TraitObligationStack<'o, 'tcx>, - candidate_i: &Candidate<'tcx>, - candidate_j: &Candidate<'tcx>) + candidate_i: &SelectionCandidate<'tcx>, + candidate_j: &SelectionCandidate<'tcx>) -> bool { match (candidate_i, candidate_j) { @@ -931,16 +941,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.infcx.probe(|snapshot| { let (skol_obligation_trait_ref, skol_map) = self.infcx().skolemize_late_bound_regions( - &*stack.obligation.predicate, snapshot); + &stack.obligation.predicate, snapshot); let impl_substs = self.rematch_impl(impl_def_id, stack.obligation, snapshot, - &skol_map, Rc::new(skol_obligation_trait_ref)); + &skol_map, skol_obligation_trait_ref.trait_ref.clone()); let impl_trait_ref = ty::impl_trait_ref(self.tcx(), impl_def_id).unwrap(); let impl_trait_ref = impl_trait_ref.subst(self.tcx(), &impl_substs); let poly_impl_trait_ref = - Rc::new(ty::Binder((*impl_trait_ref).clone())); + ty::Binder(impl_trait_ref); let origin = infer::RelateOutputImplTypes(stack.obligation.cause.span); self.infcx @@ -966,7 +976,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn assemble_builtin_bound_candidates<'o>(&mut self, bound: ty::BuiltinBound, stack: &TraitObligationStack<'o, 'tcx>, - candidates: &mut CandidateSet<'tcx>) + candidates: &mut SelectionCandidateSet<'tcx>) -> Result<(),SelectionError<'tcx>> { match self.builtin_bound(bound, stack.obligation) { @@ -987,7 +997,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &TraitObligation<'tcx>) -> Result,SelectionError<'tcx>> { - let self_ty = self.infcx.shallow_resolve(obligation.predicate.self_ty()); + // TODO seems like we ought to skolemize here, oder? + let self_ty = self.infcx.shallow_resolve(obligation.predicate.0.self_ty()); return match self_ty.sty { ty::ty_infer(ty::IntVar(_)) | ty::ty_infer(ty::FloatVar(_)) | @@ -1269,6 +1280,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { nominal(self, bound, def_id, types) } + ty::ty_projection(_) | ty::ty_param(_) => { // Note: A type parameter is only considered to meet a // particular bound if there is a where clause telling @@ -1360,7 +1372,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn confirm_candidate(&mut self, obligation: &TraitObligation<'tcx>, - candidate: Candidate<'tcx>) + candidate: SelectionCandidate<'tcx>) -> Result,SelectionError<'tcx>> { debug!("confirm_candidate({}, {})", @@ -1416,7 +1428,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // trait-ref. Repeat that unification now without any // transactional boundary; it should not fail. match self.confirm_poly_trait_refs(obligation.cause.clone(), - obligation.predicate.clone(), + obligation.predicate.to_poly_trait_ref(), param.bound.clone()) { Ok(()) => Ok(param), Err(_) => { @@ -1501,9 +1513,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // this time not in a probe. self.infcx.try(|snapshot| { let (skol_obligation_trait_ref, skol_map) = - self.infcx().skolemize_late_bound_regions(&*obligation.predicate, snapshot); - let substs = self.rematch_impl(impl_def_id, obligation, - snapshot, &skol_map, Rc::new(skol_obligation_trait_ref)); + self.infcx().skolemize_late_bound_regions(&obligation.predicate, snapshot); + let substs = + self.rematch_impl(impl_def_id, obligation, + snapshot, &skol_map, skol_obligation_trait_ref.trait_ref); debug!("confirm_impl_candidate substs={}", substs); Ok(self.vtable_impl(impl_def_id, substs, obligation.cause.clone(), obligation.recursion_depth + 1, skol_map, snapshot)) @@ -1574,13 +1587,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { vec![], vec![], self_ty); - let trait_ref = Rc::new(ty::Binder(ty::TraitRef { + let trait_ref = ty::Binder(Rc::new(ty::TraitRef { def_id: obligation.predicate.def_id(), substs: self.tcx().mk_substs(substs), })); try!(self.confirm_poly_trait_refs(obligation.cause.clone(), - obligation.predicate.clone(), + obligation.predicate.to_poly_trait_ref(), trait_ref)); Ok(self_ty) } @@ -1615,7 +1628,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { vec![], vec![], obligation.self_ty()); - let trait_ref = Rc::new(ty::Binder(ty::TraitRef { + let trait_ref = ty::Binder(Rc::new(ty::TraitRef { def_id: obligation.predicate.def_id(), substs: self.tcx().mk_substs(substs), })); @@ -1625,7 +1638,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { trait_ref.repr(self.tcx())); self.confirm_poly_trait_refs(obligation.cause.clone(), - obligation.predicate.clone(), + obligation.predicate.to_poly_trait_ref(), trait_ref) } @@ -1656,8 +1669,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// report an error to the user. fn confirm_poly_trait_refs(&mut self, obligation_cause: ObligationCause, - obligation_trait_ref: Rc>, - expected_trait_ref: Rc>) + obligation_trait_ref: ty::PolyTraitRef<'tcx>, + expected_trait_ref: ty::PolyTraitRef<'tcx>) -> Result<(), SelectionError<'tcx>> { let origin = infer::RelateOutputImplTypes(obligation_cause.span); @@ -1770,7 +1783,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // substitution if we find that any of the input types, when // simplified, do not match. - obligation.predicate.input_types().iter() + obligation.predicate.0.input_types().iter() .zip(impl_trait_ref.input_types().iter()) .any(|(&obligation_ty, &impl_ty)| { let simplified_obligation_ty = @@ -1786,7 +1799,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn match_where_clause(&mut self, obligation: &TraitObligation<'tcx>, - where_clause_trait_ref: Rc>) + where_clause_trait_ref: ty::PolyTraitRef<'tcx>) -> Result<(),()> { debug!("match_where_clause: obligation={} where_clause_trait_ref={}", @@ -1797,7 +1810,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { match self.infcx.sub_poly_trait_refs(false, origin, where_clause_trait_ref, - obligation.predicate.clone()) { + obligation.predicate.to_poly_trait_ref()) { Ok(()) => Ok(()), Err(_) => Err(()), } @@ -1879,7 +1892,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &'o TraitObligation<'tcx>) -> TraitObligationStack<'o, 'tcx> { - let fresh_trait_ref = obligation.predicate.fold_with(&mut self.freshener); + let fresh_trait_ref = + obligation.predicate.to_poly_trait_ref().fold_with(&mut self.freshener); TraitObligationStack { obligation: obligation, @@ -1932,9 +1946,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { #[allow(unused_comparisons)] fn derived_cause(&self, obligation: &TraitObligation<'tcx>, - variant: fn(Rc>>, - Rc>) - -> ObligationCauseCode<'tcx>) + variant: fn(DerivedObligationCause<'tcx>) -> ObligationCauseCode<'tcx>) -> ObligationCause<'tcx> { /*! @@ -1951,17 +1963,20 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // chain. Ideally, we should have a way to configure this either // by using -Z verbose or just a CLI argument. if obligation.recursion_depth >= 0 { + let derived_cause = DerivedObligationCause { + parent_trait_ref: obligation.predicate.to_poly_trait_ref(), + parent_code: Rc::new(obligation.cause.code.clone()), + }; ObligationCause::new(obligation.cause.span, - obligation.trait_ref.def_id().node, - variant(obligation.trait_ref.clone(), - Rc::new(obligation.cause.code.clone()))) + obligation.cause.body_id, + variant(derived_cause)) } else { obligation.cause.clone() } } } -impl<'tcx> Repr<'tcx> for Candidate<'tcx> { +impl<'tcx> Repr<'tcx> for SelectionCandidate<'tcx> { fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String { match *self { ErrorCandidate => format!("ErrorCandidate"), @@ -2021,8 +2036,7 @@ impl<'tcx> EvaluationResult<'tcx> { EvaluatedToOk | EvaluatedToAmbig | EvaluatedToErr(Overflow) | - EvaluatedToErr(OutputTypeParameterMismatch(..)) | - EvaluatedToErr(ProjectionMismatch(..)) => { + EvaluatedToErr(OutputTypeParameterMismatch(..)) => { true } EvaluatedToErr(Unimplemented) => { diff --git a/src/librustc/middle/traits/util.rs b/src/librustc/middle/traits/util.rs index 6b95e983e8891..00995e1ee43cf 100644 --- a/src/librustc/middle/traits/util.rs +++ b/src/librustc/middle/traits/util.rs @@ -10,7 +10,7 @@ use middle::subst::{Subst, Substs, VecPerParamSpace}; use middle::infer::InferCtxt; -use middle::ty::{mod, Ty}; +use middle::ty::{mod, Ty, AsPredicate, ToPolyTraitRef}; use std::collections::HashSet; use std::fmt; use std::rc::Rc; @@ -46,19 +46,19 @@ struct StackEntry<'tcx> { pub fn elaborate_trait_ref<'cx, 'tcx>( tcx: &'cx ty::ctxt<'tcx>, - trait_ref: Rc>) + trait_ref: ty::PolyTraitRef<'tcx>) -> Elaborator<'cx, 'tcx> { - elaborate_predicates(tcx, vec![ty::Predicate::Trait(trait_ref)]) + elaborate_predicates(tcx, vec![trait_ref.as_predicate()]) } pub fn elaborate_trait_refs<'cx, 'tcx>( tcx: &'cx ty::ctxt<'tcx>, - trait_refs: &[Rc>]) + trait_refs: &[ty::PolyTraitRef<'tcx>]) -> Elaborator<'cx, 'tcx> { let predicates = trait_refs.iter() - .map(|trait_ref| ty::Predicate::Trait((*trait_ref).clone())) + .map(|trait_ref| trait_ref.as_predicate()) .collect(); elaborate_predicates(tcx, predicates) } @@ -80,21 +80,28 @@ pub fn elaborate_predicates<'cx, 'tcx>( impl<'cx, 'tcx> Elaborator<'cx, 'tcx> { fn push(&mut self, predicate: &ty::Predicate<'tcx>) { match *predicate { - ty::Predicate::Trait(ref trait_ref) => { + ty::Predicate::Trait(ref data) => { let mut predicates = - ty::predicates_for_trait_ref(self.tcx, &**trait_ref); + ty::predicates_for_trait_ref(self.tcx, + &data.to_poly_trait_ref()); // Only keep those bounds that we haven't already // seen. This is necessary to prevent infinite // recursion in some cases. One common case is when // people define `trait Sized { }` rather than `trait // Sized for Sized? { }`. - predicates.retain(|r| self.visited.insert((*r).clone())); + predicates.retain(|r| self.visited.insert(r.clone())); self.stack.push(StackEntry { position: 0, predicates: predicates }); } ty::Predicate::Equate(..) => { + // Currently, we do not "elaborate" predicates like + // `X == Y`, though conceivably we might. For example, + // `&X == &Y` implies that `X == Y`. + } + ty::Predicate::Projection(..) => { + // Nothing to elaborate in a projection predicate. } ty::Predicate::RegionOutlives(..) | ty::Predicate::TypeOutlives(..) => { @@ -173,7 +180,7 @@ pub struct Supertraits<'cx, 'tcx:'cx> { } pub fn supertraits<'cx, 'tcx>(tcx: &'cx ty::ctxt<'tcx>, - trait_ref: Rc>) + trait_ref: ty::PolyTraitRef<'tcx>) -> Supertraits<'cx, 'tcx> { let elaborator = elaborate_trait_ref(tcx, trait_ref); @@ -181,26 +188,24 @@ pub fn supertraits<'cx, 'tcx>(tcx: &'cx ty::ctxt<'tcx>, } pub fn transitive_bounds<'cx, 'tcx>(tcx: &'cx ty::ctxt<'tcx>, - bounds: &[Rc>]) + bounds: &[ty::PolyTraitRef<'tcx>]) -> Supertraits<'cx, 'tcx> { let elaborator = elaborate_trait_refs(tcx, bounds); Supertraits { elaborator: elaborator } } -impl<'cx, 'tcx> Iterator>> for Supertraits<'cx, 'tcx> { - fn next(&mut self) -> Option>> { +impl<'cx, 'tcx> Iterator> for Supertraits<'cx, 'tcx> { + fn next(&mut self) -> Option> { loop { match self.elaborator.next() { None => { return None; } - Some(ty::Predicate::Trait(trait_ref)) => { - return Some(trait_ref); + Some(ty::Predicate::Trait(data)) => { + return Some(data.to_poly_trait_ref()); } - Some(ty::Predicate::Equate(..)) | - Some(ty::Predicate::RegionOutlives(..)) | - Some(ty::Predicate::TypeOutlives(..)) => { + Some(_) => { } } } @@ -265,18 +270,18 @@ pub fn predicates_for_generics<'tcx>(tcx: &ty::ctxt<'tcx>, }) } -pub fn poly_trait_ref_for_builtin_bound<'tcx>( +pub fn trait_ref_for_builtin_bound<'tcx>( tcx: &ty::ctxt<'tcx>, builtin_bound: ty::BuiltinBound, param_ty: Ty<'tcx>) - -> Result>, ErrorReported> + -> Result>, ErrorReported> { match tcx.lang_items.from_builtin_kind(builtin_bound) { Ok(def_id) => { - Ok(Rc::new(ty::Binder(ty::TraitRef { + Ok(Rc::new(ty::TraitRef { def_id: def_id, substs: tcx.mk_substs(Substs::empty().with_self_ty(param_ty)) - }))) + })) } Err(e) => { tcx.sess.err(e.as_slice()); @@ -293,11 +298,11 @@ pub fn predicate_for_builtin_bound<'tcx>( param_ty: Ty<'tcx>) -> Result, ErrorReported> { - let trait_ref = try!(poly_trait_ref_for_builtin_bound(tcx, builtin_bound, param_ty)); + let trait_ref = try!(trait_ref_for_builtin_bound(tcx, builtin_bound, param_ty)); Ok(Obligation { cause: cause, recursion_depth: recursion_depth, - predicate: ty::Predicate::Trait(trait_ref), + predicate: trait_ref.as_predicate(), }) } @@ -306,7 +311,7 @@ pub fn predicate_for_builtin_bound<'tcx>( /// true, where `d` is the def-id of the trait/supertrait. If any is found, return `Some(p)` where /// `p` is the path to that trait/supertrait. Else `None`. pub fn search_trait_and_supertraits_from_bound<'tcx,F>(tcx: &ty::ctxt<'tcx>, - caller_bound: Rc>, + caller_bound: ty::PolyTraitRef<'tcx>, mut test: F) -> Option> where F: FnMut(ast::DefId) -> bool, @@ -390,12 +395,6 @@ impl<'tcx> Repr<'tcx> for super::SelectionError<'tcx> { a.repr(tcx), b.repr(tcx), c.repr(tcx)), - - super::ProjectionMismatch(ref a, ref b, ref c) => - format!("PrjectionMismatch({},{},{})", - a.repr(tcx), - b.repr(tcx), - c.repr(tcx)), } } } @@ -412,6 +411,7 @@ impl<'tcx> Repr<'tcx> for super::FulfillmentErrorCode<'tcx> { fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String { match *self { super::CodeSelectionError(ref o) => o.repr(tcx), + super::CodeProjectionError(ref o) => o.repr(tcx), super::CodeAmbiguity => format!("Ambiguity") } } @@ -421,6 +421,7 @@ impl<'tcx> fmt::Show for super::FulfillmentErrorCode<'tcx> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { super::CodeSelectionError(ref e) => write!(f, "{}", e), + super::CodeProjectionError(ref e) => write!(f, "{}", e), super::CodeAmbiguity => write!(f, "Ambiguity") } } @@ -431,3 +432,4 @@ impl<'tcx> Repr<'tcx> for ty::type_err<'tcx> { ty::type_err_to_str(tcx, self) } } + diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 8a0e5ea0bb314..da65feb8fd3f8 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -587,7 +587,7 @@ pub enum vtable_origin<'tcx> { // For every explicit cast into an object type, maps from the cast // expr to the associated trait ref. -pub type ObjectCastMap<'tcx> = RefCell>>>; +pub type ObjectCastMap<'tcx> = RefCell>>; /// A restriction that certain types must be the same size. The use of /// `transmute` gives rise to these restrictions. These generally @@ -843,6 +843,7 @@ bitflags! { const HAS_RE_LATE_BOUND = 0b10000, const HAS_REGIONS = 0b100000, const HAS_TY_ERR = 0b1000000, + const HAS_PROJECTION = 0b10000000, const NEEDS_SUBST = HAS_PARAMS.bits | HAS_SELF.bits | HAS_REGIONS.bits, } } @@ -989,6 +990,9 @@ pub fn type_has_ty_infer(ty: Ty) -> bool { pub fn type_needs_infer(ty: Ty) -> bool { ty.flags.intersects(HAS_TY_INFER | HAS_RE_INFER) } +pub fn type_has_projection(ty: Ty) -> bool { + ty.flags.intersects(HAS_PROJECTION) +} pub fn type_has_late_bound_regions(ty: Ty) -> bool { ty.flags.intersects(HAS_RE_LATE_BOUND) @@ -1354,7 +1358,9 @@ pub enum sty<'tcx> { ty_tup(Vec>), + ty_projection(Box>), ty_param(ParamTy), // type parameter + ty_open(Ty<'tcx>), // A deref'ed fat pointer, i.e., a dynamically sized value // and its size. Only ever used in trans. It is not necessary // earlier since we don't need to distinguish a DST with its @@ -1370,22 +1376,30 @@ pub enum sty<'tcx> { #[deriving(Clone, PartialEq, Eq, Hash, Show)] pub struct TyTrait<'tcx> { // Principal trait reference. - pub principal: PolyTraitRef<'tcx>, + pub principal: ty::Binder>, pub bounds: ExistentialBounds } impl<'tcx> TyTrait<'tcx> { + pub fn principal_def_id(&self) -> ast::DefId { + self.principal.0.def_id + } + /// Object types don't have a self-type specified. Therefore, when /// we convert the principal trait-ref into a normal trait-ref, /// you must give *some* self-type. A common choice is `mk_err()` /// or some skolemized type. pub fn principal_trait_ref_with_self_ty(&self, - tcx: &ctxt<'tcx>, self_ty: Ty<'tcx>) - -> Rc> + tcx: &ctxt<'tcx>, + self_ty: Ty<'tcx>) + -> ty::PolyTraitRef<'tcx> { - Rc::new(ty::Binder(ty::TraitRef { - def_id: self.principal.def_id(), - substs: tcx.mk_substs(self.principal.substs().with_self_ty(self_ty)), + // otherwise the escaping regions would be captured by the binder + assert!(!self_ty.has_escaping_regions()); + + ty::Binder(Rc::new(ty::TraitRef { + def_id: self.principal.0.def_id, + substs: tcx.mk_substs(self.principal.0.substs.with_self_ty(self_ty)), })) } } @@ -1411,7 +1425,7 @@ pub struct TraitRef<'tcx> { pub substs: &'tcx Substs<'tcx>, } -pub type PolyTraitRef<'tcx> = Binder>; +pub type PolyTraitRef<'tcx> = Binder>>; impl<'tcx> PolyTraitRef<'tcx> { pub fn self_ty(&self) -> Ty<'tcx> { @@ -1429,6 +1443,17 @@ impl<'tcx> PolyTraitRef<'tcx> { pub fn input_types(&self) -> &[Ty<'tcx>] { self.0.input_types() } + + pub fn to_poly_trait_predicate(&self) -> PolyTraitPredicate<'tcx> { + // Note that we preserve binding levels + Binder(TraitPredicate { trait_ref: self.0.clone() }) + } + + pub fn remove_rc(&self) -> ty::Binder> { + // Annoyingly, we can't easily put a `Rc` into a `sty` structure, + // and hence we have to remove the rc to put this into a `TyTrait`. + ty::Binder((*self.0).clone()) + } } /// Binder is a binder for higher-ranked lifetimes. It is part of the @@ -1501,7 +1526,8 @@ pub enum type_err<'tcx> { pub struct ParamBounds<'tcx> { pub region_bounds: Vec, pub builtin_bounds: BuiltinBounds, - pub trait_bounds: Vec>> + pub trait_bounds: Vec>, + pub projection_bounds: Vec>, } /// Bounds suitable for an existentially quantified type parameter @@ -1672,7 +1698,6 @@ pub struct TypeParameterDef<'tcx> { pub def_id: ast::DefId, pub space: subst::ParamSpace, pub index: u32, - pub associated_with: Option, pub bounds: ParamBounds<'tcx>, pub default: Option>, } @@ -1731,7 +1756,7 @@ pub enum Predicate<'tcx> { /// Corresponds to `where Foo : Bar`. `Foo` here would be /// the `Self` type of the trait reference and `A`, `B`, and `C` /// would be the parameters in the `TypeSpace`. - Trait(Rc>), + Trait(PolyTraitPredicate<'tcx>), /// where `T1 == T2`. Equate(PolyEquatePredicate<'tcx>), @@ -1741,6 +1766,35 @@ pub enum Predicate<'tcx> { /// where T : 'a TypeOutlives(PolyTypeOutlivesPredicate<'tcx>), + + /// + Projection(PolyProjectionPredicate<'tcx>), +} + +#[deriving(Clone, PartialEq, Eq, Hash, Show)] +pub struct TraitPredicate<'tcx> { + pub trait_ref: Rc> +} +pub type PolyTraitPredicate<'tcx> = ty::Binder>; + +impl<'tcx> TraitPredicate<'tcx> { + pub fn def_id(&self) -> ast::DefId { + self.trait_ref.def_id + } + + pub fn input_types(&self) -> &[Ty<'tcx>] { + self.trait_ref.substs.types.as_slice() + } + + pub fn self_ty(&self) -> Ty<'tcx> { + self.trait_ref.self_ty() + } +} + +impl<'tcx> PolyTraitPredicate<'tcx> { + pub fn def_id(&self) -> ast::DefId { + self.0.def_id() + } } #[deriving(Clone, PartialEq, Eq, Hash, Show)] @@ -1753,13 +1807,90 @@ pub type PolyOutlivesPredicate = ty::Binder>; pub type PolyRegionOutlivesPredicate = PolyOutlivesPredicate; pub type PolyTypeOutlivesPredicate<'tcx> = PolyOutlivesPredicate, ty::Region>; +/// This kind of predicate has no *direct* correspondent in the +/// syntax, but it roughly corresponds to the syntactic forms: +/// +/// 1. `T : TraitRef<..., Item=Type>` +/// 2. `>::Item == Type` (NYI) +/// +/// In particular, form #1 is "desugared" to the combination of a +/// normal trait predicate (`T : TraitRef<...>`) and one of these +/// predicates. Form #2 is a broader form in that it also permits +/// equality between arbitrary types. Processing an instance of Form +/// #2 eventually yields one of these `ProjectionPredicate` +/// instances to normalize the LHS. +#[deriving(Clone, PartialEq, Eq, Hash, Show)] +pub struct ProjectionPredicate<'tcx> { + pub projection_ty: ProjectionTy<'tcx>, + pub ty: Ty<'tcx>, +} + +pub type PolyProjectionPredicate<'tcx> = Binder>; + +#[deriving(Clone, PartialEq, Eq, Hash, Show)] +pub struct ProjectionTy<'tcx> { + pub trait_ref: Rc>, + pub item_name: ast::Name, +} + +// Annoying: a version of `ProjectionTy` that avoids the `Rc`, because +// it is difficult to place an `Rc` in the `sty` struct. Eventually +// these two types ought to be unified. +#[deriving(Clone, PartialEq, Eq, Hash, Show)] +pub struct TyProjection<'tcx> { + pub trait_ref: ty::TraitRef<'tcx>, + pub item_name: ast::Name, +} + +pub trait ToPolyTraitRef<'tcx> { + fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx>; +} + +impl<'tcx> ToPolyTraitRef<'tcx> for Rc> { + fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx> { + assert!(!self.has_escaping_regions()); + ty::Binder(self.clone()) + } +} + +impl<'tcx> ToPolyTraitRef<'tcx> for PolyTraitPredicate<'tcx> { + fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx> { + // We are just preserving the binder levels here + ty::Binder(self.0.trait_ref.clone()) + } +} + +impl<'tcx> ToPolyTraitRef<'tcx> for PolyProjectionPredicate<'tcx> { + fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx> { + // Note: unlike with TraitRef::to_poly_trait_ref(), + // self.0.trait_ref is permitted to have escaping regions. + // This is because here `self` has a `Binder` and so does our + // return value, so we are preserving the number of binding + // levels. + ty::Binder(self.0.projection_ty.trait_ref.clone()) + } +} + pub trait AsPredicate<'tcx> { fn as_predicate(&self) -> Predicate<'tcx>; } -impl<'tcx> AsPredicate<'tcx> for Rc> { +impl<'tcx> AsPredicate<'tcx> for Rc> { fn as_predicate(&self) -> Predicate<'tcx> { - Predicate::Trait(self.clone()) + // we're about to add a binder, so let's check that we don't + // accidentally capture anything, or else that might be some + // weird debruijn accounting. + assert!(!self.has_escaping_regions()); + + ty::Predicate::Trait(ty::Binder(ty::TraitPredicate { + trait_ref: self.clone() + })) + } +} + +impl<'tcx> AsPredicate<'tcx> for PolyTraitRef<'tcx> { + fn as_predicate(&self) -> Predicate<'tcx> { + ty::Predicate::Trait(self.to_poly_trait_predicate()) } } @@ -1781,6 +1912,12 @@ impl<'tcx> AsPredicate<'tcx> for PolyTypeOutlivesPredicate<'tcx> { } } +impl<'tcx> AsPredicate<'tcx> for PolyProjectionPredicate<'tcx> { + fn as_predicate(&self) -> Predicate<'tcx> { + Predicate::Projection(self.clone()) + } +} + impl<'tcx> Predicate<'tcx> { pub fn has_escaping_regions(&self) -> bool { match *self { @@ -1788,14 +1925,16 @@ impl<'tcx> Predicate<'tcx> { Predicate::Equate(ref p) => p.has_escaping_regions(), Predicate::RegionOutlives(ref p) => p.has_escaping_regions(), Predicate::TypeOutlives(ref p) => p.has_escaping_regions(), + Predicate::Projection(ref p) => p.has_escaping_regions(), } } - pub fn to_trait(&self) -> Option>> { + pub fn to_opt_poly_trait_ref(&self) -> Option> { match *self { Predicate::Trait(ref t) => { - Some(t.clone()) + Some(t.to_poly_trait_ref()) } + Predicate::Projection(..) | Predicate::Equate(..) | Predicate::RegionOutlives(..) | Predicate::TypeOutlives(..) => { @@ -2032,7 +2171,12 @@ pub struct TraitDef<'tcx> { /// The "supertrait" bounds. pub bounds: ParamBounds<'tcx>, + pub trait_ref: Rc>, + + /// A list of the associated types defined in this trait. Useful + /// for resolving `X::Foo` type markers. + pub associated_type_names: Vec, } /// Records the substitutions used to translate the polytype for an @@ -2330,9 +2474,14 @@ impl FlagComputation { self.add_substs(substs); } + &ty_projection(ref data) => { + self.add_flags(HAS_PROJECTION); + self.add_substs(&data.trait_ref.substs); + } + &ty_trait(box TyTrait { ref principal, ref bounds }) => { let mut computation = FlagComputation::new(); - computation.add_substs(principal.substs()); + computation.add_substs(&principal.0.substs); self.add_bound_computation(&computation); self.add_bounds(bounds); @@ -2540,9 +2689,8 @@ pub fn mk_ctor_fn<'tcx>(cx: &ctxt<'tcx>, })) } - pub fn mk_trait<'tcx>(cx: &ctxt<'tcx>, - principal: ty::PolyTraitRef<'tcx>, + principal: ty::Binder>, bounds: ExistentialBounds) -> Ty<'tcx> { // take a copy of substs so that we own the vectors inside @@ -2553,6 +2701,15 @@ pub fn mk_trait<'tcx>(cx: &ctxt<'tcx>, mk_t(cx, ty_trait(inner)) } +pub fn mk_projection<'tcx>(cx: &ctxt<'tcx>, + trait_ref: ty::TraitRef<'tcx>, + item_name: ast::Name) + -> Ty<'tcx> { + // take a copy of substs so that we own the vectors inside + let inner = box TyProjection { trait_ref: trait_ref, item_name: item_name }; + mk_t(cx, ty_projection(inner)) +} + pub fn mk_struct<'tcx>(cx: &ctxt<'tcx>, struct_id: ast::DefId, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> { // take a copy of substs so that we own the vectors inside @@ -2615,7 +2772,12 @@ pub fn maybe_walk_ty<'tcx>(ty: Ty<'tcx>, f: |Ty<'tcx>| -> bool) { maybe_walk_ty(tm.ty, f); } ty_trait(box TyTrait { ref principal, .. }) => { - for subty in principal.substs().types.iter() { + for subty in principal.0.substs.types.iter() { + maybe_walk_ty(*subty, |x| f(x)); + } + } + ty_projection(box TyProjection { ref trait_ref, .. }) => { + for subty in trait_ref.substs.types.iter() { maybe_walk_ty(*subty, |x| f(x)); } } @@ -2693,6 +2855,7 @@ impl<'tcx> ParamBounds<'tcx> { builtin_bounds: empty_builtin_bounds(), trait_bounds: Vec::new(), region_bounds: Vec::new(), + projection_bounds: Vec::new(), } } } @@ -3191,6 +3354,7 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents { apply_lang_items(cx, did, res) } + ty_projection(..) | ty_param(_) => { TC::All } @@ -3372,6 +3536,7 @@ pub fn is_instantiable<'tcx>(cx: &ctxt<'tcx>, r_ty: Ty<'tcx>) -> bool { ty_infer(_) | ty_err | ty_param(_) | + ty_projection(_) | ty_vec(_, None) => { false } @@ -4448,7 +4613,7 @@ pub fn ty_sort_string<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> String { ty_bare_fn(None, _) => "fn pointer".to_string(), ty_closure(_) => "fn".to_string(), ty_trait(ref inner) => { - format!("trait {}", item_path_str(cx, inner.principal.def_id())) + format!("trait {}", item_path_str(cx, inner.principal_def_id())) } ty_struct(id, _) => { format!("struct {}", item_path_str(cx, id)) @@ -4460,6 +4625,7 @@ pub fn ty_sort_string<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> String { ty_infer(FloatVar(_)) => "floating-point variable".to_string(), ty_infer(FreshTy(_)) => "skolemized type".to_string(), ty_infer(FreshIntTy(_)) => "skolemized integral type".to_string(), + ty_projection(_) => "associated type".to_string(), ty_param(ref p) => { if p.space == subst::SelfSpace { "Self".to_string() @@ -4871,7 +5037,7 @@ pub fn try_add_builtin_trait( pub fn ty_to_def_id(ty: Ty) -> Option { match ty.sty { ty_trait(ref tt) => - Some(tt.principal.def_id()), + Some(tt.principal_def_id()), ty_struct(id, _) | ty_enum(id, _) | ty_unboxed_closure(id, _, _) => @@ -5128,7 +5294,12 @@ pub fn lookup_trait_def<'tcx>(cx: &ctxt<'tcx>, did: ast::DefId) } /// Given a reference to a trait, returns the "superbounds" declared -/// on the trait, with appropriate substitutions applied. +/// on the trait, with appropriate substitutions applied. Basically, +/// this applies a filter to the where clauses on the trait, returning +/// those that have the form: +/// +/// Self : SuperTrait<...> +/// Self : 'region pub fn predicates_for_trait_ref<'tcx>(tcx: &ctxt<'tcx>, trait_ref: &PolyTraitRef<'tcx>) -> Vec> @@ -5205,13 +5376,7 @@ pub fn predicates_for_trait_ref<'tcx>(tcx: &ctxt<'tcx>, let trait_bounds: Vec<_> = trait_def.bounds.trait_bounds .iter() - .map(|bound_trait_ref| { - let substs = tcx.mk_substs(bound_trait_ref.substs().subst(tcx, trait_ref.substs())); - ty::Binder( - ty::TraitRef::new(bound_trait_ref.def_id(), - substs)) - }) - .map(|bound_trait_ref| Rc::new(bound_trait_ref)) + .map(|poly_trait_ref| ty::Binder(poly_trait_ref.0.subst(tcx, trait_ref.substs()))) .collect(); debug!("bounds_for_trait_ref: trait_bounds={}", @@ -5228,6 +5393,11 @@ pub fn predicates_for_trait_ref<'tcx>(tcx: &ctxt<'tcx>, trait_bounds: trait_bounds, region_bounds: region_bounds, builtin_bounds: builtin_bounds, + + // FIXME(#19451) -- if a trait has a bound like `trait Foo : + // Bar`, we should probably be returning that, but this + // code here will just ignore it. + projection_bounds: Vec::new(), }; predicates(tcx, trait_ref.self_ty(), &bounds) @@ -5242,7 +5412,7 @@ pub fn predicates<'tcx>( let mut vec = Vec::new(); for builtin_bound in bounds.builtin_bounds.iter() { - match traits::poly_trait_ref_for_builtin_bound(tcx, builtin_bound, param_ty) { + match traits::trait_ref_for_builtin_bound(tcx, builtin_bound, param_ty) { Ok(trait_ref) => { vec.push(trait_ref.as_predicate()); } Err(ErrorReported) => { } } @@ -5259,6 +5429,10 @@ pub fn predicates<'tcx>( vec.push(bound_trait_ref.as_predicate()); } + for projection in bounds.projection_bounds.iter() { + vec.push(projection.as_predicate()); + } + vec } @@ -5594,10 +5768,10 @@ pub fn eval_repeat_count(tcx: &ctxt, count_expr: &ast::Expr) -> uint { // relation on the supertraits from each bounded trait's constraint // list. pub fn each_bound_trait_and_supertraits<'tcx, F>(tcx: &ctxt<'tcx>, - bounds: &[Rc>], + bounds: &[PolyTraitRef<'tcx>], mut f: F) -> bool where - F: FnMut(Rc>) -> bool, + F: FnMut(PolyTraitRef<'tcx>) -> bool, { for bound_trait_ref in traits::transitive_bounds(tcx, bounds) { if !f(bound_trait_ref) { @@ -5607,10 +5781,11 @@ pub fn each_bound_trait_and_supertraits<'tcx, F>(tcx: &ctxt<'tcx>, return true; } -pub fn object_region_bounds<'tcx>(tcx: &ctxt<'tcx>, - opt_principal: Option<&PolyTraitRef<'tcx>>, // None for closures - others: BuiltinBounds) - -> Vec +pub fn object_region_bounds<'tcx>( + tcx: &ctxt<'tcx>, + opt_principal: Option<&Binder>>, // None for closures + others: BuiltinBounds) + -> Vec { // Since we don't actually *know* the self type for an object, // this "open(err)" serves as a kind of dummy standin -- basically @@ -5618,14 +5793,17 @@ pub fn object_region_bounds<'tcx>(tcx: &ctxt<'tcx>, let open_ty = ty::mk_infer(tcx, FreshTy(0)); let opt_trait_ref = opt_principal.map_or(Vec::new(), |principal| { - let substs = principal.substs().with_self_ty(open_ty); - vec!(Rc::new(ty::Binder(ty::TraitRef::new(principal.def_id(), tcx.mk_substs(substs))))) + // Note that we preserve the overall binding levels here. + assert!(!open_ty.has_escaping_regions()); + let substs = tcx.mk_substs(principal.0.substs.with_self_ty(open_ty)); + vec!(ty::Binder(Rc::new(ty::TraitRef::new(principal.0.def_id, substs)))) }); let param_bounds = ty::ParamBounds { region_bounds: Vec::new(), builtin_bounds: others, trait_bounds: opt_trait_ref, + projection_bounds: Vec::new(), // not relevant to computing region bounds }; let predicates = ty::predicates(tcx, open_ty, ¶m_bounds); @@ -5656,6 +5834,7 @@ pub fn required_region_bounds<'tcx>(tcx: &ctxt<'tcx>, traits::elaborate_predicates(tcx, predicates) .filter_map(|predicate| { match predicate { + ty::Predicate::Projection(..) | ty::Predicate::Trait(..) | ty::Predicate::Equate(..) | ty::Predicate::RegionOutlives(..) => { @@ -6007,12 +6186,12 @@ pub fn hash_crate_independent<'tcx>(tcx: &ctxt<'tcx>, ty: Ty<'tcx>, svh: &Svh) - return false; } - ty_trait(box TyTrait { ref principal, bounds }) => { + ty_trait(ref data) => { byte!(17); - did(state, principal.def_id()); - hash!(bounds); + did(state, data.principal_def_id()); + hash!(data.bounds); - let principal = anonymize_late_bound_regions(tcx, principal); + let principal = anonymize_late_bound_regions(tcx, &data.principal); for subty in principal.substs.types.iter() { helper(tcx, *subty, svh, state); } @@ -6040,6 +6219,11 @@ pub fn hash_crate_independent<'tcx>(tcx: &ctxt<'tcx>, ty: Ty<'tcx>, svh: &Svh) - did(state, d); region(state, *r); } + ty_projection(ref data) => { + byte!(25); + did(state, data.trait_ref.def_id); + hash!(token::get_name(data.item_name)); + } } true }); @@ -6156,7 +6340,10 @@ pub fn construct_parameter_environment<'tcx>( for predicate in bounds.predicates.iter() { match *predicate { - Predicate::Trait(..) | Predicate::Equate(..) | Predicate::TypeOutlives(..) => { + Predicate::Projection(..) | + Predicate::Trait(..) | + Predicate::Equate(..) | + Predicate::TypeOutlives(..) => { // No region bounds here } Predicate::RegionOutlives(ty::Binder(ty::OutlivesPredicate(r_a, r_b))) => { @@ -6283,7 +6470,7 @@ pub fn accumulate_lifetimes_in_type(accumulator: &mut Vec, accumulator.push(*region) } ty_trait(ref t) => { - accumulator.push_all(t.principal.substs().regions().as_slice()); + accumulator.push_all(t.principal.0.substs.regions().as_slice()); } ty_enum(_, substs) | ty_struct(_, substs) => { @@ -6310,6 +6497,7 @@ pub fn accumulate_lifetimes_in_type(accumulator: &mut Vec, ty_ptr(_) | ty_bare_fn(..) | ty_tup(_) | + ty_projection(_) | ty_param(_) | ty_infer(_) | ty_open(_) | @@ -6400,6 +6588,15 @@ pub fn count_late_bound_regions<'tcx, T>( skol_map.len() } +pub fn binds_late_bound_regions<'tcx, T>( + tcx: &ty::ctxt<'tcx>, + value: &Binder) + -> bool + where T : TypeFoldable<'tcx> + Repr<'tcx> +{ + count_late_bound_regions(tcx, value) > 0 +} + /// Replace any late-bound regions bound in `value` with `'static`. Useful in trans but also /// method lookup and a few other places where precise region relationships are not required. pub fn erase_late_bound_regions<'tcx, T>( @@ -6540,9 +6737,10 @@ impl<'tcx> Repr<'tcx> for ty::Predicate<'tcx> { fn repr(&self, tcx: &ctxt<'tcx>) -> String { match *self { Predicate::Trait(ref a) => a.repr(tcx), - Predicate::Equate(ref pair) => format!("Equate({})", pair.repr(tcx)), - Predicate::RegionOutlives(ref pair) => format!("Outlives({})", pair.repr(tcx)), - Predicate::TypeOutlives(ref pair) => format!("Outlives({})", pair.repr(tcx)), + Predicate::Equate(ref pair) => pair.repr(tcx), + Predicate::RegionOutlives(ref pair) => pair.repr(tcx), + Predicate::TypeOutlives(ref pair) => pair.repr(tcx), + Predicate::Projection(ref pair) => pair.repr(tcx), } } } @@ -6638,6 +6836,11 @@ pub fn can_type_implement_copy<'tcx>(tcx: &ctxt<'tcx>, Ok(()) } +// TODO -- all of these types basically walk various structures to +// test whether types/regions are reachable with various +// properties. It should be possible to express them in terms of one +// common "walker" trait or something. + pub trait RegionEscape { fn has_escaping_regions(&self) -> bool { self.has_regions_escaping_depth(0) @@ -6677,8 +6880,193 @@ impl<'tcx> RegionEscape for EquatePredicate<'tcx> { } } +impl<'tcx> RegionEscape for TraitPredicate<'tcx> { + fn has_regions_escaping_depth(&self, depth: uint) -> bool { + self.trait_ref.has_regions_escaping_depth(depth) + } +} + impl RegionEscape for OutlivesPredicate { fn has_regions_escaping_depth(&self, depth: u32) -> bool { self.0.has_regions_escaping_depth(depth) || self.1.has_regions_escaping_depth(depth) } } + +impl<'tcx> RegionEscape for ProjectionPredicate<'tcx> { + fn has_regions_escaping_depth(&self, depth: uint) -> bool { + self.projection_ty.has_regions_escaping_depth(depth) || + self.ty.has_regions_escaping_depth(depth) + } +} + +impl<'tcx> RegionEscape for ProjectionTy<'tcx> { + fn has_regions_escaping_depth(&self, depth: uint) -> bool { + self.trait_ref.has_regions_escaping_depth(depth) + } +} + +impl<'tcx> Repr<'tcx> for ty::ProjectionPredicate<'tcx> { + fn repr(&self, tcx: &ctxt<'tcx>) -> String { + format!("ProjectionPredicate({}, {})", + self.projection_ty.repr(tcx), + self.ty.repr(tcx)) + } +} + +impl<'tcx> Repr<'tcx> for ty::TyProjection<'tcx> { + fn repr(&self, tcx: &ctxt<'tcx>) -> String { + format!("TyProjection({}, {})", + self.trait_ref.repr(tcx), + self.item_name.repr(tcx)) + } +} + +pub trait HasProjectionTypes { + fn has_projection_types(&self) -> bool; +} + +impl<'tcx> HasProjectionTypes for Ty<'tcx> { + fn has_projection_types(&self) -> bool { + ty::type_has_projection(*self) + } +} + +impl<'tcx> HasProjectionTypes for ty::TraitRef<'tcx> { + fn has_projection_types(&self) -> bool { + self.substs.has_projection_types() + } +} + +impl<'tcx> HasProjectionTypes for subst::Substs<'tcx> { + fn has_projection_types(&self) -> bool { + self.types.iter().any(|t| t.has_projection_types()) + } +} + +impl<'tcx,T> HasProjectionTypes for Option + where T : HasProjectionTypes +{ + fn has_projection_types(&self) -> bool { + self.iter().any(|t| t.has_projection_types()) + } +} + +impl<'tcx,T> HasProjectionTypes for Rc + where T : HasProjectionTypes +{ + fn has_projection_types(&self) -> bool { + (**self).has_projection_types() + } +} + +impl<'tcx,T> HasProjectionTypes for Box + where T : HasProjectionTypes +{ + fn has_projection_types(&self) -> bool { + (**self).has_projection_types() + } +} + +impl HasProjectionTypes for ty::Binder + where T : HasProjectionTypes +{ + fn has_projection_types(&self) -> bool { + self.0.has_projection_types() + } +} + +impl<'tcx> HasProjectionTypes for ty::FnOutput<'tcx> { + fn has_projection_types(&self) -> bool { + match *self { + ty::FnConverging(t) => t.has_projection_types(), + ty::FnDiverging => false, + } + } +} + +impl<'tcx> HasProjectionTypes for ty::FnSig<'tcx> { + fn has_projection_types(&self) -> bool { + self.inputs.iter().any(|t| t.has_projection_types()) || + self.output.has_projection_types() + } +} + +impl<'tcx> HasProjectionTypes for ty::BareFnTy<'tcx> { + fn has_projection_types(&self) -> bool { + self.sig.has_projection_types() + } +} + +pub trait ReferencesError { + fn references_error(&self) -> bool; +} + +impl ReferencesError for ty::Binder { + fn references_error(&self) -> bool { + self.0.references_error() + } +} + +impl ReferencesError for Rc { + fn references_error(&self) -> bool { + (&*self).references_error() + } +} + +impl<'tcx> ReferencesError for ty::TraitPredicate<'tcx> { + fn references_error(&self) -> bool { + self.trait_ref.references_error() + } +} + +impl<'tcx> ReferencesError for ty::ProjectionPredicate<'tcx> { + fn references_error(&self) -> bool { + self.projection_ty.trait_ref.references_error() || self.ty.references_error() + } +} + +impl<'tcx> ReferencesError for ty::TraitRef<'tcx> { + fn references_error(&self) -> bool { + self.input_types().iter().any(|t| t.references_error()) + } +} + +impl<'tcx> ReferencesError for ty::Ty<'tcx> { + fn references_error(&self) -> bool { + ty::type_is_error(*self) + } +} + +impl<'tcx> ReferencesError for ty::Predicate<'tcx> { + fn references_error(&self) -> bool { + match *self { + ty::Predicate::Trait(ref data) => data.references_error(), + ty::Predicate::Equate(ref data) => data.references_error(), + ty::Predicate::RegionOutlives(ref data) => data.references_error(), + ty::Predicate::TypeOutlives(ref data) => data.references_error(), + ty::Predicate::Projection(ref data) => data.references_error(), + } + } +} + +impl ReferencesError for ty::OutlivesPredicate + where A : ReferencesError, B : ReferencesError +{ + fn references_error(&self) -> bool { + self.0.references_error() || self.1.references_error() + } +} + +impl<'tcx> ReferencesError for ty::EquatePredicate<'tcx> +{ + fn references_error(&self) -> bool { + self.0.references_error() || self.1.references_error() + } +} + +impl ReferencesError for ty::Region +{ + fn references_error(&self) -> bool { + false + } +} diff --git a/src/librustc/middle/ty_fold.rs b/src/librustc/middle/ty_fold.rs index 11a130f0c5407..036fbfec28024 100644 --- a/src/librustc/middle/ty_fold.rs +++ b/src/librustc/middle/ty_fold.rs @@ -170,6 +170,13 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Rc { } } +impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Box { + fn fold_with>(&self, folder: &mut F) -> Box { + let content: T = (**self).fold_with(folder); + box content + } +} + impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Vec { fn fold_with>(&self, folder: &mut F) -> Vec { self.iter().map(|t| t.fold_with(folder)).collect() @@ -354,6 +361,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ParamBounds<'tcx> { region_bounds: self.region_bounds.fold_with(folder), builtin_bounds: self.builtin_bounds.fold_with(folder), trait_bounds: self.trait_bounds.fold_with(folder), + projection_bounds: self.projection_bounds.fold_with(folder), } } } @@ -365,7 +373,6 @@ impl<'tcx> TypeFoldable<'tcx> for ty::TypeParameterDef<'tcx> { def_id: self.def_id, space: self.space, index: self.index, - associated_with: self.associated_with, bounds: self.bounds.fold_with(folder), default: self.default.fold_with(folder), } @@ -405,6 +412,35 @@ impl<'tcx> TypeFoldable<'tcx> for ty::Predicate<'tcx> { ty::Predicate::RegionOutlives(binder.fold_with(folder)), ty::Predicate::TypeOutlives(ref binder) => ty::Predicate::TypeOutlives(binder.fold_with(folder)), + ty::Predicate::Projection(ref binder) => + ty::Predicate::Projection(binder.fold_with(folder)), + } + } +} + +impl<'tcx> TypeFoldable<'tcx> for ty::ProjectionPredicate<'tcx> { + fn fold_with>(&self, folder: &mut F) -> ty::ProjectionPredicate<'tcx> { + ty::ProjectionPredicate { + projection_ty: self.projection_ty.fold_with(folder), + ty: self.ty.fold_with(folder), + } + } +} + +impl<'tcx> TypeFoldable<'tcx> for ty::ProjectionTy<'tcx> { + fn fold_with>(&self, folder: &mut F) -> ty::ProjectionTy<'tcx> { + ty::ProjectionTy { + trait_ref: self.trait_ref.fold_with(folder), + item_name: self.item_name, + } + } +} + +impl<'tcx> TypeFoldable<'tcx> for ty::TyProjection<'tcx> { + fn fold_with>(&self, folder: &mut F) -> ty::TyProjection<'tcx> { + ty::TyProjection { + trait_ref: self.trait_ref.fold_with(folder), + item_name: self.item_name, } } } @@ -495,6 +531,14 @@ impl<'tcx> TypeFoldable<'tcx> for ty::EquatePredicate<'tcx> { } } +impl<'tcx> TypeFoldable<'tcx> for ty::TraitPredicate<'tcx> { + fn fold_with>(&self, folder: &mut F) -> ty::TraitPredicate<'tcx> { + ty::TraitPredicate { + trait_ref: self.trait_ref.fold_with(folder) + } + } +} + impl<'tcx,T,U> TypeFoldable<'tcx> for ty::OutlivesPredicate where T : TypeFoldable<'tcx>, U : TypeFoldable<'tcx>, @@ -544,7 +588,7 @@ pub fn super_fold_ty<'tcx, T: TypeFolder<'tcx>>(this: &mut T, ty::ty_bare_fn(opt_def_id, this.tcx().mk_bare_fn(bfn)) } ty::ty_closure(ref f) => { - ty::ty_closure(box f.fold_with(this)) + ty::ty_closure(f.fold_with(this)) } ty::ty_rptr(r, ref tm) => { let r = r.fold_with(this); @@ -559,6 +603,9 @@ pub fn super_fold_ty<'tcx, T: TypeFolder<'tcx>>(this: &mut T, let s = substs.fold_with(this); ty::ty_unboxed_closure(did, this.tcx().mk_region(r), this.tcx().mk_substs(s)) } + ty::ty_projection(ref data) => { + ty::ty_projection(data.fold_with(this)) + } ty::ty_bool | ty::ty_char | ty::ty_str | ty::ty_int(_) | ty::ty_uint(_) | ty::ty_float(_) | ty::ty_err | ty::ty_infer(_) | diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index ae8324d9a4f15..134a47225072d 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -448,6 +448,12 @@ pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String { bound_sep, bound_str) } + ty::ty_projection(ref data) => { + format!("<{} as {}>::{}", + data.trait_ref.self_ty().user_string(cx), + data.trait_ref.user_string(cx), + data.item_name.user_string(cx)) + } ty_str => "str".to_string(), ty_unboxed_closure(ref did, _, substs) => { let unboxed_closures = cx.unboxed_closures.borrow(); @@ -1408,17 +1414,55 @@ impl<'tcx> UserString<'tcx> for ty::EquatePredicate<'tcx> { } } +impl<'tcx> Repr<'tcx> for ty::TraitPredicate<'tcx> { + fn repr(&self, tcx: &ctxt<'tcx>) -> String { + format!("TraitPredicate({})", + self.trait_ref.repr(tcx)) + } +} + +impl<'tcx> UserString<'tcx> for ty::TraitPredicate<'tcx> { + fn user_string(&self, tcx: &ctxt<'tcx>) -> String { + format!("{} : {}", + self.trait_ref.self_ty().user_string(tcx), + self.trait_ref.user_string(tcx)) + } +} + +impl<'tcx> UserString<'tcx> for ty::ProjectionPredicate<'tcx> { + fn user_string(&self, tcx: &ctxt<'tcx>) -> String { + format!("{} == {}", + self.projection_ty.user_string(tcx), + self.ty.user_string(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.repr(tcx), + self.item_name.repr(tcx)) + } +} + +impl<'tcx> UserString<'tcx> for ty::ProjectionTy<'tcx> { + fn user_string(&self, tcx: &ctxt<'tcx>) -> String { + format!("<{} as {}>::{}", + self.trait_ref.self_ty().user_string(tcx), + self.trait_ref.user_string(tcx), + self.item_name.user_string(tcx)) + } +} + impl<'tcx> UserString<'tcx> for ty::Predicate<'tcx> { fn user_string(&self, tcx: &ctxt<'tcx>) -> String { match *self { - ty::Predicate::Trait(ref trait_ref) => { - format!("{} : {}", - trait_ref.self_ty().user_string(tcx), - trait_ref.user_string(tcx)) - } + ty::Predicate::Trait(ref data) => data.user_string(tcx), ty::Predicate::Equate(ref predicate) => predicate.user_string(tcx), ty::Predicate::RegionOutlives(ref predicate) => predicate.user_string(tcx), ty::Predicate::TypeOutlives(ref predicate) => predicate.user_string(tcx), + ty::Predicate::Projection(ref predicate) => predicate.user_string(tcx), } } } diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index e0a717d8073c9..c5d3ad805d934 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -281,6 +281,8 @@ pub fn kind_for_unboxed_closure(ccx: &CrateContext, closure_id: ast::DefId) pub fn decl_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_ty: Ty<'tcx>, name: &str) -> ValueRef { + let fn_ty = monomorphize::normalize_associated_type(ccx.tcx(), &fn_ty); + let (inputs, output, abi, env) = match fn_ty.sty { ty::ty_bare_fn(_, ref f) => { (f.sig.0.inputs.clone(), f.sig.0.output, f.abi, None) @@ -1453,7 +1455,8 @@ pub fn new_fn_ctxt<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>, let uses_outptr = match output_type { ty::FnConverging(output_type) => { - let substd_output_type = output_type.subst(ccx.tcx(), param_substs); + let substd_output_type = + monomorphize::apply_param_substs(ccx.tcx(), param_substs, &output_type); type_of::return_uses_outptr(ccx, substd_output_type) } ty::FnDiverging => false @@ -1512,7 +1515,7 @@ pub fn init_function<'a, 'tcx>(fcx: &'a FunctionContext<'a, 'tcx>, if let ty::FnConverging(output_type) = output { // This shouldn't need to recompute the return type, // as new_fn_ctxt did it already. - let substd_output_type = output_type.subst(fcx.ccx.tcx(), fcx.param_substs); + let substd_output_type = fcx.monomorphize(&output_type); if !return_type_is_void(fcx.ccx, substd_output_type) { // If the function returns nil/bot, there is no real return // value, so do not set `llretslotptr`. @@ -1732,7 +1735,7 @@ pub fn finish_fn<'blk, 'tcx>(fcx: &'blk FunctionContext<'blk, 'tcx>, // This shouldn't need to recompute the return type, // as new_fn_ctxt did it already. - let substd_retty = retty.subst(fcx.ccx.tcx(), fcx.param_substs); + let substd_retty = fcx.monomorphize(&retty); build_return_block(fcx, ret_cx, substd_retty); debuginfo::clear_source_location(fcx); @@ -2074,7 +2077,7 @@ fn trans_enum_variant_or_tuple_like_struct<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx param_substs: &Substs<'tcx>, llfndecl: ValueRef) { let ctor_ty = ty::node_id_to_type(ccx.tcx(), ctor_id); - let ctor_ty = ctor_ty.subst(ccx.tcx(), param_substs); + let ctor_ty = monomorphize::apply_param_substs(ccx.tcx(), param_substs, &ctor_ty); let result_ty = match ctor_ty.sty { ty::ty_bare_fn(_, ref bft) => bft.sig.0.output, @@ -2764,6 +2767,7 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef { } let item = ccx.tcx().map.get(id); + debug!("get_item_val: id={} item={}", id, item); let val = match item { ast_map::NodeItem(i) => { let ty = ty::node_id_to_type(ccx.tcx(), i.id); diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs index c0697c2a238df..169e52bcfe5be 100644 --- a/src/librustc_trans/trans/callee.rs +++ b/src/librustc_trans/trans/callee.rs @@ -516,6 +516,7 @@ pub fn trans_fn_ref_with_substs<'blk, 'tcx>( // Type scheme of the function item (may have type params) let fn_type_scheme = ty::lookup_item_type(tcx, def_id); + let fn_type = monomorphize::normalize_associated_type(tcx, &fn_type_scheme.ty); // Find the actual function pointer. let mut val = { @@ -524,7 +525,7 @@ pub fn trans_fn_ref_with_substs<'blk, 'tcx>( get_item_val(ccx, def_id.node) } else { // External reference. - trans_external_path(ccx, def_id, fn_type_scheme.ty) + trans_external_path(ccx, def_id, fn_type) } }; @@ -551,7 +552,7 @@ pub fn trans_fn_ref_with_substs<'blk, 'tcx>( // This can occur on either a crate-local or crate-external // reference. It also occurs when testing libcore and in some // other weird situations. Annoying. - let llty = type_of::type_of_fn_from_ty(ccx, fn_type_scheme.ty); + let llty = type_of::type_of_fn_from_ty(ccx, fn_type); let llptrty = llty.ptr_to(); if val_ty(val) != llptrty { debug!("trans_fn_ref_with_vtables(): casting pointer!"); diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs index f052a20bc89eb..694fbf251ddbf 100644 --- a/src/librustc_trans/trans/common.rs +++ b/src/librustc_trans/trans/common.rs @@ -24,20 +24,20 @@ use middle::infer; use middle::lang_items::LangItem; use middle::mem_categorization as mc; use middle::region; -use middle::subst; -use middle::subst::{Subst, Substs}; +use middle::subst::{mod, Subst, Substs}; use trans::base; use trans::build; use trans::cleanup; use trans::datum; use trans::debuginfo; use trans::machine; +use trans::monomorphize; use trans::type_::Type; use trans::type_of; use middle::traits; -use middle::ty::{mod, Ty}; +use middle::ty::{mod, HasProjectionTypes, Ty}; use middle::ty_fold; -use middle::ty_fold::TypeFoldable; +use middle::ty_fold::{TypeFolder, TypeFoldable}; use util::ppaux::Repr; use util::nodemap::{DefIdMap, FnvHashMap, NodeMap}; @@ -45,7 +45,6 @@ use arena::TypedArena; use libc::{c_uint, c_char}; use std::c_str::ToCStr; use std::cell::{Cell, RefCell}; -use std::rc::Rc; use std::vec::Vec; use syntax::ast::Ident; use syntax::ast; @@ -137,7 +136,7 @@ pub fn type_needs_unwind_cleanup<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty< ty::ty_enum(did, substs) => ty::enum_variants(tcx, did).iter().any(|v| - v.args.iter().any(|aty| { + v.args.iter().any(|&aty| { let t = aty.subst(tcx, substs); type_needs_unwind_cleanup_(tcx, t, tycache) }) @@ -465,6 +464,14 @@ impl<'a, 'tcx> FunctionContext<'a, 'tcx> { } return out; } + + pub fn monomorphize(&self, value: &T) -> T + where T : TypeFoldable<'tcx> + Repr<'tcx> + HasProjectionTypes + Clone + { + monomorphize::apply_param_substs(self.ccx.tcx(), + self.param_substs, + value) + } } // Basic block context. We create a block context for each basic block @@ -557,6 +564,14 @@ impl<'blk, 'tcx> BlockS<'blk, 'tcx> { pub fn to_str(&self) -> String { format!("[block {:p}]", self) } + + pub fn monomorphize(&self, value: &T) -> T + where T : TypeFoldable<'tcx> + Repr<'tcx> + HasProjectionTypes + Clone + { + monomorphize::apply_param_substs(self.tcx(), + self.fcx.param_substs, + value) + } } impl<'blk, 'tcx> mc::Typer<'tcx> for BlockS<'blk, 'tcx> { @@ -859,7 +874,7 @@ pub fn is_null(val: ValueRef) -> bool { } pub fn monomorphize_type<'blk, 'tcx>(bcx: &BlockS<'blk, 'tcx>, t: Ty<'tcx>) -> Ty<'tcx> { - t.subst(bcx.tcx(), bcx.fcx.param_substs) + bcx.fcx.monomorphize(&t) } pub fn node_id_type<'blk, 'tcx>(bcx: &BlockS<'blk, 'tcx>, id: ast::NodeId) -> Ty<'tcx> { @@ -881,7 +896,7 @@ pub fn expr_ty_adjusted<'blk, 'tcx>(bcx: &BlockS<'blk, 'tcx>, ex: &ast::Expr) -> /// guarantee to us that all nested obligations *could be* resolved if we wanted to. pub fn fulfill_obligation<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, span: Span, - trait_ref: Rc>) + trait_ref: ty::PolyTraitRef<'tcx>) -> traits::Vtable<'tcx, ()> { let tcx = ccx.tcx(); @@ -911,7 +926,7 @@ pub fn fulfill_obligation<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, // shallow result we are looking for -- that is, what specific impl. let mut selcx = traits::SelectionContext::new(&infcx, ¶m_env, tcx); let obligation = traits::Obligation::new(traits::ObligationCause::dummy(), - trait_ref.clone()); + trait_ref.to_poly_trait_predicate()); let selection = match selcx.select(&obligation) { Ok(Some(selection)) => selection, Ok(None) => { @@ -991,7 +1006,8 @@ pub enum ExprOrMethodCall { pub fn node_id_substs<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, node: ExprOrMethodCall) - -> subst::Substs<'tcx> { + -> subst::Substs<'tcx> +{ let tcx = bcx.tcx(); let substs = match node { @@ -1012,7 +1028,7 @@ pub fn node_id_substs<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } let substs = substs.erase_regions(); - substs.subst(tcx, bcx.fcx.param_substs) + bcx.monomorphize(&substs) } pub fn langcall(bcx: Block, diff --git a/src/librustc_trans/trans/context.rs b/src/librustc_trans/trans/context.rs index 02eaef885483f..9ceb0c6399093 100644 --- a/src/librustc_trans/trans/context.rs +++ b/src/librustc_trans/trans/context.rs @@ -100,7 +100,7 @@ pub struct LocalCrateContext<'tcx> { monomorphized: RefCell, ValueRef>>, monomorphizing: RefCell>, /// Cache generated vtables - vtables: RefCell, Rc>), ValueRef>>, + vtables: RefCell, ty::PolyTraitRef<'tcx>), ValueRef>>, /// Cache of constant strings, const_cstr_cache: RefCell>, @@ -151,7 +151,7 @@ pub struct LocalCrateContext<'tcx> { /// contexts around the same size. n_llvm_insns: Cell, - trait_cache: RefCell>, + trait_cache: RefCell, traits::Vtable<'tcx, ()>>>, } @@ -607,7 +607,7 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> { &self.local.monomorphizing } - pub fn vtables<'a>(&'a self) -> &'a RefCell, Rc>), + pub fn vtables<'a>(&'a self) -> &'a RefCell, ty::PolyTraitRef<'tcx>), ValueRef>> { &self.local.vtables } @@ -705,7 +705,7 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> { self.local.n_llvm_insns.set(self.local.n_llvm_insns.get() + 1); } - pub fn trait_cache(&self) -> &RefCell>, + pub fn trait_cache(&self) -> &RefCell, traits::Vtable<'tcx, ()>>> { &self.local.trait_cache } diff --git a/src/librustc_trans/trans/debuginfo.rs b/src/librustc_trans/trans/debuginfo.rs index 98f87b273852d..e94ce55e704a8 100644 --- a/src/librustc_trans/trans/debuginfo.rs +++ b/src/librustc_trans/trans/debuginfo.rs @@ -198,6 +198,7 @@ use middle::subst::{mod, Subst, Substs}; use trans::{mod, adt, machine, type_of}; use trans::common::*; use trans::_match::{BindingInfo, TrByCopy, TrByMove, TrByRef}; +use trans::monomorphize; use trans::type_::Type; use middle::ty::{mod, Ty}; use middle::pat_util; @@ -426,8 +427,8 @@ impl<'tcx> TypeMap<'tcx> { from_def_id_and_substs(self, cx, - trait_data.principal.def_id(), - trait_data.principal.substs(), + trait_data.principal_def_id(), + &trait_data.principal.0.substs, &mut unique_type_id); }, ty::ty_bare_fn(_, &ty::BareFnTy{ unsafety, abi, ref sig } ) => { @@ -1438,7 +1439,9 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, assert_type_for_node_id(cx, fn_ast_id, error_reporting_span); let return_type = ty::node_id_to_type(cx.tcx(), fn_ast_id); - let return_type = return_type.subst(cx.tcx(), param_substs); + let return_type = monomorphize::apply_param_substs(cx.tcx(), + param_substs, + &return_type); signature.push(type_metadata(cx, return_type, codemap::DUMMY_SP)); } } @@ -1447,7 +1450,9 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, for arg in fn_decl.inputs.iter() { assert_type_for_node_id(cx, arg.pat.id, arg.pat.span); let arg_type = ty::node_id_to_type(cx.tcx(), arg.pat.id); - let arg_type = arg_type.subst(cx.tcx(), param_substs); + let arg_type = monomorphize::apply_param_substs(cx.tcx(), + param_substs, + &arg_type); signature.push(type_metadata(cx, arg_type, codemap::DUMMY_SP)); } @@ -1459,8 +1464,10 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, param_substs: &Substs<'tcx>, file_metadata: DIFile, name_to_append_suffix_to: &mut String) - -> DIArray { + -> DIArray + { let self_type = param_substs.self_ty(); + let self_type = monomorphize::normalize_associated_type(cx.tcx(), &self_type); // Only true for static default methods: let has_self_type = self_type.is_some(); @@ -2878,7 +2885,7 @@ fn trait_pointer_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, // But it does not describe the trait's methods. let def_id = match trait_type.sty { - ty::ty_trait(box ty::TyTrait { ref principal, .. }) => principal.def_id(), + ty::ty_trait(ref data) => data.principal_def_id(), _ => { let pp_type_name = ppaux::ty_to_string(cx.tcx(), trait_type); cx.sess().bug(format!("debuginfo: Unexpected trait-object type in \ @@ -3811,8 +3818,8 @@ fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, output.push(']'); }, ty::ty_trait(ref trait_data) => { - push_item_name(cx, trait_data.principal.def_id(), false, output); - push_type_params(cx, trait_data.principal.substs(), output); + push_item_name(cx, trait_data.principal_def_id(), false, output); + push_type_params(cx, &trait_data.principal.0.substs, output); }, ty::ty_bare_fn(_, &ty::BareFnTy{ unsafety, abi, ref sig } ) => { if unsafety == ast::Unsafety::Unsafe { @@ -3920,9 +3927,10 @@ fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, ty::ty_unboxed_closure(..) => { output.push_str("closure"); } - ty::ty_err | + 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))[]); diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs index fc2e6c7b7fddb..5a7131cf68ecb 100644 --- a/src/librustc_trans/trans/expr.rs +++ b/src/librustc_trans/trans/expr.rs @@ -39,7 +39,7 @@ use back::abi; use llvm::{mod, ValueRef}; use middle::def; use middle::mem_categorization::Typer; -use middle::subst::{mod, Subst, Substs}; +use middle::subst::{mod, Substs}; use trans::{_match, adt, asm, base, callee, closure, consts, controlflow}; use trans::base::*; use trans::build::*; @@ -319,11 +319,13 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, bcx.ty_to_string(unadjusted_ty))[]) }, &ty::UnsizeVtable(ty::TyTrait { ref principal, .. }, _) => { - let substs = principal.substs().with_self_ty(unadjusted_ty).erase_regions(); + // Note that we preserve binding levels here: + let substs = principal.0.substs.with_self_ty(unadjusted_ty).erase_regions(); + let substs = tcx.tcx().mk_substs(substs); let trait_ref = - Rc::new(ty::Binder(ty::TraitRef { def_id: principal.def_id(), - substs: bcx.tcx().mk_substs(substs) })); - let trait_ref = trait_ref.subst(bcx.tcx(), bcx.fcx.param_substs); + ty::Binder(Rc::new(ty::TraitRef { def_id: principal.def_id(), + substs: substs })); + let trait_ref = bcx.monomorphize(&trait_ref); let box_ty = mk_ty(unadjusted_ty); PointerCast(bcx, meth::get_vtable(bcx, box_ty, trait_ref), @@ -1204,7 +1206,7 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, .get(&expr.id) .map(|t| (*t).clone()) .unwrap(); - let trait_ref = trait_ref.subst(bcx.tcx(), bcx.fcx.param_substs); + let trait_ref = bcx.monomorphize(&trait_ref); let datum = unpack_datum!(bcx, trans(bcx, &**val)); meth::trans_trait_cast(bcx, datum, expr.id, trait_ref, dest) diff --git a/src/librustc_trans/trans/foreign.rs b/src/librustc_trans/trans/foreign.rs index 1bad476863fdb..e234d77914b64 100644 --- a/src/librustc_trans/trans/foreign.rs +++ b/src/librustc_trans/trans/foreign.rs @@ -19,11 +19,12 @@ use trans::build::*; use trans::cabi; use trans::common::*; use trans::machine; +use trans::monomorphize; use trans::type_::Type; use trans::type_of::*; use trans::type_of; use middle::ty::{mod, Ty}; -use middle::subst::{Subst, Substs}; +use middle::subst::{Substs}; use std::cmp; use libc::c_uint; use syntax::abi::{Cdecl, Aapcs, C, Win64, Abi}; @@ -525,7 +526,7 @@ pub fn trans_rust_fn_with_foreign_abi<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, let _icx = push_ctxt("foreign::build_foreign_fn"); let fnty = ty::node_id_to_type(ccx.tcx(), id); - let mty = fnty.subst(ccx.tcx(), param_substs); + let mty = monomorphize::apply_param_substs(ccx.tcx(), param_substs, &fnty); let tys = foreign_types_for_fn_ty(ccx, mty); unsafe { // unsafe because we call LLVM operations @@ -543,10 +544,12 @@ pub fn trans_rust_fn_with_foreign_abi<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, attrs: &[ast::Attribute], id: ast::NodeId, hash: Option<&str>) - -> ValueRef { + -> ValueRef + { let _icx = push_ctxt("foreign::foreign::build_rust_fn"); let tcx = ccx.tcx(); - let t = ty::node_id_to_type(tcx, id).subst(ccx.tcx(), param_substs); + let t = ty::node_id_to_type(tcx, id); + let t = monomorphize::apply_param_substs(tcx, param_substs, &t); let ps = ccx.tcx().map.with_path(id, |path| { let abi = Some(ast_map::PathName(special_idents::clownshoe_abi.name)); diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs index a937f989b3ac5..00b17ca00dfb8 100644 --- a/src/librustc_trans/trans/meth.rs +++ b/src/librustc_trans/trans/meth.rs @@ -13,7 +13,7 @@ use back::abi; use llvm; use llvm::ValueRef; use metadata::csearch; -use middle::subst::{Subst,Substs}; +use middle::subst::{Substs}; use middle::subst::VecPerParamSpace; use middle::subst; use middle::traits; @@ -132,8 +132,7 @@ pub fn trans_method_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ref trait_ref, method_num }) => { - let trait_ref = - Rc::new(ty::Binder((**trait_ref).subst(bcx.tcx(), bcx.fcx.param_substs))); + let trait_ref = ty::Binder(bcx.monomorphize(trait_ref)); let span = bcx.tcx().map.span(method_call.expr_id); debug!("method_call={} trait_ref={}", method_call, @@ -142,8 +141,11 @@ pub fn trans_method_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, span, trait_ref.clone()); debug!("origin = {}", origin.repr(bcx.tcx())); - trans_monomorphized_callee(bcx, method_call, trait_ref.def_id(), - method_num, origin) + trans_monomorphized_callee(bcx, + method_call, + trait_ref.def_id(), + method_num, + origin) } ty::MethodTraitObject(ref mt) => { @@ -238,9 +240,10 @@ pub fn trans_static_method_callee(bcx: Block, rcvr_self, rcvr_assoc, Vec::new())); + let trait_substs = bcx.tcx().mk_substs(trait_substs); debug!("trait_substs={}", trait_substs.repr(bcx.tcx())); - let trait_ref = Rc::new(ty::Binder(ty::TraitRef { def_id: trait_id, - substs: bcx.tcx().mk_substs(trait_substs) })); + let trait_ref = ty::Binder(Rc::new(ty::TraitRef { def_id: trait_id, + substs: trait_substs })); let vtbl = fulfill_obligation(bcx.ccx(), DUMMY_SP, trait_ref); @@ -515,7 +518,7 @@ pub fn trans_trait_callee_from_llval<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, /// This will hopefully change now that DST is underway. pub fn get_vtable<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, box_ty: Ty<'tcx>, - trait_ref: Rc>) + trait_ref: ty::PolyTraitRef<'tcx>) -> ValueRef { debug!("get_vtable(box_ty={}, trait_ref={})", @@ -671,7 +674,7 @@ fn emit_vtable_methods<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, pub fn trans_trait_cast<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, datum: Datum<'tcx, Expr>, id: ast::NodeId, - trait_ref: Rc>, + trait_ref: ty::PolyTraitRef<'tcx>, dest: expr::Dest) -> Block<'blk, 'tcx> { let mut bcx = bcx; diff --git a/src/librustc_trans/trans/monomorphize.rs b/src/librustc_trans/trans/monomorphize.rs index 2a6aff56513a1..dcfe5f40ecee9 100644 --- a/src/librustc_trans/trans/monomorphize.rs +++ b/src/librustc_trans/trans/monomorphize.rs @@ -12,15 +12,18 @@ use back::link::exported_name; use session; use llvm::ValueRef; use llvm; +use middle::infer; use middle::subst; -use middle::subst::Subst; +use middle::subst::{Subst, Substs}; +use middle::traits; +use middle::ty_fold::{mod, TypeFolder, TypeFoldable}; use trans::base::{set_llvm_fn_attrs, set_inline_hint}; use trans::base::{trans_enum_variant, push_ctxt, get_item_val}; use trans::base::{trans_fn, decl_internal_rust_fn}; use trans::base; use trans::common::*; use trans::foreign; -use middle::ty::{mod, Ty}; +use middle::ty::{mod, HasProjectionTypes, Ty}; use util::ppaux::Repr; use syntax::abi; @@ -29,6 +32,7 @@ use syntax::ast_map; use syntax::ast_util::{local_def, PostExpansionMethod}; use syntax::attr; use std::hash::{sip, Hash}; +use std::rc::Rc; pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_id: ast::DefId, @@ -92,7 +96,12 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, } debug!("monomorphic_fn about to subst into {}", llitem_ty.repr(ccx.tcx())); + let mono_ty = llitem_ty.subst(ccx.tcx(), psubsts); + debug!("mono_ty = {} (post-substitution)", mono_ty.repr(ccx.tcx())); + + let mono_ty = normalize_associated_type(ccx.tcx(), &mono_ty); + debug!("mono_ty = {} (post-normalization)", mono_ty.repr(ccx.tcx())); ccx.stats().n_monos.set(ccx.stats().n_monos.get() + 1); @@ -282,3 +291,84 @@ pub struct MonoId<'tcx> { pub def: ast::DefId, pub params: subst::VecPerParamSpace> } + +/// Monomorphizes a type from the AST by first applying the in-scope +/// substitutions and then normalizing any associated types. +pub fn apply_param_substs<'tcx,T>(tcx: &ty::ctxt<'tcx>, + param_substs: &Substs<'tcx>, + value: &T) + -> T + where T : TypeFoldable<'tcx> + Repr<'tcx> + HasProjectionTypes + Clone +{ + assert!(param_substs.regions.is_erased()); + + let substituted = value.subst(tcx, param_substs); + normalize_associated_type(tcx, &substituted) +} + +/// Removes associated types, if any. Since this during +/// monomorphization, we know that only concrete types are involved, +/// and hence we can be sure that all associated types will be +/// completely normalized away. +pub fn normalize_associated_type<'tcx,T>(tcx: &ty::ctxt<'tcx>, t: &T) -> T + where T : TypeFoldable<'tcx> + Repr<'tcx> + HasProjectionTypes + Clone +{ + debug!("normalize_associated_type(t={})", t.repr(tcx)); + + if !t.has_projection_types() { + return t.clone(); + } + + // TODO cache + + let infcx = infer::new_infer_ctxt(tcx); + let param_env = ty::empty_parameter_environment(); + let mut selcx = traits::SelectionContext::new(&infcx, ¶m_env, tcx); + let mut normalizer = AssociatedTypeNormalizer { selcx: &mut selcx }; + let result = t.fold_with(&mut normalizer); + + debug!("normalize_associated_type: t={} result={}", + t.repr(tcx), + result.repr(tcx)); + + result +} + +struct AssociatedTypeNormalizer<'a,'tcx:'a> { + selcx: &'a mut traits::SelectionContext<'a,'tcx>, +} + +impl<'a,'tcx> TypeFolder<'tcx> for AssociatedTypeNormalizer<'a,'tcx> { + fn tcx(&self) -> &ty::ctxt<'tcx> { self.selcx.tcx() } + + fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { + match ty.sty { + ty::ty_projection(ref data) => { + debug!("ty_projection({})", data.repr(self.tcx())); + + let tcx = self.selcx.tcx(); + let substs = data.trait_ref.substs.clone().erase_regions(); + assert!(substs.types.iter().all(|&t| (!ty::type_has_params(t) && + !ty::type_has_self(t)))); + let trait_ref = Rc::new(ty::TraitRef::new(data.trait_ref.def_id, substs)); + let projection_ty = ty::ProjectionTy { trait_ref: trait_ref.clone(), + item_name: data.item_name }; + let obligation = traits::Obligation::new(traits::ObligationCause::dummy(), + projection_ty); + match traits::project_type(self.selcx, &obligation) { + Ok(ty) => ty, + Err(errors) => { + tcx.sess.bug( + format!("Encountered error(s) `{}` selecting `{}` during trans", + errors.repr(tcx), + trait_ref.repr(tcx)).as_slice()); + } + } + } + + _ => { + ty_fold::super_fold_ty(self, ty) + } + } + } +} diff --git a/src/librustc_trans/trans/type_of.rs b/src/librustc_trans/trans/type_of.rs index aaec82bb1771d..0bc35390cd7c0 100644 --- a/src/librustc_trans/trans/type_of.rs +++ b/src/librustc_trans/trans/type_of.rs @@ -241,7 +241,7 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ Type::struct_(cx, &[Type::i8p(cx), Type::i8p(cx)], false) } - ty::ty_infer(..) | ty::ty_param(..) | ty::ty_err(..) => { + ty::ty_projection(..) | ty::ty_infer(..) | ty::ty_param(..) | ty::ty_err(..) => { cx.sess().bug(format!("fictitious type {} in sizing_type_of()", ppaux::ty_to_string(cx.tcx(), t))[]) } @@ -414,6 +414,7 @@ pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type { }, ty::ty_infer(..) => cx.sess().bug("type_of with ty_infer"), + ty::ty_projection(..) => cx.sess().bug("type_of with ty_projection"), ty::ty_param(..) => cx.sess().bug("type_of with ty_param"), ty::ty_err(..) => cx.sess().bug("type_of with ty_err"), }; diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 0ba528ad0303d..00d3478e6a517 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -51,7 +51,7 @@ use middle::astconv_util::{ast_ty_to_prim_ty, check_path_args, NO_TPS, NO_REGION use middle::const_eval; use middle::def; use middle::resolve_lifetime as rl; -use middle::subst::{FnSpace, TypeSpace, AssocSpace, SelfSpace, Subst, Substs}; +use middle::subst::{FnSpace, TypeSpace, SelfSpace, Subst, Substs}; use middle::subst::{VecPerParamSpace}; use middle::ty::{mod, RegionEscape, Ty}; use rscope::{mod, UnelidableRscope, RegionScope, SpecificRscope, @@ -84,25 +84,45 @@ pub trait AstConv<'tcx> { /// What type should we use when a type is omitted? fn ty_infer(&self, span: Span) -> Ty<'tcx>; - /// Returns true if associated types from the given trait and type are - /// allowed to be used here and false otherwise. - fn associated_types_of_trait_are_valid(&self, - ty: Ty<'tcx>, - trait_id: ast::DefId) - -> bool; - - /// Returns the concrete type bound to the given associated type (indicated - /// by associated_type_id) in the current context. For example, - /// in `trait Foo { type A; }` looking up `A` will give a type variable; - /// in `impl Foo for ... { type A = int; ... }` looking up `A` will give `int`. - fn associated_type_binding(&self, - span: Span, - self_ty: Option>, - // DefId for the declaration of the trait - // in which the associated type is declared. - trait_id: ast::DefId, - associated_type_id: ast::DefId) - -> Option>; + /// Projecting an associated type from a (potentially) + /// higher-ranked trait reference is more complicated, because of + /// the possibility of late-bound regions appearing in the + /// associated type binding. This is not legal in function + /// signatures for that reason. In a function body, we can always + /// handle it because we can use inference variables to remove the + /// late-bound regions. + fn projected_ty_from_poly_trait_ref(&self, + span: Span, + poly_trait_ref: ty::PolyTraitRef<'tcx>, + item_name: ast::Name) + -> Ty<'tcx> + { + if ty::binds_late_bound_regions(self.tcx(), &poly_trait_ref) { + self.tcx().sess.span_err( + span, + "cannot extract an associated type from a higher-ranked trait bound \ + in this context"); + self.tcx().types.err + } else { + // no late-bound regions, we can just ignore the binder + self.projected_ty(span, poly_trait_ref.0.clone(), item_name) + } + } + + /// Project an associated type from a non-higher-ranked trait reference. + /// This is fairly straightforward and can be accommodated in any context. + fn projected_ty(&self, + span: Span, + _trait_ref: Rc>, + _item_name: ast::Name) + -> Ty<'tcx> + { + self.tcx().sess.span_err( + span, + "associated types are not accepted in this context"); + + self.tcx().types.err + } } pub fn ast_region_to_region(tcx: &ty::ctxt, lifetime: &ast::Lifetime) @@ -255,6 +275,8 @@ fn ast_path_substs_for_ty<'tcx,AC,RS>( } }; + prohibit_projections(this.tcx(), assoc_bindings.as_slice()); + create_substs_for_ast_path(this, rscope, path.span, @@ -262,21 +284,19 @@ fn ast_path_substs_for_ty<'tcx,AC,RS>( decl_generics, None, types, - regions, - assoc_bindings) + regions) } fn create_substs_for_ast_path<'tcx,AC,RS>( this: &AC, rscope: &RS, span: Span, - decl_def_id: ast::DefId, + _decl_def_id: ast::DefId, decl_generics: &ty::Generics<'tcx>, self_ty: Option>, types: Vec>, - regions: Vec, - assoc_bindings: Vec<(ast::Ident, Ty<'tcx>)>) - -> Substs<'tcx> + regions: Vec) + -> Substs<'tcx> where AC: AstConv<'tcx>, RS: RegionScope { let tcx = this.tcx(); @@ -382,52 +402,21 @@ fn create_substs_for_ast_path<'tcx,AC,RS>( } } - for formal_assoc in decl_generics.types.get_slice(AssocSpace).iter() { - let mut found = false; - for &(ident, ty) in assoc_bindings.iter() { - if formal_assoc.name.ident() == ident { - substs.types.push(AssocSpace, ty); - found = true; - break; - } - } - if !found { - match this.associated_type_binding(span, - self_ty, - decl_def_id, - formal_assoc.def_id) { - Some(ty) => { - substs.types.push(AssocSpace, ty); - } - None => { - substs.types.push(AssocSpace, ty::mk_err()); - span_err!(this.tcx().sess, span, E0171, - "missing type for associated type `{}`", - token::get_ident(formal_assoc.name.ident())); - } - } - } - } - - for &(ident, _) in assoc_bindings.iter() { - let mut formal_idents = decl_generics.types.get_slice(AssocSpace) - .iter().map(|t| t.name.ident()); - if !formal_idents.any(|i| i == ident) { - span_err!(this.tcx().sess, span, E0177, - "associated type `{}` does not exist", - token::get_ident(ident)); - } - } - return substs; } +struct ConvertedBinding<'tcx> { + item_name: ast::Name, + ty: Ty<'tcx>, + span: Span, +} + fn convert_angle_bracketed_parameters<'tcx, AC, RS>(this: &AC, rscope: &RS, data: &ast::AngleBracketedParameterData) -> (Vec, Vec>, - Vec<(ast::Ident, Ty<'tcx>)>) + Vec>) where AC: AstConv<'tcx>, RS: RegionScope { let regions: Vec<_> = @@ -442,7 +431,9 @@ fn convert_angle_bracketed_parameters<'tcx, AC, RS>(this: &AC, let assoc_bindings: Vec<_> = data.bindings.iter() - .map(|b| (b.ident, ast_ty_to_ty(this, rscope, &*b.ty))) + .map(|b| ConvertedBinding { item_name: b.ident.name, + ty: ast_ty_to_ty(this, rscope, &*b.ty), + span: b.span }) .collect(); (regions, types, assoc_bindings) @@ -534,38 +525,47 @@ pub fn instantiate_poly_trait_ref<'tcx,AC,RS>( rscope: &RS, ast_trait_ref: &ast::PolyTraitRef, self_ty: Option>, - allow_eq: AllowEqConstraints) - -> Rc> + poly_projections: &mut Vec>) + -> ty::PolyTraitRef<'tcx> where AC: AstConv<'tcx>, RS: RegionScope { + let mut projections = Vec::new(); + let trait_ref = - instantiate_trait_ref(this, rscope, &ast_trait_ref.trait_ref, self_ty, allow_eq); - let trait_ref = (*trait_ref).clone(); - Rc::new(ty::Binder(trait_ref)) // Ugh. + instantiate_trait_ref(this, rscope, &ast_trait_ref.trait_ref, + self_ty, Some(&mut projections)); + + for projection in projections.into_iter() { + poly_projections.push(ty::Binder(projection)); + } + + ty::Binder(trait_ref) } /// Instantiates the path for the given trait reference, assuming that it's /// bound to a valid trait type. Returns the def_id for the defining trait. /// Fails if the type is a type other than a trait type. -pub fn instantiate_trait_ref<'tcx,AC,RS>(this: &AC, - rscope: &RS, - ast_trait_ref: &ast::TraitRef, - self_ty: Option>, - allow_eq: AllowEqConstraints) - -> Rc> - where AC: AstConv<'tcx>, - RS: RegionScope +/// +/// If the `projections` argument is `None`, then assoc type bindings like `Foo` +/// are disallowed. Otherwise, they are pushed onto the vector given. +pub fn instantiate_trait_ref<'tcx,AC,RS>( + this: &AC, + rscope: &RS, + ast_trait_ref: &ast::TraitRef, + self_ty: Option>, + projections: Option<&mut Vec>>) + -> Rc> + where AC: AstConv<'tcx>, RS: RegionScope { match ::lookup_def_tcx(this.tcx(), ast_trait_ref.path.span, ast_trait_ref.ref_id) { def::DefTrait(trait_def_id) => { - let trait_ref = Rc::new(ast_path_to_trait_ref(this, - rscope, - trait_def_id, - self_ty, - &ast_trait_ref.path, - allow_eq)); - this.tcx().trait_refs.borrow_mut().insert(ast_trait_ref.ref_id, - trait_ref.clone()); + let trait_ref = ast_path_to_trait_ref(this, + rscope, + trait_def_id, + self_ty, + &ast_trait_ref.path, + projections); + this.tcx().trait_refs.borrow_mut().insert(ast_trait_ref.ref_id, trait_ref.clone()); trait_ref } _ => { @@ -576,20 +576,14 @@ pub fn instantiate_trait_ref<'tcx,AC,RS>(this: &AC, } } -#[deriving(PartialEq,Show)] -pub enum AllowEqConstraints { - Allow, - DontAllow -} - -fn ast_path_to_trait_ref<'tcx,AC,RS>( +fn ast_path_to_trait_ref<'a,'tcx,AC,RS>( this: &AC, rscope: &RS, trait_def_id: ast::DefId, self_ty: Option>, path: &ast::Path, - allow_eq: AllowEqConstraints) - -> ty::TraitRef<'tcx> + mut projections: Option<&mut Vec>>) + -> Rc> where AC: AstConv<'tcx>, RS: RegionScope { debug!("ast_path_to_trait_ref {}", path); @@ -624,11 +618,6 @@ fn ast_path_to_trait_ref<'tcx,AC,RS>( } }; - if allow_eq == AllowEqConstraints::DontAllow && assoc_bindings.len() > 0 { - span_err!(this.tcx().sess, path.span, E0173, - "equality constraints are not allowed in this position"); - } - let substs = create_substs_for_ast_path(this, &shifted_rscope, path.span, @@ -636,10 +625,69 @@ fn ast_path_to_trait_ref<'tcx,AC,RS>( &trait_def.generics, self_ty, types, - regions, - assoc_bindings); + regions); + let substs = this.tcx().mk_substs(substs); + + let trait_ref = Rc::new(ty::TraitRef::new(trait_def_id, substs)); + + match projections { + None => { + prohibit_projections(this.tcx(), assoc_bindings.as_slice()); + } + Some(ref mut v) => { + for binding in assoc_bindings.iter() { + match ast_type_binding_to_projection_predicate(this, trait_ref.clone(), binding) { + Ok(pp) => { v.push(pp); } + Err(ErrorReported) => { } + } + } + } + } + + trait_ref +} - ty::TraitRef::new(trait_def_id, this.tcx().mk_substs(substs)) +pub fn ast_type_binding_to_projection_predicate<'tcx,AC>( + this: &AC, + trait_ref: Rc>, + binding: &ConvertedBinding<'tcx>) + -> Result, ErrorReported> + where AC : AstConv<'tcx> +{ + // Given something like `U : SomeTrait`, we want to produce a + // predicate like `::T = X`. This is somewhat + // subtle in the event that `T` is defined in a supertrait of + // `SomeTrait`, because in that case we need to upcast. + // + // That is, consider this case: + // + // ``` + // trait SubTrait : SuperTrait { } + // trait SuperTrait { type T; } + // + // ... B : SubTrait ... + // ``` + // + // We want to produce `>::T == foo`. + + // FIXME(#19541): supertrait upcasting not actually impl'd :) + + if !trait_defines_associated_type_named(this, trait_ref.def_id, binding.item_name) { + this.tcx().sess.span_err( + binding.span, + format!("no associated type `{}` defined in `{}`", + token::get_name(binding.item_name), + trait_ref.user_string(this.tcx())).as_slice()); + return Err(ErrorReported); + } + + Ok(ty::ProjectionPredicate { + projection_ty: ty::ProjectionTy { + trait_ref: trait_ref, + item_name: binding.item_name, + }, + ty: binding.ty, + }) } pub fn ast_path_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( @@ -784,12 +832,14 @@ fn ast_ty_to_trait_ref<'tcx,AC,RS>(this: &AC, ast::TyPath(ref path, id) => { match this.tcx().def_map.borrow().get(&id) { Some(&def::DefTrait(trait_def_id)) => { - return Ok(ty::Binder(ast_path_to_trait_ref(this, - rscope, - trait_def_id, - None, - path, - AllowEqConstraints::Allow))); + // TODO do something with this + let mut projections = Vec::new(); + Ok(ty::Binder(ast_path_to_trait_ref(this, + rscope, + trait_def_id, + None, + path, + Some(&mut projections)))) } _ => { span_err!(this.tcx().sess, ty.span, E0172, "expected a reference to a trait"); @@ -831,7 +881,7 @@ fn ast_ty_to_trait_ref<'tcx,AC,RS>(this: &AC, fn trait_ref_to_object_type<'tcx,AC,RS>(this: &AC, rscope: &RS, span: Span, - trait_ref: ty::PolyTraitRef<'tcx>, + trait_ref: ty::Binder>, bounds: &[ast::TyParamBound]) -> Ty<'tcx> where AC : AstConv<'tcx>, RS : RegionScope @@ -849,6 +899,68 @@ fn trait_ref_to_object_type<'tcx,AC,RS>(this: &AC, result } +fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>, + ast_ty: &ast::Ty, + provenance: def::TyParamProvenance, + assoc_name: ast::Name) + -> Ty<'tcx> +{ + let tcx = this.tcx(); + let ty_param_def_id = provenance.def_id(); + let mut suitable_bounds: Vec<_>; + let ty_param_name: ast::Name; + { // contain scope of refcell: + let ty_param_defs = tcx.ty_param_defs.borrow(); + let ty_param_def = &ty_param_defs[ty_param_def_id.node]; + ty_param_name = ty_param_def.name; + + // FIXME(#19541): we should consider associated types in + // super-traits. Probably by elaborating the bounds. + + suitable_bounds = + ty_param_def.bounds.trait_bounds // TODO trait_bounds, no good + .iter() + .cloned() + .filter(|b| trait_defines_associated_type_named(this, b.def_id(), assoc_name)) + .collect(); + } + + if suitable_bounds.len() == 0 { + tcx.sess.span_err(ast_ty.span, + format!("associated type `{}` not found for type parameter `{}`", + token::get_name(assoc_name), + token::get_name(ty_param_name)).as_slice()); + return this.tcx().types.err; + } + + if suitable_bounds.len() > 1 { + tcx.sess.span_err(ast_ty.span, + format!("ambiguous associated type `{}` in bounds of `{}`", + token::get_name(assoc_name), + token::get_name(ty_param_name)).as_slice()); + + for suitable_bound in suitable_bounds.iter() { + span_note!(this.tcx().sess, ast_ty.span, + "associated type `{}` could derive from `{}`", + token::get_name(ty_param_name), + suitable_bound.user_string(this.tcx())); + } + } + + let suitable_bound = suitable_bounds.pop().unwrap().clone(); + return this.projected_ty_from_poly_trait_ref(ast_ty.span, suitable_bound, assoc_name); +} + +fn trait_defines_associated_type_named(this: &AstConv, + trait_def_id: ast::DefId, + assoc_name: ast::Name) + -> bool +{ + let tcx = this.tcx(); + let trait_def = ty::lookup_trait_def(tcx, trait_def_id); + trait_def.associated_type_names.contains(&assoc_name) +} + fn qpath_to_ty<'tcx,AC,RS>(this: &AC, rscope: &RS, ast_ty: &ast::Ty, // the TyQPath @@ -867,33 +979,13 @@ fn qpath_to_ty<'tcx,AC,RS>(this: &AC, rscope, &*qpath.trait_ref, Some(self_type), - AllowEqConstraints::DontAllow); + None); debug!("qpath_to_ty: trait_ref={}", trait_ref.repr(this.tcx())); - if let Some(ty) = find_assoc_ty(this, &*trait_ref, qpath.item_name) { - return ty; - } - - this.tcx().sess.span_bug(ast_ty.span, - "this associated type didn't get added \ - as a parameter for some reason") -} - -fn find_assoc_ty<'tcx, AC>(this: &AC, - trait_ref: &ty::TraitRef<'tcx>, - type_name: ast::Ident) - -> Option> -where AC: AstConv<'tcx> { - let trait_def = this.get_trait_def(trait_ref.def_id); - - for ty_param_def in trait_def.generics.types.get_slice(AssocSpace).iter() { - if ty_param_def.name == type_name.name { - return Some(trait_ref.substs.type_for_def(ty_param_def)); - } - } - - None + return this.projected_ty(ast_ty.span, + trait_ref, + qpath.item_name.name); // TODO change qpath to use name } // Parses the programmer's textual representation of a type into our @@ -928,6 +1020,7 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( ast::TyObjectSum(ref ty, ref bounds) => { match ast_ty_to_trait_ref(this, rscope, &**ty, bounds[]) { Ok(trait_ref) => { + let trait_ref = trait_ref.remove_rc(); trait_ref_to_object_type(this, rscope, ast_ty.span, trait_ref, bounds[]) } @@ -1000,13 +1093,16 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( def::DefTrait(trait_def_id) => { // N.B. this case overlaps somewhat with // TyObjectSum, see that fn for details - let result = ty::Binder(ast_path_to_trait_ref(this, - rscope, - trait_def_id, - None, - path, - AllowEqConstraints::Allow)); - trait_ref_to_object_type(this, rscope, path.span, result, &[]) + let mut projections = Vec::new(); // TODO + let trait_ref = ast_path_to_trait_ref(this, + rscope, + trait_def_id, + None, + path, + Some(&mut projections)); + let trait_ref = (*trait_ref).clone(); + let trait_ref = ty::Binder(trait_ref); + trait_ref_to_object_type(this, rscope, path.span, trait_ref, &[]) } def::DefTy(did, _) | def::DefStruct(did) => { ast_path_to_ty(this, rscope, did, path).ty @@ -1048,44 +1144,9 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( .get())[]); this.tcx().types.err } - def::DefAssociatedPath(typ, assoc_ident) => { - // FIXME(#19541): in both branches we should consider - // associated types in super-traits. - let (assoc_tys, tp_name): (Vec<_>, _) = match typ { - def::TyParamProvenance::FromParam(did) | - def::TyParamProvenance::FromSelf(did) => { - let ty_param_defs = tcx.ty_param_defs.borrow(); - let tp_def = &(*ty_param_defs)[did.node]; - let assoc_tys = tp_def.bounds.trait_bounds.iter() - .filter_map(|b| find_assoc_ty(this, &b.0, assoc_ident)) - .collect(); - (assoc_tys, token::get_name(tp_def.name).to_string()) - } - }; - - if assoc_tys.len() == 0 { - tcx.sess.span_err(ast_ty.span, - format!("associated type `{}` not \ - found for type parameter `{}`", - token::get_ident(assoc_ident), - tp_name).as_slice()); - return ty::mk_err() - } - - if assoc_tys.len() > 1 { - tcx.sess.span_err(ast_ty.span, - format!("ambiguous associated type \ - `{}` in bounds of `{}`", - token::get_ident(assoc_ident), - tp_name).as_slice()); - } - - let mut result_ty = assoc_tys[0]; - if let Some(substs) = this.get_free_substs() { - result_ty = result_ty.subst(tcx, substs); - } - - result_ty + def::DefAssociatedPath(provenance, assoc_ident) => { + // TODO update DefAssociatedPath to use name + associated_path_def_to_ty(this, ast_ty, provenance, assoc_ident.name) } _ => { tcx.sess.span_fatal(ast_ty.span, @@ -1440,7 +1501,7 @@ pub fn conv_existential_bounds<'tcx, AC: AstConv<'tcx>, RS:RegionScope>( this: &AC, rscope: &RS, span: Span, - principal_trait_ref: Option<&ty::PolyTraitRef<'tcx>>, // None for boxed closures + principal_trait_ref: Option<&ty::Binder>>, // None for boxed closures ast_bounds: &[ast::TyParamBound]) -> ty::ExistentialBounds { @@ -1461,13 +1522,15 @@ fn conv_ty_poly_trait_ref<'tcx, AC, RS>( { let mut partitioned_bounds = partition_bounds(this.tcx(), span, ast_bounds[]); + let mut projections = Vec::new(); let main_trait_bound = match partitioned_bounds.trait_bounds.remove(0) { Some(trait_bound) => { - Some(instantiate_poly_trait_ref(this, - rscope, - trait_bound, - None, - AllowEqConstraints::Allow)) + let ptr = instantiate_poly_trait_ref(this, + rscope, + trait_bound, + None, + &mut projections); + Some(ptr.remove_rc()) } None => { this.tcx().sess.span_err( @@ -1477,11 +1540,13 @@ fn conv_ty_poly_trait_ref<'tcx, AC, RS>( } }; + // TODO use projections somewhere + let bounds = conv_existential_bounds_from_partitioned_bounds(this, rscope, span, - main_trait_bound.as_ref().map(|tr| &**tr), + main_trait_bound.as_ref(), partitioned_bounds); match main_trait_bound { @@ -1494,7 +1559,7 @@ pub fn conv_existential_bounds_from_partitioned_bounds<'tcx, AC, RS>( this: &AC, rscope: &RS, span: Span, - principal_trait_ref: Option<&ty::PolyTraitRef<'tcx>>, // None for boxed closures + principal_trait_ref: Option<&ty::Binder>>, // None for boxed closures partitioned_bounds: PartitionedBounds) -> ty::ExistentialBounds where AC: AstConv<'tcx>, RS:RegionScope @@ -1532,7 +1597,7 @@ pub fn conv_existential_bounds_from_partitioned_bounds<'tcx, AC, RS>( fn compute_opt_region_bound<'tcx>(tcx: &ty::ctxt<'tcx>, span: Span, explicit_region_bounds: &[&ast::Lifetime], - principal_trait_ref: Option<&ty::PolyTraitRef<'tcx>>, + principal_trait_ref: Option<&ty::Binder>>, builtin_bounds: ty::BuiltinBounds) -> Option { @@ -1592,7 +1657,7 @@ fn compute_region_bound<'tcx, AC: AstConv<'tcx>, RS:RegionScope>( rscope: &RS, span: Span, region_bounds: &[&ast::Lifetime], - principal_trait_ref: Option<&ty::PolyTraitRef<'tcx>>, // None for closures + principal_trait_ref: Option<&ty::Binder>>, // None for closures builtin_bounds: ty::BuiltinBounds) -> ty::Region { @@ -1660,6 +1725,7 @@ pub fn partition_bounds<'a>(tcx: &ty::ctxt, if ty::try_add_builtin_trait(tcx, trait_did, &mut builtin_bounds) { + // TODO Copy? continue; // success } } @@ -1683,3 +1749,13 @@ pub fn partition_bounds<'a>(tcx: &ty::ctxt, region_bounds: region_bounds, } } + +fn prohibit_projections<'tcx>(tcx: &ty::ctxt<'tcx>, + bindings: &[ConvertedBinding<'tcx>]) +{ + for binding in bindings.iter().take(1) { + tcx.sess.span_err( + binding.span, + "associated type bindings are not allowed here"); + } +} diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index dc77a1e782bba..0e8b5b373f144 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -11,7 +11,7 @@ use middle::def; use middle::infer; use middle::pat_util::{PatIdMap, pat_id_map, pat_is_binding, pat_is_const}; -use middle::subst::{Subst, Substs}; +use middle::subst::{Substs}; use middle::ty::{mod, Ty}; use check::{check_expr, check_expr_has_type, check_expr_with_expectation}; use check::{check_expr_coercable_to_type, demand, FnCtxt, Expectation}; @@ -410,17 +410,24 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &ast::Pat, demand::eqtype(fcx, pat.span, expected, pat_ty); let real_path_ty = fcx.node_ty(pat.id); - let (arg_tys, kind_name) = match real_path_ty.sty { + let (arg_tys, kind_name): (Vec<_>, &'static str) = match real_path_ty.sty { ty::ty_enum(enum_def_id, expected_substs) - if def == def::DefVariant(enum_def_id, def.def_id(), false) => { + if def == def::DefVariant(enum_def_id, def.def_id(), false) => + { let variant = ty::enum_variant_with_id(tcx, enum_def_id, def.def_id()); - (variant.args.iter().map(|t| t.subst(tcx, expected_substs)).collect::>(), - "variant") + (variant.args.iter() + .map(|t| fcx.instantiate_type_scheme(pat.span, expected_substs, t)) + .collect(), + "variant") } ty::ty_struct(struct_def_id, expected_substs) => { let struct_fields = ty::struct_fields(tcx, struct_def_id, expected_substs); - (struct_fields.iter().map(|field| field.mt.ty).collect::>(), - "struct") + (struct_fields.iter() + .map(|field| fcx.instantiate_type_scheme(pat.span, + expected_substs, + &field.mt.ty)) + .collect(), + "struct") } _ => { let name = pprust::path_to_string(path); diff --git a/src/librustc_typeck/check/assoc.rs b/src/librustc_typeck/check/assoc.rs new file mode 100644 index 0000000000000..65ade452fa111 --- /dev/null +++ b/src/librustc_typeck/check/assoc.rs @@ -0,0 +1,73 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use middle::infer::InferCtxt; +use middle::traits::{ObligationCause, ObligationCauseCode, FulfillmentContext}; +use middle::ty::{mod, HasProjectionTypes, Ty}; +use middle::ty_fold::{mod, TypeFoldable, TypeFolder}; +use syntax::ast; +use syntax::codemap::Span; +use std::rc::Rc; + +pub fn normalize_associated_types_in<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>, + fulfillment_cx: &mut FulfillmentContext<'tcx>, + span: Span, + body_id: ast::NodeId, + value: &T) + -> T + where T : TypeFoldable<'tcx> + HasProjectionTypes + Clone +{ + let value = infcx.resolve_type_vars_if_possible(value); + + if !value.has_projection_types() { + return value.clone(); + } + + let mut normalizer = AssociatedTypeNormalizer { span: span, + body_id: body_id, + infcx: infcx, + fulfillment_cx: fulfillment_cx }; + value.fold_with(&mut normalizer) +} + +struct AssociatedTypeNormalizer<'a,'tcx:'a> { + infcx: &'a InferCtxt<'a, 'tcx>, + fulfillment_cx: &'a mut FulfillmentContext<'tcx>, + span: Span, + body_id: ast::NodeId, +} + +impl<'a,'tcx> TypeFolder<'tcx> for AssociatedTypeNormalizer<'a,'tcx> { + fn tcx(&self) -> &ty::ctxt<'tcx> { + self.infcx.tcx + } + + fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { + match ty.sty { + ty::ty_projection(ref data) => { + let cause = + ObligationCause::new( + self.span, + self.body_id, + ObligationCauseCode::MiscObligation); + let trait_ref = Rc::new(data.trait_ref.clone()); + self.fulfillment_cx + .normalize_associated_type(self.infcx, + trait_ref, + data.item_name, + cause) + } + _ => { + ty_fold::super_fold_ty(self, ty) + } + } + } +} diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index c8a8a0ff55908..ec964ab638f14 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -15,7 +15,7 @@ use super::{check_fn, Expectation, FnCtxt}; use astconv; use middle::infer; use middle::subst; -use middle::ty::{mod, Ty}; +use middle::ty::{mod, ToPolyTraitRef, Ty}; use rscope::RegionScope; use syntax::abi; use syntax::ast; @@ -168,7 +168,8 @@ fn deduce_unboxed_closure_expectations_from_expected_type<'a,'tcx>( { match expected_ty.sty { ty::ty_trait(ref object_type) => { - deduce_unboxed_closure_expectations_from_trait_ref(fcx, &object_type.principal) + let trait_ref = object_type.principal_trait_ref_with_self_ty(fcx.tcx().types.err); + deduce_unboxed_closure_expectations_from_trait_ref(fcx, &trait_ref) } ty::ty_infer(ty::TyVar(vid)) => { deduce_unboxed_closure_expectations_from_obligations(fcx, vid) @@ -227,23 +228,21 @@ fn deduce_unboxed_closure_expectations_from_obligations<'a,'tcx>( { // Here `expected_ty` is known to be a type inference variable. for obligation in fcx.inh.fulfillment_cx.borrow().pending_obligations().iter() { - match obligation.trait_ref { - ty::Predicate::Trait(ref trait_ref) => { + match obligation.predicate { + ty::Predicate::Trait(ref trait_predicate) => { + let trait_ref = trait_predicate.to_poly_trait_ref(); let self_ty = fcx.infcx().shallow_resolve(trait_ref.self_ty()); match self_ty.sty { ty::ty_infer(ty::TyVar(v)) if expected_vid == v => { } _ => { continue; } } - match deduce_unboxed_closure_expectations_from_trait_ref(fcx, &**trait_ref) { + match deduce_unboxed_closure_expectations_from_trait_ref(fcx, &trait_ref) { Some(e) => { return Some(e); } None => { } } } - ty::Predicate::Equate(..) | - ty::Predicate::RegionOutlives(..) | - ty::Predicate::TypeOutlives(..) => { - } + _ => { } } } diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 791ebc5d0ea80..de6824fa5ddd1 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -11,7 +11,7 @@ use super::probe; use check::{mod, FnCtxt, NoPreference, PreferMutLvalue, callee}; -use middle::subst::{mod, Subst}; +use middle::subst::{mod}; use middle::traits; use middle::ty::{mod, Ty}; use middle::ty::{MethodCall, MethodCallee, MethodObject, MethodOrigin, @@ -227,14 +227,14 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { let upcast_poly_trait_ref = this.upcast(original_poly_trait_ref.clone(), trait_def_id); let upcast_trait_ref = - this.replace_late_bound_regions_with_fresh_var(&*upcast_poly_trait_ref); + this.replace_late_bound_regions_with_fresh_var(&upcast_poly_trait_ref); debug!("original_poly_trait_ref={} upcast_trait_ref={} target_trait={}", original_poly_trait_ref.repr(this.tcx()), upcast_trait_ref.repr(this.tcx()), trait_def_id.repr(this.tcx())); let substs = upcast_trait_ref.substs.clone(); let origin = MethodTraitObject(MethodObject { - trait_ref: Rc::new(upcast_trait_ref), + trait_ref: upcast_trait_ref, object_trait_id: trait_def_id, method_num: method_num, real_index: real_index, @@ -254,9 +254,11 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { // parameters from the trait ([$A,$B]), not those from // the impl ([$A,$B,$C]) not the receiver type ([$C]). let impl_polytype = check::impl_self_ty(self.fcx, self.span, impl_def_id); - let impl_trait_ref = ty::impl_trait_ref(self.tcx(), impl_def_id) - .unwrap() - .subst(self.tcx(), &impl_polytype.substs); + let impl_trait_ref = + self.fcx.instantiate_type_scheme( + self.span, + &impl_polytype.substs, + &ty::impl_trait_ref(self.tcx(), impl_def_id).unwrap()); let origin = MethodTypeParam(MethodParam { trait_ref: impl_trait_ref.clone(), method_num: method_num }); (impl_trait_ref.substs.clone(), origin) @@ -284,9 +286,9 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { probe::WhereClausePick(ref poly_trait_ref, method_num) => { // Where clauses can have bound regions in them. We need to instantiate // those to convert from a poly-trait-ref to a trait-ref. - let trait_ref = self.replace_late_bound_regions_with_fresh_var(&**poly_trait_ref); + let trait_ref = self.replace_late_bound_regions_with_fresh_var(&*poly_trait_ref); let substs = trait_ref.substs.clone(); - let origin = MethodTypeParam(MethodParam { trait_ref: Rc::new(trait_ref), + let origin = MethodTypeParam(MethodParam { trait_ref: trait_ref, method_num: method_num }); (substs, origin) } @@ -425,9 +427,13 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { // Substitute the type/early-bound-regions into the method // signature. In addition, the method signature may bind // late-bound regions, so instantiate those. - let method_sig = pick.method_ty.fty.sig.subst(self.tcx(), &all_substs); - let method_sig = self.replace_late_bound_regions_with_fresh_var(&method_sig); + let method_sig = self.fcx.instantiate_type_scheme(self.span, + &all_substs, + &pick.method_ty.fty.sig); + debug!("late-bound lifetimes from method substituted, method_sig={}", + method_sig.repr(self.tcx())); + let method_sig = self.replace_late_bound_regions_with_fresh_var(&method_sig); debug!("late-bound lifetimes from method instantiated, method_sig={}", method_sig.repr(self.tcx())); @@ -626,9 +632,9 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { } fn upcast(&mut self, - source_trait_ref: Rc>, + source_trait_ref: ty::PolyTraitRef<'tcx>, target_trait_def_id: ast::DefId) - -> Rc> + -> ty::PolyTraitRef<'tcx> { for super_trait_ref in traits::supertraits(self.tcx(), source_trait_ref.clone()) { if super_trait_ref.def_id() == target_trait_def_id { diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 0c094823a7575..cb71fbce8ac4c 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -16,7 +16,6 @@ use check::{impl_self_ty}; use check::vtable; use check::vtable::select_new_fcx_obligations; use middle::subst; -use middle::subst::{Subst}; use middle::traits; use middle::ty::*; use middle::ty; @@ -167,7 +166,7 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>, let trait_ref = Rc::new(ty::TraitRef::new(trait_def_id, fcx.tcx().mk_substs(substs))); // Construct an obligation - let poly_trait_ref = Rc::new(ty::Binder((*trait_ref).clone())); + let poly_trait_ref = trait_ref.to_poly_trait_ref(); let obligation = traits::Obligation::misc(span, fcx.body_id, poly_trait_ref.as_predicate()); @@ -193,11 +192,12 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>, // Substitute the trait parameters into the method type and // instantiate late-bound regions to get the actual method type. - let ref bare_fn_ty = method_ty.fty; - let fn_sig = bare_fn_ty.sig.subst(tcx, trait_ref.substs); + let bare_fn_ty = fcx.instantiate_type_scheme(span, + &trait_ref.substs, + &method_ty.fty); let fn_sig = fcx.infcx().replace_late_bound_regions_with_fresh_var(span, infer::FnCall, - &fn_sig).0; + &bare_fn_ty.sig).0; let transformed_self_ty = fn_sig.inputs[0]; let fty = ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(ty::BareFnTy { sig: ty::Binder(fn_sig), diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 3ecd2007ff13c..1a9e124521e0f 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -18,7 +18,7 @@ use middle::fast_reject; use middle::subst; use middle::subst::Subst; use middle::traits; -use middle::ty::{mod, Ty}; +use middle::ty::{mod, Ty, ToPolyTraitRef}; use middle::ty_fold::TypeFoldable; use middle::infer; use middle::infer::InferCtxt; @@ -61,7 +61,7 @@ enum CandidateKind<'tcx> { ExtensionImplCandidate(/* Impl */ ast::DefId, Rc>, subst::Substs<'tcx>, MethodIndex), UnboxedClosureCandidate(/* Trait */ ast::DefId, MethodIndex), - WhereClauseCandidate(Rc>, MethodIndex), + WhereClauseCandidate(ty::PolyTraitRef<'tcx>, MethodIndex), } pub struct Pick<'tcx> { @@ -76,7 +76,7 @@ pub enum PickKind<'tcx> { ObjectPick(/* Trait */ ast::DefId, /* method_num */ uint, /* real_index */ uint), ExtensionImplPick(/* Impl */ ast::DefId, MethodIndex), TraitPick(/* Trait */ ast::DefId, MethodIndex), - WhereClausePick(/* Trait */ Rc>, MethodIndex), + WhereClausePick(/* Trait */ ty::PolyTraitRef<'tcx>, MethodIndex), } pub type PickResult<'tcx> = Result, MethodError>; @@ -235,7 +235,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { match self_ty.sty { ty::ty_trait(box ref data) => { self.assemble_inherent_candidates_from_object(self_ty, data); - self.assemble_inherent_impl_candidates_for_type(data.principal.def_id()); + self.assemble_inherent_impl_candidates_for_type(data.principal_def_id()); } ty::ty_enum(did, _) | ty::ty_struct(did, _) | @@ -308,7 +308,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { let trait_ref = data.principal_trait_ref_with_self_ty(self.tcx(), self_ty); self.elaborate_bounds(&[trait_ref.clone()], false, |this, new_trait_ref, m, method_num| { let vtable_index = - get_method_index(tcx, &*new_trait_ref, trait_ref.clone(), method_num); + get_method_index(tcx, &new_trait_ref, trait_ref.clone(), method_num); let xform_self_ty = this.xform_self_ty(&m, new_trait_ref.substs()); @@ -330,13 +330,16 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { .iter() .filter_map(|predicate| { match *predicate { - ty::Predicate::Trait(ref trait_ref) => { - match trait_ref.self_ty().sty { - ty::ty_param(ref p) if *p == param_ty => Some(trait_ref.clone()), + ty::Predicate::Trait(ref trait_predicate) => { + match trait_predicate.0.trait_ref.self_ty().sty { + ty::ty_param(ref p) if *p == param_ty => { + Some(trait_predicate.to_poly_trait_ref()) + } _ => None } } ty::Predicate::Equate(..) | + ty::Predicate::Projection(..) | ty::Predicate::RegionOutlives(..) | ty::Predicate::TypeOutlives(..) => { None @@ -381,10 +384,10 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { // create the candidates. fn elaborate_bounds( &mut self, - bounds: &[Rc>], + bounds: &[ty::PolyTraitRef<'tcx>], num_includes_types: bool, mk_cand: for<'b> |this: &mut ProbeContext<'b, 'tcx>, - tr: Rc>, + tr: ty::PolyTraitRef<'tcx>, m: Rc>, method_num: uint|) { @@ -996,7 +999,7 @@ fn trait_method<'tcx>(tcx: &ty::ctxt<'tcx>, // to a trait and its supertraits. fn get_method_index<'tcx>(tcx: &ty::ctxt<'tcx>, trait_ref: &ty::PolyTraitRef<'tcx>, - subtrait: Rc>, + subtrait: ty::PolyTraitRef<'tcx>, n_method: uint) -> uint { // We need to figure the "real index" of the method in a // listing of all the methods of an object. We do this by diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 7a6b2d54dc167..be8fa21cf0ee8 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -93,10 +93,10 @@ use middle::subst::{mod, Subst, Substs, VecPerParamSpace, ParamSpace}; use middle::traits; use middle::ty::{FnSig, VariantInfo, TypeScheme}; use middle::ty::{Disr, ParamTy, ParameterEnvironment}; -use middle::ty::{mod, Ty}; +use middle::ty::{mod, HasProjectionTypes, Ty}; use middle::ty::liberate_late_bound_regions; use middle::ty::{MethodCall, MethodCallee, MethodMap, ObjectCastMap}; -use middle::ty_fold::TypeFolder; +use middle::ty_fold::{TypeFolder, TypeFoldable}; use rscope::RegionScope; use session::Session; use {CrateCtxt, lookup_def_ccx, no_params, require_same_types}; @@ -120,6 +120,7 @@ use syntax::print::pprust; use syntax::ptr::P; use syntax::visit::{mod, Visitor}; +mod assoc; pub mod _match; pub mod vtable; pub mod writeback; @@ -348,6 +349,17 @@ impl<'a, 'tcx> Inherited<'a, 'tcx> { fulfillment_cx: RefCell::new(traits::FulfillmentContext::new()), } } + + fn normalize_associated_types_in(&self, span: Span, body_id: ast::NodeId, value: &T) -> T + where T : TypeFoldable<'tcx> + Clone + HasProjectionTypes + { + let mut fulfillment_cx = self.fulfillment_cx.borrow_mut(); + assoc::normalize_associated_types_in(&self.infcx, + &mut *fulfillment_cx, span, + body_id, + value) + } + } // Used by check_const and check_enum_variants @@ -414,15 +426,18 @@ fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, decl: &ast::FnDecl, body: &ast::Block, id: ast::NodeId, - fty: Ty<'tcx>, + raw_fty: Ty<'tcx>, param_env: ty::ParameterEnvironment<'tcx>) { - // Compute the fty from point of view of inside fn - // (replace any type-scheme with a type) - let fty = fty.subst(ccx.tcx, ¶m_env.free_substs); - - match fty.sty { + match raw_fty.sty { ty::ty_bare_fn(_, ref fn_ty) => { let inh = Inherited::new(ccx.tcx, param_env); + + // Compute the fty from point of view of inside fn + // (replace any type-scheme with a type, and normalize + // associated types appearing in the fn signature). + let fn_ty = fn_ty.subst(ccx.tcx, &inh.param_env.free_substs); + let fn_ty = inh.normalize_associated_types_in(body.span, body.id, &fn_ty); + let fcx = check_fn(ccx, fn_ty.unsafety, id, &fn_ty.sig, decl, id, body, &inh); @@ -532,7 +547,8 @@ fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>, fn_id: ast::NodeId, body: &ast::Block, inherited: &'a Inherited<'a, 'tcx>) - -> FnCtxt<'a, 'tcx> { + -> FnCtxt<'a, 'tcx> +{ let tcx = ccx.tcx; let err_count_on_creation = tcx.sess.err_count(); @@ -771,9 +787,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, // corresponding method definition in the trait. let opt_trait_method_ty = trait_items.iter() - .find(|ti| { - ti.name() == impl_item_ty.name() - }); + .find(|ti| ti.name() == impl_item_ty.name()); match opt_trait_method_ty { Some(trait_method_ty) => { match (trait_method_ty, &impl_item_ty) { @@ -917,6 +931,7 @@ fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>, impl_trait_ref.repr(tcx)); let infcx = infer::new_infer_ctxt(tcx); + let mut fulfillment_cx = traits::FulfillmentContext::new(); let trait_to_impl_substs = &impl_trait_ref.substs; @@ -1034,21 +1049,15 @@ fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>, // this kind of equivalency just fine. // Create mapping from impl to skolemized. - let skol_tps = - impl_m.generics.types.map( - |d| ty::mk_param_from_def(tcx, d)); - let skol_regions = - impl_m.generics.regions.map( - |l| ty::free_region_from_def(impl_m_body_id, l)); - let impl_to_skol_substs = - subst::Substs::new(skol_tps.clone(), skol_regions.clone()); + let impl_param_env = ty::construct_parameter_environment(tcx, &impl_m.generics, impl_m_body_id); + let impl_to_skol_substs = &impl_param_env.free_substs; // Create mapping from trait to skolemized. let trait_to_skol_substs = trait_to_impl_substs - .subst(tcx, &impl_to_skol_substs) - .with_method(skol_tps.get_slice(subst::FnSpace).to_vec(), - skol_regions.get_slice(subst::FnSpace).to_vec()); + .subst(tcx, impl_to_skol_substs) + .with_method(impl_to_skol_substs.types.get_slice(subst::FnSpace).to_vec(), + impl_to_skol_substs.regions().get_slice(subst::FnSpace).to_vec()); // Check region bounds. if !check_region_bounds_on_impl_method(tcx, @@ -1057,7 +1066,7 @@ fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>, &trait_m.generics, &impl_m.generics, &trait_to_skol_substs, - &impl_to_skol_substs) { + impl_to_skol_substs) { return; } @@ -1120,7 +1129,7 @@ fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>, for impl_trait_bound in impl_param_bounds.trait_bounds.iter() { debug!("compare_impl_method(): impl-trait-bound subst"); let impl_trait_bound = - impl_trait_bound.subst(tcx, &impl_to_skol_substs); + impl_trait_bound.subst(tcx, impl_to_skol_substs); // There may be late-bound regions from the impl in the // impl's bound, so "liberate" those. Note that the @@ -1134,7 +1143,6 @@ fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>, debug!("compare_impl_method(): trait-bound subst"); let trait_bound = trait_bound.subst(tcx, &trait_to_skol_substs); - let infcx = infer::new_infer_ctxt(tcx); infer::mk_sub_poly_trait_refs(&infcx, true, infer::Misc(impl_m_span), @@ -1155,9 +1163,15 @@ fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>, // Compute skolemized form of impl and trait method tys. let impl_fty = ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(impl_m.fty.clone())); - let impl_fty = impl_fty.subst(tcx, &impl_to_skol_substs); + let impl_fty = impl_fty.subst(tcx, impl_to_skol_substs); let trait_fty = ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(trait_m.fty.clone())); let trait_fty = trait_fty.subst(tcx, &trait_to_skol_substs); + let trait_fty = + assoc::normalize_associated_types_in(&infcx, + &mut fulfillment_cx, + impl_m_span, + impl_m_body_id, + &trait_fty); // Check the impl method type IM is a subtype of the trait method // type TM. To see why this makes sense, think of a vtable. The @@ -1183,6 +1197,15 @@ fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>, } } + // Run the fulfillment context to completion to accommodate any + // associated type normalizations that may have occurred. + match fulfillment_cx.select_all_or_error(&infcx, &impl_param_env, tcx) { + Ok(()) => { } + Err(errors) => { + traits::report_fulfillment_errors(&infcx, &errors); + } + } + // Finally, resolve all regions. This catches wily misuses of lifetime // parameters. infcx.resolve_regions_and_report_errors(impl_m_body_id); @@ -1526,19 +1549,28 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> { self.infcx().next_ty_var() } - fn associated_types_of_trait_are_valid(&self, _: Ty, _: ast::DefId) - -> bool { - false + fn projected_ty_from_poly_trait_ref(&self, + span: Span, + poly_trait_ref: ty::PolyTraitRef<'tcx>, + item_name: ast::Name) + -> Ty<'tcx> + { + let (trait_ref, _) = + self.infcx().replace_late_bound_regions_with_fresh_var( + span, + infer::LateBoundRegionConversionTime::AssocTypeProjection(item_name), + &poly_trait_ref); + + self.normalize_associated_type(span, trait_ref, item_name) } - fn associated_type_binding(&self, - span: Span, - _: Option>, - _: ast::DefId, - _: ast::DefId) - -> Option> { - self.tcx().sess.span_err(span, "unsupported associated type binding"); - Some(ty::mk_err()) + fn projected_ty(&self, + span: Span, + trait_ref: Rc>, + item_name: ast::Name) + -> Ty<'tcx> + { + self.normalize_associated_type(span, trait_ref, item_name) } } @@ -1560,22 +1592,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn err_count_since_creation(&self) -> uint { self.ccx.tcx.sess.err_count() - self.err_count_on_creation } -} - -impl<'a, 'tcx> RegionScope for infer::InferCtxt<'a, 'tcx> { - fn default_region_bound(&self, span: Span) -> Option { - Some(self.next_region_var(infer::MiscVariable(span))) - } - fn anon_regions(&self, span: Span, count: uint) - -> Result, Option>> { - Ok(Vec::from_fn(count, |_| { - self.next_region_var(infer::MiscVariable(span)) - })) - } -} - -impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn tag(&self) -> String { format!("{}", self as *const FnCtxt) } @@ -1609,7 +1626,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn write_object_cast(&self, key: ast::NodeId, - trait_ref: Rc>) { + trait_ref: ty::PolyTraitRef<'tcx>) { debug!("write_object_cast key={} trait_ref={}", key, trait_ref.repr(self.tcx())); self.inh.object_cast_map.borrow_mut().insert(key, trait_ref); @@ -1660,6 +1677,48 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.inh.adjustments.borrow_mut().insert(node_id, adj); } + /// Basically whenever we are converting from a type scheme into + /// the fn body space, we always want to normalize associated + /// types as well. This function combines the two. + fn instantiate_type_scheme(&self, + span: Span, + substs: &Substs<'tcx>, + value: &T) + -> T + where T : TypeFoldable<'tcx> + Clone + HasProjectionTypes + Repr<'tcx> + { + let value = value.subst(self.tcx(), substs); + let result = self.normalize_associated_types_in(span, &value); + debug!("instantiate_type_scheme(value={}, substs={}) = {}", + value.repr(self.tcx()), + substs.repr(self.tcx()), + result.repr(self.tcx())); + result + } + + fn normalize_associated_types_in(&self, span: Span, value: &T) -> T + where T : TypeFoldable<'tcx> + Clone + HasProjectionTypes + { + self.inh.normalize_associated_types_in(span, self.body_id, value) + } + + fn normalize_associated_type(&self, + span: Span, + trait_ref: Rc>, + item_name: ast::Name) + -> Ty<'tcx> + { + let cause = traits::ObligationCause::new(span, + self.body_id, + traits::ObligationCauseCode::MiscObligation); + self.inh.fulfillment_cx + .borrow_mut() + .normalize_associated_type(self.infcx(), + trait_ref, + item_name, + cause) + } + fn register_adjustment_obligations(&self, span: Span, adj: &ty::AutoAdjustment<'tcx>) { @@ -1754,7 +1813,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { traits::ItemObligation(def_id)), &bounds); let monotype = - type_scheme.ty.subst(self.tcx(), &substs); + self.instantiate_type_scheme(span, &substs, &type_scheme.ty); TypeAndSubsts { ty: monotype, @@ -2017,7 +2076,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } -#[deriving(Copy, Show,PartialEq,Eq)] +//impl<'a, 'tcx> RegionScope for infer::InferCtxt<'a, 'tcx> { +// fn default_region_bound(&self, span: Span) -> Option { +// Some(self.next_region_var(infer::MiscVariable(span))) +// } +// +// fn anon_regions(&self, span: Span, count: uint) +// -> Result, Option>> { +// Ok(Vec::from_fn(count, |_| { +// self.next_region_var(infer::MiscVariable(span)) +// })) +// } +//} + +#[deriving(Copy, Show, PartialEq, Eq)] pub enum LvaluePreference { PreferMutLvalue, NoPreference @@ -2879,7 +2951,7 @@ pub fn impl_self_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, let rps = fcx.inh.infcx.region_vars_for_defs(span, rps); let tps = fcx.inh.infcx.next_ty_vars(n_tps); let substs = subst::Substs::new_type(tps, rps); - let substd_ty = raw_ty.subst(tcx, &substs); + let substd_ty = fcx.instantiate_type_scheme(span, &substs, &raw_ty); TypeAndSubsts { substs: substs, ty: substd_ty } } @@ -5219,9 +5291,7 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, // Substitute the values for the type parameters into the type of // the referenced item. - let ty_substituted = ty_late_bound.subst(fcx.tcx(), &substs); - - debug!("ty_substituted: ty_substituted={}", ty_substituted.repr(fcx.tcx())); + let ty_substituted = fcx.instantiate_type_scheme(span, &substs, &ty_late_bound); fcx.write_ty(node_id, ty_substituted); fcx.write_substs(node_id, ty::ItemSubsts { substs: substs }); diff --git a/src/librustc_typeck/check/regionmanip.rs b/src/librustc_typeck/check/regionmanip.rs index ea70b9d9e2ef1..14405b9a92b59 100644 --- a/src/librustc_typeck/check/regionmanip.rs +++ b/src/librustc_typeck/check/regionmanip.rs @@ -121,6 +121,15 @@ impl<'a, 'tcx> Wf<'a, 'tcx> { self.push_param_constraint_from_top(p); } + ty::ty_projection(ref data) => { + // `>::Name` + + // TODO What region constraints are necessary here, if any?? + + // this seems like a minimal requirement: + self.accumulate_from_ty(data.trait_ref.self_ty()); + } + ty::ty_tup(ref tuptys) => { for &tupty in tuptys.iter() { self.accumulate_from_ty(tupty); diff --git a/src/librustc_typeck/check/vtable.rs b/src/librustc_typeck/check/vtable.rs index 626845613b41a..98badf9c04996 100644 --- a/src/librustc_typeck/check/vtable.rs +++ b/src/librustc_typeck/check/vtable.rs @@ -13,7 +13,7 @@ use middle::subst::{FnSpace}; use middle::traits; use middle::traits::{Obligation, ObligationCause}; use middle::traits::report_fulfillment_errors; -use middle::ty::{mod, Ty}; +use middle::ty::{mod, Ty, AsPredicate, ToPolyTraitRef}; use middle::infer; use std::rc::Rc; use syntax::ast; @@ -136,7 +136,7 @@ pub fn check_object_safety<'tcx>(tcx: &ty::ctxt<'tcx>, let object_trait_ref = object_trait.principal_trait_ref_with_self_ty(tcx, tcx.types.err); for tr in traits::supertraits(tcx, object_trait_ref) { - check_object_safety_inner(tcx, &*tr, span); + check_object_safety_inner(tcx, &tr, span); } } @@ -231,7 +231,7 @@ pub fn register_object_cast_obligations<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, span: Span, object_trait: &ty::TyTrait<'tcx>, referent_ty: Ty<'tcx>) - -> Rc> + -> ty::PolyTraitRef<'tcx> { // We can only make objects from sized types. fcx.register_builtin_bound( @@ -258,7 +258,7 @@ pub fn register_object_cast_obligations<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, ObligationCause::new(span, fcx.body_id, traits::ObjectCastObligation(object_trait_ty)), - ty::Predicate::Trait(object_trait_ref.clone())); + object_trait_ref.as_predicate()); fcx.register_predicate(object_obligation); // Create additional obligations for all the various builtin @@ -314,3 +314,4 @@ pub fn select_new_fcx_obligations(fcx: &FnCtxt) { Err(errors) => { report_fulfillment_errors(fcx.infcx(), &errors); } } } + diff --git a/src/librustc_typeck/check/wf.rs b/src/librustc_typeck/check/wf.rs index 3ddc81d40a5da..21c81c7be9bfa 100644 --- a/src/librustc_typeck/check/wf.rs +++ b/src/librustc_typeck/check/wf.rs @@ -13,7 +13,6 @@ use check::{FnCtxt, Inherited, blank_fn_ctxt, vtable, regionck}; use CrateCtxt; use middle::region; use middle::subst; -use middle::subst::{Subst}; use middle::traits; use middle::ty::{mod, Ty}; use middle::ty::liberate_late_bound_regions; @@ -148,7 +147,9 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { region::CodeExtent::from_node_id(item.id), Some(&mut this.cache)); let type_scheme = ty::lookup_item_type(fcx.tcx(), local_def(item.id)); - let item_ty = type_scheme.ty.subst(fcx.tcx(), &fcx.inh.param_env.free_substs); + let item_ty = fcx.instantiate_type_scheme(item.span, + &fcx.inh.param_env.free_substs, + &type_scheme.ty); bounds_checker.check_traits_in_ty(item_ty); }); } @@ -168,7 +169,9 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { // that is, with all type parameters converted from bound // to free. let self_ty = ty::node_id_to_type(fcx.tcx(), item.id); - let self_ty = self_ty.subst(fcx.tcx(), &fcx.inh.param_env.free_substs); + let self_ty = fcx.instantiate_type_scheme(item.span, + &fcx.inh.param_env.free_substs, + &self_ty); bounds_checker.check_traits_in_ty(self_ty); @@ -178,7 +181,9 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { None => { return; } Some(t) => { t } }; - let trait_ref = (*trait_ref).subst(fcx.tcx(), &fcx.inh.param_env.free_substs); + let trait_ref = fcx.instantiate_type_scheme(item.span, + &fcx.inh.param_env.free_substs, + &trait_ref); // There are special rules that apply to drop. if @@ -209,7 +214,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { // trait reference. Instead, this is done at the impl site. // Arguably this is wrong and we should treat the trait-reference // the same way as we treat the self-type. - bounds_checker.check_trait_ref(&trait_ref); + bounds_checker.check_trait_ref(&*trait_ref); let cause = traits::ObligationCause::new( @@ -344,7 +349,8 @@ impl<'cx,'tcx> TypeFolder<'tcx> for BoundsChecker<'cx,'tcx> { // // (I believe we should do the same for traits, but // that will require an RFC. -nmatsakis) - let bounds = type_scheme.generics.to_bounds(self.tcx(), substs); + let bounds = type_scheme +.generics.to_bounds(self.tcx(), substs); let bounds = filter_to_trait_obligations(bounds); self.fcx.add_obligations_for_parameters( traits::ObligationCause::new(self.span, @@ -397,7 +403,9 @@ fn struct_variant<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, .iter() .map(|field| { let field_ty = ty::node_id_to_type(fcx.tcx(), field.node.id); - let field_ty = field_ty.subst(fcx.tcx(), &fcx.inh.param_env.free_substs); + let field_ty = fcx.instantiate_type_scheme(field.span, + &fcx.inh.param_env.free_substs, + &field_ty); AdtField { ty: field_ty, span: field.span } }) .collect(); @@ -416,7 +424,10 @@ fn enum_variants<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, AdtVariant { fields: args.iter().enumerate().map(|(index, arg)| { let arg_ty = arg_tys[index]; - let arg_ty = arg_ty.subst(fcx.tcx(), &fcx.inh.param_env.free_substs); + let arg_ty = + fcx.instantiate_type_scheme(variant.span, + &fcx.inh.param_env.free_substs, + &arg_ty); AdtField { ty: arg_ty, span: arg.ty.span @@ -443,7 +454,8 @@ fn filter_to_trait_obligations<'tcx>(bounds: ty::GenericBounds<'tcx>) let mut result = ty::GenericBounds::empty(); for (space, _, predicate) in bounds.predicates.iter_enumerated() { match *predicate { - ty::Predicate::Trait(..) => { + ty::Predicate::Trait(..) | + ty::Predicate::Projection(..) => { result.predicates.push(space, predicate.clone()) } ty::Predicate::Equate(..) | diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index 30039f2ecc1cf..79e1efa618f53 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -27,6 +27,7 @@ use middle::ty::{ty_param, TypeScheme, ty_ptr}; use middle::ty::{ty_rptr, ty_struct, ty_trait, ty_tup}; use middle::ty::{ty_str, ty_vec, ty_float, ty_infer, ty_int, ty_open}; use middle::ty::{ty_uint, ty_unboxed_closure, ty_uniq, ty_bare_fn}; +use middle::ty::{ty_projection}; use middle::ty; use CrateCtxt; use middle::infer::combine::Combine; @@ -64,13 +65,13 @@ fn get_base_type_def_id<'a, 'tcx>(inference_context: &InferCtxt<'a, 'tcx>, } ty_trait(ref t) => { - Some(t.principal.def_id()) + Some(t.principal_def_id()) } ty_bool | ty_char | ty_int(..) | ty_uint(..) | ty_float(..) | ty_str(..) | ty_vec(..) | ty_bare_fn(..) | ty_closure(..) | ty_tup(..) | ty_param(..) | ty_err | ty_open(..) | ty_uniq(_) | - ty_ptr(_) | ty_rptr(_, _) => { + ty_ptr(_) | ty_rptr(_, _) | ty_projection(..) => { None } diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs index bb8efd2991070..79443200ddf0e 100644 --- a/src/librustc_typeck/coherence/orphan.rs +++ b/src/librustc_typeck/coherence/orphan.rs @@ -54,8 +54,8 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> { ty::ty_struct(def_id, _) => { self.check_def_id(item.span, def_id); } - ty::ty_trait(box ty::TyTrait{ ref principal, ..}) => { - self.check_def_id(item.span, principal.def_id()); + ty::ty_trait(ref data) => { + self.check_def_id(item.span, data.principal_def_id()); } _ => { span_err!(self.tcx.sess, item.span, E0118, diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 6bbf464441460..35599a989c106 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -29,14 +29,8 @@ bounds for each parameter. Type parameters themselves are represented as `ty_param()` instances. */ -use self::ConvertMethodContext::*; -use self::CreateTypeParametersForAssociatedTypesFlag::*; - -use astconv::{AstConv, ty_of_arg, AllowEqConstraints}; -use astconv::{ast_ty_to_ty, ast_region_to_region}; -use astconv; +use astconv::{mod, AstConv, ty_of_arg, ast_ty_to_ty, ast_region_to_region}; use metadata::csearch; -use middle::def; use middle::lang_items::SizedTraitLangItem; use middle::region; use middle::resolve_lifetime; @@ -47,7 +41,7 @@ use middle::ty::{mod, RegionEscape, Ty, TypeScheme}; use middle::ty_fold::{mod, TypeFolder, TypeFoldable}; use middle::infer; use rscope::*; -use {CrateCtxt, lookup_def_tcx, no_params, write_ty_to_tcx}; +use {CrateCtxt, no_params, write_ty_to_tcx}; use util::nodemap::{FnvHashMap, FnvHashSet}; use util::ppaux; use util::ppaux::{Repr,UserString}; @@ -139,12 +133,6 @@ pub trait ToTy<'tcx> { fn to_ty(&self, rs: &RS, ast_ty: &ast::Ty) -> Ty<'tcx>; } -impl<'a,'tcx> ToTy<'tcx> for ImplCtxt<'a,'tcx> { - fn to_ty(&self, rs: &RS, ast_ty: &ast::Ty) -> Ty<'tcx> { - ast_ty_to_ty(self, rs, ast_ty) - } -} - impl<'a,'tcx> ToTy<'tcx> for CrateCtxt<'a,'tcx> { fn to_ty(&self, rs: &RS, ast_ty: &ast::Ty) -> Ty<'tcx> { ast_ty_to_ty(self, rs, ast_ty) @@ -165,9 +153,6 @@ impl<'a, 'tcx> AstConv<'tcx> for CrateCtxt<'a, 'tcx> { let abi = self.tcx.map.get_foreign_abi(id.node); ty_of_foreign_item(self, &*foreign_item, abi) } - Some(ast_map::NodeTraitItem(trait_item)) => { - ty_of_trait_item(self, &*trait_item) - } x => { self.tcx.sess.bug(format!("unexpected sort of node \ in get_item_type_scheme(): {}", @@ -186,20 +171,13 @@ impl<'a, 'tcx> AstConv<'tcx> for CrateCtxt<'a, 'tcx> { self.tcx().types.err } - fn associated_types_of_trait_are_valid(&self, _: Ty<'tcx>, _: ast::DefId) - -> bool { - false - } - - fn associated_type_binding(&self, - span: Span, - _: Option>, - _: ast::DefId, - _: ast::DefId) - -> Option> { - self.tcx().sess.span_err(span, "associated types may not be \ - referenced here"); - Some(ty::mk_err()) + fn projected_ty(&self, + _span: Span, + trait_ref: Rc>, + item_name: ast::Name) + -> Ty<'tcx> + { + ty::mk_projection(self.tcx, (*trait_ref).clone(), item_name) } } @@ -228,10 +206,7 @@ pub fn get_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, ast::StructVariantKind(ref struct_def) => { let scheme = TypeScheme { - generics: ty_generics_for_type_or_impl( - ccx, - generics, - DontCreateTypeParametersForAssociatedTypes), + generics: ty_generics_for_type_or_impl(ccx, generics), ty: enum_ty }; @@ -241,10 +216,7 @@ pub fn get_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, }; let scheme = TypeScheme { - generics: ty_generics_for_type_or_impl( - ccx, - generics, - DontCreateTypeParametersForAssociatedTypes), + generics: ty_generics_for_type_or_impl(ccx, generics), ty: result_ty }; @@ -361,7 +333,7 @@ fn collect_trait_methods<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, fn ty_method_of_trait_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, trait_id: ast::NodeId, trait_generics: &ty::Generics<'tcx>, - trait_items: &[ast::TraitItem], + _trait_items: &[ast::TraitItem], m_id: &ast::NodeId, m_name: &ast::Name, m_explicit_self: &ast::ExplicitSelf, @@ -374,19 +346,11 @@ fn collect_trait_methods<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, ty_generics_for_fn_or_method( ccx, m_generics, - (*trait_generics).clone(), - DontCreateTypeParametersForAssociatedTypes); + (*trait_generics).clone()); let (fty, explicit_self_category) = { - let tmcx = TraitMethodCtxt { - ccx: ccx, - trait_id: local_def(trait_id), - trait_items: trait_items[], - method_generics: &ty_generics, - }; - let trait_self_ty = ty::mk_self_type(tmcx.tcx(), - local_def(trait_id)); - astconv::ty_of_method(&tmcx, + let trait_self_ty = ty::mk_self_type(ccx.tcx, local_def(trait_id)); + astconv::ty_of_method(ccx, *m_unsafety, trait_self_ty, m_explicit_self, @@ -444,36 +408,7 @@ pub fn convert_field<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, fn convert_associated_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, trait_def: &ty::TraitDef<'tcx>, associated_type: &ast::AssociatedType) - -> ty::Polytype<'tcx> { - // Find the type parameter ID corresponding to this - // associated type. - let type_parameter_def = trait_def.generics - .types - .get_slice(subst::AssocSpace) - .iter() - .find(|def| { - def.def_id == local_def(associated_type.ty_param.id) - }); - let type_parameter_def = match type_parameter_def { - Some(type_parameter_def) => type_parameter_def, - None => { - ccx.tcx().sess.span_bug(associated_type.ty_param.span, - "`convert_associated_type()` didn't find \ - a type parameter ID corresponding to \ - this type") - } - }; - let param_type = ty::mk_param(ccx.tcx, - type_parameter_def.space, - type_parameter_def.index, - local_def(associated_type.ty_param.id)); - ccx.tcx.tcache.borrow_mut().insert(local_def(associated_type.ty_param.id), - Polytype { - generics: ty::Generics::empty(), - ty: param_type, - }); - write_ty_to_tcx(ccx.tcx, associated_type.ty_param.id, param_type); - +{ let associated_type = Rc::new(ty::AssociatedType { name: associated_type.ty_param.ident.name, vis: ast::Public, @@ -485,32 +420,16 @@ fn convert_associated_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, .borrow_mut() .insert(associated_type.def_id, ty::TypeTraitItem(associated_type)); - - Polytype { - generics: ty::Generics::empty(), - ty: param_type, - } -} - -#[deriving(Copy)] -enum ConvertMethodContext<'a> { - /// Used when converting implementation methods. - ImplConvertMethodContext, - /// Used when converting method signatures. The def ID is the def ID of - /// the trait we're translating. - TraitConvertMethodContext(ast::DefId, &'a [ast::TraitItem]), } fn convert_methods<'a,'tcx,'i,I>(ccx: &CrateCtxt<'a, 'tcx>, - convert_method_context: ConvertMethodContext, container: ImplOrTraitItemContainer, mut ms: I, untransformed_rcvr_ty: Ty<'tcx>, rcvr_ty_generics: &ty::Generics<'tcx>, rcvr_visibility: ast::Visibility) where I: Iterator<&'i ast::Method> { - debug!("convert_methods(untransformed_rcvr_ty={}, \ - rcvr_ty_generics={})", + debug!("convert_methods(untransformed_rcvr_ty={}, rcvr_ty_generics={})", untransformed_rcvr_ty.repr(ccx.tcx), rcvr_ty_generics.repr(ccx.tcx)); @@ -523,7 +442,6 @@ fn convert_methods<'a,'tcx,'i,I>(ccx: &CrateCtxt<'a, 'tcx>, let m_def_id = local_def(m.id); let mty = Rc::new(ty_of_method(ccx, - convert_method_context, container, m, untransformed_rcvr_ty, @@ -552,7 +470,6 @@ fn convert_methods<'a,'tcx,'i,I>(ccx: &CrateCtxt<'a, 'tcx>, } fn ty_of_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, - convert_method_context: ConvertMethodContext, container: ImplOrTraitItemContainer, m: &ast::Method, untransformed_rcvr_ty: Ty<'tcx>, @@ -563,37 +480,14 @@ fn convert_methods<'a,'tcx,'i,I>(ccx: &CrateCtxt<'a, 'tcx>, ty_generics_for_fn_or_method( ccx, m.pe_generics(), - (*rcvr_ty_generics).clone(), - CreateTypeParametersForAssociatedTypes); - - let (fty, explicit_self_category) = match convert_method_context { - ImplConvertMethodContext => { - let imcx = ImplMethodCtxt { - ccx: ccx, - method_generics: &m_ty_generics, - }; - astconv::ty_of_method(&imcx, - m.pe_unsafety(), - untransformed_rcvr_ty, - m.pe_explicit_self(), - &*m.pe_fn_decl(), - m.pe_abi()) - } - TraitConvertMethodContext(trait_id, trait_items) => { - let tmcx = TraitMethodCtxt { - ccx: ccx, - trait_id: trait_id, - trait_items: trait_items, - method_generics: &m_ty_generics, - }; - astconv::ty_of_method(&tmcx, - m.pe_unsafety(), - untransformed_rcvr_ty, - m.pe_explicit_self(), - &*m.pe_fn_decl(), - m.pe_abi()) - } - }; + (*rcvr_ty_generics).clone()); + + let (fty, explicit_self_category) = astconv::ty_of_method(ccx, + m.pe_unsafety(), + untransformed_rcvr_ty, + m.pe_explicit_self(), + &*m.pe_fn_decl(), + m.pe_abi()); // if the method specifies a visibility, use that, otherwise // inherit the visibility from the impl (so `foo` in `pub impl @@ -641,392 +535,6 @@ pub fn ensure_no_ty_param_bounds(ccx: &CrateCtxt, } } -fn is_associated_type_valid_for_param(ty: Ty, - trait_id: ast::DefId, - generics: &ty::Generics) - -> bool { - if let ty::ty_param(param_ty) = ty.sty { - let type_parameter = generics.types.get(param_ty.space, param_ty.idx as uint); - for trait_bound in type_parameter.bounds.trait_bounds.iter() { - if trait_bound.def_id() == trait_id { - return true - } - } - } - - false -} - -fn find_associated_type_in_generics<'tcx>(tcx: &ty::ctxt<'tcx>, - span: Span, - self_ty: Option>, - associated_type_id: ast::DefId, - generics: &ty::Generics<'tcx>) - -> Option> -{ - debug!("find_associated_type_in_generics(ty={}, associated_type_id={}, generics={}", - self_ty.repr(tcx), associated_type_id.repr(tcx), generics.repr(tcx)); - - let self_ty = match self_ty { - None => { - return None; - } - Some(ty) => ty, - }; - - match self_ty.sty { - ty::ty_param(ref param_ty) => { - let param_id = param_ty.def_id; - for type_parameter in generics.types.iter() { - if type_parameter.def_id == associated_type_id - && type_parameter.associated_with == Some(param_id) { - return Some(ty::mk_param_from_def(tcx, type_parameter)); - } - } - - tcx.sess.span_err( - span, - format!("no suitable bound on `{}`", - self_ty.user_string(tcx))[]); - Some(ty::mk_err()) - } - _ => { - tcx.sess.span_err( - span, - "it is currently unsupported to access associated types except \ - through a type parameter; this restriction will be lifted in time"); - Some(ty::mk_err()) - } - } -} - -fn type_is_self(ty: Ty) -> bool { - match ty.sty { - ty::ty_param(ref param_ty) if param_ty.is_self() => true, - _ => false, - } -} - -struct ImplCtxt<'a,'tcx:'a> { - ccx: &'a CrateCtxt<'a,'tcx>, - opt_trait_ref_id: Option, - impl_items: &'a [ast::ImplItem], - impl_generics: &'a ty::Generics<'tcx>, -} - -impl<'a,'tcx> AstConv<'tcx> for ImplCtxt<'a,'tcx> { - fn tcx(&self) -> &ty::ctxt<'tcx> { - self.ccx.tcx - } - - fn get_item_ty(&self, id: ast::DefId) -> ty::Polytype<'tcx> { - self.ccx.get_item_ty(id) - } - - fn get_trait_def(&self, id: ast::DefId) -> Rc> { - self.ccx.get_trait_def(id) - } - - fn ty_infer(&self, span: Span) -> Ty<'tcx> { - self.ccx.ty_infer(span) - } - - fn associated_types_of_trait_are_valid(&self, - ty: Ty<'tcx>, - trait_id: ast::DefId) - -> bool { - // OK if the trait with the associated type is the trait we're - // implementing. - match self.opt_trait_ref_id { - Some(trait_ref_id) if trait_ref_id == trait_id => { - if type_is_self(ty) { - return true - } - } - Some(_) | None => {} - } - - // OK if the trait with the associated type is one of the traits in - // our bounds. - is_associated_type_valid_for_param(ty, trait_id, self.impl_generics) - } - - fn associated_type_binding(&self, - span: Span, - self_ty: Option>, - trait_id: ast::DefId, - associated_type_id: ast::DefId) - -> Option> - { - match self.opt_trait_ref_id { - // It's an associated type on the trait that we're - // implementing. - Some(trait_ref_id) if trait_ref_id == trait_id => { - let trait_def = ty::lookup_trait_def(self.tcx(), trait_id); - assert!(trait_def.generics.types - .get_slice(subst::AssocSpace) - .iter() - .any(|type_param_def| type_param_def.def_id == associated_type_id)); - let associated_type = ty::impl_or_trait_item(self.ccx.tcx, associated_type_id); - for impl_item in self.impl_items.iter() { - match *impl_item { - ast::MethodImplItem(_) => {} - ast::TypeImplItem(ref typedef) => { - if associated_type.name() == typedef.ident.name { - return Some(self.ccx.to_ty(&ExplicitRscope, &*typedef.typ)) - } - } - } - } - self.ccx - .tcx - .sess - .span_bug(span, - "ImplCtxt::associated_type_binding(): didn't \ - find associated type") - } - Some(_) | None => {} - } - - // OK then, it should be an associated type on one of the traits in - // our bounds. - find_associated_type_in_generics(self.ccx.tcx, - span, - self_ty, - associated_type_id, - self.impl_generics) - } -} - -struct FnCtxt<'a,'tcx:'a> { - ccx: &'a CrateCtxt<'a,'tcx>, - generics: &'a ty::Generics<'tcx>, -} - -impl<'a,'tcx> AstConv<'tcx> for FnCtxt<'a,'tcx> { - fn tcx(&self) -> &ty::ctxt<'tcx> { - self.ccx.tcx - } - - fn get_item_ty(&self, id: ast::DefId) -> ty::Polytype<'tcx> { - self.ccx.get_item_ty(id) - } - - fn get_trait_def(&self, id: ast::DefId) -> Rc> { - self.ccx.get_trait_def(id) - } - - fn ty_infer(&self, span: Span) -> Ty<'tcx> { - self.ccx.ty_infer(span) - } - - fn associated_types_of_trait_are_valid(&self, - ty: Ty<'tcx>, - trait_id: ast::DefId) - -> bool { - // OK if the trait with the associated type is one of the traits in - // our bounds. - is_associated_type_valid_for_param(ty, trait_id, self.generics) - } - - fn associated_type_binding(&self, - span: Span, - self_ty: Option>, - _: ast::DefId, - associated_type_id: ast::DefId) - -> Option> { - debug!("collect::FnCtxt::associated_type_binding()"); - - // The ID should map to an associated type on one of the traits in - // our bounds. - find_associated_type_in_generics(self.ccx.tcx, - span, - self_ty, - associated_type_id, - self.generics) - } -} - -struct ImplMethodCtxt<'a,'tcx:'a> { - ccx: &'a CrateCtxt<'a,'tcx>, - method_generics: &'a ty::Generics<'tcx>, -} - -impl<'a,'tcx> AstConv<'tcx> for ImplMethodCtxt<'a,'tcx> { - fn tcx(&self) -> &ty::ctxt<'tcx> { - self.ccx.tcx - } - - fn get_item_ty(&self, id: ast::DefId) -> ty::Polytype<'tcx> { - self.ccx.get_item_ty(id) - } - - fn get_trait_def(&self, id: ast::DefId) -> Rc> { - self.ccx.get_trait_def(id) - } - - fn ty_infer(&self, span: Span) -> Ty<'tcx> { - self.ccx.ty_infer(span) - } - - fn associated_types_of_trait_are_valid(&self, - ty: Ty<'tcx>, - trait_id: ast::DefId) - -> bool { - is_associated_type_valid_for_param(ty, trait_id, self.method_generics) - } - - fn associated_type_binding(&self, - span: Span, - self_ty: Option>, - _: ast::DefId, - associated_type_id: ast::DefId) - -> Option> { - debug!("collect::ImplMethodCtxt::associated_type_binding()"); - - // The ID should map to an associated type on one of the traits in - // our bounds. - find_associated_type_in_generics(self.ccx.tcx, - span, - self_ty, - associated_type_id, - self.method_generics) - } -} - -struct TraitMethodCtxt<'a,'tcx:'a> { - ccx: &'a CrateCtxt<'a,'tcx>, - trait_id: ast::DefId, - trait_items: &'a [ast::TraitItem], - method_generics: &'a ty::Generics<'tcx>, -} - -impl<'a,'tcx> AstConv<'tcx> for TraitMethodCtxt<'a,'tcx> { - fn tcx(&self) -> &ty::ctxt<'tcx> { - self.ccx.tcx - } - - fn get_item_ty(&self, id: ast::DefId) -> ty::Polytype<'tcx> { - self.ccx.get_item_ty(id) - } - - fn get_trait_def(&self, id: ast::DefId) -> Rc> { - self.ccx.get_trait_def(id) - } - - fn ty_infer(&self, span: Span) -> Ty<'tcx> { - self.ccx.ty_infer(span) - } - - fn associated_types_of_trait_are_valid(&self, - ty: Ty<'tcx>, - trait_id: ast::DefId) - -> bool { - // OK if the trait with the associated type is this trait. - if self.trait_id == trait_id && type_is_self(ty) { - return true - } - - // OK if the trait with the associated type is one of the traits in - // our bounds. - is_associated_type_valid_for_param(ty, trait_id, self.method_generics) - } - - fn associated_type_binding(&self, - span: Span, - self_ty: Option>, - trait_id: ast::DefId, - associated_type_id: ast::DefId) - -> Option> { - debug!("collect::TraitMethodCtxt::associated_type_binding()"); - - // If this is one of our own associated types, return it. - if trait_id == self.trait_id { - let mut index = 0; - for item in self.trait_items.iter() { - match *item { - ast::RequiredMethod(_) | ast::ProvidedMethod(_) => {} - ast::TypeTraitItem(ref item) => { - if local_def(item.ty_param.id) == associated_type_id { - return Some(ty::mk_param(self.tcx(), - subst::AssocSpace, - index, - associated_type_id)) - } - index += 1; - } - } - } - self.ccx - .tcx - .sess - .span_bug(span, - "TraitMethodCtxt::associated_type_binding(): \ - didn't find associated type anywhere in the item \ - list") - } - - // The ID should map to an associated type on one of the traits in - // our bounds. - find_associated_type_in_generics(self.ccx.tcx, - span, - self_ty, - associated_type_id, - self.method_generics) - } -} - -struct GenericsCtxt<'a,'tcx:'a,AC:'a> { - chain: &'a AC, - associated_types_generics: &'a ty::Generics<'tcx>, -} - -impl<'a,'tcx,AC:AstConv<'tcx>> AstConv<'tcx> for GenericsCtxt<'a,'tcx,AC> { - fn tcx(&self) -> &ty::ctxt<'tcx> { - self.chain.tcx() - } - - fn get_item_ty(&self, id: ast::DefId) -> ty::Polytype<'tcx> { - self.chain.get_item_ty(id) - } - - fn get_trait_def(&self, id: ast::DefId) -> Rc> { - self.chain.get_trait_def(id) - } - - fn ty_infer(&self, span: Span) -> Ty<'tcx> { - self.chain.ty_infer(span) - } - - fn associated_types_of_trait_are_valid(&self, - ty: Ty<'tcx>, - trait_id: ast::DefId) - -> bool { - // OK if the trait with the associated type is one of the traits in - // our bounds. - is_associated_type_valid_for_param(ty, - trait_id, - self.associated_types_generics) - } - - fn associated_type_binding(&self, - span: Span, - self_ty: Option>, - _: ast::DefId, - associated_type_id: ast::DefId) - -> Option> { - debug!("collect::GenericsCtxt::associated_type_binding()"); - - // The ID should map to an associated type on one of the traits in - // our bounds. - find_associated_type_in_generics(self.chain.tcx(), - span, - self_ty, - associated_type_id, - self.associated_types_generics) - } -} - pub fn convert(ccx: &CrateCtxt, it: &ast::Item) { let tcx = ccx.tcx; debug!("convert: item {} with id {}", token::get_ident(it.ident), it.id); @@ -1047,10 +555,7 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) { ref selfty, ref impl_items) => { // Create generics from the generics specified in the impl head. - let ty_generics = ty_generics_for_type_or_impl( - ccx, - generics, - CreateTypeParametersForAssociatedTypes); + let ty_generics = ty_generics_for_type_or_impl(ccx, generics); let selfty = ccx.to_ty(&ExplicitRscope, &**selfty); write_ty_to_tcx(tcx, it.id, selfty); @@ -1074,20 +579,6 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) { it.vis }; - let icx = ImplCtxt { - ccx: ccx, - opt_trait_ref_id: match *opt_trait_ref { - None => None, - Some(ref ast_trait_ref) => { - Some(lookup_def_tcx(tcx, - ast_trait_ref.path.span, - ast_trait_ref.ref_id).def_id()) - } - }, - impl_items: impl_items[], - impl_generics: &ty_generics, - }; - let mut methods = Vec::new(); for impl_item in impl_items.iter() { match *impl_item { @@ -1101,7 +592,7 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) { methods.push(&**method); } ast::TypeImplItem(ref typedef) => { - let typ = icx.to_ty(&ExplicitRscope, &*typedef.typ); + let typ = ccx.to_ty(&ExplicitRscope, &*typedef.typ); tcx.tcache .borrow_mut() .insert(local_def(typedef.id), @@ -1126,7 +617,6 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) { } convert_methods(ccx, - ImplConvertMethodContext, ImplContainer(local_def(it.id)), methods.into_iter(), selfty, @@ -1134,11 +624,11 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) { parent_visibility); for trait_ref in opt_trait_ref.iter() { - astconv::instantiate_trait_ref(&icx, + astconv::instantiate_trait_ref(ccx, &ExplicitRscope, trait_ref, Some(selfty), - AllowEqConstraints::DontAllow); + None); } }, ast::ItemTrait(_, _, _, ref trait_methods) => { @@ -1180,11 +670,7 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) { // Run convert_methods on the provided methods. let untransformed_rcvr_ty = ty::mk_self_type(tcx, local_def(it.id)); - let convert_method_context = - TraitConvertMethodContext(local_def(it.id), - trait_methods[]); convert_methods(ccx, - convert_method_context, TraitContainer(local_def(it.id)), trait_methods.iter().filter_map(|m| match *m { ast::RequiredMethod(_) => None, @@ -1326,7 +812,8 @@ fn get_trait_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, pub fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &ast::Item) - -> Rc> { + -> Rc> +{ let def_id = local_def(it.id); let tcx = ccx.tcx; if let Some(def) = tcx.trait_defs.borrow().get(&def_id) { @@ -1347,7 +834,7 @@ pub fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, } }; - let substs = ccx.tcx.mk_substs(mk_trait_substs(ccx, it.id, generics, items)); + let substs = ccx.tcx.mk_substs(mk_trait_substs(ccx, it.id, generics)); let ty_generics = ty_generics_for_trait(ccx, it.id, @@ -1363,15 +850,27 @@ pub fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, bounds.as_slice(), it.span); - let substs = mk_item_substs(ccx, &ty_generics); + let substs = ccx.tcx.mk_substs(mk_item_substs(ccx, &ty_generics)); + + let associated_type_names: Vec<_> = + items.iter() + .filter_map(|item| { + match *item { + ast::RequiredMethod(_) | ast::ProvidedMethod(_) => None, + ast::TypeTraitItem(ref data) => Some(data.ty_param.ident.name), + } + }) + .collect(); + let trait_def = Rc::new(ty::TraitDef { unsafety: unsafety, generics: ty_generics, bounds: bounds, trait_ref: Rc::new(ty::TraitRef { def_id: def_id, - substs: ccx.tcx.mk_substs(substs) - }) + substs: substs + }), + associated_type_names: associated_type_names, }); tcx.trait_defs.borrow_mut().insert(def_id, trait_def.clone()); @@ -1379,8 +878,7 @@ pub fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, fn mk_trait_substs<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, trait_id: ast::NodeId, - generics: &ast::Generics, - items: &[ast::TraitItem]) + generics: &ast::Generics) -> subst::Substs<'tcx> { // Creates a no-op substitution for the trait's type parameters. @@ -1403,28 +901,11 @@ pub fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, i as u32, local_def(def.id))) .collect(); - // ...and also create generics synthesized from the associated types. - let mut index = 0; - let assoc_types: Vec<_> = - items.iter() - .flat_map(|item| match *item { - ast::TypeTraitItem(ref trait_item) => { - index += 1; - Some(ty::mk_param(ccx.tcx, - subst::AssocSpace, - index - 1, - local_def(trait_item.ty_param.id))).into_iter() - } - ast::RequiredMethod(_) | ast::ProvidedMethod(_) => { - None.into_iter() - } - }) - .collect(); - + // ...and also create the `Self` parameter. let self_ty = ty::mk_param(ccx.tcx, subst::SelfSpace, 0, local_def(trait_id)); - subst::Substs::new_trait(types, regions, assoc_types, self_ty) + subst::Substs::new_trait(types, regions, Vec::new(), self_ty) } } @@ -1444,18 +925,10 @@ pub fn ty_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &ast::Item) return scheme; } ast::ItemFn(ref decl, unsafety, abi, ref generics, _) => { - let ty_generics = ty_generics_for_fn_or_method( - ccx, - generics, - ty::Generics::empty(), - CreateTypeParametersForAssociatedTypes); - let tofd = { - let fcx = FnCtxt { - ccx: ccx, - generics: &ty_generics, - }; - astconv::ty_of_bare_fn(&fcx, unsafety, abi, &**decl) - }; + let ty_generics = ty_generics_for_fn_or_method(ccx, + generics, + ty::Generics::empty()); + let tofd = astconv::ty_of_bare_fn(ccx, unsafety, abi, &**decl); let scheme = TypeScheme { generics: ty_generics, ty: ty::mk_bare_fn(ccx.tcx, Some(local_def(it.id)), ccx.tcx.mk_bare_fn(tofd)) @@ -1477,10 +950,7 @@ pub fn ty_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &ast::Item) let scheme = { let ty = ccx.to_ty(&ExplicitRscope, &**t); TypeScheme { - generics: ty_generics_for_type_or_impl( - ccx, - generics, - DontCreateTypeParametersForAssociatedTypes), + generics: ty_generics_for_type_or_impl(ccx, generics), ty: ty } }; @@ -1490,10 +960,7 @@ pub fn ty_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &ast::Item) } ast::ItemEnum(_, ref generics) => { // Create a new generic polytype. - let ty_generics = ty_generics_for_type_or_impl( - ccx, - generics, - DontCreateTypeParametersForAssociatedTypes); + let ty_generics = ty_generics_for_type_or_impl(ccx, generics); let substs = mk_item_substs(ccx, &ty_generics); let t = ty::mk_enum(tcx, local_def(it.id), tcx.mk_substs(substs)); let scheme = TypeScheme { @@ -1508,10 +975,7 @@ pub fn ty_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &ast::Item) tcx.sess.span_bug(it.span, "invoked ty_of_item on trait"); } ast::ItemStruct(_, ref generics) => { - let ty_generics = ty_generics_for_type_or_impl( - ccx, - generics, - DontCreateTypeParametersForAssociatedTypes); + let ty_generics = ty_generics_for_type_or_impl(ccx, generics); let substs = mk_item_substs(ccx, &ty_generics); let t = ty::mk_struct(tcx, local_def(it.id), tcx.mk_substs(substs)); let scheme = TypeScheme { @@ -1548,52 +1012,22 @@ pub fn ty_of_foreign_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, } } -fn ty_of_trait_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, - trait_item: &ast::TraitItem) - -> ty::Polytype<'tcx> { - match *trait_item { - ast::RequiredMethod(ref m) => { - ccx.tcx.sess.span_bug(m.span, - "ty_of_trait_item() on required method") - } - ast::ProvidedMethod(ref m) => { - ccx.tcx.sess.span_bug(m.span, - "ty_of_trait_item() on provided method") - } - ast::TypeTraitItem(ref associated_type) => { - let parent = ccx.tcx.map.get_parent(associated_type.ty_param.id); - let trait_def = match ccx.tcx.map.get(parent) { - ast_map::NodeItem(item) => trait_def_of_item(ccx, &*item), - _ => { - ccx.tcx.sess.span_bug(associated_type.ty_param.span, - "associated type's parent wasn't \ - an item?!") - } - }; - convert_associated_type(ccx, &*trait_def, &**associated_type) - } - } -} - fn ty_generics_for_type_or_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, - generics: &ast::Generics, - create_type_parameters_for_associated_types: - CreateTypeParametersForAssociatedTypesFlag) + generics: &ast::Generics) -> ty::Generics<'tcx> { ty_generics(ccx, subst::TypeSpace, generics.lifetimes[], generics.ty_params[], ty::Generics::empty(), - &generics.where_clause, - create_type_parameters_for_associated_types) + &generics.where_clause) } fn ty_generics_for_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, trait_id: ast::NodeId, substs: &'tcx subst::Substs<'tcx>, ast_generics: &ast::Generics, - items: &[ast::TraitItem]) + _items: &[ast::TraitItem]) -> ty::Generics<'tcx> { let mut generics = @@ -1602,27 +1036,7 @@ fn ty_generics_for_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, ast_generics.lifetimes[], ast_generics.ty_params[], ty::Generics::empty(), - &ast_generics.where_clause, - DontCreateTypeParametersForAssociatedTypes); - - // Add in type parameters for any associated types. - for item in items.iter() { - match *item { - ast::TypeTraitItem(ref associated_type) => { - let def = - get_or_create_type_parameter_def( - ccx, - subst::AssocSpace, - &associated_type.ty_param, - generics.types.len(subst::AssocSpace) as u32, - Some(local_def(trait_id))); - ccx.tcx.ty_param_defs.borrow_mut().insert(associated_type.ty_param.id, - def.clone()); - generics.types.push(subst::AssocSpace, def); - } - ast::ProvidedMethod(_) | ast::RequiredMethod(_) => {} - } - } + &ast_generics.where_clause); // Add in the self type parameter. // @@ -1631,7 +1045,7 @@ fn ty_generics_for_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let param_id = trait_id; let self_trait_ref = - Rc::new(ty::Binder(ty::TraitRef { def_id: local_def(trait_id), + ty::Binder(Rc::new(ty::TraitRef { def_id: local_def(trait_id), substs: substs })); let def = ty::TypeParameterDef { @@ -1643,8 +1057,8 @@ fn ty_generics_for_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, region_bounds: vec!(), builtin_bounds: ty::empty_builtin_bounds(), trait_bounds: vec!(self_trait_ref.clone()), + projection_bounds: vec!(), }, - associated_with: None, default: None }; @@ -1652,8 +1066,7 @@ fn ty_generics_for_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, generics.types.push(subst::SelfSpace, def); - generics.predicates.push(subst::SelfSpace, - ty::Predicate::Trait(self_trait_ref)); + generics.predicates.push(subst::SelfSpace, self_trait_ref.as_predicate()); generics } @@ -1661,9 +1074,7 @@ fn ty_generics_for_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, fn ty_generics_for_fn_or_method<'tcx,AC>( this: &AC, generics: &ast::Generics, - base_generics: ty::Generics<'tcx>, - create_type_parameters_for_associated_types: - CreateTypeParametersForAssociatedTypesFlag) + base_generics: ty::Generics<'tcx>) -> ty::Generics<'tcx> where AC: AstConv<'tcx> { let early_lifetimes = resolve_lifetime::early_bound_lifetimes(generics); @@ -1672,8 +1083,7 @@ fn ty_generics_for_fn_or_method<'tcx,AC>( early_lifetimes[], generics.ty_params[], base_generics, - &generics.where_clause, - create_type_parameters_for_associated_types) + &generics.where_clause) } // Add the Sized bound, unless the type parameter is marked as `?Sized`. @@ -1722,20 +1132,12 @@ fn add_unsized_bound<'tcx,AC>(this: &AC, } } -#[deriving(Clone, PartialEq, Eq)] -enum CreateTypeParametersForAssociatedTypesFlag { - DontCreateTypeParametersForAssociatedTypes, - CreateTypeParametersForAssociatedTypes, -} - fn ty_generics<'tcx,AC>(this: &AC, space: subst::ParamSpace, lifetime_defs: &[ast::LifetimeDef], types: &[ast::TyParam], base_generics: ty::Generics<'tcx>, - where_clause: &ast::WhereClause, - create_type_parameters_for_associated_types_flag: - CreateTypeParametersForAssociatedTypesFlag) + where_clause: &ast::WhereClause) -> ty::Generics<'tcx> where AC: AstConv<'tcx> { @@ -1756,46 +1158,18 @@ fn ty_generics<'tcx,AC>(this: &AC, assert!(result.types.is_empty_in(space)); - // First, create the virtual type parameters for associated types if - // necessary. - let mut associated_types_generics = ty::Generics::empty(); - match create_type_parameters_for_associated_types_flag { - DontCreateTypeParametersForAssociatedTypes => {} - CreateTypeParametersForAssociatedTypes => { - create_type_parameters_for_associated_types(this, space, types, - &mut associated_types_generics); - } - } - // Now create the real type parameters. - let gcx = GenericsCtxt { - chain: this, - associated_types_generics: &associated_types_generics, - }; for (i, param) in types.iter().enumerate() { - let def = get_or_create_type_parameter_def(&gcx, + let def = get_or_create_type_parameter_def(this, space, param, - i as u32, - None); + i as u32); debug!("ty_generics: def for type param: {}, {}", def.repr(this.tcx()), space); result.types.push(space, def); } - // Append the associated types to the result. - for associated_type_param in associated_types_generics.types - .get_slice(space) - .iter() { - assert!(result.types.get_slice(space).len() == - associated_type_param.index as uint); - debug!("ty_generics: def for associated type: {}, {}", - associated_type_param.repr(this.tcx()), - space); - result.types.push(space, (*associated_type_param).clone()); - } - // Just for fun, also push the bounds from the type parameters // into the predicates list. This is currently kind of non-DRY. create_predicates(this.tcx(), &mut result, space); @@ -1809,16 +1183,21 @@ fn ty_generics<'tcx,AC>(this: &AC, for bound in bound_pred.bounds.iter() { match bound { &ast::TyParamBound::TraitTyParamBound(ref poly_trait_ref, _) => { + let mut projections = Vec::new(); + let trait_ref = astconv::instantiate_poly_trait_ref( this, &ExplicitRscope, - //@jroesch: for now trait_ref, poly_trait_ref? poly_trait_ref, Some(ty), - AllowEqConstraints::Allow + &mut projections, ); - result.predicates.push(space, ty::Predicate::Trait(trait_ref)); + result.predicates.push(space, trait_ref.as_predicate()); + + for projection in projections.iter() { + result.predicates.push(space, projection.as_predicate()); + } } &ast::TyParamBound::RegionTyParamBound(ref lifetime) => { @@ -1850,91 +1229,6 @@ fn ty_generics<'tcx,AC>(this: &AC, return result; - fn create_type_parameters_for_associated_types<'tcx, AC>( - this: &AC, - space: subst::ParamSpace, - types: &[ast::TyParam], - associated_types_generics: &mut ty::Generics<'tcx>) - where AC: AstConv<'tcx> - { - // The idea here is roughly as follows. We start with - // an item that is paramerized by various type parameters - // with bounds: - // - // fn foo(t: T) { ... } - // - // The traits in those bounds declare associated types: - // - // trait Iterator { type Elem; ... } - // - // And we rewrite the original function so that every associated - // type is bound to some fresh type parameter: - // - // fn foo>(t: T) { ... } - - // Number of synthetic type parameters created thus far - let mut index = 0; - - // Iterate over the each type parameter `T` (from the example) - for param in types.iter() { - // Iterate over the bound `Iterator` - for bound in param.bounds.iter() { - // In the above example, `ast_trait_ref` is `Iterator`. - let ast_trait_ref = match *bound { - ast::TraitTyParamBound(ref r, _) => r, - ast::RegionTyParamBound(..) => { continue; } - }; - - let trait_def_id = - match lookup_def_tcx(this.tcx(), - ast_trait_ref.trait_ref.path.span, - ast_trait_ref.trait_ref.ref_id) { - def::DefTrait(trait_def_id) => trait_def_id, - _ => { - this.tcx().sess.span_bug(ast_trait_ref.trait_ref.path.span, - "not a trait?!") - } - }; - - // trait_def_id is def-id of `Iterator` - let trait_def = ty::lookup_trait_def(this.tcx(), trait_def_id); - let associated_type_defs = trait_def.generics.types.get_slice(subst::AssocSpace); - - // Find any associated type bindings in the bound. - let ref segments = ast_trait_ref.trait_ref.path.segments; - let bindings = segments[segments.len() -1].parameters.bindings(); - - // Iterate over each associated type `Elem` - for associated_type_def in associated_type_defs.iter() { - if bindings.iter().any(|b| associated_type_def.name.ident() == b.ident) { - // Don't add a variable for a bound associated type. - continue; - } - - // Create the fresh type parameter `A` - let def = ty::TypeParameterDef { - name: associated_type_def.name, - def_id: associated_type_def.def_id, - space: space, - index: types.len() as u32 + index, - bounds: ty::ParamBounds { - builtin_bounds: associated_type_def.bounds.builtin_bounds, - - // FIXME(#18178) -- we should add the other bounds, but - // that requires subst and more logic - trait_bounds: Vec::new(), - region_bounds: Vec::new(), - }, - associated_with: Some(local_def(param.id)), - default: None, - }; - associated_types_generics.types.push(space, def); - index += 1; - } - } - } - } - fn create_predicates<'tcx>( tcx: &ty::ctxt<'tcx>, result: &mut ty::Generics<'tcx>, @@ -1964,8 +1258,7 @@ fn ty_generics<'tcx,AC>(this: &AC, fn get_or_create_type_parameter_def<'tcx,AC>(this: &AC, space: subst::ParamSpace, param: &ast::TyParam, - index: u32, - associated_with: Option) + index: u32) -> ty::TypeParameterDef<'tcx> where AC: AstConv<'tcx> { @@ -2006,7 +1299,6 @@ fn get_or_create_type_parameter_def<'tcx,AC>(this: &AC, index: index, name: param.ident.name, def_id: local_def(param.id), - associated_with: associated_with, bounds: bounds, default: default }; @@ -2081,14 +1373,17 @@ fn conv_param_bounds<'tcx,AC>(this: &AC, trait_bounds, region_bounds } = astconv::partition_bounds(this.tcx(), span, ast_bounds.as_slice()); - let trait_bounds: Vec> = + + let mut projection_bounds = Vec::new(); + + let trait_bounds: Vec = trait_bounds.into_iter() .map(|bound| { astconv::instantiate_poly_trait_ref(this, &ExplicitRscope, bound, Some(param_ty.to_ty(this.tcx())), - AllowEqConstraints::Allow) + &mut projection_bounds) }) .collect(); let region_bounds: Vec = @@ -2099,6 +1394,7 @@ fn conv_param_bounds<'tcx,AC>(this: &AC, region_bounds: region_bounds, builtin_bounds: builtin_bounds, trait_bounds: trait_bounds, + projection_bounds: projection_bounds, } } @@ -2119,11 +1415,9 @@ pub fn ty_of_foreign_fn_decl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, } } - let ty_generics_for_fn_or_method = ty_generics_for_fn_or_method( - ccx, - ast_generics, - ty::Generics::empty(), - DontCreateTypeParametersForAssociatedTypes); + let ty_generics_for_fn_or_method = ty_generics_for_fn_or_method(ccx, + ast_generics, + ty::Generics::empty()); let rb = BindingRscope::new(); let input_tys = decl.inputs .iter() diff --git a/src/librustc_typeck/variance.rs b/src/librustc_typeck/variance.rs index 30869186ba5e9..c3a3993b66b76 100644 --- a/src/librustc_typeck/variance.rs +++ b/src/librustc_typeck/variance.rs @@ -770,33 +770,38 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { variance); } - ty::ty_trait(box ty::TyTrait { ref principal, bounds }) => { - let trait_def = ty::lookup_trait_def(self.tcx(), principal.def_id()); + ty::ty_projection(ref data) => { + let trait_ref = &data.trait_ref; + let trait_def = ty::lookup_trait_def(self.tcx(), trait_ref.def_id); let generics = &trait_def.generics; + self.add_constraints_from_substs( + trait_ref.def_id, + generics.types.as_slice(), + generics.regions.as_slice(), + &trait_ref.substs, + variance); + } - // Traits DO have a Self type parameter, but it is - // erased from object types. - assert!(!generics.types.is_empty_in(subst::SelfSpace) && - principal.substs().types.is_empty_in(subst::SelfSpace)); + ty::ty_trait(ref data) => { + let trait_ref = data.principal_trait_ref_with_self_ty(self.tcx().types.err); + let trait_def = ty::lookup_trait_def(self.tcx(), trait_ref.def_id()); + let generics = &trait_def.generics; // Traits never declare region parameters in the self - // space. + // space nor anything in the fn space. assert!(generics.regions.is_empty_in(subst::SelfSpace)); - - // Traits never declare type/region parameters in the - // fn space. assert!(generics.types.is_empty_in(subst::FnSpace)); assert!(generics.regions.is_empty_in(subst::FnSpace)); // The type `Foo` is contravariant w/r/t `'a`: let contra = self.contravariant(variance); - self.add_constraints_from_region(bounds.region_bound, contra); + self.add_constraints_from_region(data.bounds.region_bound, contra); self.add_constraints_from_substs( - principal.def_id(), + trait_ref.def_id(), generics.types.get_slice(subst::TypeSpace), generics.regions.get_slice(subst::TypeSpace), - principal.substs(), + trait_ref.substs(), variance); } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index b7845f23be298..d5ffce8db78f8 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1466,6 +1466,18 @@ impl<'tcx> Clean for ty::Ty<'tcx> { } ty::ty_tup(ref t) => Tuple(t.clean(cx)), + ty::ty_projection(ref data) => { + let trait_ref = match data.trait_ref.clean(cx) { + TyParamBound::TraitBound(t) => t, + TyParamBound::RegionBound(_) => panic!("cleaning a trait got a region??"), + }; + Type::QPath { + name: data.item_name.clean(cx), + self_type: box data.trait_ref.self_ty().clean(cx), + trait_: box trait_ref, + } + } + ty::ty_param(ref p) => { if p.space == subst::SelfSpace { Self(p.def_id) diff --git a/src/test/compile-fail/assoc-eq-1.rs b/src/test/compile-fail/associated-types-eq-1.rs similarity index 100% rename from src/test/compile-fail/assoc-eq-1.rs rename to src/test/compile-fail/associated-types-eq-1.rs diff --git a/src/test/compile-fail/assoc-eq-2.rs b/src/test/compile-fail/associated-types-eq-2.rs similarity index 100% rename from src/test/compile-fail/assoc-eq-2.rs rename to src/test/compile-fail/associated-types-eq-2.rs diff --git a/src/test/compile-fail/assoc-eq-3.rs b/src/test/compile-fail/associated-types-eq-3.rs similarity index 100% rename from src/test/compile-fail/assoc-eq-3.rs rename to src/test/compile-fail/associated-types-eq-3.rs diff --git a/src/test/compile-fail/assoc-eq-expr-path.rs b/src/test/compile-fail/associated-types-eq-expr-path.rs similarity index 100% rename from src/test/compile-fail/assoc-eq-expr-path.rs rename to src/test/compile-fail/associated-types-eq-expr-path.rs diff --git a/src/test/compile-fail/associated-types-for-unimpl-trait.rs b/src/test/compile-fail/associated-types-for-unimpl-trait.rs new file mode 100644 index 0000000000000..2c6ee502fca3e --- /dev/null +++ b/src/test/compile-fail/associated-types-for-unimpl-trait.rs @@ -0,0 +1,25 @@ +// Copyright 2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(associated_types)] + +trait Get { + type Value; + fn get(&self) -> ::Value; +} + +trait Other { + fn uhoh(&self, foo: U, bar: ::Value) {} + //~^ ERROR the trait `Get` is not implemented for the type `Self` +} + +fn main() { +} + diff --git a/src/test/compile-fail/associated-types-in-wrong-context.rs b/src/test/compile-fail/associated-types-in-wrong-context.rs index 8cab2759ad55a..28a4ad01e23a9 100644 --- a/src/test/compile-fail/associated-types-in-wrong-context.rs +++ b/src/test/compile-fail/associated-types-in-wrong-context.rs @@ -15,9 +15,6 @@ trait Get { fn get(&self) -> ::Value; } -fn get(x: int) -> ::Value {} -//~^ ERROR unsupported - struct Struct { x: int, } diff --git a/src/test/compile-fail/assoc-path-1.rs b/src/test/compile-fail/associated-types-path-1.rs similarity index 100% rename from src/test/compile-fail/assoc-path-1.rs rename to src/test/compile-fail/associated-types-path-1.rs diff --git a/src/test/compile-fail/assoc-path-2.rs b/src/test/compile-fail/associated-types-path-2.rs similarity index 100% rename from src/test/compile-fail/assoc-path-2.rs rename to src/test/compile-fail/associated-types-path-2.rs diff --git a/src/test/run-pass/associated-types-basic.rs b/src/test/run-pass/associated-types-basic.rs new file mode 100644 index 0000000000000..fcfcce3ff1b78 --- /dev/null +++ b/src/test/run-pass/associated-types-basic.rs @@ -0,0 +1,26 @@ +// Copyright 2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(associated_types)] + +trait Foo { + type T; +} + +impl Foo for i32 { + type T = int; +} + +fn main() { + let x: ::T = 22; + let y: int = 44; + assert_eq!(x * 2, y); +} + diff --git a/src/test/run-pass/associated-types-binding-in-where-clause.rs b/src/test/run-pass/associated-types-binding-in-where-clause.rs new file mode 100644 index 0000000000000..c3300c5293575 --- /dev/null +++ b/src/test/run-pass/associated-types-binding-in-where-clause.rs @@ -0,0 +1,47 @@ +// Copyright 2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test equality constraints on associated types in a where clause. + +#![feature(associated_types)] + +pub trait Foo { + type A; + fn boo(&self) -> ::A; +} + +#[deriving(PartialEq)] +struct Bar; + +impl Foo for int { + type A = uint; + fn boo(&self) -> uint { 42 } +} + +impl Foo for char { + type A = Bar; + fn boo(&self) -> Bar { Bar } +} + +fn foo_bar>(x: I) -> Bar { + x.boo() +} + +fn foo_uint>(x: I) -> uint { + x.boo() +} + +pub fn main() { + let a = 42i; + foo_uint(a); + + let a = 'a'; + foo_bar(a); +} diff --git a/src/test/run-pass/associated-types-constant-type.rs b/src/test/run-pass/associated-types-constant-type.rs new file mode 100644 index 0000000000000..ea2cf84b757c3 --- /dev/null +++ b/src/test/run-pass/associated-types-constant-type.rs @@ -0,0 +1,42 @@ +// Copyright 2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(associated_types)] + +trait SignedUnsigned { + type Opposite; + fn convert(self) -> Self::Opposite; +} + +impl SignedUnsigned for int { + type Opposite = uint; + + fn convert(self) -> uint { + self as uint + } +} + +impl SignedUnsigned for uint { + type Opposite = int; + + fn convert(self) -> int { + self as int + } +} + +fn get(x: int) -> ::Opposite { + x.convert() +} + +fn main() { + let x = get(22); + assert_eq!(22u, x); +} + diff --git a/src/test/run-pass/associated-types-eq-obj.rs b/src/test/run-pass/associated-types-eq-obj.rs new file mode 100644 index 0000000000000..f0343a743cb50 --- /dev/null +++ b/src/test/run-pass/associated-types-eq-obj.rs @@ -0,0 +1,34 @@ +// Copyright 2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test equality constraints on associated types inside of an object type + +#![feature(associated_types)] + +pub trait Foo { + type A; + fn boo(&self) -> ::A; +} + +struct Bar; + +impl Foo for char { + type A = Bar; + fn boo(&self) -> Bar { Bar } +} + +fn baz(x: &Foo) -> Bar { + x.boo() +} + +pub fn main() { + let a = 'a'; + baz(&a); +} diff --git a/src/test/run-pass/assoc-eq.rs b/src/test/run-pass/associated-types-return.rs similarity index 89% rename from src/test/run-pass/assoc-eq.rs rename to src/test/run-pass/associated-types-return.rs index f1ba382b42dad..d8e277510ed10 100644 --- a/src/test/run-pass/assoc-eq.rs +++ b/src/test/run-pass/associated-types-return.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Test equality constraints on associated types. +// Test equality constraints on associated types in a where clause. #![feature(associated_types)] @@ -17,16 +17,19 @@ pub trait Foo { fn boo(&self) -> ::A; } +#[deriving(PartialEq)] struct Bar; impl Foo for int { type A = uint; fn boo(&self) -> uint { 42 } } + impl Foo for Bar { type A = int; fn boo(&self) -> int { 43 } } + impl Foo for char { type A = Bar; fn boo(&self) -> Bar { Bar } @@ -35,12 +38,10 @@ impl Foo for char { fn foo1>(x: I) -> Bar { x.boo() } + fn foo2(x: I) -> ::A { x.boo() } -fn baz(x: &Foo) -> Bar { - x.boo() -} pub fn main() { let a = 42i; @@ -51,5 +52,5 @@ pub fn main() { let a = 'a'; foo1(a); - baz(&a); + assert!(foo2(a) == Bar); } diff --git a/src/test/run-pass/assoc-sugar-path.rs b/src/test/run-pass/associated-types-sugar-path.rs similarity index 100% rename from src/test/run-pass/assoc-sugar-path.rs rename to src/test/run-pass/associated-types-sugar-path.rs From 82787c2252267561777303bcc4e4d0394c34e5c9 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 26 Dec 2014 03:31:58 -0500 Subject: [PATCH 09/36] Convert to use `Rc` in object types (finally!). --- src/librustc/metadata/decoder.rs | 10 +++---- src/librustc/metadata/tydecode.rs | 14 ++++----- src/librustc/metadata/tyencode.rs | 4 +-- src/librustc/middle/astencode.rs | 12 ++++---- src/librustc/middle/infer/combine.rs | 4 +-- src/librustc/middle/traits/fulfill.rs | 4 +-- src/librustc/middle/ty.rs | 41 ++++++--------------------- src/librustc/middle/ty_fold.rs | 9 ------ src/librustc_typeck/astconv.rs | 20 ++++++------- src/librustc_typeck/check/assoc.rs | 2 +- src/librustc_typeck/collect.rs | 2 +- 11 files changed, 43 insertions(+), 79 deletions(-) diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index fe0a2beb9ab21..c189aed05abf1 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -245,13 +245,13 @@ pub fn item_type<'tcx>(_item_id: ast::DefId, item: rbml::Doc, } fn doc_trait_ref<'tcx>(doc: rbml::Doc, tcx: &ty::ctxt<'tcx>, cdata: Cmd) - -> ty::TraitRef<'tcx> { + -> Rc> { parse_trait_ref_data(doc.data, cdata.cnum, doc.start, tcx, |_, did| translate_def_id(cdata, did)) } fn item_trait_ref<'tcx>(doc: rbml::Doc, tcx: &ty::ctxt<'tcx>, cdata: Cmd) - -> ty::TraitRef<'tcx> { + -> Rc> { let tp = reader::get_doc(doc, tag_item_trait_ref); doc_trait_ref(tp, tcx, cdata) } @@ -394,7 +394,7 @@ pub fn get_trait_def<'tcx>(cdata: Cmd, unsafety: unsafety, generics: generics, bounds: bounds, - trait_ref: Rc::new(item_trait_ref(item_doc, tcx, cdata)), + trait_ref: item_trait_ref(item_doc, tcx, cdata), associated_type_names: associated_type_names, } } @@ -441,7 +441,7 @@ pub fn get_impl_trait<'tcx>(cdata: Cmd, { let item_doc = lookup_item(id, cdata.data()); reader::maybe_get_doc(item_doc, tag_item_trait_ref).map(|tp| { - Rc::new(doc_trait_ref(tp, tcx, cdata)) + doc_trait_ref(tp, tcx, cdata) }) } @@ -937,7 +937,7 @@ pub fn get_supertraits<'tcx>(cdata: Cmd, id: ast::NodeId, tcx: &ty::ctxt<'tcx>) // FIXME(#8559): The builtin bounds shouldn't be encoded in the first place. let trait_ref = doc_trait_ref(trait_doc, tcx, cdata); if tcx.lang_items.to_builtin_kind(trait_ref.def_id).is_none() { - results.push(Rc::new(trait_ref)); + results.push(trait_ref); } true }); diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs index 7daef30e25325..2a4d5f36a17c9 100644 --- a/src/librustc/metadata/tydecode.rs +++ b/src/librustc/metadata/tydecode.rs @@ -180,7 +180,7 @@ pub fn parse_bare_fn_ty_data<'tcx>(data: &[u8], crate_num: ast::CrateNum, pos: u pub fn parse_trait_ref_data<'tcx>(data: &[u8], crate_num: ast::CrateNum, pos: uint, tcx: &ty::ctxt<'tcx>, conv: conv_did) - -> ty::TraitRef<'tcx> { + -> Rc> { debug!("parse_trait_ref_data {}", data_log_string(data, pos)); let mut st = parse_state_from_data(data, crate_num, pos, tcx); parse_trait_ref(&mut st, conv) @@ -377,10 +377,10 @@ fn parse_str(st: &mut PState, term: char) -> String { } fn parse_trait_ref<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did) - -> ty::TraitRef<'tcx> { + -> Rc> { let def = parse_def(st, NominalType, |x,y| conv(x,y)); - let substs = parse_substs(st, |x,y| conv(x,y)); - ty::TraitRef {def_id: def, substs: st.tcx.mk_substs(substs)} + let substs = st.tcx.mk_substs(parse_substs(st, |x,y| conv(x,y))); + Rc::new(ty::TraitRef {def_id: def, substs: substs}) } fn parse_ty<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did) -> Ty<'tcx> { @@ -689,7 +689,7 @@ pub fn parse_predicate<'a,'tcx>(st: &mut PState<'a, 'tcx>, -> ty::Predicate<'tcx> { match next(st) { - 't' => ty::Binder(Rc::new(parse_trait_ref(st, conv))).as_predicate(), + 't' => ty::Binder(parse_trait_ref(st, conv)).as_predicate(), 'e' => ty::Binder(ty::EquatePredicate(parse_ty(st, |x,y| conv(x,y)), parse_ty(st, |x,y| conv(x,y)))).as_predicate(), 'r' => ty::Binder(ty::OutlivesPredicate(parse_region(st, |x,y| conv(x,y)), @@ -708,7 +708,7 @@ fn parse_projection_predicate<'a,'tcx>( { ty::ProjectionPredicate { projection_ty: ty::ProjectionTy { - trait_ref: Rc::new(parse_trait_ref(st, |x,y| conv(x,y))), + trait_ref: parse_trait_ref(st, |x,y| conv(x,y)), item_name: token::str_to_ident(parse_str(st, '|').as_slice()).name, }, ty: parse_ty(st, |x,y| conv(x,y)), @@ -795,7 +795,7 @@ fn parse_bounds<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did) } 'I' => { param_bounds.trait_bounds.push( - ty::Binder(Rc::new(parse_trait_ref(st, |x,y| conv(x,y))))); + ty::Binder(parse_trait_ref(st, |x,y| conv(x,y)))); } 'P' => { param_bounds.projection_bounds.push( diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs index 6d2b7e0ba93f6..015724d38eee6 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -91,7 +91,7 @@ pub fn enc_ty<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>, t: Ty<'t ty::ty_trait(box ty::TyTrait { ref principal, ref bounds }) => { mywrite!(w, "x["); - enc_trait_ref(w, cx, &principal.0); + enc_trait_ref(w, cx, &*principal.0); enc_existential_bounds(w, cx, bounds); mywrite!(w, "]"); } @@ -151,7 +151,7 @@ pub fn enc_ty<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>, t: Ty<'t } ty::ty_projection(ref data) => { mywrite!(w, "P["); - enc_trait_ref(w, cx, &data.trait_ref); + enc_trait_ref(w, cx, &*data.trait_ref); mywrite!(w, "{}]", token::get_name(data.item_name)); } ty::ty_err => { diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index 57dac607fa6b7..4dee3ee471365 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -1120,7 +1120,7 @@ impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> { this.emit_enum_variant("UnsizeVtable", 2, 4, |this| { this.emit_enum_variant_arg(0, |this| { try!(this.emit_struct_field("principal", 0, |this| { - Ok(this.emit_trait_ref(ecx, &principal.0)) + Ok(this.emit_trait_ref(ecx, &*principal.0)) })); this.emit_struct_field("bounds", 1, |this| { Ok(this.emit_existential_bounds(ecx, b)) @@ -1546,7 +1546,7 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> { fn read_trait_ref<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>) -> Rc> { - Rc::new(self.read_opaque(|this, doc| { + self.read_opaque(|this, doc| { let ty = tydecode::parse_trait_ref_data( doc.data, dcx.cdata.cnum, @@ -1554,12 +1554,12 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> { dcx.tcx, |s, a| this.convert_def_id(dcx, s, a)); Ok(ty) - }).unwrap()) + }).unwrap() } fn read_poly_trait_ref<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>) -> ty::PolyTraitRef<'tcx> { - ty::Binder(Rc::new(self.read_opaque(|this, doc| { + ty::Binder(self.read_opaque(|this, doc| { let ty = tydecode::parse_trait_ref_data( doc.data, dcx.cdata.cnum, @@ -1567,7 +1567,7 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> { dcx.tcx, |s, a| this.convert_def_id(dcx, s, a)); Ok(ty) - }).unwrap())) + }).unwrap()) } fn read_type_param_def<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>) @@ -1786,7 +1786,7 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> { Ok(this.read_poly_trait_ref(dcx)) })); Ok(ty::TyTrait { - principal: ty::Binder((*principal.0).clone()), + principal: principal, bounds: try!(this.read_struct_field("bounds", 1, |this| { Ok(this.read_existential_bounds(dcx)) })), diff --git a/src/librustc/middle/infer/combine.rs b/src/librustc/middle/infer/combine.rs index 8ff2d0ba1f0d8..4114394041dc3 100644 --- a/src/librustc/middle/infer/combine.rs +++ b/src/librustc/middle/infer/combine.rs @@ -596,8 +596,8 @@ pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C, (&ty::ty_projection(ref a_data), &ty::ty_projection(ref b_data)) => { if a_data.item_name == b_data.item_name { - let trait_ref = try!(this.trait_refs(&a_data.trait_ref, &b_data.trait_ref)); - Ok(ty::mk_projection(tcx, trait_ref, a_data.item_name)) + let trait_ref = try!(this.trait_refs(&*a_data.trait_ref, &*b_data.trait_ref)); + Ok(ty::mk_projection(tcx, Rc::new(trait_ref), a_data.item_name)) } else { Err(ty::terr_sorts(expected_found(this, a, b))) } diff --git a/src/librustc/middle/traits/fulfill.rs b/src/librustc/middle/traits/fulfill.rs index e5024e000df0d..9cd1725e4df88 100644 --- a/src/librustc/middle/traits/fulfill.rs +++ b/src/librustc/middle/traits/fulfill.rs @@ -422,8 +422,8 @@ fn process_predicate<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>, // somewhat constrained, and we cannot verify // that constraint, so yield an error. let ty_projection = ty::mk_projection(tcx, - (*trait_ref.0).clone(), - data.0.projection_ty.item_name); + trait_ref.0.clone(), + data.0.projection_ty.item_name); debug!("process_predicate: falling back to projection {}", ty_projection.repr(selcx.tcx())); diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index da65feb8fd3f8..6b2ac04f5ce2a 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -1352,13 +1352,13 @@ pub enum sty<'tcx> { ty_closure(Box>), ty_trait(Box>), - ty_struct(DefId, &'tcx Substs<'tcx>), + ty_struct(DefId, Substs<'tcx>), ty_unboxed_closure(DefId, &'tcx Region, &'tcx Substs<'tcx>), ty_tup(Vec>), - ty_projection(Box>), + ty_projection(ProjectionTy<'tcx>), ty_param(ParamTy), // type parameter ty_open(Ty<'tcx>), // A deref'ed fat pointer, i.e., a dynamically sized value @@ -1375,8 +1375,7 @@ pub enum sty<'tcx> { #[deriving(Clone, PartialEq, Eq, Hash, Show)] pub struct TyTrait<'tcx> { - // Principal trait reference. - pub principal: ty::Binder>, + pub principal: ty::PolyTraitRef<'tcx>, pub bounds: ExistentialBounds } @@ -1448,12 +1447,6 @@ impl<'tcx> PolyTraitRef<'tcx> { // Note that we preserve binding levels Binder(TraitPredicate { trait_ref: self.0.clone() }) } - - pub fn remove_rc(&self) -> ty::Binder> { - // Annoyingly, we can't easily put a `Rc` into a `sty` structure, - // and hence we have to remove the rc to put this into a `TyTrait`. - ty::Binder((*self.0).clone()) - } } /// Binder is a binder for higher-ranked lifetimes. It is part of the @@ -1833,15 +1826,6 @@ pub struct ProjectionTy<'tcx> { pub item_name: ast::Name, } -// Annoying: a version of `ProjectionTy` that avoids the `Rc`, because -// it is difficult to place an `Rc` in the `sty` struct. Eventually -// these two types ought to be unified. -#[deriving(Clone, PartialEq, Eq, Hash, Show)] -pub struct TyProjection<'tcx> { - pub trait_ref: ty::TraitRef<'tcx>, - pub item_name: ast::Name, -} - pub trait ToPolyTraitRef<'tcx> { fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx>; } @@ -2690,10 +2674,9 @@ pub fn mk_ctor_fn<'tcx>(cx: &ctxt<'tcx>, } pub fn mk_trait<'tcx>(cx: &ctxt<'tcx>, - principal: ty::Binder>, + principal: ty::PolyTraitRef<'tcx>, bounds: ExistentialBounds) -> Ty<'tcx> { - // take a copy of substs so that we own the vectors inside let inner = box TyTrait { principal: principal, bounds: bounds @@ -2702,11 +2685,11 @@ pub fn mk_trait<'tcx>(cx: &ctxt<'tcx>, } pub fn mk_projection<'tcx>(cx: &ctxt<'tcx>, - trait_ref: ty::TraitRef<'tcx>, + trait_ref: Rc>, item_name: ast::Name) -> Ty<'tcx> { // take a copy of substs so that we own the vectors inside - let inner = box TyProjection { trait_ref: trait_ref, item_name: item_name }; + let inner = ProjectionTy { trait_ref: trait_ref, item_name: item_name }; mk_t(cx, ty_projection(inner)) } @@ -2776,7 +2759,7 @@ pub fn maybe_walk_ty<'tcx>(ty: Ty<'tcx>, f: |Ty<'tcx>| -> bool) { maybe_walk_ty(*subty, |x| f(x)); } } - ty_projection(box TyProjection { ref trait_ref, .. }) => { + ty_projection(ProjectionTy { ref trait_ref, .. }) => { for subty in trait_ref.substs.types.iter() { maybe_walk_ty(*subty, |x| f(x)); } @@ -5783,7 +5766,7 @@ pub fn each_bound_trait_and_supertraits<'tcx, F>(tcx: &ctxt<'tcx>, pub fn object_region_bounds<'tcx>( tcx: &ctxt<'tcx>, - opt_principal: Option<&Binder>>, // None for closures + opt_principal: Option<&PolyTraitRef<'tcx>>, // None for closures others: BuiltinBounds) -> Vec { @@ -6913,14 +6896,6 @@ impl<'tcx> Repr<'tcx> for ty::ProjectionPredicate<'tcx> { } } -impl<'tcx> Repr<'tcx> for ty::TyProjection<'tcx> { - fn repr(&self, tcx: &ctxt<'tcx>) -> String { - format!("TyProjection({}, {})", - self.trait_ref.repr(tcx), - self.item_name.repr(tcx)) - } -} - pub trait HasProjectionTypes { fn has_projection_types(&self) -> bool; } diff --git a/src/librustc/middle/ty_fold.rs b/src/librustc/middle/ty_fold.rs index 036fbfec28024..4ef597d21081e 100644 --- a/src/librustc/middle/ty_fold.rs +++ b/src/librustc/middle/ty_fold.rs @@ -436,15 +436,6 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ProjectionTy<'tcx> { } } -impl<'tcx> TypeFoldable<'tcx> for ty::TyProjection<'tcx> { - fn fold_with>(&self, folder: &mut F) -> ty::TyProjection<'tcx> { - ty::TyProjection { - trait_ref: self.trait_ref.fold_with(folder), - item_name: self.item_name, - } - } -} - impl<'tcx> TypeFoldable<'tcx> for ty::GenericBounds<'tcx> { fn fold_with>(&self, folder: &mut F) -> ty::GenericBounds<'tcx> { ty::GenericBounds { diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 00d3478e6a517..26959dfd1d524 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -881,7 +881,7 @@ fn ast_ty_to_trait_ref<'tcx,AC,RS>(this: &AC, fn trait_ref_to_object_type<'tcx,AC,RS>(this: &AC, rscope: &RS, span: Span, - trait_ref: ty::Binder>, + trait_ref: ty::PolyTraitRef<'tcx>, bounds: &[ast::TyParamBound]) -> Ty<'tcx> where AC : AstConv<'tcx>, RS : RegionScope @@ -889,7 +889,7 @@ fn trait_ref_to_object_type<'tcx,AC,RS>(this: &AC, let existential_bounds = conv_existential_bounds(this, rscope, span, - Some(&trait_ref), + Some(trait_ref.clone()), bounds); let result = ty::mk_trait(this.tcx(), trait_ref, existential_bounds); @@ -1020,7 +1020,6 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( ast::TyObjectSum(ref ty, ref bounds) => { match ast_ty_to_trait_ref(this, rscope, &**ty, bounds[]) { Ok(trait_ref) => { - let trait_ref = trait_ref.remove_rc(); trait_ref_to_object_type(this, rscope, ast_ty.span, trait_ref, bounds[]) } @@ -1100,7 +1099,6 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( None, path, Some(&mut projections)); - let trait_ref = (*trait_ref).clone(); let trait_ref = ty::Binder(trait_ref); trait_ref_to_object_type(this, rscope, path.span, trait_ref, &[]) } @@ -1501,7 +1499,7 @@ pub fn conv_existential_bounds<'tcx, AC: AstConv<'tcx>, RS:RegionScope>( this: &AC, rscope: &RS, span: Span, - principal_trait_ref: Option<&ty::Binder>>, // None for boxed closures + principal_trait_ref: Option>, // None for boxed closures ast_bounds: &[ast::TyParamBound]) -> ty::ExistentialBounds { @@ -1530,7 +1528,7 @@ fn conv_ty_poly_trait_ref<'tcx, AC, RS>( trait_bound, None, &mut projections); - Some(ptr.remove_rc()) + Some(ptr) } None => { this.tcx().sess.span_err( @@ -1546,7 +1544,7 @@ fn conv_ty_poly_trait_ref<'tcx, AC, RS>( conv_existential_bounds_from_partitioned_bounds(this, rscope, span, - main_trait_bound.as_ref(), + main_trait_bound.clone(), partitioned_bounds); match main_trait_bound { @@ -1559,7 +1557,7 @@ pub fn conv_existential_bounds_from_partitioned_bounds<'tcx, AC, RS>( this: &AC, rscope: &RS, span: Span, - principal_trait_ref: Option<&ty::Binder>>, // None for boxed closures + principal_trait_ref: Option>, // None for boxed closures partitioned_bounds: PartitionedBounds) -> ty::ExistentialBounds where AC: AstConv<'tcx>, RS:RegionScope @@ -1597,7 +1595,7 @@ pub fn conv_existential_bounds_from_partitioned_bounds<'tcx, AC, RS>( fn compute_opt_region_bound<'tcx>(tcx: &ty::ctxt<'tcx>, span: Span, explicit_region_bounds: &[&ast::Lifetime], - principal_trait_ref: Option<&ty::Binder>>, + principal_trait_ref: Option>, builtin_bounds: ty::BuiltinBounds) -> Option { @@ -1622,7 +1620,7 @@ fn compute_opt_region_bound<'tcx>(tcx: &ty::ctxt<'tcx>, // No explicit region bound specified. Therefore, examine trait // bounds and see if we can derive region bounds from those. let derived_region_bounds = - ty::object_region_bounds(tcx, principal_trait_ref, builtin_bounds); + ty::object_region_bounds(tcx, principal_trait_ref.as_ref(), builtin_bounds); // If there are no derived region bounds, then report back that we // can find no region bound. @@ -1657,7 +1655,7 @@ fn compute_region_bound<'tcx, AC: AstConv<'tcx>, RS:RegionScope>( rscope: &RS, span: Span, region_bounds: &[&ast::Lifetime], - principal_trait_ref: Option<&ty::Binder>>, // None for closures + principal_trait_ref: Option>, // None for closures builtin_bounds: ty::BuiltinBounds) -> ty::Region { diff --git a/src/librustc_typeck/check/assoc.rs b/src/librustc_typeck/check/assoc.rs index 65ade452fa111..fbc6d49d6e9a8 100644 --- a/src/librustc_typeck/check/assoc.rs +++ b/src/librustc_typeck/check/assoc.rs @@ -58,7 +58,7 @@ impl<'a,'tcx> TypeFolder<'tcx> for AssociatedTypeNormalizer<'a,'tcx> { self.span, self.body_id, ObligationCauseCode::MiscObligation); - let trait_ref = Rc::new(data.trait_ref.clone()); + let trait_ref = data.trait_ref.clone(); self.fulfillment_cx .normalize_associated_type(self.infcx, trait_ref, diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 35599a989c106..dfe54674d63ec 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -177,7 +177,7 @@ impl<'a, 'tcx> AstConv<'tcx> for CrateCtxt<'a, 'tcx> { item_name: ast::Name) -> Ty<'tcx> { - ty::mk_projection(self.tcx, (*trait_ref).clone(), item_name) + ty::mk_projection(self.tcx, trait_ref, item_name) } } From becbd81aaa1b8c60eb13fee898163d1a2ac33de3 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 26 Dec 2014 04:36:04 -0500 Subject: [PATCH 10/36] Integrate projection bounds to `ExistentialBounds` but do not use them for anything. --- src/librustc/metadata/tydecode.rs | 22 +++++--- src/librustc/metadata/tyencode.rs | 11 ++-- src/librustc/middle/astencode.rs | 10 ++-- src/librustc/middle/infer/coercion.rs | 13 +++-- src/librustc/middle/infer/combine.rs | 76 +++++++++++++++++++++----- src/librustc/middle/ty.rs | 78 ++++++++++++++++++++------- src/librustc/middle/ty_fold.rs | 25 +++++---- src/librustc/util/ppaux.rs | 8 +-- src/librustc_typeck/astconv.rs | 63 ++++++++++++++-------- src/librustc_typeck/check/assoc.rs | 1 - src/librustc_typeck/check/closure.rs | 2 +- src/librustc_typeck/check/regionck.rs | 8 +-- src/librustc_typeck/check/vtable.rs | 2 +- src/librustdoc/clean/mod.rs | 29 ++++++---- 14 files changed, 240 insertions(+), 108 deletions(-) diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs index 2a4d5f36a17c9..7dccc49dcbbda 100644 --- a/src/librustc/metadata/tydecode.rs +++ b/src/librustc/metadata/tydecode.rs @@ -200,9 +200,9 @@ pub fn parse_bounds_data<'tcx>(data: &[u8], crate_num: ast::CrateNum, parse_bounds(&mut st, conv) } -pub fn parse_existential_bounds_data(data: &[u8], crate_num: ast::CrateNum, - pos: uint, tcx: &ty::ctxt, conv: conv_did) - -> ty::ExistentialBounds { +pub fn parse_existential_bounds_data<'tcx>(data: &[u8], crate_num: ast::CrateNum, + pos: uint, tcx: &ty::ctxt<'tcx>, conv: conv_did) + -> ty::ExistentialBounds<'tcx> { let mut st = parse_state_from_data(data, crate_num, pos, tcx); parse_existential_bounds(&mut st, conv) } @@ -744,10 +744,18 @@ fn parse_type_param_def<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did) } } -fn parse_existential_bounds(st: &mut PState, conv: conv_did) -> ty::ExistentialBounds { - let r = parse_region(st, |x,y| conv(x,y)); - let bb = parse_builtin_bounds(st, conv); - return ty::ExistentialBounds { region_bound: r, builtin_bounds: bb }; +fn parse_existential_bounds<'a,'tcx>(st: &mut PState<'a,'tcx>, + conv: conv_did) + -> ty::ExistentialBounds<'tcx> +{ + let ty::ParamBounds { trait_bounds, mut region_bounds, builtin_bounds, projection_bounds } = + parse_bounds(st, conv); + assert_eq!(region_bounds.len(), 1); + assert_eq!(trait_bounds.len(), 0); + let region_bound = region_bounds.pop().unwrap(); + return ty::ExistentialBounds { region_bound: region_bound, + builtin_bounds: builtin_bounds, + projection_bounds: projection_bounds }; } fn parse_builtin_bounds(st: &mut PState, _conv: conv_did) -> ty::BuiltinBounds { diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs index 015724d38eee6..b6d05882dce23 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -392,9 +392,14 @@ pub fn enc_builtin_bounds(w: &mut SeekableMemWriter, _cx: &ctxt, bs: &ty::Builti mywrite!(w, "."); } -pub fn enc_existential_bounds(w: &mut SeekableMemWriter, cx: &ctxt, bs: &ty::ExistentialBounds) { - enc_region(w, cx, bs.region_bound); - enc_builtin_bounds(w, cx, &bs.builtin_bounds); +pub fn enc_existential_bounds<'a,'tcx>(w: &mut SeekableMemWriter, + cx: &ctxt<'a,'tcx>, + bs: &ty::ExistentialBounds<'tcx>) { + let param_bounds = ty::ParamBounds { trait_bounds: vec!(), + region_bounds: vec!(bs.region_bound), + builtin_bounds: bs.builtin_bounds, + projection_bounds: bs.projection_bounds.clone() }; + enc_bounds(w, cx, ¶m_bounds); } pub fn enc_bounds<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>, diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index 4dee3ee471365..0b78f2b1cfce9 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -842,7 +842,8 @@ trait rbml_writer_helpers<'tcx> { type_scheme: ty::TypeScheme<'tcx>); fn emit_substs<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>, substs: &subst::Substs<'tcx>); - fn emit_existential_bounds(&mut self, ecx: &e::EncodeContext, bounds: &ty::ExistentialBounds); + fn emit_existential_bounds<'b>(&mut self, ecx: &e::EncodeContext<'b,'tcx>, + bounds: &ty::ExistentialBounds<'tcx>); fn emit_builtin_bounds(&mut self, ecx: &e::EncodeContext, bounds: &ty::BuiltinBounds); fn emit_auto_adjustment<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>, adj: &ty::AutoAdjustment<'tcx>); @@ -982,7 +983,8 @@ impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> { }); } - fn emit_existential_bounds(&mut self, ecx: &e::EncodeContext, bounds: &ty::ExistentialBounds) { + fn emit_existential_bounds<'b>(&mut self, ecx: &e::EncodeContext<'b,'tcx>, + bounds: &ty::ExistentialBounds<'tcx>) { self.emit_opaque(|this| Ok(tyencode::enc_existential_bounds(this.writer, &ecx.ty_str_ctxt(), bounds))); @@ -1372,7 +1374,7 @@ trait rbml_decoder_decoder_helpers<'tcx> { fn read_type_scheme<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>) -> ty::TypeScheme<'tcx>; fn read_existential_bounds<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>) - -> ty::ExistentialBounds; + -> ty::ExistentialBounds<'tcx>; fn read_substs<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>) -> subst::Substs<'tcx>; fn read_auto_adjustment<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>) @@ -1626,7 +1628,7 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> { } fn read_existential_bounds<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>) - -> ty::ExistentialBounds + -> ty::ExistentialBounds<'tcx> { self.read_opaque(|this, doc| { Ok(tydecode::parse_existential_bounds_data(doc.data, diff --git a/src/librustc/middle/infer/coercion.rs b/src/librustc/middle/infer/coercion.rs index 13017da508d28..11ca202971e1d 100644 --- a/src/librustc/middle/infer/coercion.rs +++ b/src/librustc/middle/infer/coercion.rs @@ -351,11 +351,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { (&ty::ty_trait(..), &ty::ty_trait(..)) => { None } - (_, &ty::ty_trait(box ty::TyTrait { ref principal, bounds })) => { + (_, &ty::ty_trait(box ty::TyTrait { ref principal, ref bounds })) => { // FIXME what is the purpose of `ty`? - let ty = ty::mk_trait(tcx, principal.clone(), bounds); - Some((ty, ty::UnsizeVtable(ty::TyTrait { principal: (*principal).clone(), - bounds: bounds }, + let ty = ty::mk_trait(tcx, principal.clone(), bounds.clone()); + Some((ty, ty::UnsizeVtable(ty::TyTrait { principal: principal.clone(), + bounds: bounds.clone() }, ty_a))) } (&ty::ty_struct(did_a, substs_a), &ty::ty_struct(did_b, substs_b)) @@ -458,10 +458,9 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { match a.sty { ty::ty_rptr(_, ty::mt{ty, mutbl}) => match ty.sty { - ty::ty_trait(box ty::TyTrait { ref principal, bounds }) => { + ty::ty_trait(box ty::TyTrait { ref principal, ref bounds }) => { debug!("mutbl={} b_mutbl={}", mutbl, b_mutbl); - // FIXME what is purpose of this type `tr`? - let tr = ty::mk_trait(tcx, principal.clone(), bounds); + let tr = ty::mk_trait(tcx, principal.clone(), bounds.clone()); try!(self.subtype(mk_ty(tr), b)); Ok(Some(AdjustDerefRef(AutoDerefRef { autoderefs: 1, diff --git a/src/librustc/middle/infer/combine.rs b/src/librustc/middle/infer/combine.rs index 4114394041dc3..e0bcdfc6d8d93 100644 --- a/src/librustc/middle/infer/combine.rs +++ b/src/librustc/middle/infer/combine.rs @@ -222,7 +222,7 @@ pub trait Combine<'tcx> { }; let unsafety = try!(self.unsafeties(a.unsafety, b.unsafety)); let onceness = try!(self.oncenesses(a.onceness, b.onceness)); - let bounds = try!(self.existential_bounds(a.bounds, b.bounds)); + let bounds = try!(self.existential_bounds(&a.bounds, &b.bounds)); let sig = try!(self.binders(&a.sig, &b.sig)); let abi = try!(self.abi(a.abi, b.abi)); Ok(ty::ClosureTy { @@ -289,15 +289,61 @@ pub trait Combine<'tcx> { fn oncenesses(&self, a: Onceness, b: Onceness) -> cres<'tcx, Onceness>; + fn projection_tys(&self, + a: &ty::ProjectionTy<'tcx>, + b: &ty::ProjectionTy<'tcx>) + -> cres<'tcx, ty::ProjectionTy<'tcx>> + { + if a.item_name != b.item_name { + Err(ty::terr_projection_name_mismatched( + expected_found(self, a.item_name, b.item_name))) + } else { + let trait_ref = try!(self.trait_refs(&*a.trait_ref, &*b.trait_ref)); + Ok(ty::ProjectionTy { trait_ref: Rc::new(trait_ref), item_name: a.item_name }) + } + } + + fn projection_predicates(&self, + a: &ty::ProjectionPredicate<'tcx>, + b: &ty::ProjectionPredicate<'tcx>) + -> cres<'tcx, ty::ProjectionPredicate<'tcx>> + { + let projection_ty = try!(self.projection_tys(&a.projection_ty, &b.projection_ty)); + let ty = try!(self.tys(a.ty, b.ty)); + Ok(ty::ProjectionPredicate { projection_ty: projection_ty, ty: ty }) + } + + fn projection_bounds(&self, + a: &Vec>, + b: &Vec>) + -> cres<'tcx, Vec>> + { + // To be compatible, `a` and `b` must be for precisely the + // same set of traits and item names. We always require that + // projection bounds lists are sorted by trait-def-id and item-name, + // so we can just iterate through the lists pairwise, so long as they are the + // same length. + if a.len() != b.len() { + Err(ty::terr_projection_bounds_length(expected_found(self, a.len(), b.len()))) + } else { + a.iter() + .zip(b.iter()) + .map(|(a, b)| self.binders(a, b)) + .collect() + } + } + fn existential_bounds(&self, - a: ty::ExistentialBounds, - b: ty::ExistentialBounds) - -> cres<'tcx, ty::ExistentialBounds> + a: &ty::ExistentialBounds<'tcx>, + b: &ty::ExistentialBounds<'tcx>) + -> cres<'tcx, ty::ExistentialBounds<'tcx>> { let r = try!(self.contraregions(a.region_bound, b.region_bound)); let nb = try!(self.builtin_bounds(a.builtin_bounds, b.builtin_bounds)); + let pb = try!(self.projection_bounds(&a.projection_bounds, &b.projection_bounds)); Ok(ty::ExistentialBounds { region_bound: r, - builtin_bounds: nb }) + builtin_bounds: nb, + projection_bounds: pb }) } fn builtin_bounds(&self, @@ -381,6 +427,16 @@ impl<'tcx> Combineable<'tcx> for ty::TraitRef<'tcx> { } } +impl<'tcx> Combineable<'tcx> for ty::ProjectionPredicate<'tcx> { + fn combine>(combiner: &C, + a: &ty::ProjectionPredicate<'tcx>, + b: &ty::ProjectionPredicate<'tcx>) + -> cres<'tcx, ty::ProjectionPredicate<'tcx>> + { + combiner.projection_predicates(a, b) + } +} + impl<'tcx> Combineable<'tcx> for ty::FnSig<'tcx> { fn combine>(combiner: &C, a: &ty::FnSig<'tcx>, @@ -496,7 +552,7 @@ pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C, &ty::ty_trait(ref b_)) => { debug!("Trying to match traits {} and {}", a, b); let principal = try!(this.binders(&a_.principal, &b_.principal)); - let bounds = try!(this.existential_bounds(a_.bounds, b_.bounds)); + let bounds = try!(this.existential_bounds(&a_.bounds, &b_.bounds)); Ok(ty::mk_trait(tcx, principal, bounds)) } @@ -595,12 +651,8 @@ pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C, } (&ty::ty_projection(ref a_data), &ty::ty_projection(ref b_data)) => { - if a_data.item_name == b_data.item_name { - let trait_ref = try!(this.trait_refs(&*a_data.trait_ref, &*b_data.trait_ref)); - Ok(ty::mk_projection(tcx, Rc::new(trait_ref), a_data.item_name)) - } else { - Err(ty::terr_sorts(expected_found(this, a, b))) - } + let projection_ty = try!(this.projection_tys(a_data, b_data)); + Ok(ty::mk_projection(tcx, projection_ty.trait_ref, projection_ty.item_name)) } _ => Err(ty::terr_sorts(expected_found(this, a, b))) diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 6b2ac04f5ce2a..e989f5a2cc2b4 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -396,14 +396,14 @@ pub fn type_of_adjust<'tcx>(cx: &ctxt<'tcx>, adj: &AutoAdjustment<'tcx>) -> Opti fn type_of_autoref<'tcx>(cx: &ctxt<'tcx>, autoref: &AutoRef<'tcx>) -> Option> { match autoref { &AutoUnsize(ref k) => match k { - &UnsizeVtable(TyTrait { ref principal, bounds }, _) => { - Some(mk_trait(cx, (*principal).clone(), bounds)) + &UnsizeVtable(TyTrait { ref principal, ref bounds }, _) => { + Some(mk_trait(cx, principal.clone(), bounds.clone())) } _ => None }, &AutoUnsizeUniq(ref k) => match k { - &UnsizeVtable(TyTrait { ref principal, bounds }, _) => { - Some(mk_uniq(cx, mk_trait(cx, (*principal).clone(), bounds))) + &UnsizeVtable(TyTrait { ref principal, ref bounds }, _) => { + Some(mk_uniq(cx, mk_trait(cx, principal.clone(), bounds.clone()))) } _ => None }, @@ -1040,7 +1040,7 @@ pub struct ClosureTy<'tcx> { pub unsafety: ast::Unsafety, pub onceness: ast::Onceness, pub store: TraitStore, - pub bounds: ExistentialBounds, + pub bounds: ExistentialBounds<'tcx>, pub sig: PolyFnSig<'tcx>, pub abi: abi::Abi, } @@ -1376,7 +1376,7 @@ pub enum sty<'tcx> { #[deriving(Clone, PartialEq, Eq, Hash, Show)] pub struct TyTrait<'tcx> { pub principal: ty::PolyTraitRef<'tcx>, - pub bounds: ExistentialBounds + pub bounds: ExistentialBounds<'tcx>, } impl<'tcx> TyTrait<'tcx> { @@ -1510,7 +1510,9 @@ pub enum type_err<'tcx> { terr_builtin_bounds(expected_found), terr_variadic_mismatch(expected_found), terr_cyclic_ty, - terr_convergence_mismatch(expected_found) + terr_convergence_mismatch(expected_found), + terr_projection_name_mismatched(expected_found), + terr_projection_bounds_length(expected_found), } /// Bounds suitable for a named type parameter like `A` in `fn foo` @@ -1528,10 +1530,11 @@ pub struct ParamBounds<'tcx> { /// major difference between this case and `ParamBounds` is that /// general purpose trait bounds are omitted and there must be /// *exactly one* region. -#[deriving(Copy, PartialEq, Eq, Hash, Clone, Show)] -pub struct ExistentialBounds { +#[deriving(PartialEq, Eq, Hash, Clone, Show)] +pub struct ExistentialBounds<'tcx> { pub region_bound: ty::Region, - pub builtin_bounds: BuiltinBounds + pub builtin_bounds: BuiltinBounds, + pub projection_bounds: Vec>, } pub type BuiltinBounds = EnumSet; @@ -1559,9 +1562,10 @@ pub fn all_builtin_bounds() -> BuiltinBounds { } /// An existential bound that does not implement any traits. -pub fn region_existential_bound(r: ty::Region) -> ExistentialBounds { +pub fn region_existential_bound<'tcx>(r: ty::Region) -> ExistentialBounds<'tcx> { ty::ExistentialBounds { region_bound: r, - builtin_bounds: empty_builtin_bounds() } + builtin_bounds: empty_builtin_bounds(), + projection_bounds: Vec::new() } } impl CLike for BuiltinBound { @@ -1820,12 +1824,24 @@ pub struct ProjectionPredicate<'tcx> { pub type PolyProjectionPredicate<'tcx> = Binder>; +impl<'tcx> PolyProjectionPredicate<'tcx> { + pub fn sort_key(&self) -> (ast::DefId, ast::Name) { + self.0.projection_ty.sort_key() + } +} + #[deriving(Clone, PartialEq, Eq, Hash, Show)] pub struct ProjectionTy<'tcx> { pub trait_ref: Rc>, pub item_name: ast::Name, } +impl<'tcx> ProjectionTy<'tcx> { + pub fn sort_key(&self) -> (ast::DefId, ast::Name) { + (self.trait_ref.def_id, self.item_name) + } +} + pub trait ToPolyTraitRef<'tcx> { fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx>; } @@ -2675,8 +2691,11 @@ pub fn mk_ctor_fn<'tcx>(cx: &ctxt<'tcx>, pub fn mk_trait<'tcx>(cx: &ctxt<'tcx>, principal: ty::PolyTraitRef<'tcx>, - bounds: ExistentialBounds) - -> Ty<'tcx> { + bounds: ExistentialBounds<'tcx>) + -> Ty<'tcx> +{ + assert!(bound_list_is_sorted(bounds.projection_bounds.as_slice())); + let inner = box TyTrait { principal: principal, bounds: bounds @@ -2684,6 +2703,16 @@ pub fn mk_trait<'tcx>(cx: &ctxt<'tcx>, mk_t(cx, ty_trait(inner)) } +fn bound_list_is_sorted(bounds: &[ty::PolyProjectionPredicate]) -> bool { + bounds.len() == 0 || + bounds[1..].iter().enumerate().all( + |(index, bound)| bounds[index].sort_key() <= bound.sort_key()) +} + +pub fn sort_bounds_list(bounds: &mut [ty::PolyProjectionPredicate]) { + bounds.sort_by(|a, b| a.sort_key().cmp(&b.sort_key())) +} + pub fn mk_projection<'tcx>(cx: &ctxt<'tcx>, trait_ref: Rc>, item_name: ast::Name) @@ -3226,7 +3255,7 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents { } } - ty_trait(box TyTrait { bounds, .. }) => { + ty_trait(box TyTrait { ref bounds, .. }) => { object_contents(bounds) | TC::ReachesFfiUnsafe | TC::Nonsized } @@ -3391,7 +3420,7 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents { fn closure_contents(cty: &ClosureTy) -> TypeContents { // Closure contents are just like trait contents, but with potentially // even more stuff. - let st = object_contents(cty.bounds); + let st = object_contents(&cty.bounds); let st = match cty.store { UniqTraitStore => { @@ -3405,7 +3434,7 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents { st } - fn object_contents(bounds: ExistentialBounds) -> TypeContents { + fn object_contents(bounds: &ExistentialBounds) -> TypeContents { // These are the type contents of the (opaque) interior. We // make no assumptions (other than that it cannot have an // in-scope type parameter within, which makes no sense). @@ -4205,6 +4234,7 @@ pub fn adjust_ty<'tcx, F>(cx: &ctxt<'tcx>, let bounds = ty::ExistentialBounds { region_bound: ReStatic, builtin_bounds: all_builtin_bounds(), + projection_bounds: vec!(), }; ty::mk_closure( @@ -4339,8 +4369,8 @@ pub fn unsize_ty<'tcx>(cx: &ctxt<'tcx>, format!("UnsizeStruct with bad sty: {}", ty_to_string(cx, ty))[]) }, - &UnsizeVtable(TyTrait { ref principal, bounds }, _) => { - mk_trait(cx, (*principal).clone(), bounds) + &UnsizeVtable(TyTrait { ref principal, ref bounds }, _) => { + mk_trait(cx, principal.clone(), bounds.clone()) } } } @@ -4760,6 +4790,16 @@ pub fn type_err_to_str<'tcx>(cx: &ctxt<'tcx>, err: &type_err<'tcx>) -> String { if values.expected { "converging" } else { "diverging" }, if values.found { "converging" } else { "diverging" }) } + terr_projection_name_mismatched(ref values) => { + format!("expected {}, found {}", + token::get_name(values.expected), + token::get_name(values.found)) + } + terr_projection_bounds_length(ref values) => { + format!("expected {} associated type bindings, found {}", + values.expected, + values.found) + } } } diff --git a/src/librustc/middle/ty_fold.rs b/src/librustc/middle/ty_fold.rs index 4ef597d21081e..3aff69c017846 100644 --- a/src/librustc/middle/ty_fold.rs +++ b/src/librustc/middle/ty_fold.rs @@ -121,8 +121,8 @@ pub trait TypeFolder<'tcx> { super_fold_trait_store(self, s) } - fn fold_existential_bounds(&mut self, s: ty::ExistentialBounds) - -> ty::ExistentialBounds { + fn fold_existential_bounds(&mut self, s: &ty::ExistentialBounds<'tcx>) + -> ty::ExistentialBounds<'tcx> { super_fold_existential_bounds(self, s) } @@ -349,9 +349,9 @@ impl<'tcx> TypeFoldable<'tcx> for ty::BuiltinBounds { } } -impl<'tcx> TypeFoldable<'tcx> for ty::ExistentialBounds { - fn fold_with>(&self, folder: &mut F) -> ty::ExistentialBounds { - folder.fold_existential_bounds(*self) +impl<'tcx> TypeFoldable<'tcx> for ty::ExistentialBounds<'tcx> { + fn fold_with>(&self, folder: &mut F) -> ty::ExistentialBounds<'tcx> { + folder.fold_existential_bounds(self) } } @@ -449,7 +449,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::UnsizeKind<'tcx> { match *self { ty::UnsizeLength(len) => ty::UnsizeLength(len), ty::UnsizeStruct(box ref k, n) => ty::UnsizeStruct(box k.fold_with(folder), n), - ty::UnsizeVtable(ty::TyTrait{ref principal, bounds}, self_ty) => { + ty::UnsizeVtable(ty::TyTrait{ref principal, ref bounds}, self_ty) => { ty::UnsizeVtable( ty::TyTrait { principal: principal.fold_with(folder), @@ -565,9 +565,9 @@ pub fn super_fold_ty<'tcx, T: TypeFolder<'tcx>>(this: &mut T, let substs = substs.fold_with(this); ty::ty_enum(tid, this.tcx().mk_substs(substs)) } - ty::ty_trait(box ty::TyTrait { ref principal, bounds }) => { + ty::ty_trait(box ty::TyTrait { ref principal, ref bounds }) => { ty::ty_trait(box ty::TyTrait { - principal: (*principal).fold_with(this), + principal: principal.fold_with(this), bounds: bounds.fold_with(this), }) } @@ -693,12 +693,15 @@ pub fn super_fold_trait_store<'tcx, T: TypeFolder<'tcx>>(this: &mut T, } } -pub fn super_fold_existential_bounds<'tcx, T: TypeFolder<'tcx>>(this: &mut T, - bounds: ty::ExistentialBounds) - -> ty::ExistentialBounds { +pub fn super_fold_existential_bounds<'tcx, T: TypeFolder<'tcx>>( + this: &mut T, + bounds: &ty::ExistentialBounds<'tcx>) + -> ty::ExistentialBounds<'tcx> +{ ty::ExistentialBounds { region_bound: bounds.region_bound.fold_with(this), builtin_bounds: bounds.builtin_bounds, + projection_bounds: bounds.projection_bounds.fold_with(this), } } diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 134a47225072d..3e7b24ac93f9e 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -739,8 +739,8 @@ impl<'tcx> Repr<'tcx> for ty::BuiltinBounds { } } -impl<'tcx> Repr<'tcx> for ty::ExistentialBounds { - fn repr(&self, tcx: &ctxt) -> String { +impl<'tcx> Repr<'tcx> for ty::ExistentialBounds<'tcx> { + fn repr(&self, tcx: &ctxt<'tcx>) -> String { self.user_string(tcx) } } @@ -1142,8 +1142,8 @@ impl<'tcx> UserString<'tcx> for ty::ParamBounds<'tcx> { } } -impl<'tcx> UserString<'tcx> for ty::ExistentialBounds { - fn user_string(&self, tcx: &ctxt) -> String { +impl<'tcx> UserString<'tcx> for ty::ExistentialBounds<'tcx> { + fn user_string(&self, tcx: &ctxt<'tcx>) -> String { if self.builtin_bounds.contains(&ty::BoundSend) && self.region_bound == ty::ReStatic { // Region bound is implied by builtin bounds: diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 26959dfd1d524..26fadb0dfb102 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -810,11 +810,13 @@ pub fn ast_ty_to_builtin_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( } } +type TraitAndProjections<'tcx> = (ty::PolyTraitRef<'tcx>, Vec>); + fn ast_ty_to_trait_ref<'tcx,AC,RS>(this: &AC, rscope: &RS, ty: &ast::Ty, bounds: &[ast::TyParamBound]) - -> Result, ErrorReported> + -> Result, ErrorReported> where AC : AstConv<'tcx>, RS : RegionScope { /*! @@ -832,14 +834,17 @@ fn ast_ty_to_trait_ref<'tcx,AC,RS>(this: &AC, ast::TyPath(ref path, id) => { match this.tcx().def_map.borrow().get(&id) { Some(&def::DefTrait(trait_def_id)) => { - // TODO do something with this - let mut projections = Vec::new(); - Ok(ty::Binder(ast_path_to_trait_ref(this, - rscope, - trait_def_id, - None, - path, - Some(&mut projections)))) + 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(); + Ok((trait_ref, projection_bounds)) } _ => { span_err!(this.tcx().sess, ty.span, E0172, "expected a reference to a trait"); @@ -882,6 +887,7 @@ fn trait_ref_to_object_type<'tcx,AC,RS>(this: &AC, rscope: &RS, span: Span, trait_ref: ty::PolyTraitRef<'tcx>, + projection_bounds: Vec>, bounds: &[ast::TyParamBound]) -> Ty<'tcx> where AC : AstConv<'tcx>, RS : RegionScope @@ -890,6 +896,7 @@ fn trait_ref_to_object_type<'tcx,AC,RS>(this: &AC, rscope, span, Some(trait_ref.clone()), + projection_bounds, bounds); let result = ty::mk_trait(this.tcx(), trait_ref, existential_bounds); @@ -1019,9 +1026,9 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( } ast::TyObjectSum(ref ty, ref bounds) => { match ast_ty_to_trait_ref(this, rscope, &**ty, bounds[]) { - Ok(trait_ref) => { + Ok((trait_ref, projection_bounds)) => { trait_ref_to_object_type(this, rscope, ast_ty.span, - trait_ref, bounds[]) + trait_ref, projection_bounds, bounds[]) } Err(ErrorReported) => { this.tcx().types.err @@ -1062,13 +1069,15 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( rscope, ast_ty.span, None, + Vec::new(), f.bounds.as_slice()); + let region_bound = bounds.region_bound; let fn_decl = ty_of_closure(this, f.unsafety, f.onceness, bounds, ty::RegionTraitStore( - bounds.region_bound, + region_bound, ast::MutMutable), &*f.decl, abi::Rust, @@ -1092,15 +1101,19 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( def::DefTrait(trait_def_id) => { // N.B. this case overlaps somewhat with // TyObjectSum, see that fn for details - let mut projections = Vec::new(); // TODO + let mut projection_bounds = Vec::new(); let trait_ref = ast_path_to_trait_ref(this, rscope, trait_def_id, None, path, - Some(&mut projections)); + Some(&mut projection_bounds)); let trait_ref = ty::Binder(trait_ref); - trait_ref_to_object_type(this, rscope, path.span, trait_ref, &[]) + let projection_bounds = projection_bounds.into_iter() + .map(ty::Binder) + .collect(); + trait_ref_to_object_type(this, rscope, path.span, + trait_ref, projection_bounds, &[]) } def::DefTy(did, _) | def::DefStruct(did) => { ast_path_to_ty(this, rscope, did, path).ty @@ -1437,7 +1450,7 @@ pub fn ty_of_closure<'tcx, AC: AstConv<'tcx>>( this: &AC, unsafety: ast::Unsafety, onceness: ast::Onceness, - bounds: ty::ExistentialBounds, + bounds: ty::ExistentialBounds<'tcx>, store: ty::TraitStore, decl: &ast::FnDecl, abi: abi::Abi, @@ -1500,14 +1513,15 @@ pub fn conv_existential_bounds<'tcx, AC: AstConv<'tcx>, RS:RegionScope>( rscope: &RS, span: Span, principal_trait_ref: Option>, // None for boxed closures + projection_bounds: Vec>, ast_bounds: &[ast::TyParamBound]) - -> ty::ExistentialBounds + -> ty::ExistentialBounds<'tcx> { let partitioned_bounds = partition_bounds(this.tcx(), span, ast_bounds); conv_existential_bounds_from_partitioned_bounds( - this, rscope, span, principal_trait_ref, partitioned_bounds) + this, rscope, span, principal_trait_ref, projection_bounds, partitioned_bounds) } fn conv_ty_poly_trait_ref<'tcx, AC, RS>( @@ -1520,14 +1534,14 @@ fn conv_ty_poly_trait_ref<'tcx, AC, RS>( { let mut partitioned_bounds = partition_bounds(this.tcx(), span, ast_bounds[]); - let mut projections = Vec::new(); + let mut projection_bounds = Vec::new(); let main_trait_bound = match partitioned_bounds.trait_bounds.remove(0) { Some(trait_bound) => { let ptr = instantiate_poly_trait_ref(this, rscope, trait_bound, None, - &mut projections); + &mut projection_bounds); Some(ptr) } None => { @@ -1538,13 +1552,12 @@ fn conv_ty_poly_trait_ref<'tcx, AC, RS>( } }; - // TODO use projections somewhere - let bounds = conv_existential_bounds_from_partitioned_bounds(this, rscope, span, main_trait_bound.clone(), + projection_bounds, partitioned_bounds); match main_trait_bound { @@ -1558,8 +1571,9 @@ pub fn conv_existential_bounds_from_partitioned_bounds<'tcx, AC, RS>( rscope: &RS, span: Span, principal_trait_ref: Option>, // None for boxed closures + mut projection_bounds: Vec>, // Empty for boxed closures partitioned_bounds: PartitionedBounds) - -> ty::ExistentialBounds + -> ty::ExistentialBounds<'tcx> where AC: AstConv<'tcx>, RS:RegionScope { let PartitionedBounds { builtin_bounds, @@ -1582,9 +1596,12 @@ pub fn conv_existential_bounds_from_partitioned_bounds<'tcx, AC, RS>( principal_trait_ref, builtin_bounds); + ty::sort_bounds_list(projection_bounds.as_mut_slice()); + ty::ExistentialBounds { region_bound: region_bound, builtin_bounds: builtin_bounds, + projection_bounds: projection_bounds, } } diff --git a/src/librustc_typeck/check/assoc.rs b/src/librustc_typeck/check/assoc.rs index fbc6d49d6e9a8..e737bb1b237fb 100644 --- a/src/librustc_typeck/check/assoc.rs +++ b/src/librustc_typeck/check/assoc.rs @@ -15,7 +15,6 @@ use middle::ty::{mod, HasProjectionTypes, Ty}; use middle::ty_fold::{mod, TypeFoldable, TypeFolder}; use syntax::ast; use syntax::codemap::Span; -use std::rc::Rc; pub fn normalize_associated_types_in<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>, fulfillment_cx: &mut FulfillmentContext<'tcx>, diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index ec964ab638f14..19108ca710bc1 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -289,7 +289,7 @@ fn check_boxed_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, (&ty::UniqTraitStore, _) => ast::Once, (&ty::RegionTraitStore(..), _) => ast::Many, }; - (Some(sig), onceness, cenv.bounds) + (Some(sig), onceness, cenv.bounds.clone()) } _ => { // Not an error! Means we're inferring the closure type diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index b8cf215f89eec..1da8852c9b23c 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -768,7 +768,7 @@ fn constrain_cast(rcx: &mut Rcx, } /*From:*/ (_, - /*To: */ &ty::ty_trait(box ty::TyTrait { bounds, .. })) => { + /*To: */ &ty::ty_trait(box ty::TyTrait { ref bounds, .. })) => { // When T is existentially quantified as a trait // `Foo+'to`, it must outlive the region bound `'to`. type_must_outlive(rcx, infer::RelateObjectBound(cast_expr.span), @@ -851,7 +851,7 @@ fn check_expr_fn_block(rcx: &mut Rcx, } match function_type.sty { - ty::ty_closure(box ty::ClosureTy {bounds, ..}) => { + ty::ty_closure(box ty::ClosureTy {ref bounds, ..}) => { ty::with_freevars(tcx, expr.id, |freevars| { ensure_free_variable_types_outlive_closure_bound(rcx, bounds, expr, freevars); }) @@ -859,7 +859,7 @@ fn check_expr_fn_block(rcx: &mut Rcx, ty::ty_unboxed_closure(_, region, _) => { ty::with_freevars(tcx, expr.id, |freevars| { let bounds = ty::region_existential_bound(*region); - ensure_free_variable_types_outlive_closure_bound(rcx, bounds, expr, freevars); + ensure_free_variable_types_outlive_closure_bound(rcx, &bounds, expr, freevars); }) } _ => {} @@ -870,7 +870,7 @@ fn check_expr_fn_block(rcx: &mut Rcx, /// over values outliving the object's lifetime bound. fn ensure_free_variable_types_outlive_closure_bound( rcx: &mut Rcx, - bounds: ty::ExistentialBounds, + bounds: &ty::ExistentialBounds, expr: &ast::Expr, freevars: &[ty::Freevar]) { diff --git a/src/librustc_typeck/check/vtable.rs b/src/librustc_typeck/check/vtable.rs index 98badf9c04996..5cf759a4dce66 100644 --- a/src/librustc_typeck/check/vtable.rs +++ b/src/librustc_typeck/check/vtable.rs @@ -244,7 +244,7 @@ pub fn register_object_cast_obligations<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, let object_trait_ty = ty::mk_trait(fcx.tcx(), object_trait.principal.clone(), - object_trait.bounds); + object_trait.bounds.clone()); debug!("register_object_cast_obligations: referent_ty={} object_trait_ty={}", referent_ty.repr(fcx.tcx()), diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index d5ffce8db78f8..5063ce36019d1 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -500,13 +500,14 @@ impl Clean for ast::TyParamBound { } } -impl Clean> for ty::ExistentialBounds { +impl<'tcx> Clean> for ty::ExistentialBounds<'tcx> { fn clean(&self, cx: &DocContext) -> Vec { let mut vec = vec![]; self.region_bound.clean(cx).map(|b| vec.push(RegionBound(b))); for bb in self.builtin_bounds.iter() { vec.push(bb.clean(cx)); } + // TODO projection bounds vec } } @@ -1441,18 +1442,11 @@ impl<'tcx> Clean for ty::Ty<'tcx> { } } ty::ty_struct(did, substs) | - ty::ty_enum(did, substs) | - ty::ty_trait(box ty::TyTrait { - principal: ty::Binder(ty::TraitRef { def_id: did, substs }), - .. }) => - { + ty::ty_enum(did, substs) => { let fqn = csearch::get_item_path(cx.tcx(), did); - let fqn: Vec = fqn.into_iter().map(|i| { - i.to_string() - }).collect(); + let fqn: Vec<_> = fqn.into_iter().map(|i| i.to_string()).collect(); let kind = match self.sty { ty::ty_struct(..) => TypeStruct, - ty::ty_trait(..) => TypeTrait, _ => TypeEnum, }; let path = external_path(cx, fqn.last().unwrap().to_string().as_slice(), @@ -1464,11 +1458,24 @@ impl<'tcx> Clean for ty::Ty<'tcx> { did: did, } } + ty::ty_trait(box ty::TyTrait { ref principal, ref bounds }) => { + let did = principal.def_id(); + let fqn = csearch::get_item_path(cx.tcx(), did); + let fqn: Vec<_> = fqn.into_iter().map(|i| i.to_string()).collect(); + let path = external_path(cx, fqn.last().unwrap().to_string().as_slice(), + Some(did), principal.substs()); + cx.external_paths.borrow_mut().as_mut().unwrap().insert(did, (fqn, TypeTrait)); + ResolvedPath { + path: path, + typarams: Some(bounds.clean(cx)), + did: did, + } + } ty::ty_tup(ref t) => Tuple(t.clean(cx)), ty::ty_projection(ref data) => { let trait_ref = match data.trait_ref.clean(cx) { - TyParamBound::TraitBound(t) => t, + TyParamBound::TraitBound(t) => t.trait_, TyParamBound::RegionBound(_) => panic!("cleaning a trait got a region??"), }; Type::QPath { From 5b53b11ad9aed822ce4c573714de6cb28289f321 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 26 Dec 2014 06:40:25 -0500 Subject: [PATCH 11/36] Allow object safe traits to access associated types. --- src/librustc_typeck/check/vtable.rs | 103 ++++++++++++++++++++++++++-- 1 file changed, 98 insertions(+), 5 deletions(-) diff --git a/src/librustc_typeck/check/vtable.rs b/src/librustc_typeck/check/vtable.rs index 5cf759a4dce66..e8bd5c088fca7 100644 --- a/src/librustc_typeck/check/vtable.rs +++ b/src/librustc_typeck/check/vtable.rs @@ -9,7 +9,7 @@ // except according to those terms. use check::{FnCtxt, structurally_resolved_type}; -use middle::subst::{FnSpace}; +use middle::subst::{FnSpace, SelfSpace}; use middle::traits; use middle::traits::{Obligation, ObligationCause}; use middle::traits::report_fulfillment_errors; @@ -141,15 +141,15 @@ pub fn check_object_safety<'tcx>(tcx: &ty::ctxt<'tcx>, } fn check_object_safety_inner<'tcx>(tcx: &ty::ctxt<'tcx>, - object_trait: &ty::PolyTraitRef<'tcx>, - span: Span) { + object_trait: &ty::PolyTraitRef<'tcx>, + span: Span) { let trait_items = ty::trait_items(tcx, object_trait.def_id()); let mut errors = Vec::new(); for item in trait_items.iter() { match *item { ty::MethodTraitItem(ref m) => { - errors.push(check_object_safety_of_method(tcx, &**m)) + errors.push(check_object_safety_of_method(tcx, object_trait, &**m)) } ty::TypeTraitItem(_) => {} } @@ -173,6 +173,7 @@ fn check_object_safety_inner<'tcx>(tcx: &ty::ctxt<'tcx>, /// type is not known (that's the whole point of a trait instance, after all, to obscure the /// self type) and (b) the call must go through a vtable and hence cannot be monomorphized. fn check_object_safety_of_method<'tcx>(tcx: &ty::ctxt<'tcx>, + object_trait: &ty::PolyTraitRef<'tcx>, method: &ty::Method<'tcx>) -> Vec { let mut msgs = Vec::new(); @@ -196,7 +197,7 @@ fn check_object_safety_inner<'tcx>(tcx: &ty::ctxt<'tcx>, // reason (a) above let check_for_self_ty = |ty| { - if ty::type_has_self(ty) { + if contains_illegal_self_type_reference(tcx, object_trait.def_id(), ty) { Some(format!( "cannot call a method (`{}`) whose type contains \ a self-type (`{}`) through a trait object", @@ -225,6 +226,98 @@ fn check_object_safety_inner<'tcx>(tcx: &ty::ctxt<'tcx>, msgs } + + fn contains_illegal_self_type_reference<'tcx>(tcx: &ty::ctxt<'tcx>, + trait_def_id: ast::DefId, + ty: Ty<'tcx>) + -> bool + { + // This is somewhat subtle. In general, we want to forbid + // references to `Self` in the argument and return types, + // since the value of `Self` is erased. However, there is one + // exception: it is ok to reference `Self` in order to access + // an associated type of the current trait, since we retain + // the value of those associated types in the object type + // itself. + // + // ```rust + // trait SuperTrait { + // type X; + // } + // + // trait Trait : SuperTrait { + // type Y; + // fn foo(&self, x: Self) // bad + // fn foo(&self) -> Self // bad + // fn foo(&self) -> Option // bad + // fn foo(&self) -> Self::Y // OK, desugars to next example + // fn foo(&self) -> ::Y // OK + // fn foo(&self) -> Self::X // OK, desugars to next example + // fn foo(&self) -> ::X // OK + // } + // ``` + // + // However, it is not as simple as allowing `Self` in a projected + // type, because there are illegal ways to use `Self` as well: + // + // ```rust + // trait Trait : SuperTrait { + // ... + // fn foo(&self) -> ::X; + // } + // ``` + // + // Here we will not have the type of `X` recorded in the + // object type, and we cannot resolve `Self as SomeOtherTrait` + // without knowing what `Self` is. + + let mut supertraits: Option>> = None; + let mut error = false; + ty::maybe_walk_ty(ty, |ty| { + match ty.sty { + ty::ty_param(ref param_ty) => { + if param_ty.space == SelfSpace { + error = true; + } + + false // no contained types to walk + } + + ty::ty_projection(ref data) => { + // This is a projected type `::X`. + + // Compute supertraits of current trait lazilly. + if supertraits.is_none() { + let trait_def = ty::lookup_trait_def(tcx, trait_def_id); + let trait_ref = ty::Binder(trait_def.trait_ref.clone()); + supertraits = Some(traits::supertraits(tcx, trait_ref).collect()); + } + + // Determine whether the trait reference `Foo as + // SomeTrait` is in fact a supertrait of the + // current trait. In that case, this type is + // legal, because the type `X` will be specified + // in the object type. Note that we can just use + // direct equality here because all of these types + // are part of the formal parameter listing, and + // hence there should be no inference variables. + let projection_trait_ref = ty::Binder(data.trait_ref.clone()); + let is_supertrait_of_current_trait = + supertraits.as_ref().unwrap().contains(&projection_trait_ref); + + if is_supertrait_of_current_trait { + false // do not walk contained types, do not report error, do collect $200 + } else { + true // DO walk contained types, POSSIBLY reporting an error + } + } + + _ => true, // walk contained types, if any + } + }); + + error + } } pub fn register_object_cast_obligations<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, From de806bc057caa599fce959ce56259e6e919f1041 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 26 Dec 2014 07:07:55 -0500 Subject: [PATCH 12/36] Teach `project` to project associated types out of object types. --- src/librustc/middle/traits/project.rs | 55 ++++++++++++++++++++++++--- src/librustc/middle/ty.rs | 25 ++++++++++++ src/librustc_typeck/check/vtable.rs | 53 ++++++++++++++++++++------ 3 files changed, 116 insertions(+), 17 deletions(-) diff --git a/src/librustc/middle/traits/project.rs b/src/librustc/middle/traits/project.rs index 083227d02bd06..0594c0ac3b833 100644 --- a/src/librustc/middle/traits/project.rs +++ b/src/librustc/middle/traits/project.rs @@ -19,7 +19,7 @@ use super::VtableImplData; use middle::infer; use middle::subst::Subst; -use middle::ty::{mod, ToPolyTraitRef, Ty}; +use middle::ty::{mod, AsPredicate, ToPolyTraitRef, Ty}; use std::fmt; use util::ppaux::Repr; @@ -46,7 +46,7 @@ pub enum ProjectionError<'tcx> { #[deriving(Clone)] pub struct MismatchedProjectionTypes<'tcx> { - pub err: ty::type_err<'tcx> // TODO expected/actual/etc + pub err: ty::type_err<'tcx> } pub type ProjectionResult<'tcx, T> = Result>; @@ -123,9 +123,20 @@ pub fn project_type<'cx,'tcx>( obligation, &mut candidates); - let () = try!(assemble_candidates_from_impls(selcx, - obligation, - &mut candidates)); + let () = assemble_candidates_from_object_type(selcx, + obligation, + &mut candidates); + + if candidates.vec.is_empty() { + // TODO This `if` is not necessarily wrong, but it needs an + // explanation, and it should probably be accompanied by a + // similar rule in `select.rs`. Currently it's *needed* + // because the impl-trait-for-trait branch has not landed. + + let () = try!(assemble_candidates_from_impls(selcx, + obligation, + &mut candidates)); + } debug!("{} candidates, ambiguous={}", candidates.vec.len(), @@ -155,9 +166,21 @@ fn assemble_candidates_from_param_env<'cx,'tcx>( obligation: &ProjectionTyObligation<'tcx>, candidate_set: &mut ProjectionTyCandidateSet<'tcx>) { - let infcx = selcx.infcx(); let env_predicates = selcx.param_env().caller_bounds.predicates.clone(); let env_predicates = env_predicates.iter().cloned().collect(); + assemble_candidates_from_predicates(selcx, obligation, candidate_set, env_predicates); +} + +fn assemble_candidates_from_predicates<'cx,'tcx>( + selcx: &mut SelectionContext<'cx,'tcx>, + obligation: &ProjectionTyObligation<'tcx>, + candidate_set: &mut ProjectionTyCandidateSet<'tcx>, + env_predicates: Vec>) +{ + debug!("assemble_candidates_from_predicates(obligation={}, env_predicates={})", + obligation.repr(selcx.tcx()), + env_predicates.repr(selcx.tcx())); + let infcx = selcx.infcx(); for predicate in elaborate_predicates(selcx.tcx(), env_predicates) { match predicate { ty::Predicate::Projection(ref data) => { @@ -183,6 +206,26 @@ fn assemble_candidates_from_param_env<'cx,'tcx>( } } +fn assemble_candidates_from_object_type<'cx,'tcx>( + selcx: &mut SelectionContext<'cx,'tcx>, + obligation: &ProjectionTyObligation<'tcx>, + candidate_set: &mut ProjectionTyCandidateSet<'tcx>) +{ + let infcx = selcx.infcx(); + let trait_ref = infcx.resolve_type_vars_if_possible(&obligation.predicate.trait_ref); + debug!("assemble_candidates_from_object_type(trait_ref={})", + trait_ref.repr(infcx.tcx)); + let self_ty = trait_ref.self_ty(); + let data = match self_ty.sty { + ty::ty_trait(ref data) => data, + _ => { return; } + }; + let env_predicates = data.projection_bounds_with_self_ty(self_ty).iter() + .map(|p| p.as_predicate()) + .collect(); + assemble_candidates_from_predicates(selcx, obligation, candidate_set, env_predicates) +} + fn assemble_candidates_from_impls<'cx,'tcx>( selcx: &mut SelectionContext<'cx,'tcx>, obligation: &ProjectionTyObligation<'tcx>, diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index e989f5a2cc2b4..98539b4d15260 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -1401,6 +1401,31 @@ impl<'tcx> TyTrait<'tcx> { substs: tcx.mk_substs(self.principal.0.substs.with_self_ty(self_ty)), })) } + + pub fn projection_bounds_with_self_ty(&self, self_ty: Ty<'tcx>) + -> Vec> + { + // otherwise the escaping regions would be captured by the binders + assert!(!self_ty.has_escaping_regions()); + + self.bounds.projection_bounds.iter() + .map(|in_poly_projection_predicate| { + let in_projection_ty = &in_poly_projection_predicate.0.projection_ty; + let trait_ref = + Rc::new(ty::TraitRef::new( + in_projection_ty.trait_ref.def_id, + in_projection_ty.trait_ref.substs.with_self_ty(self_ty))); + let projection_ty = ty::ProjectionTy { + trait_ref: trait_ref, + item_name: in_projection_ty.item_name + }; + ty::Binder(ty::ProjectionPredicate { + projection_ty: projection_ty, + ty: in_poly_projection_predicate.0.ty + }) + }) + .collect() + } } /// A complete reference to a trait. These take numerous guises in syntax, diff --git a/src/librustc_typeck/check/vtable.rs b/src/librustc_typeck/check/vtable.rs index e8bd5c088fca7..f5cbfcdcc5216 100644 --- a/src/librustc_typeck/check/vtable.rs +++ b/src/librustc_typeck/check/vtable.rs @@ -13,12 +13,12 @@ use middle::subst::{FnSpace, SelfSpace}; use middle::traits; use middle::traits::{Obligation, ObligationCause}; use middle::traits::report_fulfillment_errors; -use middle::ty::{mod, Ty, AsPredicate, ToPolyTraitRef}; +use middle::ty::{mod, Ty, AsPredicate}; use middle::infer; -use std::rc::Rc; use syntax::ast; use syntax::codemap::Span; -use util::ppaux::{Repr, ty_to_string}; +use util::nodemap::FnvHashSet; +use util::ppaux::{Repr, UserString}; pub fn check_object_cast<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, cast_expr: &ast::Expr, @@ -133,10 +133,33 @@ pub fn check_object_safety<'tcx>(tcx: &ty::ctxt<'tcx>, object_trait: &ty::TyTrait<'tcx>, span: Span) { + // Also check that the type `object_trait` specifies all + // associated types for all supertraits. + let mut associated_types: FnvHashSet<(ast::DefId, ast::Name)> = FnvHashSet::new(); + let object_trait_ref = object_trait.principal_trait_ref_with_self_ty(tcx, tcx.types.err); - for tr in traits::supertraits(tcx, object_trait_ref) { + for tr in traits::supertraits(tcx, object_trait_ref.clone()) { check_object_safety_inner(tcx, &tr, span); + + let trait_def = ty::lookup_trait_def(tcx, object_trait_ref.def_id()); + for &associated_type_name in trait_def.associated_type_names.iter() { + associated_types.insert((object_trait_ref.def_id(), associated_type_name)); + } + } + + for projection_bound in object_trait.bounds.projection_bounds.iter() { + let pair = (projection_bound.0.projection_ty.trait_ref.def_id, + projection_bound.0.projection_ty.item_name); + associated_types.remove(&pair); + } + + for (trait_def_id, name) in associated_types.into_iter() { + tcx.sess.span_err( + span, + format!("the value of the associated type `{}` (from the trait `{}`) must be specified", + name.user_string(tcx), + ty::item_path_str(tcx, trait_def_id)).as_slice()); } } @@ -201,7 +224,7 @@ fn check_object_safety_inner<'tcx>(tcx: &ty::ctxt<'tcx>, Some(format!( "cannot call a method (`{}`) whose type contains \ a self-type (`{}`) through a trait object", - method_name, ty_to_string(tcx, ty))) + method_name, ty.user_string(tcx))) } else { None } @@ -343,15 +366,15 @@ pub fn register_object_cast_obligations<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, referent_ty.repr(fcx.tcx()), object_trait_ty.repr(fcx.tcx())); + let cause = ObligationCause::new(span, + fcx.body_id, + traits::ObjectCastObligation(object_trait_ty)); + // Create the obligation for casting from T to Trait. let object_trait_ref = object_trait.principal_trait_ref_with_self_ty(fcx.tcx(), referent_ty); let object_obligation = - Obligation::new( - ObligationCause::new(span, - fcx.body_id, - traits::ObjectCastObligation(object_trait_ty)), - object_trait_ref.as_predicate()); + Obligation::new(cause.clone(), object_trait_ref.as_predicate()); fcx.register_predicate(object_obligation); // Create additional obligations for all the various builtin @@ -362,7 +385,15 @@ pub fn register_object_cast_obligations<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, fcx.register_builtin_bound( referent_ty, builtin_bound, - ObligationCause::new(span, fcx.body_id, traits::ObjectCastObligation(object_trait_ty))); + cause.clone()); + } + + // Finally, create obligations for the projection predicates. + let projection_bounds = object_trait.projection_bounds_with_self_ty(referent_ty); + for projection_bound in projection_bounds.iter() { + let projection_obligation = + Obligation::new(cause.clone(), projection_bound.as_predicate()); + fcx.register_predicate(projection_obligation); } object_trait_ref From b7c6e317b0d45f2129885d9148180be93ed0b025 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sat, 27 Dec 2014 04:22:29 -0500 Subject: [PATCH 13/36] Make projected types select out of the trait bounds. --- src/librustc/middle/check_static.rs | 20 +- src/librustc/middle/subst.rs | 4 + src/librustc/middle/traits/fulfill.rs | 60 +++--- src/librustc/middle/traits/mod.rs | 24 +-- src/librustc/middle/traits/project.rs | 10 +- src/librustc/middle/traits/select.rs | 201 ++++++++++++++++-- src/librustc/middle/traits/util.rs | 49 +---- src/librustc/middle/ty_fold.rs | 10 +- src/librustc_trans/trans/common.rs | 2 +- src/librustc_trans/trans/meth.rs | 2 +- src/librustc_typeck/check/mod.rs | 6 +- src/librustc_typeck/collect.rs | 88 ++++++-- .../compile-fail/associated-types-path-2.rs | 9 +- 13 files changed, 321 insertions(+), 164 deletions(-) diff --git a/src/librustc/middle/check_static.rs b/src/librustc/middle/check_static.rs index e8df8e8402964..fb20df020acf8 100644 --- a/src/librustc/middle/check_static.rs +++ b/src/librustc/middle/check_static.rs @@ -31,7 +31,6 @@ use middle::infer; use middle::traits; use middle::mem_categorization as mc; use middle::expr_use_visitor as euv; -use util::common::ErrorReported; use util::nodemap::NodeSet; use syntax::ast; @@ -120,19 +119,14 @@ impl<'a, 'tcx> CheckStaticVisitor<'a, 'tcx> { let ty = ty::node_id_to_type(self.tcx, e.id); let infcx = infer::new_infer_ctxt(self.tcx); let mut fulfill_cx = traits::FulfillmentContext::new(); - match traits::poly_trait_ref_for_builtin_bound(self.tcx, ty::BoundSync, ty) { - Ok(trait_ref) => { - let cause = traits::ObligationCause::new(e.span, e.id, traits::SharedStatic); - fulfill_cx.register_trait_ref(self.tcx, trait_ref, cause); - let env = ty::empty_parameter_environment(); - match fulfill_cx.select_all_or_error(&infcx, &env, self.tcx) { - Ok(()) => { }, - Err(ref errors) => { - traits::report_fulfillment_errors(&infcx, errors); - } - } + let cause = traits::ObligationCause::new(e.span, e.id, traits::SharedStatic); + fulfill_cx.register_builtin_bound(&infcx, ty, ty::BoundSync, cause); + let env = ty::empty_parameter_environment(); + match fulfill_cx.select_all_or_error(&infcx, &env, self.tcx) { + Ok(()) => { }, + Err(ref errors) => { + traits::report_fulfillment_errors(&infcx, errors); } - Err(ErrorReported) => { } } } } diff --git a/src/librustc/middle/subst.rs b/src/librustc/middle/subst.rs index 8d920e0a8211f..a87db776ce053 100644 --- a/src/librustc/middle/subst.rs +++ b/src/librustc/middle/subst.rs @@ -412,6 +412,10 @@ impl VecPerParamSpace { self.content.as_slice() } + pub fn to_vec(self) -> Vec { + self.content + } + pub fn all_vecs

(&self, mut pred: P) -> bool where P: FnMut(&[T]) -> bool, { diff --git a/src/librustc/middle/traits/fulfill.rs b/src/librustc/middle/traits/fulfill.rs index 9cd1725e4df88..0d2023ead4fcc 100644 --- a/src/librustc/middle/traits/fulfill.rs +++ b/src/librustc/middle/traits/fulfill.rs @@ -119,43 +119,43 @@ impl<'tcx> FulfillmentContext<'tcx> { ty: ty_var }); let obligation = Obligation::new(cause, projection.as_predicate()); - self.register_predicate(infcx.tcx, obligation); + self.register_predicate(infcx, obligation); ty_var } - pub fn register_builtin_bound(&mut self, - tcx: &ty::ctxt<'tcx>, - ty: Ty<'tcx>, - builtin_bound: ty::BuiltinBound, - cause: ObligationCause<'tcx>) + pub fn register_builtin_bound<'a>(&mut self, + infcx: &InferCtxt<'a,'tcx>, + ty: Ty<'tcx>, + builtin_bound: ty::BuiltinBound, + cause: ObligationCause<'tcx>) { - match predicate_for_builtin_bound(tcx, cause, builtin_bound, 0, ty) { + match predicate_for_builtin_bound(infcx.tcx, cause, builtin_bound, 0, ty) { Ok(predicate) => { - self.register_predicate(tcx, predicate); + self.register_predicate(infcx, predicate); } Err(ErrorReported) => { } } } - pub fn register_region_obligation(&mut self, - tcx: &ty::ctxt<'tcx>, - t_a: Ty<'tcx>, - r_b: ty::Region, - cause: ObligationCause<'tcx>) + pub fn register_region_obligation<'a>(&mut self, + infcx: &InferCtxt<'a,'tcx>, + t_a: Ty<'tcx>, + r_b: ty::Region, + cause: ObligationCause<'tcx>) { - register_region_obligation(tcx, t_a, r_b, cause, &mut self.region_obligations); + register_region_obligation(infcx.tcx, t_a, r_b, cause, &mut self.region_obligations); } pub fn register_predicate<'a>(&mut self, - tcx: &ty::ctxt<'tcx>, + infcx: &InferCtxt<'a,'tcx>, obligation: PredicateObligation<'tcx>) { if !self.duplicate_set.insert(obligation.predicate.clone()) { - debug!("register_predicate({}) -- already seen, skip", obligation.repr(tcx)); + debug!("register_predicate({}) -- already seen, skip", obligation.repr(infcx.tcx)); return; } - debug!("register_predicate({})", obligation.repr(tcx)); + debug!("register_predicate({})", obligation.repr(infcx.tcx)); self.predicates.push(obligation); } @@ -230,7 +230,6 @@ impl<'tcx> FulfillmentContext<'tcx> { self.predicates.len(), only_new_obligations); - let tcx = selcx.tcx(); let mut errors = Vec::new(); loop { @@ -279,7 +278,7 @@ impl<'tcx> FulfillmentContext<'tcx> { // Now go through all the successful ones, // registering any nested obligations for the future. for new_obligation in new_obligations.into_iter() { - self.register_predicate(tcx, new_obligation); + self.register_predicate(selcx.infcx(), new_obligation); } } @@ -469,17 +468,22 @@ fn process_predicate<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>, CodeProjectionError(e))); true } - Err(project::ProjectionError::TraitSelectionError(e)) => { - // Extract just the `T : Trait` from `::Name == U`, so that when we report an - // error to the user, it says something like "`T : - // Trait` not satisfied".5D + Err(project::ProjectionError::TraitSelectionError(_)) => { + // There was an error matching `T : Trait` (which + // is a pre-requisite for `::Name` + // being valid). We could just report the error + // now, but that tends to lead to double error + // reports for the user (one for the obligation `T + // : Trait`, typically incurred somewhere else, + // and one from here). Instead, we'll create the + // `T : Trait` obligation and add THAT as a + // requirement. This will (eventually) trigger the + // same error, but it will also wind up flagged as + // a duplicate if another requirement that `T : + // Trait` arises from somewhere else. let trait_predicate = data.to_poly_trait_ref(); let trait_obligation = obligation.with(trait_predicate.as_predicate()); - errors.push( - FulfillmentError::new( - trait_obligation, - CodeSelectionError(e))); + new_obligations.push(trait_obligation); true } } diff --git a/src/librustc/middle/traits/mod.rs b/src/librustc/middle/traits/mod.rs index b7e2304849a14..d7febea8909b1 100644 --- a/src/librustc/middle/traits/mod.rs +++ b/src/librustc/middle/traits/mod.rs @@ -37,7 +37,6 @@ pub use self::util::elaborate_predicates; pub use self::util::trait_ref_for_builtin_bound; pub use self::util::supertraits; pub use self::util::Supertraits; -pub use self::util::search_trait_and_supertraits_from_bound; pub use self::util::transitive_bounds; mod coherence; @@ -189,10 +188,10 @@ pub type SelectionResult<'tcx, T> = Result, SelectionError<'tcx>>; /// /// // Case B: Vtable must be provided by caller. This applies when /// // type is a type parameter. -/// param.clone(); // VtableParam(Oblig_1) +/// param.clone(); // VtableParam /// /// // Case C: A mix of cases A and B. -/// mixed.clone(); // Vtable(Impl_1, [VtableParam(Oblig_1)]) +/// mixed.clone(); // Vtable(Impl_1, [VtableParam]) /// } /// ``` /// @@ -206,7 +205,7 @@ pub enum Vtable<'tcx, N> { /// Successful resolution to an obligation provided by the caller /// for some type parameter. - VtableParam(VtableParamData<'tcx>), + VtableParam, /// Successful resolution for a builtin trait. VtableBuiltin(VtableBuiltinData), @@ -243,15 +242,6 @@ pub struct VtableBuiltinData { pub nested: subst::VecPerParamSpace } -/// A vtable provided as a parameter by the caller. For example, in a -/// function like `fn foo(...)`, if the `eq()` method is invoked -/// on an instance of `T`, the vtable would be of type `VtableParam`. -#[deriving(PartialEq,Eq,Clone)] -pub struct VtableParamData<'tcx> { - // In the above example, this would `Eq` - pub bound: ty::PolyTraitRef<'tcx>, -} - /// True if neither the trait nor self type is local. Note that `impl_def_id` must refer to an impl /// of a trait, not an inherent impl. pub fn is_orphan_impl(tcx: &ty::ctxt, @@ -302,7 +292,7 @@ pub fn type_known_to_meet_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>, // (there shouldn't really be any anyhow). let cause = ObligationCause::misc(DUMMY_SP, ast::DUMMY_NODE_ID); - fulfill_cx.register_builtin_bound(infcx.tcx, ty, bound, cause); + fulfill_cx.register_builtin_bound(infcx, ty, bound, cause); // Note: we only assume something is `Copy` if we can // *definitively* show that it implements `Copy`. Otherwise, @@ -361,7 +351,7 @@ impl<'tcx, N> Vtable<'tcx, N> { VtableImpl(ref i) => i.iter_nested(), VtableFnPointer(..) => (&[]).iter(), VtableUnboxedClosure(..) => (&[]).iter(), - VtableParam(_) => (&[]).iter(), + VtableParam => (&[]).iter(), VtableBuiltin(ref i) => i.iter_nested(), } } @@ -371,7 +361,7 @@ impl<'tcx, N> Vtable<'tcx, N> { VtableImpl(ref i) => VtableImpl(i.map_nested(op)), VtableFnPointer(ref sig) => VtableFnPointer((*sig).clone()), VtableUnboxedClosure(d, ref s) => VtableUnboxedClosure(d, s.clone()), - VtableParam(ref p) => VtableParam((*p).clone()), + VtableParam => VtableParam, VtableBuiltin(ref b) => VtableBuiltin(b.map_nested(op)), } } @@ -383,7 +373,7 @@ impl<'tcx, N> Vtable<'tcx, N> { VtableImpl(i) => VtableImpl(i.map_move_nested(op)), VtableFnPointer(sig) => VtableFnPointer(sig), VtableUnboxedClosure(d, s) => VtableUnboxedClosure(d, s), - VtableParam(p) => VtableParam(p), + VtableParam => VtableParam, VtableBuiltin(no) => VtableBuiltin(no.map_move_nested(op)), } } diff --git a/src/librustc/middle/traits/project.rs b/src/librustc/middle/traits/project.rs index 0594c0ac3b833..43f97de2d4383 100644 --- a/src/librustc/middle/traits/project.rs +++ b/src/librustc/middle/traits/project.rs @@ -128,10 +128,12 @@ pub fn project_type<'cx,'tcx>( &mut candidates); if candidates.vec.is_empty() { - // TODO This `if` is not necessarily wrong, but it needs an - // explanation, and it should probably be accompanied by a - // similar rule in `select.rs`. Currently it's *needed* - // because the impl-trait-for-trait branch has not landed. + // FIXME(#20297) -- In `select.rs` there is similar logic that + // gives precedence to where-clauses, but it's a bit more + // fine-grained. I was lazy here and just always give + // precedence to where-clauses or other such sources over + // actually dredging through impls. This logic probably should + // be tightened up. let () = try!(assemble_candidates_from_impls(selcx, obligation, diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index 2a3bb3c80c894..2e4bdadb8c231 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -24,7 +24,7 @@ use super::{SelectionError, Unimplemented, Overflow, OutputTypeParameterMismatch use super::{Selection}; use super::{SelectionResult}; use super::{VtableBuiltin, VtableImpl, VtableParam, VtableUnboxedClosure, VtableFnPointer}; -use super::{VtableImplData, VtableParamData, VtableBuiltinData}; +use super::{VtableImplData, VtableBuiltinData}; use super::{util}; use middle::fast_reject; @@ -131,9 +131,13 @@ pub enum MethodMatchedData { #[deriving(PartialEq,Eq,Show,Clone)] enum SelectionCandidate<'tcx> { BuiltinCandidate(ty::BuiltinBound), - ParamCandidate(VtableParamData<'tcx>), + ParamCandidate(ty::PolyTraitRef<'tcx>), ImplCandidate(ast::DefId), + /// This is a trait matching with a projected type as `Self`, and + /// we found an applicable bound in the trait definition. + ProjectionCandidate, + /// Implementation of a `Fn`-family trait by one of the /// anonymous types generated for a `||` expression. UnboxedClosureCandidate(/* closure */ ast::DefId, Substs<'tcx>), @@ -507,8 +511,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let mut candidates = candidate_set.vec; - debug!("assembled {} candidates for {}", - candidates.len(), stack.repr(self.tcx())); + debug!("assembled {} candidates for {}: {}", + candidates.len(), + stack.repr(self.tcx()), + candidates.repr(self.tcx())); // At this point, we know that each of the entries in the // candidate set is *individually* applicable. Now we have to @@ -706,11 +712,137 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } + self.assemble_candidates_from_projected_tys(obligation, &mut candidates); try!(self.assemble_candidates_from_caller_bounds(obligation, &mut candidates)); debug!("candidate list size: {}", candidates.vec.len()); Ok(candidates) } + fn assemble_candidates_from_projected_tys(&mut self, + obligation: &TraitObligation<'tcx>, + candidates: &mut SelectionCandidateSet<'tcx>) + { + let poly_trait_predicate = + self.infcx().resolve_type_vars_if_possible(&obligation.predicate); + + debug!("assemble_candidates_for_projected_tys({},{})", + obligation.repr(self.tcx()), + poly_trait_predicate.repr(self.tcx())); + + // FIXME(#20297) -- just examining the self-type is very simplistic + + // before we go into the whole skolemization thing, just + // quickly check if the self-type is a projection at all. + let trait_def_id = match poly_trait_predicate.0.trait_ref.self_ty().sty { + ty::ty_projection(ref data) => data.trait_ref.def_id, + ty::ty_infer(ty::TyVar(_)) => { + // TODO ignore potential ambiguity so that we can do + // better inference, need to get our story + // straight(er) here, I think. + // candidates.ambiguous = true; + return; + } + _ => { return; } + }; + + debug!("assemble_candidates_for_projected_tys: trait_def_id={}", + trait_def_id.repr(self.tcx())); + + let result = self.infcx.probe(|snapshot| { + self.match_projection_obligation_against_bounds_from_trait(obligation, + snapshot) + }); + + if result { + candidates.vec.push(ProjectionCandidate); + } + } + + fn match_projection_obligation_against_bounds_from_trait( + &mut self, + obligation: &TraitObligation<'tcx>, + snapshot: &infer::CombinedSnapshot) + -> bool + { + let poly_trait_predicate = + self.infcx().resolve_type_vars_if_possible(&obligation.predicate); + let (skol_trait_predicate, skol_map) = + self.infcx().skolemize_late_bound_regions(&poly_trait_predicate, snapshot); + debug!("match_projection_obligation_against_bounds_from_trait: \ + skol_trait_predicate={} skol_map={}", + skol_trait_predicate.repr(self.tcx()), + skol_map.repr(self.tcx())); + + let projection_trait_ref = match skol_trait_predicate.trait_ref.self_ty().sty { + ty::ty_projection(ref data) => &data.trait_ref, + _ => { + self.tcx().sess.span_bug( + obligation.cause.span, + format!("match_projection_obligation_against_bounds_from_trait() called \ + but self-ty not a projection: {}", + skol_trait_predicate.trait_ref.self_ty().repr(self.tcx())).as_slice()); + } + }; + debug!("match_projection_obligation_against_bounds_from_trait: \ + projection_trait_ref={}", + projection_trait_ref.repr(self.tcx())); + + let trait_def = ty::lookup_trait_def(self.tcx(), projection_trait_ref.def_id); + let bounds = trait_def.generics.to_bounds(self.tcx(), &projection_trait_ref.substs); + debug!("match_projection_obligation_against_bounds_from_trait: \ + bounds={}", + bounds.repr(self.tcx())); + + let matching_bound = + util::elaborate_predicates(self.tcx(), bounds.predicates.to_vec()) + .filter_to_traits() + .find( + |bound| self.infcx.probe( + |_| self.match_projection(obligation, + bound.clone(), + skol_trait_predicate.trait_ref.clone(), + &skol_map, + snapshot))); + + debug!("match_projection_obligation_against_bounds_from_trait: \ + matching_bound={}", + matching_bound.repr(self.tcx())); + match matching_bound { + None => false, + Some(bound) => { + // Repeat the successful match, if any, this time outside of a probe. + let result = self.match_projection(obligation, + bound, + skol_trait_predicate.trait_ref.clone(), + &skol_map, + snapshot); + assert!(result); + true + } + } + } + + fn match_projection(&mut self, + obligation: &TraitObligation<'tcx>, + trait_bound: ty::PolyTraitRef<'tcx>, + skol_trait_ref: Rc>, + skol_map: &infer::SkolemizationMap, + snapshot: &infer::CombinedSnapshot) + -> bool + { + assert!(!skol_trait_ref.has_escaping_regions()); + let origin = infer::RelateOutputImplTypes(obligation.cause.span); + match self.infcx.sub_poly_trait_refs(false, + origin, + trait_bound.clone(), + ty::Binder(skol_trait_ref.clone())) { + Ok(()) => { } + Err(_) => { return false; } + } + + self.infcx.leak_check(skol_map, snapshot).is_ok() + } + /// Given an obligation like ``, search the obligations that the caller /// supplied to find out whether it is listed among them. /// @@ -738,8 +870,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { |_| self.match_where_clause(obligation, bound.clone())).is_ok()); let param_candidates = - matching_bounds.map( - |bound| ParamCandidate(VtableParamData { bound: bound })); + matching_bounds.map(|bound| ParamCandidate(bound)); candidates.vec.extend(param_candidates); @@ -933,7 +1064,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { -> bool { match (candidate_i, candidate_j) { - (&ImplCandidate(impl_def_id), &ParamCandidate(ref vt)) => { + (&ImplCandidate(impl_def_id), &ParamCandidate(ref bound)) => { debug!("Considering whether to drop param {} in favor of impl {}", candidate_i.repr(self.tcx()), candidate_j.repr(self.tcx())); @@ -954,10 +1085,23 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let origin = infer::RelateOutputImplTypes(stack.obligation.cause.span); self.infcx - .sub_poly_trait_refs(false, origin, poly_impl_trait_ref, vt.bound.clone()) + .sub_poly_trait_refs(false, origin, poly_impl_trait_ref, bound.clone()) .is_ok() }) } + (&ProjectionCandidate, &ParamCandidate(_)) => { + // FIXME(#20297) -- this gives where clauses precedent + // over projections. Really these are just two means + // of deducing information (one based on the where + // clauses on the trait definition; one based on those + // on the enclosing scope), and it'd be better to + // integrate them more intelligently. But for now this + // seems ok. If we DON'T give where clauses + // precedence, we run into trouble in default methods, + // where both the projection bounds for `Self::A` and + // the where clauses are in scope. + true + } _ => { *candidate_i == *candidate_j } @@ -1390,8 +1534,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } ParamCandidate(param) => { - Ok(VtableParam( - try!(self.confirm_param_candidate(obligation, param)))) + self.confirm_param_candidate(obligation, param); + Ok(VtableParam) } ImplCandidate(impl_def_id) => { @@ -1410,14 +1554,30 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { try!(self.confirm_fn_pointer_candidate(obligation)); Ok(VtableFnPointer(fn_type)) } + + ProjectionCandidate => { + self.confirm_projection_candidate(obligation); + Ok(VtableParam) + } } } + fn confirm_projection_candidate(&mut self, + obligation: &TraitObligation<'tcx>) + { + let _: Result<(),()> = + self.infcx.try(|snapshot| { + let result = + self.match_projection_obligation_against_bounds_from_trait(obligation, + snapshot); + assert!(result); + Ok(()) + }); + } + fn confirm_param_candidate(&mut self, obligation: &TraitObligation<'tcx>, - param: VtableParamData<'tcx>) - -> Result, - SelectionError<'tcx>> + param: ty::PolyTraitRef<'tcx>) { debug!("confirm_param_candidate({},{})", obligation.repr(self.tcx()), @@ -1429,12 +1589,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // transactional boundary; it should not fail. match self.confirm_poly_trait_refs(obligation.cause.clone(), obligation.predicate.to_poly_trait_ref(), - param.bound.clone()) { - Ok(()) => Ok(param), + param.clone()) { + Ok(()) => { } Err(_) => { self.tcx().sess.bug( format!("Where clause `{}` was applicable to `{}` but now is not", - param.bound.repr(self.tcx()), + param.repr(self.tcx()), obligation.repr(self.tcx())).as_slice()); } } @@ -1981,14 +2141,13 @@ impl<'tcx> Repr<'tcx> for SelectionCandidate<'tcx> { match *self { ErrorCandidate => format!("ErrorCandidate"), BuiltinCandidate(b) => format!("BuiltinCandidate({})", b), + ParamCandidate(ref a) => format!("ParamCandidate({})", a.repr(tcx)), + ImplCandidate(a) => format!("ImplCandidate({})", a.repr(tcx)), + ProjectionCandidate => format!("ProjectionCandidate"), + FnPointerCandidate => format!("FnPointerCandidate"), UnboxedClosureCandidate(c, ref s) => { format!("UnboxedClosureCandidate({},{})", c, s.repr(tcx)) } - FnPointerCandidate => { - format!("FnPointerCandidate") - } - ParamCandidate(ref a) => format!("ParamCandidate({})", a.repr(tcx)), - ImplCandidate(a) => format!("ImplCandidate({})", a.repr(tcx)), } } } diff --git a/src/librustc/middle/traits/util.rs b/src/librustc/middle/traits/util.rs index 00995e1ee43cf..95567d8240a2d 100644 --- a/src/librustc/middle/traits/util.rs +++ b/src/librustc/middle/traits/util.rs @@ -20,7 +20,7 @@ use util::common::ErrorReported; use util::ppaux::Repr; use super::{Obligation, ObligationCause, PredicateObligation, - VtableImpl, VtableParam, VtableParamData, VtableImplData}; + VtableImpl, VtableParam, VtableImplData}; /////////////////////////////////////////////////////////////////////////// // `Elaboration` iterator @@ -78,6 +78,10 @@ pub fn elaborate_predicates<'cx, 'tcx>( } impl<'cx, 'tcx> Elaborator<'cx, 'tcx> { + pub fn filter_to_traits(self) -> Supertraits<'cx, 'tcx> { + Supertraits { elaborator: self } + } + fn push(&mut self, predicate: &ty::Predicate<'tcx>) { match *predicate { ty::Predicate::Trait(ref data) => { @@ -183,16 +187,14 @@ pub fn supertraits<'cx, 'tcx>(tcx: &'cx ty::ctxt<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>) -> Supertraits<'cx, 'tcx> { - let elaborator = elaborate_trait_ref(tcx, trait_ref); - Supertraits { elaborator: elaborator } + elaborate_trait_ref(tcx, trait_ref).filter_to_traits() } pub fn transitive_bounds<'cx, 'tcx>(tcx: &'cx ty::ctxt<'tcx>, bounds: &[ty::PolyTraitRef<'tcx>]) -> Supertraits<'cx, 'tcx> { - let elaborator = elaborate_trait_refs(tcx, bounds); - Supertraits { elaborator: elaborator } + elaborate_trait_refs(tcx, bounds).filter_to_traits() } impl<'cx, 'tcx> Iterator> for Supertraits<'cx, 'tcx> { @@ -247,12 +249,6 @@ impl<'tcx, N> fmt::Show for VtableImplData<'tcx, N> { } } -impl<'tcx> fmt::Show for VtableParamData<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "VtableParam(...)") - } -} - /// See `super::obligations_for_generics` pub fn predicates_for_generics<'tcx>(tcx: &ty::ctxt<'tcx>, cause: ObligationCause<'tcx>, @@ -306,26 +302,6 @@ pub fn predicate_for_builtin_bound<'tcx>( }) } -/// Starting from a caller obligation `caller_bound` (which has coordinates `space`/`i` in the list -/// of caller obligations), search through the trait and supertraits to find one where `test(d)` is -/// true, where `d` is the def-id of the trait/supertrait. If any is found, return `Some(p)` where -/// `p` is the path to that trait/supertrait. Else `None`. -pub fn search_trait_and_supertraits_from_bound<'tcx,F>(tcx: &ty::ctxt<'tcx>, - caller_bound: ty::PolyTraitRef<'tcx>, - mut test: F) - -> Option> - where F: FnMut(ast::DefId) -> bool, -{ - for bound in transitive_bounds(tcx, &[caller_bound]) { - if test(bound.def_id()) { - let vtable_param = VtableParamData { bound: bound }; - return Some(vtable_param); - } - } - - return None; -} - impl<'tcx,O:Repr<'tcx>> Repr<'tcx> for super::Obligation<'tcx, O> { fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String { format!("Obligation(predicate={},depth={})", @@ -349,8 +325,8 @@ impl<'tcx, N:Repr<'tcx>> Repr<'tcx> for super::Vtable<'tcx, N> { format!("VtableFnPointer({})", d.repr(tcx)), - super::VtableParam(ref v) => - format!("VtableParam({})", v.repr(tcx)), + super::VtableParam => + format!("VtableParam"), super::VtableBuiltin(ref d) => d.repr(tcx) @@ -374,13 +350,6 @@ impl<'tcx, N:Repr<'tcx>> Repr<'tcx> for super::VtableBuiltinData { } } -impl<'tcx> Repr<'tcx> for super::VtableParamData<'tcx> { - fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String { - format!("VtableParam(bound={})", - self.bound.repr(tcx)) - } -} - impl<'tcx> Repr<'tcx> for super::SelectionError<'tcx> { fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String { match *self { diff --git a/src/librustc/middle/ty_fold.rs b/src/librustc/middle/ty_fold.rs index 3aff69c017846..1e7605c0f171c 100644 --- a/src/librustc/middle/ty_fold.rs +++ b/src/librustc/middle/ty_fold.rs @@ -501,20 +501,12 @@ impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Vtable<'tcx, N> traits::VtableFnPointer(ref d) => { traits::VtableFnPointer(d.fold_with(folder)) } - traits::VtableParam(ref p) => traits::VtableParam(p.fold_with(folder)), + traits::VtableParam => traits::VtableParam, traits::VtableBuiltin(ref d) => traits::VtableBuiltin(d.fold_with(folder)), } } } -impl<'tcx> TypeFoldable<'tcx> for traits::VtableParamData<'tcx> { - fn fold_with>(&self, folder: &mut F) -> traits::VtableParamData<'tcx> { - traits::VtableParamData { - bound: self.bound.fold_with(folder), - } - } -} - impl<'tcx> TypeFoldable<'tcx> for ty::EquatePredicate<'tcx> { fn fold_with>(&self, folder: &mut F) -> ty::EquatePredicate<'tcx> { ty::EquatePredicate(self.0.fold_with(folder), diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs index 694fbf251ddbf..06819aac5bc04 100644 --- a/src/librustc_trans/trans/common.rs +++ b/src/librustc_trans/trans/common.rs @@ -960,7 +960,7 @@ pub fn fulfill_obligation<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, // iterating early. let mut fulfill_cx = traits::FulfillmentContext::new(); let vtable = selection.map_move_nested(|predicate| { - fulfill_cx.register_predicate(infcx.tcx, predicate); + fulfill_cx.register_predicate(&infcx, predicate); }); match fulfill_cx.select_all_or_error(&infcx, ¶m_env, tcx) { Ok(()) => { } diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs index 00b17ca00dfb8..2ede6e2e47fd2 100644 --- a/src/librustc_trans/trans/meth.rs +++ b/src/librustc_trans/trans/meth.rs @@ -565,7 +565,7 @@ pub fn get_vtable<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let llfn = vec![trans_fn_pointer_shim(bcx.ccx(), bare_fn_ty)]; llfn.into_iter() } - traits::VtableParam(..) => { + traits::VtableParam => { bcx.sess().bug( format!("resolved vtable for {} to bad vtable {} in trans", trait_ref.repr(bcx.tcx()), diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index be8fa21cf0ee8..4bc1246d39359 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1871,7 +1871,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { cause: traits::ObligationCause<'tcx>) { self.inh.fulfillment_cx.borrow_mut() - .register_builtin_bound(self.tcx(), ty, builtin_bound, cause); + .register_builtin_bound(self.infcx(), ty, builtin_bound, cause); } pub fn register_predicate(&self, @@ -1882,7 +1882,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.inh.fulfillment_cx .borrow_mut() - .register_predicate(self.tcx(), obligation); + .register_predicate(self.infcx(), obligation); } pub fn to_ty(&self, ast_t: &ast::Ty) -> Ty<'tcx> { @@ -2026,7 +2026,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { cause: traits::ObligationCause<'tcx>) { let mut fulfillment_cx = self.inh.fulfillment_cx.borrow_mut(); - fulfillment_cx.register_region_obligation(self.tcx(), ty, region, cause); + fulfillment_cx.register_region_obligation(self.infcx(), ty, region, cause); } pub fn add_default_region_param_bounds(&self, diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index dfe54674d63ec..b311f10c0a320 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -842,16 +842,15 @@ pub fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, generics, items); + assert_eq!(mk_item_substs(ccx, &ty_generics), substs); + let self_param_ty = ty::ParamTy::for_self(def_id); let bounds = compute_bounds(ccx, - token::SELF_KEYWORD_NAME, - self_param_ty, + self_param_ty.to_ty(ccx.tcx), bounds.as_slice(), it.span); - let substs = ccx.tcx.mk_substs(mk_item_substs(ccx, &ty_generics)); - let associated_type_names: Vec<_> = items.iter() .filter_map(|item| { @@ -862,14 +861,16 @@ pub fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, }) .collect(); + let trait_ref = Rc::new(ty::TraitRef { + def_id: def_id, + substs: substs + }); + let trait_def = Rc::new(ty::TraitDef { unsafety: unsafety, generics: ty_generics, bounds: bounds, - trait_ref: Rc::new(ty::TraitRef { - def_id: def_id, - substs: substs - }), + trait_ref: trait_ref, associated_type_names: associated_type_names, }); tcx.trait_defs.borrow_mut().insert(def_id, trait_def.clone()); @@ -1027,9 +1028,12 @@ fn ty_generics_for_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, trait_id: ast::NodeId, substs: &'tcx subst::Substs<'tcx>, ast_generics: &ast::Generics, - _items: &[ast::TraitItem]) + trait_items: &[ast::TraitItem]) -> ty::Generics<'tcx> { + debug!("ty_generics_for_trait(trait_id={}, substs={})", + local_def(trait_id).repr(ccx.tcx), substs.repr(ccx.tcx)); + let mut generics = ty_generics(ccx, subst::TypeSpace, @@ -1045,8 +1049,8 @@ fn ty_generics_for_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let param_id = trait_id; let self_trait_ref = - ty::Binder(Rc::new(ty::TraitRef { def_id: local_def(trait_id), - substs: substs })); + Rc::new(ty::TraitRef { def_id: local_def(trait_id), + substs: substs }); let def = ty::TypeParameterDef { space: subst::SelfSpace, @@ -1056,7 +1060,7 @@ fn ty_generics_for_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, bounds: ty::ParamBounds { region_bounds: vec!(), builtin_bounds: ty::empty_builtin_bounds(), - trait_bounds: vec!(self_trait_ref.clone()), + trait_bounds: vec!(ty::Binder(self_trait_ref.clone())), projection_bounds: vec!(), }, default: None @@ -1068,7 +1072,47 @@ fn ty_generics_for_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, generics.predicates.push(subst::SelfSpace, self_trait_ref.as_predicate()); - generics + let assoc_predicates = predicates_for_associated_types(ccx, + &self_trait_ref, + trait_items); + + debug!("ty_generics_for_trait: assoc_predicates={}", assoc_predicates.repr(ccx.tcx)); + + for assoc_predicate in assoc_predicates.into_iter() { + generics.predicates.push(subst::SelfSpace, assoc_predicate); + } + + return generics; + + fn predicates_for_associated_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, + self_trait_ref: &Rc>, + trait_items: &[ast::TraitItem]) + -> Vec> + { + trait_items + .iter() + .flat_map(|trait_item| { + let assoc_type_def = match *trait_item { + ast::TypeTraitItem(ref assoc_type) => &assoc_type.ty_param, + ast::RequiredMethod(..) | ast::ProvidedMethod(..) => { + return vec!().into_iter(); + } + }; + + let assoc_ty = ty::mk_projection(ccx.tcx, + self_trait_ref.clone(), + assoc_type_def.ident.name); + + let bounds = compute_bounds(ccx, + assoc_ty, + assoc_type_def.bounds.as_slice(), + &assoc_type_def.unbound, + assoc_type_def.span); + + ty::predicates(ccx.tcx, assoc_ty, &bounds).into_iter() + }) + .collect() + } } fn ty_generics_for_fn_or_method<'tcx,AC>( @@ -1269,8 +1313,7 @@ fn get_or_create_type_parameter_def<'tcx,AC>(this: &AC, let param_ty = ty::ParamTy::new(space, index, local_def(param.id)); let bounds = compute_bounds(this, - param.ident.name, - param_ty, + param_ty.to_ty(this.tcx()), param.bounds[], param.span); let default = match param.default { @@ -1312,8 +1355,7 @@ fn get_or_create_type_parameter_def<'tcx,AC>(this: &AC, /// a region) to ty's notion of ty param bounds, which can either be user-defined traits, or the /// built-in trait (formerly known as kind): Send. fn compute_bounds<'tcx,AC>(this: &AC, - name_of_bounded_thing: ast::Name, - param_ty: ty::ParamTy, + param_ty: ty::Ty<'tcx>, ast_bounds: &[ast::TyParamBound], span: Span) -> ty::ParamBounds<'tcx> @@ -1329,7 +1371,7 @@ fn compute_bounds<'tcx,AC>(this: &AC, span); check_bounds_compatible(this.tcx(), - name_of_bounded_thing, + param_ty, ¶m_bounds, span); @@ -1339,7 +1381,7 @@ fn compute_bounds<'tcx,AC>(this: &AC, } fn check_bounds_compatible<'tcx>(tcx: &ty::ctxt<'tcx>, - name_of_bounded_thing: ast::Name, + param_ty: Ty<'tcx>, param_bounds: &ty::ParamBounds<'tcx>, span: Span) { // Currently the only bound which is incompatible with other bounds is @@ -1352,9 +1394,9 @@ fn check_bounds_compatible<'tcx>(tcx: &ty::ctxt<'tcx>, let trait_def = ty::lookup_trait_def(tcx, trait_ref.def_id()); if trait_def.bounds.builtin_bounds.contains(&ty::BoundSized) { span_err!(tcx.sess, span, E0129, - "incompatible bounds on type parameter `{}`, \ + "incompatible bounds on `{}`, \ bound `{}` does not allow unsized type", - name_of_bounded_thing.user_string(tcx), + param_ty.user_string(tcx), trait_ref.user_string(tcx)); } true @@ -1364,7 +1406,7 @@ fn check_bounds_compatible<'tcx>(tcx: &ty::ctxt<'tcx>, fn conv_param_bounds<'tcx,AC>(this: &AC, span: Span, - param_ty: ty::ParamTy, + param_ty: ty::Ty<'tcx>, ast_bounds: &[ast::TyParamBound]) -> ty::ParamBounds<'tcx> where AC: AstConv<'tcx> @@ -1382,7 +1424,7 @@ fn conv_param_bounds<'tcx,AC>(this: &AC, astconv::instantiate_poly_trait_ref(this, &ExplicitRscope, bound, - Some(param_ty.to_ty(this.tcx())), + Some(param_ty), &mut projection_bounds) }) .collect(); diff --git a/src/test/compile-fail/associated-types-path-2.rs b/src/test/compile-fail/associated-types-path-2.rs index caf8ab3695d1c..486d3d38c60af 100644 --- a/src/test/compile-fail/associated-types-path-2.rs +++ b/src/test/compile-fail/associated-types-path-2.rs @@ -26,9 +26,10 @@ pub fn f2(a: T) -> T::A { } pub fn main() { - f1(2i, 4i); //~ERROR the trait `Foo` is not implemented - f1(2u, 4u); //~ERROR the trait `Foo` is not implemented - f1(2u, 4i); //~ERROR the trait `Foo` is not implemented + f1(2i, 4i); //~ ERROR expected uint, found int + f1(2i, 4u); + f1(2u, 4u); //~ ERROR the trait `Foo` is not implemented + f1(2u, 4i); //~ ERROR the trait `Foo` is not implemented - let _: int = f2(2i); //~ERROR mismatched types: expected `int`, found `uint` + let _: int = f2(2i); //~ERROR expected `int`, found `uint` } From 964a5fabb7e32ac2b53678497a359e6eba2d5261 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sat, 27 Dec 2014 16:42:01 -0500 Subject: [PATCH 14/36] Update error messages in various compile-fail tests --- src/test/compile-fail/issue-15965.rs | 2 -- src/test/compile-fail/issue-18345.rs | 1 - src/test/compile-fail/issue-18532.rs | 1 - src/test/compile-fail/issue-18611.rs | 7 +++---- src/test/compile-fail/issue-19081.rs | 4 ++-- src/test/compile-fail/unsized4.rs | 1 + 6 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/test/compile-fail/issue-15965.rs b/src/test/compile-fail/issue-15965.rs index f3636edeaa589..08b896f387bbe 100644 --- a/src/test/compile-fail/issue-15965.rs +++ b/src/test/compile-fail/issue-15965.rs @@ -12,8 +12,6 @@ fn main() { return { return () } //~^ ERROR the type of this value must be known in this context -//~| ERROR this function takes 1 parameter -//~| ERROR mismatched types () ; } diff --git a/src/test/compile-fail/issue-18345.rs b/src/test/compile-fail/issue-18345.rs index c8b3463b0911d..e93acb3f064af 100644 --- a/src/test/compile-fail/issue-18345.rs +++ b/src/test/compile-fail/issue-18345.rs @@ -15,7 +15,6 @@ fn mapping<'f, R, T, U>(f: |T|: 'f -> U) -> &'f Transducer<'f, R, T, U> { |step| |r, x| step(r, f(x)) //~^ ERROR the type of this value must be known in this context - //~| ERROR this function takes 1 parameter but 2 parameters were supplied } fn main() {} diff --git a/src/test/compile-fail/issue-18532.rs b/src/test/compile-fail/issue-18532.rs index ec44ab7b27705..9cf922ae99002 100644 --- a/src/test/compile-fail/issue-18532.rs +++ b/src/test/compile-fail/issue-18532.rs @@ -17,5 +17,4 @@ fn main() { (return)((),()); //~^ ERROR the type of this value must be known - //~| ERROR this function takes 1 parameter } diff --git a/src/test/compile-fail/issue-18611.rs b/src/test/compile-fail/issue-18611.rs index b2f204d747671..49eeccb2b0cf1 100644 --- a/src/test/compile-fail/issue-18611.rs +++ b/src/test/compile-fail/issue-18611.rs @@ -10,10 +10,9 @@ #![feature(associated_types)] -fn add_state(op: - ::State -//~^ ERROR it is currently unsupported to access associated types except through a type parameter -) {} +fn add_state(op: ::State) { +//~^ ERROR the trait `HasState` is not implemented for the type `int` +} trait HasState { type State; diff --git a/src/test/compile-fail/issue-19081.rs b/src/test/compile-fail/issue-19081.rs index 613ec8acd4131..2f42dbd77fd0d 100644 --- a/src/test/compile-fail/issue-19081.rs +++ b/src/test/compile-fail/issue-19081.rs @@ -10,7 +10,7 @@ #![feature(associated_types)] -pub trait Hasher{ +pub trait Hasher { type State; fn hash>(&self, value: &T) -> u64; } -trait Hash { +pub trait Hash { fn hash(&self, state: &mut S); } diff --git a/src/test/compile-fail/unsized4.rs b/src/test/compile-fail/unsized4.rs index a66c1d85009c3..253ec2a84ea52 100644 --- a/src/test/compile-fail/unsized4.rs +++ b/src/test/compile-fail/unsized4.rs @@ -11,6 +11,7 @@ // Test that bounds are sized-compatible. trait T {} + fn f() { //~^ERROR incompatible bounds on type parameter `Y`, bound `T` does not allow unsized type } From 2bbd2f9ceafb86614b431cff4184f6e8ce7c973f Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sat, 27 Dec 2014 19:42:27 -0500 Subject: [PATCH 15/36] Remove the def-id from type parameters. Having this def-id was bad for several reasons: 1. Produced more unique types than is necessary. This increases memory consumption. 2. Linking the type parameter to its definition *seems* like a good idea, but it encourages reliance on the bounds listing. 3. It made pretty-printing harder and in particular was causing bad error messages when errors occurred before the `TypeParameterDef` entries were fully stored. --- src/librustc/metadata/tydecode.rs | 8 +-- src/librustc/metadata/tyencode.rs | 4 +- src/librustc/middle/astencode.rs | 2 +- src/librustc/middle/def.rs | 4 +- src/librustc/middle/ty.rs | 60 ++++++++----------- src/librustc/util/ppaux.rs | 13 +--- src/librustc_resolve/lib.rs | 9 +-- src/librustc_typeck/astconv.rs | 9 ++- src/librustc_typeck/check/mod.rs | 5 +- src/librustc_typeck/check/regionck.rs | 6 +- src/librustc_typeck/collect.rs | 22 +++---- src/librustc_typeck/variance.rs | 86 ++++++++++++++++----------- src/librustdoc/clean/mod.rs | 25 +++----- src/librustdoc/html/format.rs | 5 +- 14 files changed, 120 insertions(+), 138 deletions(-) diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs index 7dccc49dcbbda..88c7ccf1b1e36 100644 --- a/src/librustc/metadata/tydecode.rs +++ b/src/librustc/metadata/tydecode.rs @@ -420,13 +420,13 @@ fn parse_ty<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did) -> Ty<'tcx> { return ty::mk_trait(tcx, trait_ref, bounds); } 'p' => { - let did = parse_def(st, TypeParameter, |x,y| conv(x,y)); - debug!("parsed ty_param: did={}", did); + assert_eq!(next(st), '['); let index = parse_u32(st); assert_eq!(next(st), '|'); let space = parse_param_space(st); assert_eq!(next(st), '|'); - return ty::mk_param(tcx, space, index, did); + let name = token::intern(parse_str(st, ']')[]); + return ty::mk_param(tcx, space, index, name); } '~' => return ty::mk_uniq(tcx, parse_ty(st, |x,y| conv(x,y))), '*' => return ty::mk_ptr(tcx, parse_mt(st, |x,y| conv(x,y))), @@ -507,7 +507,7 @@ fn parse_ty<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did) -> Ty<'tcx> { 'P' => { assert_eq!(next(st), '['); let trait_ref = parse_trait_ref(st, |x,y| conv(x,y)); - let name = token::str_to_ident(parse_str(st, ']').as_slice()).name; + let name = token::intern(parse_str(st, ']').as_slice()); return ty::mk_projection(tcx, trait_ref, name); } 'e' => { diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs index b6d05882dce23..30746f51a8fe7 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -135,8 +135,8 @@ pub fn enc_ty<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>, t: Ty<'t ty::ty_infer(_) => { cx.diag.handler().bug("cannot encode inference variable types"); } - ty::ty_param(ParamTy {space, idx: id, def_id: did}) => { - mywrite!(w, "p{}|{}|{}|", (cx.ds)(did), id, space.to_uint()) + ty::ty_param(ParamTy {space, idx, name}) => { + mywrite!(w, "p[{}|{}|{}]", idx, space.to_uint(), token::get_name(name)) } ty::ty_struct(def, substs) => { mywrite!(w, "a[{}|", (cx.ds)(def)); diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index 0b78f2b1cfce9..a9c4f0ddd8c2d 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -448,7 +448,7 @@ impl tr for def::Def { def::DefAssociatedPath(def::TyParamProvenance::FromParam(did), ident) => def::DefAssociatedPath(def::TyParamProvenance::FromParam(did.tr(dcx)), ident), def::DefPrimTy(p) => def::DefPrimTy(p), - def::DefTyParam(s, did, v) => def::DefTyParam(s, did.tr(dcx), v), + def::DefTyParam(s, index, def_id, n) => def::DefTyParam(s, index, def_id.tr(dcx), n), def::DefUse(did) => def::DefUse(did.tr(dcx)), def::DefUpvar(nid1, nid2, nid3) => { def::DefUpvar(dcx.tr_id(nid1), diff --git a/src/librustc/middle/def.rs b/src/librustc/middle/def.rs index 023182df33652..59fd41b5d29e3 100644 --- a/src/librustc/middle/def.rs +++ b/src/librustc/middle/def.rs @@ -39,7 +39,7 @@ pub enum Def { DefAssociatedPath(TyParamProvenance, ast::Ident), DefTrait(ast::DefId), DefPrimTy(ast::PrimTy), - DefTyParam(ParamSpace, ast::DefId, u32), + DefTyParam(ParamSpace, u32, ast::DefId, ast::Name), DefUse(ast::DefId), DefUpvar(ast::NodeId, // id of closed over local ast::NodeId, // expr node that creates the closure @@ -130,7 +130,7 @@ impl Def { DefFn(id, _) | DefStaticMethod(id, _) | DefMod(id) | DefForeignMod(id) | DefStatic(id, _) | DefVariant(_, id, _) | DefTy(id, _) | DefAssociatedTy(id) | - DefTyParam(_, id, _) | DefUse(id) | DefStruct(id) | DefTrait(id) | + DefTyParam(_, _, id, _) | DefUse(id) | DefStruct(id) | DefTrait(id) | DefMethod(id, _, _) | DefConst(id) | DefAssociatedPath(TyParamProvenance::FromSelf(id), _) | DefAssociatedPath(TyParamProvenance::FromParam(id), _) => { diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 98539b4d15260..6225a0f3fba18 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -86,7 +86,7 @@ use syntax::ast::{Visibility}; use syntax::ast_util::{mod, is_local, lit_is_str, local_def, PostExpansionMethod}; use syntax::attr::{mod, AttrMetaMethods}; use syntax::codemap::Span; -use syntax::parse::token::{mod, InternedString}; +use syntax::parse::token::{mod, InternedString, special_idents}; use syntax::{ast, ast_map}; pub type Disr = u64; @@ -1079,7 +1079,7 @@ pub type PolyFnSig<'tcx> = Binder>; pub struct ParamTy { pub space: subst::ParamSpace, pub idx: u32, - pub def_id: DefId + pub name: ast::Name, } /// A [De Bruijn index][dbi] is a standard means of representing @@ -2775,17 +2775,19 @@ pub fn mk_infer<'tcx>(cx: &ctxt<'tcx>, it: InferTy) -> Ty<'tcx> { mk_t(cx, ty_infer(it)) } -pub fn mk_param<'tcx>(cx: &ctxt<'tcx>, space: subst::ParamSpace, - n: u32, k: DefId) -> Ty<'tcx> { - mk_t(cx, ty_param(ParamTy { space: space, idx: n, def_id: k })) +pub fn mk_param<'tcx>(cx: &ctxt<'tcx>, + space: subst::ParamSpace, + index: u32, + name: ast::Name) -> Ty<'tcx> { + mk_t(cx, ty_param(ParamTy { space: space, idx: index, name: name })) } -pub fn mk_self_type<'tcx>(cx: &ctxt<'tcx>, did: ast::DefId) -> Ty<'tcx> { - mk_param(cx, subst::SelfSpace, 0, did) +pub fn mk_self_type<'tcx>(cx: &ctxt<'tcx>) -> Ty<'tcx> { + mk_param(cx, subst::SelfSpace, 0, special_idents::type_self.name) } pub fn mk_param_from_def<'tcx>(cx: &ctxt<'tcx>, def: &TypeParameterDef) -> Ty<'tcx> { - mk_param(cx, def.space, def.index, def.def_id) + mk_param(cx, def.space, def.index, def.name) } pub fn mk_open<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { mk_t(cx, ty_open(ty)) } @@ -2854,21 +2856,21 @@ pub fn fold_ty<'tcx, F>(cx: &ctxt<'tcx>, t0: Ty<'tcx>, impl ParamTy { pub fn new(space: subst::ParamSpace, index: u32, - def_id: ast::DefId) + name: ast::Name) -> ParamTy { - ParamTy { space: space, idx: index, def_id: def_id } + ParamTy { space: space, idx: index, name: name } } - pub fn for_self(trait_def_id: ast::DefId) -> ParamTy { - ParamTy::new(subst::SelfSpace, 0, trait_def_id) + pub fn for_self() -> ParamTy { + ParamTy::new(subst::SelfSpace, 0, special_idents::type_self.name) } pub fn for_def(def: &TypeParameterDef) -> ParamTy { - ParamTy::new(def.space, def.index, def.def_id) + ParamTy::new(def.space, def.index, def.name) } pub fn to_ty<'tcx>(self, tcx: &ty::ctxt<'tcx>) -> Ty<'tcx> { - ty::mk_param(tcx, self.space, self.idx, self.def_id) + ty::mk_param(tcx, self.space, self.idx, self.name) } pub fn is_self(&self) -> bool { @@ -6256,8 +6258,9 @@ pub fn hash_crate_independent<'tcx>(tcx: &ctxt<'tcx>, ty: Ty<'tcx>, svh: &Svh) - } ty_param(p) => { byte!(20); + hash!(p.space); hash!(p.idx); - did(state, p.def_id); + hash!(token::get_name(p.name)); } ty_open(_) => byte!(22), ty_infer(_) => unreachable!(), @@ -6312,17 +6315,11 @@ pub fn construct_parameter_environment<'tcx>( // map T => T let mut types = VecPerParamSpace::empty(); - for &space in subst::ParamSpace::all().iter() { - push_types_from_defs(tcx, &mut types, space, - generics.types.get_slice(space)); - } + push_types_from_defs(tcx, &mut types, generics.types.as_slice()); // map bound 'a => free 'a let mut regions = VecPerParamSpace::empty(); - for &space in subst::ParamSpace::all().iter() { - push_region_params(&mut regions, space, free_id, - generics.regions.get_slice(space)); - } + push_region_params(&mut regions, free_id, generics.regions.as_slice()); let free_substs = Substs { types: types, @@ -6359,27 +6356,22 @@ pub fn construct_parameter_environment<'tcx>( }; fn push_region_params(regions: &mut VecPerParamSpace, - space: subst::ParamSpace, free_id: ast::NodeId, region_params: &[RegionParameterDef]) { for r in region_params.iter() { - regions.push(space, ty::free_region_from_def(free_id, r)); + regions.push(r.space, ty::free_region_from_def(free_id, r)); } } fn push_types_from_defs<'tcx>(tcx: &ty::ctxt<'tcx>, types: &mut subst::VecPerParamSpace>, - space: subst::ParamSpace, defs: &[TypeParameterDef<'tcx>]) { - for (i, def) in defs.iter().enumerate() { - debug!("construct_parameter_environment(): push_types_from_defs: \ - space={} def={} index={}", - space, - def.repr(tcx), - i); - let ty = ty::mk_param(tcx, space, i as u32, def.def_id); - types.push(space, ty); + for def in defs.iter() { + debug!("construct_parameter_environment(): push_types_from_defs: def={}", + def.repr(tcx)); + let ty = ty::mk_param_from_def(tcx, def); + types.push(def.space, ty); } } diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 3e7b24ac93f9e..ee1432bc953de 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -1328,17 +1328,8 @@ impl<'tcx> Repr<'tcx> for ty::ExplicitSelfCategory { } impl<'tcx> UserString<'tcx> for ParamTy { - fn user_string(&self, tcx: &ctxt) -> String { - let id = self.idx; - let did = self.def_id; - let ident = match tcx.ty_param_defs.borrow().get(&did.node) { - Some(def) => token::get_name(def.name).get().to_string(), - - // This can only happen when a type mismatch error happens and - // the actual type has more type parameters than the expected one. - None => format!("", id), - }; - ident + fn user_string(&self, _tcx: &ctxt) -> String { + format!("{}", token::get_name(self.name)) } } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 7f01bf087381b..52bd096eb83de 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -3906,7 +3906,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // If the def is a ty param, and came from the parent // item, it's ok match def { - DefTyParam(_, did, _) if { + DefTyParam(_, _, did, _) if { self.def_map.borrow().get(&did.node).cloned() == Some(DefTyParamBinder(item_id)) } => {} // ok @@ -3959,7 +3959,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // If the def is a ty param, and came from the parent // item, it's ok match def { - DefTyParam(_, did, _) if { + DefTyParam(_, _, did, _) if { self.def_map.borrow().get(&did.node).cloned() == Some(DefTyParamBinder(item_id)) } => {} // ok @@ -4265,8 +4265,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { seen_bindings.insert(name); let def_like = DlDef(DefTyParam(space, + index as u32, local_def(type_parameter.id), - index as u32)); + name)); // Associate this type parameter with // the item that bound it self.record_def(type_parameter.id, @@ -5161,7 +5162,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { path.span) { Some((def, last_private)) => { match def { - DefTyParam(_, did, _) => { + DefTyParam(_, _, did, _) => { let def = DefAssociatedPath(TyParamProvenance::FromParam(did), path.segments.last() .unwrap().identifier); diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 26fadb0dfb102..477171051640b 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1118,17 +1118,16 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( def::DefTy(did, _) | def::DefStruct(did) => { ast_path_to_ty(this, rscope, did, path).ty } - def::DefTyParam(space, id, n) => { + def::DefTyParam(space, index, _, name) => { check_path_args(tcx, path, NO_TPS | NO_REGIONS); - ty::mk_param(tcx, space, n, id) + ty::mk_param(tcx, space, index, name) } - def::DefSelfTy(id) => { + def::DefSelfTy(_) => { // n.b.: resolve guarantees that the this type only appears in a // trait, which we rely upon in various places when creating // substs check_path_args(tcx, path, NO_TPS | NO_REGIONS); - let did = ast_util::local_def(id); - ty::mk_self_type(tcx, did) + ty::mk_self_type(tcx) } def::DefMod(id) => { tcx.sess.span_fatal(ast_ty.span, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 4bc1246d39359..139ef010d2124 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -5065,7 +5065,7 @@ pub fn type_scheme_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, def::DefAssociatedTy(..) | def::DefAssociatedPath(..) | def::DefPrimTy(_) | - def::DefTyParam(..)=> { + def::DefTyParam(..) => { fcx.ccx.tcx.sess.span_bug(sp, "expected value, found type"); } def::DefMod(..) | def::DefForeignMod(..) => { @@ -5635,7 +5635,8 @@ pub fn check_bounds_are_used<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) { fn param<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, n: u32) -> Ty<'tcx> { - ty::mk_param(ccx.tcx, subst::FnSpace, n, local_def(0)) + let name = token::intern(format!("P{}", n).as_slice()); + ty::mk_param(ccx.tcx, subst::FnSpace, n, name) } let tcx = ccx.tcx; diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 1da8852c9b23c..d01b79068aa2c 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -1848,11 +1848,9 @@ fn param_must_outlive<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>, // well-formed, then, A must be lower-bounded by `'a`, but we // don't know that this holds from first principles. for &(ref r, ref p) in rcx.region_param_pairs.iter() { - debug!("param_ty={}/{} p={}/{}", + debug!("param_ty={} p={}", param_ty.repr(rcx.tcx()), - param_ty.def_id, - p.repr(rcx.tcx()), - p.def_id); + p.repr(rcx.tcx())); if param_ty == *p { param_bounds.push(*r); } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index b311f10c0a320..1187baa9a9ce9 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -349,7 +349,7 @@ fn collect_trait_methods<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, (*trait_generics).clone()); let (fty, explicit_self_category) = { - let trait_self_ty = ty::mk_self_type(ccx.tcx, local_def(trait_id)); + let trait_self_ty = ty::mk_self_type(ccx.tcx); astconv::ty_of_method(ccx, *m_unsafety, trait_self_ty, @@ -639,10 +639,7 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) { trait_def.repr(ccx.tcx())); for trait_method in trait_methods.iter() { - let self_type = ty::mk_param(ccx.tcx, - subst::SelfSpace, - 0, - local_def(it.id)); + let self_type = ty::mk_self_type(tcx); match *trait_method { ast::RequiredMethod(ref type_method) => { let rscope = BindingRscope::new(); @@ -668,8 +665,7 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) { } // Run convert_methods on the provided methods. - let untransformed_rcvr_ty = ty::mk_self_type(tcx, - local_def(it.id)); + let untransformed_rcvr_ty = ty::mk_self_type(tcx); convert_methods(ccx, TraitContainer(local_def(it.id)), trait_methods.iter().filter_map(|m| match *m { @@ -834,7 +830,7 @@ pub fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, } }; - let substs = ccx.tcx.mk_substs(mk_trait_substs(ccx, it.id, generics)); + let substs = ccx.tcx.mk_substs(mk_trait_substs(ccx, generics)); let ty_generics = ty_generics_for_trait(ccx, it.id, @@ -844,7 +840,7 @@ pub fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, assert_eq!(mk_item_substs(ccx, &ty_generics), substs); - let self_param_ty = ty::ParamTy::for_self(def_id); + let self_param_ty = ty::ParamTy::for_self(); let bounds = compute_bounds(ccx, self_param_ty.to_ty(ccx.tcx), @@ -878,7 +874,6 @@ pub fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, return trait_def; fn mk_trait_substs<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, - trait_id: ast::NodeId, generics: &ast::Generics) -> subst::Substs<'tcx> { @@ -899,12 +894,11 @@ pub fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, .iter() .enumerate() .map(|(i, def)| ty::mk_param(ccx.tcx, subst::TypeSpace, - i as u32, local_def(def.id))) + i as u32, def.ident.name)) .collect(); // ...and also create the `Self` parameter. - let self_ty = - ty::mk_param(ccx.tcx, subst::SelfSpace, 0, local_def(trait_id)); + let self_ty = ty::mk_self_type(ccx.tcx); subst::Substs::new_trait(types, regions, Vec::new(), self_ty) } @@ -1311,7 +1305,7 @@ fn get_or_create_type_parameter_def<'tcx,AC>(this: &AC, None => { } } - let param_ty = ty::ParamTy::new(space, index, local_def(param.id)); + let param_ty = ty::ParamTy::new(space, index, param.ident.name); let bounds = compute_bounds(this, param_ty.to_ty(this.tcx()), param.bounds[], diff --git a/src/librustc_typeck/variance.rs b/src/librustc_typeck/variance.rs index c3a3993b66b76..2914895aa7a73 100644 --- a/src/librustc_typeck/variance.rs +++ b/src/librustc_typeck/variance.rs @@ -479,8 +479,13 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ConstraintContext<'a, 'tcx> { let did = ast_util::local_def(item.id); let tcx = self.terms_cx.tcx; + debug!("visit_item item={}", + item.repr(tcx)); + match item.node { ast::ItemEnum(ref enum_definition, _) => { + let generics = &ty::lookup_item_type(tcx, did).generics; + // Hack: If we directly call `ty::enum_variants`, it // annoyingly takes it upon itself to run off and // evaluate the discriminants eagerly (*grumpy* that's @@ -497,17 +502,18 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ConstraintContext<'a, 'tcx> { &**ast_variant, /*discriminant*/ 0); for arg_ty in variant.args.iter() { - self.add_constraints_from_ty(*arg_ty, self.covariant); + self.add_constraints_from_ty(generics, *arg_ty, self.covariant); } } } ast::ItemStruct(..) => { + let generics = &ty::lookup_item_type(tcx, did).generics; let struct_fields = ty::lookup_struct_fields(tcx, did); for field_info in struct_fields.iter() { assert_eq!(field_info.id.krate, ast::LOCAL_CRATE); let field_ty = ty::node_id_to_type(tcx, field_info.id.node); - self.add_constraints_from_ty(field_ty, self.covariant); + self.add_constraints_from_ty(generics, field_ty, self.covariant); } } @@ -516,7 +522,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ConstraintContext<'a, 'tcx> { for trait_item in trait_items.iter() { match *trait_item { ty::MethodTraitItem(ref method) => { - self.add_constraints_from_sig(&method.fty.sig, + self.add_constraints_from_sig(&method.generics, + &method.fty.sig, self.covariant); } ty::TypeTraitItem(_) => {} @@ -713,8 +720,10 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { } /// Adds constraints appropriate for an instance of `ty` appearing - /// in a context with ambient variance `variance` + /// in a context with the generics defined in `generics` and + /// ambient variance `variance` fn add_constraints_from_ty(&mut self, + generics: &ty::Generics<'tcx>, ty: Ty<'tcx>, variance: VarianceTermPtr<'a>) { debug!("add_constraints_from_ty(ty={})", ty.repr(self.tcx())); @@ -732,40 +741,40 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { ty::ty_rptr(region, ref mt) => { let contra = self.contravariant(variance); - self.add_constraints_from_region(*region, contra); - self.add_constraints_from_mt(mt, variance); + self.add_constraints_from_region(generics, *region, contra); + self.add_constraints_from_mt(generics, mt, variance); } ty::ty_uniq(typ) | ty::ty_vec(typ, _) | ty::ty_open(typ) => { - self.add_constraints_from_ty(typ, variance); + self.add_constraints_from_ty(generics, typ, variance); } ty::ty_ptr(ref mt) => { - self.add_constraints_from_mt(mt, variance); + self.add_constraints_from_mt(generics, mt, variance); } ty::ty_tup(ref subtys) => { for &subty in subtys.iter() { - self.add_constraints_from_ty(subty, variance); + self.add_constraints_from_ty(generics, subty, variance); } } ty::ty_enum(def_id, substs) | ty::ty_struct(def_id, substs) => { let item_type = ty::lookup_item_type(self.tcx(), def_id); - let generics = &item_type.generics; // All type parameters on enums and structs should be // in the TypeSpace. - assert!(generics.types.is_empty_in(subst::SelfSpace)); - assert!(generics.types.is_empty_in(subst::FnSpace)); - assert!(generics.regions.is_empty_in(subst::SelfSpace)); - assert!(generics.regions.is_empty_in(subst::FnSpace)); + assert!(item_type.generics.types.is_empty_in(subst::SelfSpace)); + assert!(item_type.generics.types.is_empty_in(subst::FnSpace)); + assert!(item_type.generics.regions.is_empty_in(subst::SelfSpace)); + assert!(item_type.generics.regions.is_empty_in(subst::FnSpace)); self.add_constraints_from_substs( + generics, def_id, - generics.types.get_slice(subst::TypeSpace), - generics.regions.get_slice(subst::TypeSpace), + item_type.generics.types.get_slice(subst::TypeSpace), + item_type.generics.regions.get_slice(subst::TypeSpace), substs, variance); } @@ -773,11 +782,11 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { ty::ty_projection(ref data) => { let trait_ref = &data.trait_ref; let trait_def = ty::lookup_trait_def(self.tcx(), trait_ref.def_id); - let generics = &trait_def.generics; self.add_constraints_from_substs( + generics, trait_ref.def_id, - generics.types.as_slice(), - generics.regions.as_slice(), + trait_def.generics.types.as_slice(), + trait_def.generics.regions.as_slice(), &trait_ref.substs, variance); } @@ -785,27 +794,28 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { ty::ty_trait(ref data) => { let trait_ref = data.principal_trait_ref_with_self_ty(self.tcx().types.err); let trait_def = ty::lookup_trait_def(self.tcx(), trait_ref.def_id()); - let generics = &trait_def.generics; // Traits never declare region parameters in the self // space nor anything in the fn space. - assert!(generics.regions.is_empty_in(subst::SelfSpace)); - assert!(generics.types.is_empty_in(subst::FnSpace)); - assert!(generics.regions.is_empty_in(subst::FnSpace)); + assert!(trait_def.generics.regions.is_empty_in(subst::SelfSpace)); + assert!(trait_def.generics.types.is_empty_in(subst::FnSpace)); + assert!(trait_def.generics.regions.is_empty_in(subst::FnSpace)); // The type `Foo` is contravariant w/r/t `'a`: let contra = self.contravariant(variance); - self.add_constraints_from_region(data.bounds.region_bound, contra); + self.add_constraints_from_region(generics, data.bounds.region_bound, contra); self.add_constraints_from_substs( + generics, trait_ref.def_id(), - generics.types.get_slice(subst::TypeSpace), - generics.regions.get_slice(subst::TypeSpace), + trait_def.generics.types.get_slice(subst::TypeSpace), + trait_def.generics.regions.get_slice(subst::TypeSpace), trait_ref.substs(), variance); } - ty::ty_param(ty::ParamTy { ref def_id, .. }) => { + ty::ty_param(ref data) => { + let def_id = generics.types.get(data.space, data.idx).def_id; assert_eq!(def_id.krate, ast::LOCAL_CRATE); match self.terms_cx.inferred_map.get(&def_id.node) { Some(&index) => { @@ -826,14 +836,14 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { .. }) => { - self.add_constraints_from_sig(sig, variance); + self.add_constraints_from_sig(generics, sig, variance); } ty::ty_closure(box ty::ClosureTy { ref sig, store: ty::RegionTraitStore(region, _), .. }) => { let contra = self.contravariant(variance); - self.add_constraints_from_region(region, contra); - self.add_constraints_from_sig(sig, variance); + self.add_constraints_from_region(generics, region, contra); + self.add_constraints_from_sig(generics, sig, variance); } ty::ty_infer(..) | ty::ty_err => { @@ -849,6 +859,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { /// Adds constraints appropriate for a nominal type (enum, struct, /// object, etc) appearing in a context with ambient variance `variance` fn add_constraints_from_substs(&mut self, + generics: &ty::Generics<'tcx>, def_id: ast::DefId, type_param_defs: &[ty::TypeParameterDef<'tcx>], region_param_defs: &[ty::RegionParameterDef], @@ -862,7 +873,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { p.space, p.index as uint); let variance_i = self.xform(variance, variance_decl); let substs_ty = *substs.types.get(p.space, p.index as uint); - self.add_constraints_from_ty(substs_ty, variance_i); + self.add_constraints_from_ty(generics, substs_ty, variance_i); } for p in region_param_defs.iter() { @@ -871,27 +882,29 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { RegionParam, p.space, p.index as uint); let variance_i = self.xform(variance, variance_decl); let substs_r = *substs.regions().get(p.space, p.index as uint); - self.add_constraints_from_region(substs_r, variance_i); + self.add_constraints_from_region(generics, substs_r, variance_i); } } /// Adds constraints appropriate for a function with signature /// `sig` appearing in a context with ambient variance `variance` fn add_constraints_from_sig(&mut self, + generics: &ty::Generics<'tcx>, sig: &ty::PolyFnSig<'tcx>, variance: VarianceTermPtr<'a>) { let contra = self.contravariant(variance); for &input in sig.0.inputs.iter() { - self.add_constraints_from_ty(input, contra); + self.add_constraints_from_ty(generics, input, contra); } if let ty::FnConverging(result_type) = sig.0.output { - self.add_constraints_from_ty(result_type, variance); + self.add_constraints_from_ty(generics, result_type, variance); } } /// Adds constraints appropriate for a region appearing in a /// context with ambient variance `variance` fn add_constraints_from_region(&mut self, + _generics: &ty::Generics<'tcx>, region: ty::Region, variance: VarianceTermPtr<'a>) { match region { @@ -925,16 +938,17 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { /// Adds constraints appropriate for a mutability-type pair /// appearing in a context with ambient variance `variance` fn add_constraints_from_mt(&mut self, + generics: &ty::Generics<'tcx>, mt: &ty::mt<'tcx>, variance: VarianceTermPtr<'a>) { match mt.mutbl { ast::MutMutable => { let invar = self.invariant(variance); - self.add_constraints_from_ty(mt.ty, invar); + self.add_constraints_from_ty(generics, mt.ty, invar); } ast::MutImmutable => { - self.add_constraints_from_ty(mt.ty, variance); + self.add_constraints_from_ty(generics, mt.ty, variance); } } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 5063ce36019d1..b4bfaa9afdabe 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -34,8 +34,7 @@ use syntax::ast_util::PostExpansionMethod; use syntax::attr; use syntax::attr::{AttributeMethods, AttrMetaMethods}; use syntax::codemap::{DUMMY_SP, Pos, Spanned}; -use syntax::parse::token::InternedString; -use syntax::parse::token; +use syntax::parse::token::{mod, InternedString, special_idents}; use syntax::ptr::P; use rustc_trans::back::link; @@ -1200,11 +1199,9 @@ pub enum Type { }, // I have no idea how to usefully use this. TyParamBinder(ast::NodeId), - /// For parameterized types, so the consumer of the JSON don't go looking - /// for types which don't exist anywhere. - Generic(ast::DefId), - /// For references to self - Self(ast::DefId), + /// For parameterized types, so the consumer of the JSON don't go + /// looking for types which don't exist anywhere. + Generic(String), /// Primitives are just the fixed-size numeric types (plus int/uint/float), and char. Primitive(PrimitiveType), Closure(Box), @@ -1485,13 +1482,7 @@ impl<'tcx> Clean for ty::Ty<'tcx> { } } - ty::ty_param(ref p) => { - if p.space == subst::SelfSpace { - Self(p.def_id) - } else { - Generic(p.def_id) - } - } + ty::ty_param(ref p) => Generic(token::get_name(p.name).to_string()), ty::ty_unboxed_closure(..) => Tuple(vec![]), // FIXME(pcwalton) @@ -2276,7 +2267,9 @@ fn resolve_type(cx: &DocContext, }; match def { - def::DefSelfTy(i) => return Self(ast_util::local_def(i)), + def::DefSelfTy(..) => { + return Generic(token::get_name(special_idents::type_self.name).to_string()); + } def::DefPrimTy(p) => match p { ast::TyStr => return Primitive(Str), ast::TyBool => return Primitive(Bool), @@ -2294,7 +2287,7 @@ fn resolve_type(cx: &DocContext, ast::TyFloat(ast::TyF32) => return Primitive(F32), ast::TyFloat(ast::TyF64) => return Primitive(F64), }, - def::DefTyParam(_, i, _) => return Generic(i), + def::DefTyParam(_, _, _, n) => return Generic(token::get_name(n).to_string()), def::DefTyParamBinder(i) => return TyParamBinder(i), _ => {} }; diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 585183e2af75e..dc264a5b5aa05 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -435,15 +435,14 @@ impl fmt::Show for clean::Type { clean::TyParamBinder(id) => { f.write(cache().typarams[ast_util::local_def(id)].as_bytes()) } - clean::Generic(did) => { - f.write(cache().typarams[did].as_bytes()) + clean::Generic(ref name) => { + f.write(name.as_bytes()) } clean::ResolvedPath{ did, ref typarams, ref path } => { try!(resolved_path(f, did, path, false)); tybounds(f, typarams) } clean::Infer => write!(f, "_"), - clean::Self(..) => f.write("Self".as_bytes()), clean::Primitive(prim) => primitive_link(f, prim, prim.to_string()), clean::Closure(ref decl) => { write!(f, "{style}{lifetimes}|{args}|{bounds}{arrow}", From 3657ae13f5f7ef4367a6de4b61bd4143fc6b52b4 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sun, 28 Dec 2014 10:07:21 -0500 Subject: [PATCH 16/36] Don't normalize associated types when in region binders, wait until we instantiate them. Also fix some assertions and handling of builtin bounds. --- src/librustc/middle/traits/fulfill.rs | 7 ++ src/librustc/middle/traits/select.rs | 38 ++++-- src/librustc/middle/ty.rs | 21 +++- src/librustc_typeck/check/assoc.rs | 26 +++- src/librustc_typeck/check/closure.rs | 13 +- src/librustc_typeck/check/method/confirm.rs | 19 +-- src/librustc_typeck/check/method/mod.rs | 18 +-- src/librustc_typeck/check/mod.rs | 129 +++++++++++++------- src/librustc_typeck/check/regionmanip.rs | 13 +- src/librustc_typeck/check/wf.rs | 3 +- src/libsyntax/visit.rs | 12 ++ 11 files changed, 214 insertions(+), 85 deletions(-) diff --git a/src/librustc/middle/traits/fulfill.rs b/src/librustc/middle/traits/fulfill.rs index 0d2023ead4fcc..e72d5b405c4e4 100644 --- a/src/librustc/middle/traits/fulfill.rs +++ b/src/librustc/middle/traits/fulfill.rs @@ -109,6 +109,10 @@ impl<'tcx> FulfillmentContext<'tcx> { cause: ObligationCause<'tcx>) -> Ty<'tcx> { + debug!("normalize_associated_type(trait_ref={}, item_name={})", + trait_ref.repr(infcx.tcx), + item_name.repr(infcx.tcx)); + assert!(!trait_ref.has_escaping_regions()); let ty_var = infcx.next_ty_var(); @@ -120,6 +124,9 @@ impl<'tcx> FulfillmentContext<'tcx> { }); let obligation = Obligation::new(cause, projection.as_predicate()); self.register_predicate(infcx, obligation); + + debug!("normalize_associated_type: result={}", ty_var.repr(infcx.tcx)); + ty_var } diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index 2e4bdadb8c231..9301531e84d5e 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -1141,7 +1141,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &TraitObligation<'tcx>) -> Result,SelectionError<'tcx>> { - // TODO seems like we ought to skolemize here, oder? + // Note: these tests operate on types that may contain bound + // regions. To be proper, we ought to skolemize here, but we + // forego the skolemization and defer it until the + // confirmation step. + let self_ty = self.infcx.shallow_resolve(obligation.predicate.0.self_ty()); return match self_ty.sty { ty::ty_infer(ty::IntVar(_)) | @@ -1627,13 +1631,31 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { -> VtableBuiltinData> { let derived_cause = self.derived_cause(obligation, BuiltinDerivedObligation); - let obligations = nested.iter().map(|&t| { - util::predicate_for_builtin_bound( - self.tcx(), - derived_cause.clone(), - bound, - obligation.recursion_depth + 1, - t) + let obligations = nested.iter().map(|&bound_ty| { + // the obligation might be higher-ranked, e.g. for<'a> &'a + // int : Copy. In that case, we will wind up with + // late-bound regions in the `nested` vector. So for each + // one we instantiate to a skolemized region, do our work + // to produce something like `&'0 int : Copy`, and then + // re-bind it. This is a bit of busy-work but preserves + // the invariant that we only manipulate free regions, not + // bound ones. + self.infcx.try(|snapshot| { + let (skol_ty, skol_map) = + self.infcx().skolemize_late_bound_regions(&ty::Binder(bound_ty), snapshot); + let skol_predicate = + util::predicate_for_builtin_bound( + self.tcx(), + derived_cause.clone(), + bound, + obligation.recursion_depth + 1, + skol_ty); + match skol_predicate { + Ok(skol_predicate) => Ok(self.infcx().plug_leaks(skol_map, snapshot, + &skol_predicate)), + Err(ErrorReported) => Err(ErrorReported) + } + }) }).collect::>(); let mut obligations = match obligations { Ok(o) => o, diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 6225a0f3fba18..583d2ce3b67c2 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -6903,8 +6903,19 @@ impl RegionEscape for Region { impl<'tcx> RegionEscape for TraitRef<'tcx> { fn has_regions_escaping_depth(&self, depth: u32) -> bool { - self.substs.types.iter().any(|t| t.has_regions_escaping_depth(depth)) && - self.substs.regions().iter().any(|t| t.has_regions_escaping_depth(depth)) + self.substs.types.iter().any(|t| t.has_regions_escaping_depth(depth)) || + self.substs.regions.has_regions_escaping_depth(depth) + } +} + +impl<'tcx> RegionEscape for subst::RegionSubsts { + fn has_regions_escaping_depth(&self, depth: u32) -> bool { + match *self { + subst::ErasedRegions => false, + subst::NonerasedRegions(ref r) => { + r.iter().any(|t| t.has_regions_escaping_depth(depth)) + } + } } } @@ -6921,7 +6932,7 @@ impl<'tcx> RegionEscape for EquatePredicate<'tcx> { } impl<'tcx> RegionEscape for TraitPredicate<'tcx> { - fn has_regions_escaping_depth(&self, depth: uint) -> bool { + fn has_regions_escaping_depth(&self, depth: u32) -> bool { self.trait_ref.has_regions_escaping_depth(depth) } } @@ -6933,14 +6944,14 @@ impl RegionEscape for OutlivesPredicate { } impl<'tcx> RegionEscape for ProjectionPredicate<'tcx> { - fn has_regions_escaping_depth(&self, depth: uint) -> bool { + fn has_regions_escaping_depth(&self, depth: u32) -> bool { self.projection_ty.has_regions_escaping_depth(depth) || self.ty.has_regions_escaping_depth(depth) } } impl<'tcx> RegionEscape for ProjectionTy<'tcx> { - fn has_regions_escaping_depth(&self, depth: uint) -> bool { + fn has_regions_escaping_depth(&self, depth: u32) -> bool { self.trait_ref.has_regions_escaping_depth(depth) } } diff --git a/src/librustc_typeck/check/assoc.rs b/src/librustc_typeck/check/assoc.rs index e737bb1b237fb..b59f9291e4fc6 100644 --- a/src/librustc_typeck/check/assoc.rs +++ b/src/librustc_typeck/check/assoc.rs @@ -33,7 +33,8 @@ pub fn normalize_associated_types_in<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>, let mut normalizer = AssociatedTypeNormalizer { span: span, body_id: body_id, infcx: infcx, - fulfillment_cx: fulfillment_cx }; + fulfillment_cx: fulfillment_cx, + region_binders: 0 }; value.fold_with(&mut normalizer) } @@ -42,6 +43,7 @@ struct AssociatedTypeNormalizer<'a,'tcx:'a> { fulfillment_cx: &'a mut FulfillmentContext<'tcx>, span: Span, body_id: ast::NodeId, + region_binders: uint, } impl<'a,'tcx> TypeFolder<'tcx> for AssociatedTypeNormalizer<'a,'tcx> { @@ -49,9 +51,29 @@ impl<'a,'tcx> TypeFolder<'tcx> for AssociatedTypeNormalizer<'a,'tcx> { self.infcx.tcx } + fn enter_region_binder(&mut self) { + self.region_binders += 1; + } + + fn exit_region_binder(&mut self) { + self.region_binders -= 1; + } + fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { + // We don't want to normalize associated types that occur inside of region + // binders, because they may contain bound regions, and we can't cope with that. + // + // Example: + // + // for<'a> fn(>::A) + // + // Instead of normalizing `>::A` here, we'll + // normalize it when we instantiate those bound regions (which + // should occur eventually). + let no_region_binders = self.region_binders == 0; + match ty.sty { - ty::ty_projection(ref data) => { + ty::ty_projection(ref data) if no_region_binders => { let cause = ObligationCause::new( self.span, diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 19108ca710bc1..340cc9b355c02 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -14,6 +14,7 @@ use super::{check_fn, Expectation, FnCtxt}; use astconv; use middle::infer; +use middle::region::CodeExtent; use middle::subst; use middle::ty::{mod, ToPolyTraitRef, Ty}; use rscope::RegionScope; @@ -132,10 +133,13 @@ fn check_unboxed_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, fcx.write_ty(expr.id, closure_type); + let fn_sig = + ty::liberate_late_bound_regions(fcx.tcx(), CodeExtent::from_node_id(body.id), &fn_ty.sig); + check_fn(fcx.ccx, ast::Unsafety::Normal, expr.id, - &fn_ty.sig, + &fn_sig, decl, expr.id, &*body, @@ -310,7 +314,7 @@ fn check_boxed_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, decl, abi::Rust, expected_sig); - let fty_sig = fn_ty.sig.clone(); + let fn_sig = fn_ty.sig.clone(); let fty = ty::mk_closure(tcx, fn_ty); debug!("check_expr_fn fty={}", fcx.infcx().ty_to_string(fty)); @@ -325,10 +329,13 @@ fn check_boxed_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, ty::UniqTraitStore => (ast::Unsafety::Normal, expr.id) }; + let fn_sig = + ty::liberate_late_bound_regions(tcx, CodeExtent::from_node_id(body.id), &fn_sig); + check_fn(fcx.ccx, inherited_style, inherited_style_id, - &fty_sig, + &fn_sig, &*decl, expr.id, &*body, diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index de6824fa5ddd1..1aa9adaf9ec4d 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -424,17 +424,18 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { debug!("method_bounds after subst = {}", method_bounds.repr(self.tcx())); - // Substitute the type/early-bound-regions into the method - // signature. In addition, the method signature may bind - // late-bound regions, so instantiate those. - let method_sig = self.fcx.instantiate_type_scheme(self.span, - &all_substs, - &pick.method_ty.fty.sig); - debug!("late-bound lifetimes from method substituted, method_sig={}", + // Instantiate late-bound regions and substitute the trait + // parameters into the method type to get the actual method type. + // + // NB: Instantiate late-bound regions first so that + // `instantiate_type_scheme` can normalize associated types that + // may reference those regions. + let method_sig = self.replace_late_bound_regions_with_fresh_var(&pick.method_ty.fty.sig); + debug!("late-bound lifetimes from method instantiated, method_sig={}", method_sig.repr(self.tcx())); - let method_sig = self.replace_late_bound_regions_with_fresh_var(&method_sig); - debug!("late-bound lifetimes from method instantiated, method_sig={}", + let method_sig = self.fcx.instantiate_type_scheme(self.span, &all_substs, &method_sig); + debug!("type scheme substituted, method_sig={}", method_sig.repr(self.tcx())); InstantiatedMethodSig { diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index cb71fbce8ac4c..5b6acdbf3ada5 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -190,19 +190,21 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>, debug!("lookup_in_trait_adjusted: method_num={} method_ty={}", method_num, method_ty.repr(fcx.tcx())); - // Substitute the trait parameters into the method type and - // instantiate late-bound regions to get the actual method type. - let bare_fn_ty = fcx.instantiate_type_scheme(span, - &trait_ref.substs, - &method_ty.fty); + // Instantiate late-bound regions and substitute the trait + // parameters into the method type to get the actual method type. + // + // NB: Instantiate late-bound regions first so that + // `instantiate_type_scheme` can normalize associated types that + // may reference those regions. let fn_sig = fcx.infcx().replace_late_bound_regions_with_fresh_var(span, infer::FnCall, - &bare_fn_ty.sig).0; + &method_ty.fty.sig).0; + let fn_sig = fcx.instantiate_type_scheme(span, &trait_ref.substs, &fn_sig); let transformed_self_ty = fn_sig.inputs[0]; let fty = ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(ty::BareFnTy { sig: ty::Binder(fn_sig), - unsafety: bare_fn_ty.unsafety, - abi: bare_fn_ty.abi.clone(), + unsafety: method_ty.fty.unsafety, + abi: method_ty.fty.abi.clone(), })); debug!("lookup_in_trait_adjusted: matched method fty={} obligation={}", diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 139ef010d2124..e485e49148fe4 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -432,13 +432,15 @@ fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, ty::ty_bare_fn(_, ref fn_ty) => { let inh = Inherited::new(ccx.tcx, param_env); - // Compute the fty from point of view of inside fn - // (replace any type-scheme with a type, and normalize - // associated types appearing in the fn signature). - let fn_ty = fn_ty.subst(ccx.tcx, &inh.param_env.free_substs); - let fn_ty = inh.normalize_associated_types_in(body.span, body.id, &fn_ty); - - let fcx = check_fn(ccx, fn_ty.unsafety, id, &fn_ty.sig, + // Compute the fty from point of view of inside fn. + let fn_sig = + fn_ty.sig.subst(ccx.tcx, &inh.param_env.free_substs); + let fn_sig = + liberate_late_bound_regions(ccx.tcx, CodeExtent::from_node_id(body.id), &fn_sig); + let fn_sig = + inh.normalize_associated_types_in(body.span, body.id, &fn_sig); + + let fcx = check_fn(ccx, fn_ty.unsafety, id, &fn_sig, decl, id, body, &inh); vtable::select_all_fcx_obligations_or_error(&fcx); @@ -542,7 +544,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for GatherLocalsVisitor<'a, 'tcx> { fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>, unsafety: ast::Unsafety, unsafety_id: ast::NodeId, - fn_sig: &ty::PolyFnSig<'tcx>, + fn_sig: &ty::FnSig<'tcx>, decl: &ast::FnDecl, fn_id: ast::NodeId, body: &ast::Block, @@ -552,10 +554,6 @@ fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>, let tcx = ccx.tcx; let err_count_on_creation = tcx.sess.err_count(); - // First, we have to replace any bound regions in the fn type with free ones. - // The free region references will be bound the node_id of the body block. - let fn_sig = liberate_late_bound_regions(tcx, CodeExtent::from_node_id(body.id), fn_sig); - let arg_tys = fn_sig.inputs[]; let ret_ty = fn_sig.output; @@ -1161,39 +1159,80 @@ fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>, } } + // We now need to check that the signature of the impl method is + // compatible with that of the trait method. We do this by + // checking that `impl_fty <: trait_fty`. + // + // FIXME. Unfortunately, this doesn't quite work right now because + // associated type normalization is not integrated into subtype + // checks. For the comparison to be valid, we need to + // normalize the associated types in the impl/trait methods + // first. However, because function types bind regions, just + // calling `normalize_associated_types_in` would have no effect on + // any associated types appearing in the fn arguments or return + // type. + + // Compute skolemized form of impl and trait method tys. let impl_fty = ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(impl_m.fty.clone())); let impl_fty = impl_fty.subst(tcx, impl_to_skol_substs); let trait_fty = ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(trait_m.fty.clone())); let trait_fty = trait_fty.subst(tcx, &trait_to_skol_substs); - let trait_fty = - assoc::normalize_associated_types_in(&infcx, - &mut fulfillment_cx, - impl_m_span, - impl_m_body_id, - &trait_fty); - - // Check the impl method type IM is a subtype of the trait method - // type TM. To see why this makes sense, think of a vtable. The - // expected type of the function pointers in the vtable is the - // type TM of the trait method. The actual type will be the type - // IM of the impl method. Because we know that IM <: TM, that - // means that anywhere a TM is expected, a IM will do instead. In - // other words, anyone expecting to call a method with the type - // from the trait, can safely call a method with the type from the - // impl instead. - debug!("checking trait method for compatibility: impl ty {}, trait ty {}", - impl_fty.repr(tcx), - trait_fty.repr(tcx)); - match infer::mk_subty(&infcx, false, infer::MethodCompatCheck(impl_m_span), - impl_fty, trait_fty) { - Ok(()) => {} - Err(ref terr) => { + + let err = infcx.try(|snapshot| { + let origin = infer::MethodCompatCheck(impl_m_span); + + let (impl_sig, _) = + infcx.replace_late_bound_regions_with_fresh_var(impl_m_span, + infer::HigherRankedType, + &impl_m.fty.sig); + let impl_sig = + impl_sig.subst(tcx, impl_to_skol_substs); + let impl_sig = + assoc::normalize_associated_types_in(&infcx, + &mut fulfillment_cx, + impl_m_span, + impl_m_body_id, + &impl_sig); + let impl_fty = ty::mk_bare_fn(tcx, None, ty::BareFnTy { unsafety: impl_m.fty.unsafety, + abi: impl_m.fty.abi, + sig: ty::Binder(impl_sig) }); + debug!("compare_impl_method: impl_fty={}", + impl_fty.repr(tcx)); + + let (trait_sig, skol_map) = + infcx.skolemize_late_bound_regions(&trait_m.fty.sig, snapshot); + let trait_sig = + trait_sig.subst(tcx, &trait_to_skol_substs); + let trait_sig = + assoc::normalize_associated_types_in(&infcx, + &mut fulfillment_cx, + impl_m_span, + impl_m_body_id, + &trait_sig); + let trait_fty = ty::mk_bare_fn(tcx, None, ty::BareFnTy { unsafety: trait_m.fty.unsafety, + abi: trait_m.fty.abi, + sig: ty::Binder(trait_sig) }); + + debug!("compare_impl_method: trait_fty={}", + trait_fty.repr(tcx)); + + try!(infer::mk_subty(&infcx, false, origin, impl_fty, trait_fty)); + + infcx.leak_check(&skol_map, snapshot) + }); + + match err { + Ok(()) => { } + Err(terr) => { + debug!("checking trait method for compatibility: impl ty {}, trait ty {}", + impl_fty.repr(tcx), + trait_fty.repr(tcx)); span_err!(tcx.sess, impl_m_span, E0053, - "method `{}` has an incompatible type for trait: {}", - token::get_name(trait_m.name), - ty::type_err_to_str(tcx, terr)); - ty::note_and_explain_type_err(tcx, terr); + "method `{}` has an incompatible type for trait: {}", + token::get_name(trait_m.name), + ty::type_err_to_str(tcx, &terr)); + return; } } @@ -1791,7 +1830,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Also returns the substitution from the type parameters on `def_id` to the fresh variables. /// Registers any trait obligations specified on `def_id` at the same time. /// - /// Note that function is only intended to be used with types (notably, not impls). This is + /// Note that function is only intended to be used with types (notably, not fns). This is /// because it doesn't do any instantiation of late-bound regions. pub fn instantiate_type(&self, span: Span, @@ -3061,12 +3100,18 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, } }; - // Replace any bound regions that appear in the function - // signature with region variables + // Replace any late-bound regions that appear in the function + // signature with region variables. We also have to + // renormalize the associated types at this point, since they + // previously appeared within a `Binder<>` and hence would not + // have been normalized before. let fn_sig = fcx.infcx().replace_late_bound_regions_with_fresh_var(call_expr.span, infer::FnCall, fn_sig).0; + let fn_sig = + fcx.normalize_associated_types_in(call_expr.span, + &fn_sig); // Call the generic checker. check_argument_types(fcx, diff --git a/src/librustc_typeck/check/regionmanip.rs b/src/librustc_typeck/check/regionmanip.rs index 14405b9a92b59..c0b281450a2c0 100644 --- a/src/librustc_typeck/check/regionmanip.rs +++ b/src/librustc_typeck/check/regionmanip.rs @@ -104,7 +104,8 @@ impl<'a, 'tcx> Wf<'a, 'tcx> { ty::ty_enum(def_id, substs) | ty::ty_struct(def_id, substs) => { - self.accumulate_from_adt(ty, def_id, substs) + let item_scheme = ty::lookup_item_type(self.tcx, def_id); + self.accumulate_from_adt(ty, def_id, &item_scheme.generics, substs) } ty::ty_vec(t, _) | @@ -127,7 +128,9 @@ impl<'a, 'tcx> Wf<'a, 'tcx> { // TODO What region constraints are necessary here, if any?? // this seems like a minimal requirement: - self.accumulate_from_ty(data.trait_ref.self_ty()); + let trait_def = ty::lookup_trait_def(self.tcx, data.trait_ref.def_id); + self.accumulate_from_adt(ty, data.trait_ref.def_id, + &trait_def.generics, &data.trait_ref.substs) } ty::ty_tup(ref tuptys) => { @@ -222,14 +225,12 @@ impl<'a, 'tcx> Wf<'a, 'tcx> { fn accumulate_from_adt(&mut self, ty: Ty<'tcx>, def_id: ast::DefId, + generics: &ty::Generics<'tcx>, substs: &Substs<'tcx>) { // The generic declarations from the type, appropriately // substituted for the actual substitutions. - let generics = - ty::lookup_item_type(self.tcx, def_id) - .generics - .subst(self.tcx, substs); + let generics = generics.subst(self.tcx, substs); // Variance of each type/region parameter. let variances = ty::item_variances(self.tcx, def_id); diff --git a/src/librustc_typeck/check/wf.rs b/src/librustc_typeck/check/wf.rs index 21c81c7be9bfa..2a3f528809cfd 100644 --- a/src/librustc_typeck/check/wf.rs +++ b/src/librustc_typeck/check/wf.rs @@ -349,8 +349,7 @@ impl<'cx,'tcx> TypeFolder<'tcx> for BoundsChecker<'cx,'tcx> { // // (I believe we should do the same for traits, but // that will require an RFC. -nmatsakis) - let bounds = type_scheme -.generics.to_bounds(self.tcx(), substs); + let bounds = type_scheme.generics.to_bounds(self.tcx(), substs); let bounds = filter_to_trait_obligations(bounds); self.fcx.add_obligations_for_parameters( traits::ObligationCause::new(self.span, diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 1cd21ccac7a0e..40ca6354ca6d1 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -133,6 +133,9 @@ pub trait Visitor<'v> { fn visit_path_parameters(&mut self, path_span: Span, path_parameters: &'v PathParameters) { walk_path_parameters(self, path_span, path_parameters) } + fn visit_assoc_type_binding(&mut self, type_binding: &'v TypeBinding) { + walk_assoc_type_binding(self, type_binding) + } fn visit_attribute(&mut self, _attr: &'v Attribute) {} } @@ -467,6 +470,9 @@ pub fn walk_path_parameters<'v, V: Visitor<'v>>(visitor: &mut V, for lifetime in data.lifetimes.iter() { visitor.visit_lifetime_ref(lifetime); } + for binding in data.bindings.iter() { + visitor.visit_assoc_type_binding(&**binding); + } } ast::ParenthesizedParameters(ref data) => { for typ in data.inputs.iter() { @@ -479,6 +485,12 @@ pub fn walk_path_parameters<'v, V: Visitor<'v>>(visitor: &mut V, } } +pub fn walk_assoc_type_binding<'v, V: Visitor<'v>>(visitor: &mut V, + type_binding: &'v TypeBinding) { + visitor.visit_ident(type_binding.span, type_binding.ident); + visitor.visit_ty(&*type_binding.ty); +} + pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) { match pattern.node { PatEnum(ref path, ref children) => { From 7836c72ebae3124443fd4009b65eb2cc4cc6cf38 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 26 Dec 2014 15:37:56 -0500 Subject: [PATCH 17/36] Patch tests and create new tests related to projection from a HRTB. --- .../compile-fail/associated-types-eq-2.rs | 3 +- .../compile-fail/associated-types-eq-3.rs | 4 +- .../compile-fail/associated-types-eq-hr.rs | 72 ++++++++++++++++++ .../associated-types-in-ambiguous-context.rs | 10 --- .../associated-types-incomplete-object.rs | 44 +++++++++++ ... => associated-types-no-suitable-bound.rs} | 2 +- ...associated-types-no-suitable-supertrait.rs | 21 +++++ ...ciated-types-project-from-hrtb-explicit.rs | 28 +++++++ .../associated-types-project-from-hrtb-in-fn | Bin 0 -> 526235 bytes ...ated-types-project-from-hrtb-in-fn-body.rs | 37 +++++++++ ...ssociated-types-project-from-hrtb-in-fn.rs | 47 ++++++++++++ ...iated-types-project-from-hrtb-in-struct.rs | 36 +++++++++ ...types-project-from-hrtb-in-trait-method.rs | 35 +++++++++ .../trait-bounds-on-structs-and-enums.rs | 8 +- .../unsized-inherent-impl-self-type.rs | 20 +++++ .../unsized-trait-impl-self-type.rs | 22 ++++++ .../unsized-trait-impl-trait-arg.rs | 21 +++++ src/test/compile-fail/unsized4.rs | 2 +- src/test/compile-fail/unsized7.rs | 19 ----- .../{compile-fail => run-pass}/issue-19081.rs | 4 +- .../{compile-fail => run-pass}/issue-19121.rs | 4 +- 21 files changed, 399 insertions(+), 40 deletions(-) create mode 100644 src/test/compile-fail/associated-types-eq-hr.rs create mode 100644 src/test/compile-fail/associated-types-incomplete-object.rs rename src/test/compile-fail/{associated-types-in-wrong-context.rs => associated-types-no-suitable-bound.rs} (90%) create mode 100644 src/test/compile-fail/associated-types-no-suitable-supertrait.rs create mode 100644 src/test/compile-fail/associated-types-project-from-hrtb-explicit.rs create mode 100755 src/test/compile-fail/associated-types-project-from-hrtb-in-fn create mode 100644 src/test/compile-fail/associated-types-project-from-hrtb-in-fn-body.rs create mode 100644 src/test/compile-fail/associated-types-project-from-hrtb-in-fn.rs create mode 100644 src/test/compile-fail/associated-types-project-from-hrtb-in-struct.rs create mode 100644 src/test/compile-fail/associated-types-project-from-hrtb-in-trait-method.rs create mode 100644 src/test/compile-fail/unsized-inherent-impl-self-type.rs create mode 100644 src/test/compile-fail/unsized-trait-impl-self-type.rs create mode 100644 src/test/compile-fail/unsized-trait-impl-trait-arg.rs rename src/test/{compile-fail => run-pass}/issue-19081.rs (83%) rename src/test/{compile-fail => run-pass}/issue-19121.rs (83%) diff --git a/src/test/compile-fail/associated-types-eq-2.rs b/src/test/compile-fail/associated-types-eq-2.rs index 652bf4fb57753..b89cdd8c0eed7 100644 --- a/src/test/compile-fail/associated-types-eq-2.rs +++ b/src/test/compile-fail/associated-types-eq-2.rs @@ -25,6 +25,7 @@ impl Foo for int { fn boo(&self) -> uint { 42 } } -fn baz(x: &>::A) {} //~ERROR equality constraints are not allowed in this +fn baz(x: &>::A) {} +//~^ ERROR associated type bindings are not allowed here pub fn main() {} diff --git a/src/test/compile-fail/associated-types-eq-3.rs b/src/test/compile-fail/associated-types-eq-3.rs index 880b2e9cc4a77..e5974925d7370 100644 --- a/src/test/compile-fail/associated-types-eq-3.rs +++ b/src/test/compile-fail/associated-types-eq-3.rs @@ -43,6 +43,6 @@ pub fn baz(x: &Foo) { pub fn main() { let a = 42i; - foo1(a); //~ERROR the trait `Foo` is not implemented for the type `int` - baz(&a); //~ERROR the trait `Foo` is not implemented for the type `int` + foo1(a); //~ERROR expected uint, found struct Bar + baz(&a); //~ERROR expected uint, found struct Bar } diff --git a/src/test/compile-fail/associated-types-eq-hr.rs b/src/test/compile-fail/associated-types-eq-hr.rs new file mode 100644 index 0000000000000..aad55745c25df --- /dev/null +++ b/src/test/compile-fail/associated-types-eq-hr.rs @@ -0,0 +1,72 @@ +// Copyright 2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Check testing of equality constraints in a higher-ranked context. + +#![feature(associated_types)] + +pub trait TheTrait { + type A; + + fn get(&self, t: T) -> Self::A; +} + +struct IntStruct { + x: int +} + +impl<'a> TheTrait<&'a int> for IntStruct { + type A = &'a int; + + fn get(&self, t: &'a int) -> &'a int { + t + } +} + +struct UintStruct { + x: int +} + +impl<'a> TheTrait<&'a int> for UintStruct { + type A = &'a uint; + + fn get(&self, t: &'a int) -> &'a uint { + panic!() + } +} + +fn foo() + where T : for<'x> TheTrait<&'x int, A = &'x int> +{ + // ok for IntStruct, but not UintStruct +} + +fn bar() + where T : for<'x> TheTrait<&'x int, A = &'x uint> +{ + // ok for UintStruct, but not IntStruct +} + +fn baz() + where T : for<'x,'y> TheTrait<&'x int, A = &'y int> +{ + // not ok for either struct, due to the use of two lifetimes +} + +pub fn main() { + foo::(); + foo::(); //~ ERROR type mismatch + + bar::(); //~ ERROR type mismatch + bar::(); + + baz::(); //~ ERROR type mismatch + baz::(); //~ ERROR type mismatch +} diff --git a/src/test/compile-fail/associated-types-in-ambiguous-context.rs b/src/test/compile-fail/associated-types-in-ambiguous-context.rs index 24de1fa2f7844..fcd3e4d163646 100644 --- a/src/test/compile-fail/associated-types-in-ambiguous-context.rs +++ b/src/test/compile-fail/associated-types-in-ambiguous-context.rs @@ -18,16 +18,6 @@ trait Get { fn get(x: T, y: U) -> Get::Value {} //~^ ERROR ambiguous associated type -trait Other { - fn uhoh(&self, foo: U, bar: ::Value) {} - //~^ ERROR no suitable bound on `Self` -} - -impl Other for T { - fn uhoh(&self, foo: U, bar: <(T, U) as Get>::Value) {} - //~^ ERROR currently unsupported -} - trait Grab { type Value; fn grab(&self) -> Grab::Value; diff --git a/src/test/compile-fail/associated-types-incomplete-object.rs b/src/test/compile-fail/associated-types-incomplete-object.rs new file mode 100644 index 0000000000000..7e4e1315110af --- /dev/null +++ b/src/test/compile-fail/associated-types-incomplete-object.rs @@ -0,0 +1,44 @@ +// Copyright 2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Check that the user gets an errror if they omit a binding from an +// object type. + +#![feature(associated_types)] + +pub trait Foo { + type A; + type B; + fn boo(&self) -> ::A; +} + +struct Bar; + +impl Foo for int { + type A = uint; + type B = char; + fn boo(&self) -> uint { + 42 + } +} + +pub fn main() { + let a = &42i as &Foo; + + let b = &42i as &Foo; + //~^ ERROR the value of the associated type `B` (from the trait `Foo`) must be specified + + let c = &42i as &Foo; + //~^ ERROR the value of the associated type `A` (from the trait `Foo`) must be specified + + let d = &42i as &Foo; + //~^ ERROR the value of the associated type `A` (from the trait `Foo`) must be specified + //~| ERROR the value of the associated type `B` (from the trait `Foo`) must be specified +} diff --git a/src/test/compile-fail/associated-types-in-wrong-context.rs b/src/test/compile-fail/associated-types-no-suitable-bound.rs similarity index 90% rename from src/test/compile-fail/associated-types-in-wrong-context.rs rename to src/test/compile-fail/associated-types-no-suitable-bound.rs index 28a4ad01e23a9..6b85620409151 100644 --- a/src/test/compile-fail/associated-types-in-wrong-context.rs +++ b/src/test/compile-fail/associated-types-no-suitable-bound.rs @@ -21,7 +21,7 @@ struct Struct { impl Struct { fn uhoh(foo: ::Value) {} - //~^ ERROR no suitable bound on `T` + //~^ ERROR the trait `Get` is not implemented for the type `T` } fn main() { diff --git a/src/test/compile-fail/associated-types-no-suitable-supertrait.rs b/src/test/compile-fail/associated-types-no-suitable-supertrait.rs new file mode 100644 index 0000000000000..c4110a6946d9d --- /dev/null +++ b/src/test/compile-fail/associated-types-no-suitable-supertrait.rs @@ -0,0 +1,21 @@ +#![feature(associated_types)] + +// Check that we get an error when you use `::Value` in +// the trait definition but `Self` does not, in fact, implement `Get`. + +trait Get { + type Value; +} + +trait Other { + fn uhoh(&self, foo: U, bar: ::Value) {} + //~^ ERROR the trait `Get` is not implemented for the type `Self` +} + +impl Other for T { + fn uhoh(&self, foo: U, bar: <(T, U) as Get>::Value) {} + //~^ ERROR the trait `Get` is not implemented for the type `(T, U)` + //~| ERROR the trait `Get` is not implemented for the type `(T, U)` +} + +fn main() { } diff --git a/src/test/compile-fail/associated-types-project-from-hrtb-explicit.rs b/src/test/compile-fail/associated-types-project-from-hrtb-explicit.rs new file mode 100644 index 0000000000000..1f0f044a4c0c3 --- /dev/null +++ b/src/test/compile-fail/associated-types-project-from-hrtb-explicit.rs @@ -0,0 +1,28 @@ +// Copyright 2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test you can't use a higher-ranked trait bound inside of a qualified +// path (just won't parse). + +#![feature(associated_types)] + +pub trait Foo { + type A; + + fn get(&self, t: T) -> Self::A; +} + +fn foo2(x: Foo<&'x int>>::A) + //~^ ERROR expected identifier, found keyword `for` + //~| ERROR expected one of `::` or `>` +{ +} + +pub fn main() {} diff --git a/src/test/compile-fail/associated-types-project-from-hrtb-in-fn b/src/test/compile-fail/associated-types-project-from-hrtb-in-fn new file mode 100755 index 0000000000000000000000000000000000000000..6d2392c124b30170f239832200d833c3cd78d0e1 GIT binary patch literal 526235 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 X0sJIU0HqeO5M|Az$kkxYtG`DBwESL=i3 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 literal 0 HcmV?d00001 diff --git a/src/test/compile-fail/associated-types-project-from-hrtb-in-fn-body.rs b/src/test/compile-fail/associated-types-project-from-hrtb-in-fn-body.rs new file mode 100644 index 0000000000000..8cdca50d9b6bd --- /dev/null +++ b/src/test/compile-fail/associated-types-project-from-hrtb-in-fn-body.rs @@ -0,0 +1,37 @@ +// Copyright 2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Check projection of an associated type out of a higher-ranked +// trait-bound in the context of a function body. + +#![feature(associated_types)] + +pub trait Foo { + type A; + + fn get(&self, t: T) -> Self::A; +} + +fn foo<'a, I : for<'x> Foo<&'x int>>( + x: >::A) +{ + let y: I::A = x; +} + +fn bar<'a, 'b, I : for<'x> Foo<&'x int>>( + x: >::A, + y: >::A, + cond: bool) +{ //~ ERROR cannot infer + // x and y here have two distinct lifetimes: + let z: I::A = if cond { x } else { y }; +} + +pub fn main() {} diff --git a/src/test/compile-fail/associated-types-project-from-hrtb-in-fn.rs b/src/test/compile-fail/associated-types-project-from-hrtb-in-fn.rs new file mode 100644 index 0000000000000..0d5c69591423b --- /dev/null +++ b/src/test/compile-fail/associated-types-project-from-hrtb-in-fn.rs @@ -0,0 +1,47 @@ +// Copyright 2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Check projection of an associated type out of a higher-ranked trait-bound +// in the context of a function signature. + +#![feature(associated_types)] + +pub trait Foo { + type A; + + fn get(&self, t: T) -> Self::A; +} + +fn foo2 Foo<&'x int>>( + x: I::A) + //~^ ERROR cannot extract an associated type from a higher-ranked trait bound in this context +{ + // This case is illegal because we have to instantiate `'x`, and + // we don't know what region to instantiate it with. + // + // This could perhaps be made equivalent to the examples below, + // specifically for fn signatures. +} + +fn foo3 Foo<&'x int>>( + x: >::A) +{ + // OK, in this case we spelled out the precise regions involved, though we left one of + // them anonymous. +} + +fn foo4<'a, I : for<'x> Foo<&'x int>>( + x: >::A) +{ + // OK, in this case we spelled out the precise regions involved. +} + + +pub fn main() {} diff --git a/src/test/compile-fail/associated-types-project-from-hrtb-in-struct.rs b/src/test/compile-fail/associated-types-project-from-hrtb-in-struct.rs new file mode 100644 index 0000000000000..5016c6448a50e --- /dev/null +++ b/src/test/compile-fail/associated-types-project-from-hrtb-in-struct.rs @@ -0,0 +1,36 @@ +// Copyright 2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Check projection of an associated type out of a higher-ranked trait-bound +// in the context of a struct definition. + +#![feature(associated_types)] + +pub trait Foo { + type A; + + fn get(&self, t: T) -> Self::A; +} + +struct SomeStruct Foo<&'x int>> { + field: I::A + //~^ ERROR cannot extract an associated type from a higher-ranked trait bound in this context +} + +struct AnotherStruct Foo<&'x int>> { + field: >::A + //~^ ERROR missing lifetime specifier +} + +struct YetAnotherStruct<'a, I : for<'x> Foo<&'x int>> { + field: >::A +} + +pub fn main() {} diff --git a/src/test/compile-fail/associated-types-project-from-hrtb-in-trait-method.rs b/src/test/compile-fail/associated-types-project-from-hrtb-in-trait-method.rs new file mode 100644 index 0000000000000..a92d4ec04cb20 --- /dev/null +++ b/src/test/compile-fail/associated-types-project-from-hrtb-in-trait-method.rs @@ -0,0 +1,35 @@ +// Copyright 2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Check projection of an associated type out of a higher-ranked trait-bound +// in the context of a method definition in a trait. + +#![feature(associated_types)] + +pub trait Foo { + type A; + + fn get(&self, t: T) -> Self::A; +} + +trait SomeTrait Foo<&'x int>> { + fn some_method(&self, arg: I::A); + //~^ ERROR cannot extract an associated type from a higher-ranked trait bound in this context +} + +trait AnotherTrait Foo<&'x int>> { + fn some_method(&self, arg: >::A); +} + +trait YetAnotherTrait Foo<&'x int>> { + fn some_method<'a>(&self, arg: >::A); +} + +pub fn main() {} diff --git a/src/test/compile-fail/trait-bounds-on-structs-and-enums.rs b/src/test/compile-fail/trait-bounds-on-structs-and-enums.rs index 5fe8e435e6806..c11b5d2287855 100644 --- a/src/test/compile-fail/trait-bounds-on-structs-and-enums.rs +++ b/src/test/compile-fail/trait-bounds-on-structs-and-enums.rs @@ -41,14 +41,14 @@ enum Boo { Quux(Bar), } -struct Badness { +struct Badness { //~^ ERROR not implemented - b: Foo, + b: Foo, } -enum MoreBadness { +enum MoreBadness { //~^ ERROR not implemented - EvenMoreBadness(Bar), + EvenMoreBadness(Bar), } trait PolyTrait { diff --git a/src/test/compile-fail/unsized-inherent-impl-self-type.rs b/src/test/compile-fail/unsized-inherent-impl-self-type.rs new file mode 100644 index 0000000000000..2c8a2b361d596 --- /dev/null +++ b/src/test/compile-fail/unsized-inherent-impl-self-type.rs @@ -0,0 +1,20 @@ +// Copyright 2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test sized-ness checking in substitution in impls. + +// impl - struct + +struct S5; + +impl S5 { //~ ERROR not implemented +} + +fn main() { } diff --git a/src/test/compile-fail/unsized-trait-impl-self-type.rs b/src/test/compile-fail/unsized-trait-impl-self-type.rs new file mode 100644 index 0000000000000..0f0a97fab4d75 --- /dev/null +++ b/src/test/compile-fail/unsized-trait-impl-self-type.rs @@ -0,0 +1,22 @@ +// Copyright 2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test sized-ness checking in substitution in impls. + +// impl - struct +trait T3 { +} + +struct S5; + +impl T3 for S5 { //~ ERROR not implemented +} + +fn main() { } diff --git a/src/test/compile-fail/unsized-trait-impl-trait-arg.rs b/src/test/compile-fail/unsized-trait-impl-trait-arg.rs new file mode 100644 index 0000000000000..bdb652b168a8c --- /dev/null +++ b/src/test/compile-fail/unsized-trait-impl-trait-arg.rs @@ -0,0 +1,21 @@ +// Copyright 2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test sized-ness checking in substitution in impls. + +// impl - unbounded +trait T2 { +} +struct S4; +impl T2 for S4 { + //~^ ERROR `core::kinds::Sized` is not implemented for the type `X` +} + +fn main() { } diff --git a/src/test/compile-fail/unsized4.rs b/src/test/compile-fail/unsized4.rs index 253ec2a84ea52..0537fc1f94ad7 100644 --- a/src/test/compile-fail/unsized4.rs +++ b/src/test/compile-fail/unsized4.rs @@ -13,7 +13,7 @@ trait T {} fn f() { -//~^ERROR incompatible bounds on type parameter `Y`, bound `T` does not allow unsized type +//~^ERROR incompatible bounds on `Y`, bound `T` does not allow unsized type } pub fn main() { diff --git a/src/test/compile-fail/unsized7.rs b/src/test/compile-fail/unsized7.rs index fd9dffe00d2d5..c0e6ae1db92c4 100644 --- a/src/test/compile-fail/unsized7.rs +++ b/src/test/compile-fail/unsized7.rs @@ -21,23 +21,4 @@ impl T1 for S3 { //~^ ERROR `core::kinds::Sized` is not implemented for the type `X` } -// impl - unbounded -trait T2 { -} -struct S4; -impl T2 for S4 { - //~^ ERROR `core::kinds::Sized` is not implemented for the type `X` -} - -// impl - struct -trait T3 { -} -struct S5; -impl T3 for S5 { //~ ERROR not implemented -} - -impl S5 { //~ ERROR not implemented -} - - fn main() { } diff --git a/src/test/compile-fail/issue-19081.rs b/src/test/run-pass/issue-19081.rs similarity index 83% rename from src/test/compile-fail/issue-19081.rs rename to src/test/run-pass/issue-19081.rs index 2f42dbd77fd0d..aeb140874779d 100644 --- a/src/test/compile-fail/issue-19081.rs +++ b/src/test/run-pass/issue-19081.rs @@ -8,13 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-pretty -- currently pretty prints as `Hash<::State //~ ERROR no suitable bound on `Self` + ::State >>(&self, value: &T) -> u64; } diff --git a/src/test/compile-fail/issue-19121.rs b/src/test/run-pass/issue-19121.rs similarity index 83% rename from src/test/compile-fail/issue-19121.rs rename to src/test/run-pass/issue-19121.rs index 998c6a8253539..79afb856be26f 100644 --- a/src/test/compile-fail/issue-19121.rs +++ b/src/test/run-pass/issue-19121.rs @@ -17,6 +17,8 @@ trait Foo { type A; } -fn bar(x: &Foo) {} //~ERROR missing type for associated type `A` +fn bar(x: &Foo) {} +// FIXME(#19482) -- `Foo` should specify `A`, but this is not +// currently enforced except at object creation pub fn main() {} From adca15a151422a72d69c39ade946f36a2ff072a6 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 29 Dec 2014 11:00:56 -0500 Subject: [PATCH 18/36] Add a FIXME relating to using `ast::Name` --- src/librustc/middle/def.rs | 1 + src/librustc_typeck/astconv.rs | 3 +-- src/libsyntax/ast.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc/middle/def.rs b/src/librustc/middle/def.rs index 59fd41b5d29e3..ff1ee39496626 100644 --- a/src/librustc/middle/def.rs +++ b/src/librustc/middle/def.rs @@ -36,6 +36,7 @@ pub enum Def { // A partially resolved path to an associated type `T::U` where `T` is a concrete // type (indicated by the DefId) which implements a trait which has an associated // type `U` (indicated by the Ident). + // FIXME(#20301) -- should use Name DefAssociatedPath(TyParamProvenance, ast::Ident), DefTrait(ast::DefId), DefPrimTy(ast::PrimTy), diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 477171051640b..480bba16e6348 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -992,7 +992,7 @@ fn qpath_to_ty<'tcx,AC,RS>(this: &AC, return this.projected_ty(ast_ty.span, trait_ref, - qpath.item_name.name); // TODO change qpath to use name + qpath.item_name.name); } // Parses the programmer's textual representation of a type into our @@ -1155,7 +1155,6 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( this.tcx().types.err } def::DefAssociatedPath(provenance, assoc_ident) => { - // TODO update DefAssociatedPath to use name associated_path_def_to_ty(this, ast_ty, provenance, assoc_ident.name) } _ => { diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index f253943943dcc..12432c8c78f2c 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -764,7 +764,7 @@ pub enum Expr_ { pub struct QPath { pub self_type: P, pub trait_ref: P, - pub item_name: Ident, + pub item_name: Ident, // FIXME(#20301) -- should use Name } #[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show, Copy)] From df967306e3f9b26ca089fbb59e1f961f913b89fd Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 29 Dec 2014 11:01:11 -0500 Subject: [PATCH 19/36] Add a FIXME relating to Copy not being checked --- src/librustc_typeck/astconv.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 480bba16e6348..70abfa724ed34 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1738,7 +1738,7 @@ pub fn partition_bounds<'a>(tcx: &ty::ctxt, if ty::try_add_builtin_trait(tcx, trait_did, &mut builtin_bounds) { - // TODO Copy? + // FIXME(#20302) -- we should check for things like Copy continue; // success } } From 58467fab0f4e5be4d7fbc8a6c774aea500ec1f47 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 29 Dec 2014 11:02:07 -0500 Subject: [PATCH 20/36] File a FIXME relating to using where clauses, not bounds --- src/librustc_typeck/astconv.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 70abfa724ed34..82a023202097f 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -925,7 +925,7 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>, // super-traits. Probably by elaborating the bounds. suitable_bounds = - ty_param_def.bounds.trait_bounds // TODO trait_bounds, no good + ty_param_def.bounds.trait_bounds // FIXME(#20300) -- search where clauses, not bounds .iter() .cloned() .filter(|b| trait_defines_associated_type_named(this, b.def_id(), assoc_name)) From d62d4953d29462fe1e4af04e6016160d25bb0a71 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 29 Dec 2014 11:02:24 -0500 Subject: [PATCH 21/36] Add a FIXME to patch up rustdoc --- src/librustdoc/clean/mod.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index b4bfaa9afdabe..467f34261ba78 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -506,7 +506,9 @@ impl<'tcx> Clean> for ty::ExistentialBounds<'tcx> { for bb in self.builtin_bounds.iter() { vec.push(bb.clean(cx)); } - // TODO projection bounds + + // FIXME(#20299) -- should do something with projection bounds + vec } } From 97d8a668f66377c5adb85e89c2fa207e9d4a511c Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 29 Dec 2014 11:02:37 -0500 Subject: [PATCH 22/36] Add a FIXME relating to regions and projection types --- src/librustc_typeck/check/regionmanip.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/librustc_typeck/check/regionmanip.rs b/src/librustc_typeck/check/regionmanip.rs index c0b281450a2c0..8d9e241e73beb 100644 --- a/src/librustc_typeck/check/regionmanip.rs +++ b/src/librustc_typeck/check/regionmanip.rs @@ -125,7 +125,8 @@ impl<'a, 'tcx> Wf<'a, 'tcx> { ty::ty_projection(ref data) => { // `>::Name` - // TODO What region constraints are necessary here, if any?? + // FIXME(#20303) -- gain ability to require that ty_projection : in-scope region, + // like a type parameter // this seems like a minimal requirement: let trait_def = ty::lookup_trait_def(self.tcx, data.trait_ref.def_id); From 00cf176a5ee694907e5bddd5ff56d5e318e0edc8 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 29 Dec 2014 11:03:04 -0500 Subject: [PATCH 23/36] Add FIXMEs relating to caching of projection results --- src/librustc/middle/traits/fulfill.rs | 2 ++ src/librustc_trans/trans/monomorphize.rs | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/librustc/middle/traits/fulfill.rs b/src/librustc/middle/traits/fulfill.rs index e72d5b405c4e4..b55504da237af 100644 --- a/src/librustc/middle/traits/fulfill.rs +++ b/src/librustc/middle/traits/fulfill.rs @@ -115,6 +115,8 @@ impl<'tcx> FulfillmentContext<'tcx> { assert!(!trait_ref.has_escaping_regions()); + // FIXME(#20304) -- cache + let ty_var = infcx.next_ty_var(); let projection = ty::Binder(ty::ProjectionPredicate { diff --git a/src/librustc_trans/trans/monomorphize.rs b/src/librustc_trans/trans/monomorphize.rs index dcfe5f40ecee9..6e52454fa783d 100644 --- a/src/librustc_trans/trans/monomorphize.rs +++ b/src/librustc_trans/trans/monomorphize.rs @@ -319,7 +319,7 @@ pub fn normalize_associated_type<'tcx,T>(tcx: &ty::ctxt<'tcx>, t: &T) -> T return t.clone(); } - // TODO cache + // FIXME(#20304) -- cache let infcx = infer::new_infer_ctxt(tcx); let param_env = ty::empty_parameter_environment(); From f1c041a54d89dad7d8857d84dd3424624e32486a Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 29 Dec 2014 11:05:35 -0500 Subject: [PATCH 24/36] Patch long line. --- src/librustc/middle/traits/select.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index 9301531e84d5e..4ca98a6de64be 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -1259,12 +1259,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } else { // Recursively check all supertraits to find out if any further // bounds are required and thus we must fulfill. - let tmp_tr = + let principal = data.principal_trait_ref_with_self_ty(self.tcx(), self.tcx().types.err); - for tr in util::supertraits(self.tcx(), tmp_tr) { + for tr in util::supertraits(self.tcx(), principal) { let td = ty::lookup_trait_def(self.tcx(), tr.def_id()); - if td.bounds.builtin_bounds.contains(&bound) { return Ok(If(Vec::new())) } From c197911c60ce7eaea53ecb357d0409d3e38ff914 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 29 Dec 2014 11:06:15 -0500 Subject: [PATCH 25/36] Add a FIXME relating to these type-testing traits --- src/librustc/middle/ty.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 583d2ce3b67c2..0f3037c06fd34 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -6876,8 +6876,8 @@ pub fn can_type_implement_copy<'tcx>(tcx: &ctxt<'tcx>, Ok(()) } -// TODO -- all of these types basically walk various structures to -// test whether types/regions are reachable with various +// FIXME(#20298) -- all of these types basically walk various +// structures to test whether types/regions are reachable with various // properties. It should be possible to express them in terms of one // common "walker" trait or something. From 05eb2eeb61985f481982285ae7714d5cc0d7bdb7 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 29 Dec 2014 11:22:16 -0500 Subject: [PATCH 26/36] Adjust tests for inferenceGet more conservative about inference for now. Seems better to err on the side of being more correct rather than less. Fix a bug in typing index expressions that was exposed as a result, and add one type annotation that is not required. Delete some random tests that were relying on old behavior and don't seem to add anything anymore. --- src/librustc/metadata/decoder.rs | 2 +- src/librustc/middle/traits/select.rs | 11 ++-- src/librustc_typeck/check/method/confirm.rs | 15 ++++-- .../associated-types-bound-failure.rs} | 35 +++++++----- .../{run-pass => compile-fail}/issue-12028.rs | 7 ++- src/test/run-pass/associated-types-bound.rs | 53 +++++++++++++++++++ 6 files changed, 100 insertions(+), 23 deletions(-) rename src/test/{run-pass/multidispatch-infer-from-single-impl.rs => compile-fail/associated-types-bound-failure.rs} (51%) rename src/test/{run-pass => compile-fail}/issue-12028.rs (79%) create mode 100644 src/test/run-pass/associated-types-bound.rs diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index c189aed05abf1..0a001d475046a 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -1366,7 +1366,7 @@ pub fn get_dylib_dependency_formats(cdata: Cmd) if spec.len() == 0 { continue } let cnum = spec.split(':').nth(0).unwrap(); let link = spec.split(':').nth(1).unwrap(); - let cnum = cnum.parse().unwrap(); + let cnum: ast::CrateNum = cnum.parse().unwrap(); let cnum = match cdata.cnum_map.get(&cnum) { Some(&n) => n, None => panic!("didn't find a crate in the cnum_map") diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index 4ca98a6de64be..9670ebdb03c79 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -736,10 +736,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let trait_def_id = match poly_trait_predicate.0.trait_ref.self_ty().sty { ty::ty_projection(ref data) => data.trait_ref.def_id, ty::ty_infer(ty::TyVar(_)) => { - // TODO ignore potential ambiguity so that we can do - // better inference, need to get our story - // straight(er) here, I think. - // candidates.ambiguous = true; + // If the self-type is an inference variable, then it MAY wind up + // being a projected type, so induce an ambiguity. + // + // FIXME(#20297) -- being strict about this can cause + // inference failures with BorrowFrom, which is + // unfortunate. Can we do better here? + candidates.ambiguous = true; return; } _ => { return; } diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 1aa9adaf9ec4d..9704439c468b2 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -10,7 +10,8 @@ use super::probe; -use check::{mod, FnCtxt, NoPreference, PreferMutLvalue, callee}; +use check::{mod, FnCtxt, NoPreference, PreferMutLvalue, callee, demand}; +use middle::mem_categorization::Typer; use middle::subst::{mod}; use middle::traits; use middle::ty::{mod, Ty}; @@ -540,7 +541,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { // Don't retry the first one or we might infinite loop! if i != 0 { match expr.node { - ast::ExprIndex(ref base_expr, _) => { + ast::ExprIndex(ref base_expr, ref index_expr) => { let mut base_adjustment = match self.fcx.inh.adjustments.borrow().get(&base_expr.id) { Some(&ty::AdjustDerefRef(ref adr)) => (*adr).clone(), @@ -576,7 +577,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { &**base_expr, Some(&ty::AdjustDerefRef(base_adjustment.clone()))); - check::try_index_step( + let result = check::try_index_step( self.fcx, MethodCall::expr(expr.id), *expr, @@ -584,6 +585,14 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { adjusted_base_ty, base_adjustment, PreferMutLvalue); + + if let Some((input_ty, return_ty)) = result { + let index_expr_ty = self.fcx.expr_ty(&**index_expr); + demand::suptype(self.fcx, index_expr.span, input_ty, index_expr_ty); + + let expr_ty = self.fcx.expr_ty(&**expr); + demand::suptype(self.fcx, expr.span, expr_ty, return_ty); + } } ast::ExprUnary(ast::UnDeref, ref base_expr) => { // if this is an overloaded deref, then re-evaluate with diff --git a/src/test/run-pass/multidispatch-infer-from-single-impl.rs b/src/test/compile-fail/associated-types-bound-failure.rs similarity index 51% rename from src/test/run-pass/multidispatch-infer-from-single-impl.rs rename to src/test/compile-fail/associated-types-bound-failure.rs index f4ca67548fd53..7981fe3182712 100644 --- a/src/test/run-pass/multidispatch-infer-from-single-impl.rs +++ b/src/test/compile-fail/associated-types-bound-failure.rs @@ -8,25 +8,32 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Test that we correctly infer that `E` must be `()` here. This is -// known because there is just one impl that could apply where -// `Self=()`. +// Test equality constraints on associated types in a where clause. -pub trait FromError { - fn from_error(err: E) -> Self; +#![feature(associated_types)] + +pub trait ToInt { + fn to_int(&self) -> int; +} + +pub trait GetToInt +{ + type R; + + fn get(&self) -> ::R; } -impl FromError for E { - fn from_error(err: E) -> E { - err - } +fn foo(g: G) -> int + where G : GetToInt +{ + ToInt::to_int(&g.get()) //~ ERROR not implemented } -fn test() -> Result<(), ()> { - Err(FromError::from_error(())) +fn bar(g: G) -> int + where G::R : ToInt +{ + ToInt::to_int(&g.get()) // OK } -fn main() { - let result = (|| Err(FromError::from_error(())))(); - let foo: () = result.unwrap_or(()); +pub fn main() { } diff --git a/src/test/run-pass/issue-12028.rs b/src/test/compile-fail/issue-12028.rs similarity index 79% rename from src/test/run-pass/issue-12028.rs rename to src/test/compile-fail/issue-12028.rs index dbfa330d33d9e..78502efdec520 100644 --- a/src/test/run-pass/issue-12028.rs +++ b/src/test/compile-fail/issue-12028.rs @@ -8,6 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// Test an example where we fail to infer the type parameter H. This +// is because there is really nothing constraining it. At one time, we +// would infer based on the where clauses in scope, but that no longer +// works. + trait Hash { fn hash2(&self, hasher: &H) -> u64; } @@ -30,7 +35,7 @@ trait StreamHash>: Hash { impl> Hash for u8 { fn hash2(&self, hasher: &H) -> u64 { let mut stream = hasher.stream(); - self.input_stream(&mut stream); + self.input_stream(&mut stream); //~ ERROR type annotations required stream.result() } } diff --git a/src/test/run-pass/associated-types-bound.rs b/src/test/run-pass/associated-types-bound.rs new file mode 100644 index 0000000000000..db5119132cc3f --- /dev/null +++ b/src/test/run-pass/associated-types-bound.rs @@ -0,0 +1,53 @@ +// Copyright 2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test equality constraints on associated types in a where clause. + +#![feature(associated_types)] + +pub trait ToInt { + fn to_int(&self) -> int; +} + +impl ToInt for int { + fn to_int(&self) -> int { *self } +} + +impl ToInt for uint { + fn to_int(&self) -> int { *self as int } +} + +pub trait GetToInt +{ + type R : ToInt; + + fn get(&self) -> ::R; +} + +impl GetToInt for int { + type R = int; + fn get(&self) -> int { *self } +} + +impl GetToInt for uint { + type R = uint; + fn get(&self) -> uint { *self } +} + +fn foo(g: G) -> int + where G : GetToInt +{ + ToInt::to_int(&g.get()) +} + +pub fn main() { + assert_eq!(foo(22i), 22i); + assert_eq!(foo(22u), 22i); +} From 7ed0e2320975a00c3a61cef72d56c5fae8f3c608 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 29 Dec 2014 13:41:25 -0500 Subject: [PATCH 27/36] Resolve merge conflicts. This changes should really be integrated back to their respective commits but oh dear what a pain. --- src/librustc/middle/traits/project.rs | 7 ++++--- src/librustc/middle/traits/select.rs | 2 +- src/librustc/middle/ty.rs | 22 ++++++++++++---------- src/librustc_trans/trans/debuginfo.rs | 4 ++-- src/librustc_trans/trans/expr.rs | 2 +- src/librustc_trans/trans/monomorphize.rs | 1 + src/librustc_typeck/check/closure.rs | 4 +++- src/librustc_typeck/check/method/mod.rs | 2 +- src/librustc_typeck/check/mod.rs | 18 ++++++++++++------ src/librustc_typeck/check/regionmanip.rs | 2 +- src/librustc_typeck/check/vtable.rs | 3 ++- src/librustc_typeck/collect.rs | 4 +--- src/librustc_typeck/variance.rs | 7 ++++--- 13 files changed, 45 insertions(+), 33 deletions(-) diff --git a/src/librustc/middle/traits/project.rs b/src/librustc/middle/traits/project.rs index 43f97de2d4383..d319e44141519 100644 --- a/src/librustc/middle/traits/project.rs +++ b/src/librustc/middle/traits/project.rs @@ -222,9 +222,10 @@ fn assemble_candidates_from_object_type<'cx,'tcx>( ty::ty_trait(ref data) => data, _ => { return; } }; - let env_predicates = data.projection_bounds_with_self_ty(self_ty).iter() - .map(|p| p.as_predicate()) - .collect(); + let projection_bounds = data.projection_bounds_with_self_ty(selcx.tcx(), self_ty); + let env_predicates = projection_bounds.iter() + .map(|p| p.as_predicate()) + .collect(); assemble_candidates_from_predicates(selcx, obligation, candidate_set, env_predicates) } diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index 9670ebdb03c79..91f1b50521d4f 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -791,7 +791,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { projection_trait_ref.repr(self.tcx())); let trait_def = ty::lookup_trait_def(self.tcx(), projection_trait_ref.def_id); - let bounds = trait_def.generics.to_bounds(self.tcx(), &projection_trait_ref.substs); + let bounds = trait_def.generics.to_bounds(self.tcx(), projection_trait_ref.substs); debug!("match_projection_obligation_against_bounds_from_trait: \ bounds={}", bounds.repr(self.tcx())); diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 0f3037c06fd34..caec56800c63a 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -914,7 +914,7 @@ impl<'tcx> ctxt<'tcx> { sty_debug_print!( self, ty_enum, ty_uniq, ty_vec, ty_ptr, ty_rptr, ty_bare_fn, ty_closure, ty_trait, - ty_struct, ty_unboxed_closure, ty_tup, ty_param, ty_open, ty_infer); + ty_struct, ty_unboxed_closure, ty_tup, ty_param, ty_open, ty_infer, ty_projection); println!("Substs interner: #{}", self.substs_interner.borrow().len()); println!("BareFnTy interner: #{}", self.bare_fn_interner.borrow().len()); @@ -1352,7 +1352,7 @@ pub enum sty<'tcx> { ty_closure(Box>), ty_trait(Box>), - ty_struct(DefId, Substs<'tcx>), + ty_struct(DefId, &'tcx Substs<'tcx>), ty_unboxed_closure(DefId, &'tcx Region, &'tcx Substs<'tcx>), @@ -1402,7 +1402,9 @@ impl<'tcx> TyTrait<'tcx> { })) } - pub fn projection_bounds_with_self_ty(&self, self_ty: Ty<'tcx>) + pub fn projection_bounds_with_self_ty(&self, + tcx: &ctxt<'tcx>, + self_ty: Ty<'tcx>) -> Vec> { // otherwise the escaping regions would be captured by the binders @@ -1411,10 +1413,10 @@ impl<'tcx> TyTrait<'tcx> { self.bounds.projection_bounds.iter() .map(|in_poly_projection_predicate| { let in_projection_ty = &in_poly_projection_predicate.0.projection_ty; + let substs = tcx.mk_substs(in_projection_ty.trait_ref.substs.with_self_ty(self_ty)); let trait_ref = - Rc::new(ty::TraitRef::new( - in_projection_ty.trait_ref.def_id, - in_projection_ty.trait_ref.substs.with_self_ty(self_ty))); + Rc::new(ty::TraitRef::new(in_projection_ty.trait_ref.def_id, + substs)); let projection_ty = ty::ProjectionTy { trait_ref: trait_ref, item_name: in_projection_ty.item_name @@ -2286,7 +2288,7 @@ pub fn mk_ctxt<'tcx>(s: Session, ctxt { arenas: arenas, - interner: RefCell::new(FnvHashMap::new()), + interner: RefCell::new(interner), substs_interner: RefCell::new(FnvHashMap::new()), bare_fn_interner: RefCell::new(FnvHashMap::new()), region_interner: RefCell::new(FnvHashMap::new()), @@ -2386,7 +2388,7 @@ impl<'tcx> ctxt<'tcx> { // and returns the box as cast to an unsafe ptr (see comments for Ty above). pub fn mk_t<'tcx>(cx: &ctxt<'tcx>, st: sty<'tcx>) -> Ty<'tcx> { let mut interner = cx.interner.borrow_mut(); - intern_ty(cx.type_arena, &mut *interner, st) + intern_ty(&cx.arenas.type_, &mut *interner, st) } fn intern_ty<'tcx>(type_arena: &'tcx TypedArena>, @@ -2501,12 +2503,12 @@ impl FlagComputation { &ty_projection(ref data) => { self.add_flags(HAS_PROJECTION); - self.add_substs(&data.trait_ref.substs); + self.add_substs(data.trait_ref.substs); } &ty_trait(box TyTrait { ref principal, ref bounds }) => { let mut computation = FlagComputation::new(); - computation.add_substs(&principal.0.substs); + computation.add_substs(principal.0.substs); self.add_bound_computation(&computation); self.add_bounds(bounds); diff --git a/src/librustc_trans/trans/debuginfo.rs b/src/librustc_trans/trans/debuginfo.rs index e94ce55e704a8..b5b1c6ff86479 100644 --- a/src/librustc_trans/trans/debuginfo.rs +++ b/src/librustc_trans/trans/debuginfo.rs @@ -428,7 +428,7 @@ impl<'tcx> TypeMap<'tcx> { from_def_id_and_substs(self, cx, trait_data.principal_def_id(), - &trait_data.principal.0.substs, + trait_data.principal.0.substs, &mut unique_type_id); }, ty::ty_bare_fn(_, &ty::BareFnTy{ unsafety, abi, ref sig } ) => { @@ -3819,7 +3819,7 @@ fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, }, ty::ty_trait(ref trait_data) => { push_item_name(cx, trait_data.principal_def_id(), false, output); - push_type_params(cx, &trait_data.principal.0.substs, output); + push_type_params(cx, trait_data.principal.0.substs, output); }, ty::ty_bare_fn(_, &ty::BareFnTy{ unsafety, abi, ref sig } ) => { if unsafety == ast::Unsafety::Unsafe { diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs index 5a7131cf68ecb..5a20a297fdb09 100644 --- a/src/librustc_trans/trans/expr.rs +++ b/src/librustc_trans/trans/expr.rs @@ -321,7 +321,7 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, &ty::UnsizeVtable(ty::TyTrait { ref principal, .. }, _) => { // Note that we preserve binding levels here: let substs = principal.0.substs.with_self_ty(unadjusted_ty).erase_regions(); - let substs = tcx.tcx().mk_substs(substs); + let substs = bcx.tcx().mk_substs(substs); let trait_ref = ty::Binder(Rc::new(ty::TraitRef { def_id: principal.def_id(), substs: substs })); diff --git a/src/librustc_trans/trans/monomorphize.rs b/src/librustc_trans/trans/monomorphize.rs index 6e52454fa783d..3b7043e4f40f0 100644 --- a/src/librustc_trans/trans/monomorphize.rs +++ b/src/librustc_trans/trans/monomorphize.rs @@ -348,6 +348,7 @@ impl<'a,'tcx> TypeFolder<'tcx> for AssociatedTypeNormalizer<'a,'tcx> { let tcx = self.selcx.tcx(); let substs = data.trait_ref.substs.clone().erase_regions(); + let substs = self.tcx().mk_substs(substs); assert!(substs.types.iter().all(|&t| (!ty::type_has_params(t) && !ty::type_has_self(t)))); let trait_ref = Rc::new(ty::TraitRef::new(data.trait_ref.def_id, substs)); diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 340cc9b355c02..85ead053d1d29 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -172,7 +172,9 @@ fn deduce_unboxed_closure_expectations_from_expected_type<'a,'tcx>( { match expected_ty.sty { ty::ty_trait(ref object_type) => { - let trait_ref = object_type.principal_trait_ref_with_self_ty(fcx.tcx().types.err); + let trait_ref = + object_type.principal_trait_ref_with_self_ty(fcx.tcx(), + fcx.tcx().types.err); deduce_unboxed_closure_expectations_from_trait_ref(fcx, &trait_ref) } ty::ty_infer(ty::TyVar(vid)) => { diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 5b6acdbf3ada5..e483609407175 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -199,7 +199,7 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>, let fn_sig = fcx.infcx().replace_late_bound_regions_with_fresh_var(span, infer::FnCall, &method_ty.fty.sig).0; - let fn_sig = fcx.instantiate_type_scheme(span, &trait_ref.substs, &fn_sig); + let fn_sig = fcx.instantiate_type_scheme(span, trait_ref.substs, &fn_sig); let transformed_self_ty = fn_sig.inputs[0]; let fty = ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(ty::BareFnTy { sig: ty::Binder(fn_sig), diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index e485e49148fe4..a11f7b15e03a5 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1194,9 +1194,12 @@ fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>, impl_m_span, impl_m_body_id, &impl_sig); - let impl_fty = ty::mk_bare_fn(tcx, None, ty::BareFnTy { unsafety: impl_m.fty.unsafety, - abi: impl_m.fty.abi, - sig: ty::Binder(impl_sig) }); + let impl_fty = + ty::mk_bare_fn(tcx, + None, + tcx.mk_bare_fn(ty::BareFnTy { unsafety: impl_m.fty.unsafety, + abi: impl_m.fty.abi, + sig: ty::Binder(impl_sig) })); debug!("compare_impl_method: impl_fty={}", impl_fty.repr(tcx)); @@ -1210,9 +1213,12 @@ fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>, impl_m_span, impl_m_body_id, &trait_sig); - let trait_fty = ty::mk_bare_fn(tcx, None, ty::BareFnTy { unsafety: trait_m.fty.unsafety, - abi: trait_m.fty.abi, - sig: ty::Binder(trait_sig) }); + let trait_fty = + ty::mk_bare_fn(tcx, + None, + tcx.mk_bare_fn(ty::BareFnTy { unsafety: trait_m.fty.unsafety, + abi: trait_m.fty.abi, + sig: ty::Binder(trait_sig) })); debug!("compare_impl_method: trait_fty={}", trait_fty.repr(tcx)); diff --git a/src/librustc_typeck/check/regionmanip.rs b/src/librustc_typeck/check/regionmanip.rs index 8d9e241e73beb..bb051ab15250c 100644 --- a/src/librustc_typeck/check/regionmanip.rs +++ b/src/librustc_typeck/check/regionmanip.rs @@ -131,7 +131,7 @@ impl<'a, 'tcx> Wf<'a, 'tcx> { // this seems like a minimal requirement: let trait_def = ty::lookup_trait_def(self.tcx, data.trait_ref.def_id); self.accumulate_from_adt(ty, data.trait_ref.def_id, - &trait_def.generics, &data.trait_ref.substs) + &trait_def.generics, data.trait_ref.substs) } ty::ty_tup(ref tuptys) => { diff --git a/src/librustc_typeck/check/vtable.rs b/src/librustc_typeck/check/vtable.rs index f5cbfcdcc5216..23a8643aadcf5 100644 --- a/src/librustc_typeck/check/vtable.rs +++ b/src/librustc_typeck/check/vtable.rs @@ -389,7 +389,8 @@ pub fn register_object_cast_obligations<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, } // Finally, create obligations for the projection predicates. - let projection_bounds = object_trait.projection_bounds_with_self_ty(referent_ty); + let projection_bounds = + object_trait.projection_bounds_with_self_ty(fcx.tcx(), referent_ty); for projection_bound in projection_bounds.iter() { let projection_obligation = Obligation::new(cause.clone(), projection_bound.as_predicate()); diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 1187baa9a9ce9..da591ca04b745 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -838,8 +838,6 @@ pub fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, generics, items); - assert_eq!(mk_item_substs(ccx, &ty_generics), substs); - let self_param_ty = ty::ParamTy::for_self(); let bounds = compute_bounds(ccx, @@ -1476,7 +1474,7 @@ pub fn ty_of_foreign_fn_decl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, sig: ty::Binder(ty::FnSig {inputs: input_tys, output: output, variadic: decl.variadic}), - }); + })); let scheme = TypeScheme { generics: ty_generics_for_fn_or_method, ty: t_fn diff --git a/src/librustc_typeck/variance.rs b/src/librustc_typeck/variance.rs index 2914895aa7a73..c4c33f24f87e2 100644 --- a/src/librustc_typeck/variance.rs +++ b/src/librustc_typeck/variance.rs @@ -787,12 +787,13 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { trait_ref.def_id, trait_def.generics.types.as_slice(), trait_def.generics.regions.as_slice(), - &trait_ref.substs, + trait_ref.substs, variance); } ty::ty_trait(ref data) => { - let trait_ref = data.principal_trait_ref_with_self_ty(self.tcx().types.err); + let trait_ref = data.principal_trait_ref_with_self_ty(self.tcx(), + self.tcx().types.err); let trait_def = ty::lookup_trait_def(self.tcx(), trait_ref.def_id()); // Traits never declare region parameters in the self @@ -815,7 +816,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { } ty::ty_param(ref data) => { - let def_id = generics.types.get(data.space, data.idx).def_id; + let def_id = generics.types.get(data.space, data.idx as uint).def_id; assert_eq!(def_id.krate, ast::LOCAL_CRATE); match self.terms_cx.inferred_map.get(&def_id.node) { Some(&index) => { From c1bc150bc43de8f8895c9d87dddf9b915eddbb2e Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 29 Dec 2014 14:38:16 -0500 Subject: [PATCH 28/36] Correct licenses. --- src/librustc_typeck/check/assoc.rs | 1 - .../associated-types-no-suitable-supertrait.rs | 10 ++++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/librustc_typeck/check/assoc.rs b/src/librustc_typeck/check/assoc.rs index b59f9291e4fc6..c20dd5aebaddb 100644 --- a/src/librustc_typeck/check/assoc.rs +++ b/src/librustc_typeck/check/assoc.rs @@ -1,6 +1,5 @@ // Copyright 2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at -// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + #![feature(associated_types)] // Check that we get an error when you use `::Value` in From 30e8ab01822632acd08f6c4fb5ce6b2afe82af52 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 4 Dec 2014 09:00:16 -0500 Subject: [PATCH 29/36] Encode the name for associated items on a trait. Fixes #18048. --- src/librustc/metadata/encoder.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index e541768b3578e..9378ff028e0a9 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -1398,6 +1398,8 @@ fn encode_info_for_item(ecx: &EncodeContext, ty::StaticExplicitSelfCategory; } ty::TypeTraitItem(associated_type) => { + encode_name(rbml_w, associated_type.name); + let elem = ast_map::PathName(associated_type.name); encode_path(rbml_w, path.clone().chain(Some(elem).into_iter())); From 42e645ca9acb7166623bee25dd4143dd266ae4a7 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 4 Dec 2014 10:29:41 -0500 Subject: [PATCH 30/36] Patch more metadata decoding problems. --- src/librustc/metadata/decoder.rs | 11 ++++++----- src/librustc/metadata/encoder.rs | 3 ++- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index 0a001d475046a..a168ac7fa9a78 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -172,14 +172,15 @@ fn item_visibility(item: rbml::Doc) -> ast::Visibility { } fn item_sort(item: rbml::Doc) -> char { - // NB(pcwalton): The default of 'r' here is relied upon in - // `is_associated_type` below. - let mut ret = 'r'; + let mut ret = None; reader::tagged_docs(item, tag_item_trait_item_sort, |doc| { - ret = doc.as_str_slice().as_bytes()[0] as char; + ret = Some(doc.as_str_slice().as_bytes()[0] as char); false }); - ret + match ret { + Some(r) => r, + None => panic!("No item_sort found") + } } fn item_symbol(item: rbml::Doc) -> String { diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 9378ff028e0a9..20e7cb63133df 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -898,7 +898,7 @@ fn encode_info_for_associated_type(ecx: &EncodeContext, encode_visibility(rbml_w, associated_type.vis); encode_family(rbml_w, 'y'); encode_parent_item(rbml_w, local_def(parent_id)); - encode_item_sort(rbml_w, 'r'); + encode_item_sort(rbml_w, 't'); let stab = stability::lookup(ecx.tcx, associated_type.def_id); encode_stability(rbml_w, stab); @@ -1404,6 +1404,7 @@ fn encode_info_for_item(ecx: &EncodeContext, encode_path(rbml_w, path.clone().chain(Some(elem).into_iter())); + encode_item_sort(rbml_w, 't'); encode_family(rbml_w, 'y'); is_nonstatic_method = false; From de8e0ae22cd10aac86acbfedd8d1f411117de93e Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 29 Dec 2014 16:32:12 -0500 Subject: [PATCH 31/36] Remove the AssocSpace --- src/librustc/middle/astencode.rs | 3 +- src/librustc/middle/infer/mod.rs | 5 +- src/librustc/middle/subst.rs | 65 +++++------------- src/librustc/middle/traits/select.rs | 5 +- src/librustc/middle/traits/util.rs | 15 +--- src/librustc/util/ppaux.rs | 3 +- src/librustc_trans/trans/meth.rs | 7 +- src/librustc_typeck/check/method/mod.rs | 5 +- src/librustc_typeck/check/mod.rs | 1 - src/librustc_typeck/collect.rs | 2 +- .../associated-types-project-from-hrtb-in-fn | Bin 526235 -> 0 bytes .../compile-fail/variance-regions-direct.rs | 14 ++-- .../compile-fail/variance-regions-indirect.rs | 10 +-- .../variance-trait-object-bound.rs | 2 +- 14 files changed, 41 insertions(+), 96 deletions(-) delete mode 100755 src/test/compile-fail/associated-types-project-from-hrtb-in-fn diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index a9c4f0ddd8c2d..6efc80ed8d343 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -707,9 +707,8 @@ impl<'tcx, 'a> vtable_decoder_helpers<'tcx> for reader::Decoder<'a> { { let types = self.read_to_vec(|this| Ok(f(this))).unwrap(); let selfs = self.read_to_vec(|this| Ok(f(this))).unwrap(); - let assocs = self.read_to_vec(|this| Ok(f(this))).unwrap(); let fns = self.read_to_vec(|this| Ok(f(this))).unwrap(); - VecPerParamSpace::new(types, selfs, assocs, fns) + VecPerParamSpace::new(types, selfs, fns) } fn read_vtable_res_with_key(&mut self, diff --git a/src/librustc/middle/infer/mod.rs b/src/librustc/middle/infer/mod.rs index cf9520ecfbbde..386768bd9d6f7 100644 --- a/src/librustc/middle/infer/mod.rs +++ b/src/librustc/middle/infer/mod.rs @@ -864,10 +864,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let region_param_defs = generics.regions.get_slice(subst::TypeSpace); let regions = self.region_vars_for_defs(span, region_param_defs); - let assoc_type_parameter_count = generics.types.len(subst::AssocSpace); - let assoc_type_parameters = self.next_ty_vars(assoc_type_parameter_count); - - subst::Substs::new_trait(type_parameters, regions, assoc_type_parameters, self_ty) + subst::Substs::new_trait(type_parameters, regions, self_ty) } pub fn fresh_bound_region(&self, debruijn: ty::DebruijnIndex) -> ty::Region { diff --git a/src/librustc/middle/subst.rs b/src/librustc/middle/subst.rs index a87db776ce053..3066ae5b479ef 100644 --- a/src/librustc/middle/subst.rs +++ b/src/librustc/middle/subst.rs @@ -55,18 +55,17 @@ impl<'tcx> Substs<'tcx> { r: Vec) -> Substs<'tcx> { - Substs::new(VecPerParamSpace::new(t, Vec::new(), Vec::new(), Vec::new()), - VecPerParamSpace::new(r, Vec::new(), Vec::new(), Vec::new())) + Substs::new(VecPerParamSpace::new(t, Vec::new(), Vec::new()), + VecPerParamSpace::new(r, Vec::new(), Vec::new())) } pub fn new_trait(t: Vec>, r: Vec, - a: Vec>, s: Ty<'tcx>) -> Substs<'tcx> { - Substs::new(VecPerParamSpace::new(t, vec!(s), a, Vec::new()), - VecPerParamSpace::new(r, Vec::new(), Vec::new(), Vec::new())) + Substs::new(VecPerParamSpace::new(t, vec!(s), Vec::new()), + VecPerParamSpace::new(r, Vec::new(), Vec::new())) } pub fn erased(t: VecPerParamSpace>) -> Substs<'tcx> @@ -123,13 +122,6 @@ impl<'tcx> Substs<'tcx> { s } - pub fn with_assoc_tys(&self, assoc_tys: Vec>) -> Substs<'tcx> { - assert!(self.types.is_empty_in(AssocSpace)); - let mut s = (*self).clone(); - s.types.replace(AssocSpace, assoc_tys); - s - } - pub fn erase_regions(self) -> Substs<'tcx> { let Substs { types, regions: _ } = self; Substs { types: types, regions: ErasedRegions } @@ -192,21 +184,19 @@ impl RegionSubsts { pub enum ParamSpace { TypeSpace, // Type parameters attached to a type definition, trait, or impl SelfSpace, // Self parameter on a trait - AssocSpace, // Assoc types defined in a trait/impl FnSpace, // Type parameters attached to a method or fn } impl ParamSpace { - pub fn all() -> [ParamSpace, ..4] { - [TypeSpace, SelfSpace, AssocSpace, FnSpace] + pub fn all() -> [ParamSpace, ..3] { + [TypeSpace, SelfSpace, FnSpace] } pub fn to_uint(self) -> uint { match self { TypeSpace => 0, SelfSpace => 1, - AssocSpace => 2, - FnSpace => 3, + FnSpace => 2, } } @@ -214,8 +204,7 @@ impl ParamSpace { match u { 0 => TypeSpace, 1 => SelfSpace, - 2 => AssocSpace, - 3 => FnSpace, + 2 => FnSpace, _ => panic!("Invalid ParamSpace: {}", u) } } @@ -235,11 +224,9 @@ pub struct VecPerParamSpace { // // AF(self) = (self.content[..self.type_limit], // self.content[self.type_limit..self.self_limit], - // self.content[self.self_limit..self.assoc_limit], - // self.content[self.assoc_limit..]) + // self.content[self.self_limit..]) type_limit: uint, self_limit: uint, - assoc_limit: uint, content: Vec, } @@ -248,7 +235,6 @@ pub struct VecPerParamSpace { pub struct SeparateVecsPerParamSpace { pub types: Vec, pub selfs: Vec, - pub assocs: Vec, pub fns: Vec, } @@ -268,8 +254,7 @@ impl VecPerParamSpace { match space { TypeSpace => (0, self.type_limit), SelfSpace => (self.type_limit, self.self_limit), - AssocSpace => (self.self_limit, self.assoc_limit), - FnSpace => (self.assoc_limit, self.content.len()), + FnSpace => (self.self_limit, self.content.len()), } } @@ -277,7 +262,6 @@ impl VecPerParamSpace { VecPerParamSpace { type_limit: 0, self_limit: 0, - assoc_limit: 0, content: Vec::new() } } @@ -290,31 +274,27 @@ impl VecPerParamSpace { /// `s` is the self space. /// `a` is the assoc space. /// `f` is the fn space. - pub fn new(t: Vec, s: Vec, a: Vec, f: Vec) -> VecPerParamSpace { + pub fn new(t: Vec, s: Vec, f: Vec) -> VecPerParamSpace { let type_limit = t.len(); let self_limit = type_limit + s.len(); - let assoc_limit = self_limit + a.len(); let mut content = t; content.extend(s.into_iter()); - content.extend(a.into_iter()); content.extend(f.into_iter()); VecPerParamSpace { type_limit: type_limit, self_limit: self_limit, - assoc_limit: assoc_limit, content: content, } } - fn new_internal(content: Vec, type_limit: uint, self_limit: uint, assoc_limit: uint) + fn new_internal(content: Vec, type_limit: uint, self_limit: uint) -> VecPerParamSpace { VecPerParamSpace { type_limit: type_limit, self_limit: self_limit, - assoc_limit: assoc_limit, content: content, } } @@ -326,9 +306,8 @@ impl VecPerParamSpace { pub fn push(&mut self, space: ParamSpace, value: T) { let (_, limit) = self.limits(space); match space { - TypeSpace => { self.type_limit += 1; self.self_limit += 1; self.assoc_limit += 1; } - SelfSpace => { self.self_limit += 1; self.assoc_limit += 1; } - AssocSpace => { self.assoc_limit += 1; } + TypeSpace => { self.type_limit += 1; self.self_limit += 1; } + SelfSpace => { self.self_limit += 1; } FnSpace => { } } self.content.insert(limit, value); @@ -340,9 +319,8 @@ impl VecPerParamSpace { None } else { match space { - TypeSpace => { self.type_limit -= 1; self.self_limit -= 1; self.assoc_limit -= 1; } - SelfSpace => { self.self_limit -= 1; self.assoc_limit -= 1; } - AssocSpace => { self.assoc_limit -= 1; } + TypeSpace => { self.type_limit -= 1; self.self_limit -= 1; } + SelfSpace => { self.self_limit -= 1; } FnSpace => {} } self.content.remove(limit - 1) @@ -439,8 +417,7 @@ impl VecPerParamSpace { let result = self.iter().map(pred).collect(); VecPerParamSpace::new_internal(result, self.type_limit, - self.self_limit, - self.assoc_limit) + self.self_limit) } pub fn map_enumerated(&self, pred: P) -> VecPerParamSpace where @@ -449,8 +426,7 @@ impl VecPerParamSpace { let result = self.iter_enumerated().map(pred).collect(); VecPerParamSpace::new_internal(result, self.type_limit, - self.self_limit, - self.assoc_limit) + self.self_limit) } pub fn map_move(self, mut pred: F) -> VecPerParamSpace where @@ -459,25 +435,22 @@ impl VecPerParamSpace { let SeparateVecsPerParamSpace { types: t, selfs: s, - assocs: a, fns: f } = self.split(); VecPerParamSpace::new(t.into_iter().map(|p| pred(p)).collect(), s.into_iter().map(|p| pred(p)).collect(), - a.into_iter().map(|p| pred(p)).collect(), f.into_iter().map(|p| pred(p)).collect()) } pub fn split(self) -> SeparateVecsPerParamSpace { - let VecPerParamSpace { type_limit, self_limit, assoc_limit, content } = self; + let VecPerParamSpace { type_limit, self_limit, content } = self; let mut content_iter = content.into_iter(); SeparateVecsPerParamSpace { types: content_iter.by_ref().take(type_limit).collect(), selfs: content_iter.by_ref().take(self_limit - type_limit).collect(), - assocs: content_iter.by_ref().take(assoc_limit - self_limit).collect(), fns: content_iter.collect() } } diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index 91f1b50521d4f..755e50f13275e 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -1674,8 +1674,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }); } - let obligations = VecPerParamSpace::new(obligations, Vec::new(), - Vec::new(), Vec::new()); + let obligations = VecPerParamSpace::new(obligations, Vec::new(), Vec::new()); debug!("vtable_builtin_data: obligations={}", obligations.repr(self.tcx())); @@ -1769,7 +1768,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Substs::new_trait( vec![arguments_tuple, output_type], vec![], - vec![], self_ty); let trait_ref = ty::Binder(Rc::new(ty::TraitRef { def_id: obligation.predicate.def_id(), @@ -1810,7 +1808,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { vec![arguments_tuple.subst(self.tcx(), substs), closure_sig.0.output.unwrap().subst(self.tcx(), substs)], vec![], - vec![], obligation.self_ty()); let trait_ref = ty::Binder(Rc::new(ty::TraitRef { def_id: obligation.predicate.def_id(), diff --git a/src/librustc/middle/traits/util.rs b/src/librustc/middle/traits/util.rs index 95567d8240a2d..ddf2c9d87fee2 100644 --- a/src/librustc/middle/traits/util.rs +++ b/src/librustc/middle/traits/util.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use middle::subst::{Subst, Substs, VecPerParamSpace}; +use middle::subst::{Substs, VecPerParamSpace}; use middle::infer::InferCtxt; use middle::ty::{mod, Ty, AsPredicate, ToPolyTraitRef}; use std::collections::HashSet; @@ -229,18 +229,7 @@ pub fn fresh_substs_for_impl<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>, { let tcx = infcx.tcx; let impl_generics = ty::lookup_item_type(tcx, impl_def_id).generics; - let input_substs = infcx.fresh_substs_for_generics(span, &impl_generics); - - // Add substs for the associated types bound in the impl. - let ref items = tcx.impl_items.borrow()[impl_def_id]; - let mut assoc_tys = Vec::new(); - for item in items.iter() { - if let &ty::ImplOrTraitItemId::TypeTraitItemId(id) = item { - assoc_tys.push(tcx.tcache.borrow()[id].ty.subst(tcx, &input_substs)); - } - } - - input_substs.with_assoc_tys(assoc_tys) + infcx.fresh_substs_for_generics(span, &impl_generics) } impl<'tcx, N> fmt::Show for VtableImplData<'tcx, N> { diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index ee1432bc953de..9639af5ca1cd5 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -701,10 +701,9 @@ impl<'tcx> Repr<'tcx> for subst::Substs<'tcx> { impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for subst::VecPerParamSpace { fn repr(&self, tcx: &ctxt<'tcx>) -> String { - format!("[{};{};{};{}]", + format!("[{};{};{}]", self.get_slice(subst::TypeSpace).repr(tcx), self.get_slice(subst::SelfSpace).repr(tcx), - self.get_slice(subst::AssocSpace).repr(tcx), self.get_slice(subst::FnSpace).repr(tcx)) } } diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs index 2ede6e2e47fd2..9535ffaec0e6a 100644 --- a/src/librustc_trans/trans/meth.rs +++ b/src/librustc_trans/trans/meth.rs @@ -209,7 +209,6 @@ pub fn trans_static_method_callee(bcx: Block, let subst::SeparateVecsPerParamSpace { types: rcvr_type, selfs: rcvr_self, - assocs: rcvr_assoc, fns: rcvr_method } = rcvr_substs.types.split(); @@ -238,7 +237,6 @@ pub fn trans_static_method_callee(bcx: Block, let trait_substs = Substs::erased(VecPerParamSpace::new(rcvr_type, rcvr_self, - rcvr_assoc, Vec::new())); let trait_substs = bcx.tcx().mk_substs(trait_substs); debug!("trait_substs={}", trait_substs.repr(bcx.tcx())); @@ -276,13 +274,11 @@ pub fn trans_static_method_callee(bcx: Block, let subst::SeparateVecsPerParamSpace { types: impl_type, selfs: impl_self, - assocs: impl_assoc, fns: _ } = impl_substs.types.split(); let callee_substs = Substs::erased(VecPerParamSpace::new(impl_type, impl_self, - impl_assoc, rcvr_method)); let mth_id = method_with_name(ccx, impl_did, mname); @@ -411,13 +407,12 @@ fn combine_impl_and_methods_tps<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let subst::SeparateVecsPerParamSpace { types: rcvr_type, selfs: rcvr_self, - assocs: rcvr_assoc, fns: rcvr_method } = rcvr_substs.types.clone().split(); assert!(rcvr_method.is_empty()); subst::Substs { regions: subst::ErasedRegions, - types: subst::VecPerParamSpace::new(rcvr_type, rcvr_self, rcvr_assoc, node_method) + types: subst::VecPerParamSpace::new(rcvr_type, rcvr_self, node_method) } } diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index e483609407175..1971be117605c 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -155,14 +155,11 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>, } }; - let number_assoc_types = trait_def.generics.types.len(subst::AssocSpace); - let assoc_types = fcx.inh.infcx.next_ty_vars(number_assoc_types); - assert_eq!(trait_def.generics.types.len(subst::FnSpace), 0); assert!(trait_def.generics.regions.is_empty()); // Construct a trait-reference `self_ty : Trait` - let substs = subst::Substs::new_trait(input_types, Vec::new(), assoc_types, self_ty); + let substs = subst::Substs::new_trait(input_types, Vec::new(), self_ty); let trait_ref = Rc::new(ty::TraitRef::new(trait_def_id, fcx.tcx().mk_substs(substs))); // Construct an obligation diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index a11f7b15e03a5..7929a005af2c8 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -5430,7 +5430,6 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, span_err!(fcx.tcx().sess, data.bindings[0].span, E0182, "unexpected binding of associated item in expression path \ (only allowed in type paths)"); - substs.types.truncate(subst::ParamSpace::AssocSpace, 0); } { diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index da591ca04b745..8f70966dd14c4 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -898,7 +898,7 @@ pub fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, // ...and also create the `Self` parameter. let self_ty = ty::mk_self_type(ccx.tcx); - subst::Substs::new_trait(types, regions, Vec::new(), self_ty) + subst::Substs::new_trait(types, regions, self_ty) } } diff --git a/src/test/compile-fail/associated-types-project-from-hrtb-in-fn b/src/test/compile-fail/associated-types-project-from-hrtb-in-fn deleted file mode 100755 index 6d2392c124b30170f239832200d833c3cd78d0e1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 526235 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 X0sJIU0HqeO5M|Az$kkxYtG`DBwESL=i3 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 diff --git a/src/test/compile-fail/variance-regions-direct.rs b/src/test/compile-fail/variance-regions-direct.rs index 48813ff142c18..fa38482b21c50 100644 --- a/src/test/compile-fail/variance-regions-direct.rs +++ b/src/test/compile-fail/variance-regions-direct.rs @@ -14,7 +14,7 @@ // Regions that just appear in normal spots are contravariant: #[rustc_variance] -struct Test2<'a, 'b, 'c> { //~ ERROR regions=[[-, -, -];[];[];[]] +struct Test2<'a, 'b, 'c> { //~ ERROR regions=[[-, -, -];[];[]] x: &'a int, y: &'b [int], c: &'c str @@ -23,7 +23,7 @@ struct Test2<'a, 'b, 'c> { //~ ERROR regions=[[-, -, -];[];[];[]] // Those same annotations in function arguments become covariant: #[rustc_variance] -struct Test3<'a, 'b, 'c> { //~ ERROR regions=[[+, +, +];[];[];[]] +struct Test3<'a, 'b, 'c> { //~ ERROR regions=[[+, +, +];[];[]] x: extern "Rust" fn(&'a int), y: extern "Rust" fn(&'b [int]), c: extern "Rust" fn(&'c str), @@ -32,7 +32,7 @@ struct Test3<'a, 'b, 'c> { //~ ERROR regions=[[+, +, +];[];[];[]] // Mutability induces invariance: #[rustc_variance] -struct Test4<'a, 'b:'a> { //~ ERROR regions=[[-, o];[];[];[]] +struct Test4<'a, 'b:'a> { //~ ERROR regions=[[-, o];[];[]] x: &'a mut &'b int, } @@ -40,7 +40,7 @@ struct Test4<'a, 'b:'a> { //~ ERROR regions=[[-, o];[];[];[]] // contravariant context: #[rustc_variance] -struct Test5<'a, 'b> { //~ ERROR regions=[[+, o];[];[];[]] +struct Test5<'a, 'b> { //~ ERROR regions=[[+, o];[];[]] x: extern "Rust" fn(&'a mut &'b int), } @@ -50,21 +50,21 @@ struct Test5<'a, 'b> { //~ ERROR regions=[[+, o];[];[];[]] // argument list occurs in an invariant context. #[rustc_variance] -struct Test6<'a, 'b> { //~ ERROR regions=[[-, o];[];[];[]] +struct Test6<'a, 'b> { //~ ERROR regions=[[-, o];[];[]] x: &'a mut extern "Rust" fn(&'b int), } // No uses at all is bivariant: #[rustc_variance] -struct Test7<'a> { //~ ERROR regions=[[*];[];[];[]] +struct Test7<'a> { //~ ERROR regions=[[*];[];[]] x: int } // Try enums too. #[rustc_variance] -enum Test8<'a, 'b, 'c:'b> { //~ ERROR regions=[[+, -, o];[];[];[]] +enum Test8<'a, 'b, 'c:'b> { //~ ERROR regions=[[+, -, o];[];[]] Test8A(extern "Rust" fn(&'a int)), Test8B(&'b [int]), Test8C(&'b mut &'c str), diff --git a/src/test/compile-fail/variance-regions-indirect.rs b/src/test/compile-fail/variance-regions-indirect.rs index 0e8e52df456af..c049fbc0fedbc 100644 --- a/src/test/compile-fail/variance-regions-indirect.rs +++ b/src/test/compile-fail/variance-regions-indirect.rs @@ -13,29 +13,29 @@ // Try enums too. #[rustc_variance] -enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR regions=[[+, -, o, *];[];[];[]] +enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR regions=[[+, -, o, *];[];[]] Test8A(extern "Rust" fn(&'a int)), Test8B(&'b [int]), Test8C(&'b mut &'c str), } #[rustc_variance] -struct Derived1<'w, 'x:'y, 'y, 'z> { //~ ERROR regions=[[*, o, -, +];[];[];[]] +struct Derived1<'w, 'x:'y, 'y, 'z> { //~ ERROR regions=[[*, o, -, +];[];[]] f: Base<'z, 'y, 'x, 'w> } #[rustc_variance] // Combine - and + to yield o -struct Derived2<'a, 'b:'a, 'c> { //~ ERROR regions=[[o, o, *];[];[];[]] +struct Derived2<'a, 'b:'a, 'c> { //~ ERROR regions=[[o, o, *];[];[]] f: Base<'a, 'a, 'b, 'c> } #[rustc_variance] // Combine + and o to yield o (just pay attention to 'a here) -struct Derived3<'a:'b, 'b, 'c> { //~ ERROR regions=[[o, -, *];[];[];[]] +struct Derived3<'a:'b, 'b, 'c> { //~ ERROR regions=[[o, -, *];[];[]] f: Base<'a, 'b, 'a, 'c> } #[rustc_variance] // Combine + and * to yield + (just pay attention to 'a here) -struct Derived4<'a, 'b, 'c:'b> { //~ ERROR regions=[[+, -, o];[];[];[]] +struct Derived4<'a, 'b, 'c:'b> { //~ ERROR regions=[[+, -, o];[];[]] f: Base<'a, 'b, 'c, 'a> } diff --git a/src/test/compile-fail/variance-trait-object-bound.rs b/src/test/compile-fail/variance-trait-object-bound.rs index c576c5e2edd64..c61f2ff79c019 100644 --- a/src/test/compile-fail/variance-trait-object-bound.rs +++ b/src/test/compile-fail/variance-trait-object-bound.rs @@ -19,7 +19,7 @@ use std::mem; trait T { fn foo(); } #[rustc_variance] -struct TOption<'a> { //~ ERROR regions=[[-];[];[];[]] +struct TOption<'a> { //~ ERROR regions=[[-];[];[]] v: Option>, } From 208d32d19253603833ec6f5184a71e8730a35285 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 29 Dec 2014 16:32:24 -0500 Subject: [PATCH 32/36] Encode the TypeScheme for associated types --- src/librustc/metadata/encoder.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 20e7cb63133df..db29d0111f446 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -900,6 +900,9 @@ fn encode_info_for_associated_type(ecx: &EncodeContext, encode_parent_item(rbml_w, local_def(parent_id)); encode_item_sort(rbml_w, 't'); + let type_scheme = ty::lookup_item_type(ecx.tcx, associated_type.def_id); + encode_bounds_and_type(rbml_w, ecx, &type_scheme); + let stab = stability::lookup(ecx.tcx, associated_type.def_id); encode_stability(rbml_w, stab); From cdd5ff842db9eec168736998b2a5b72ba415e5bb Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 29 Dec 2014 15:12:11 -0500 Subject: [PATCH 33/36] Add a test case using associated types cross crate. Fixes #18048. --- src/test/auxiliary/issue-18048-lib.rs | 24 +++++++++++++++++++++++ src/test/run-pass/issue-18048.rs | 28 +++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 src/test/auxiliary/issue-18048-lib.rs create mode 100644 src/test/run-pass/issue-18048.rs diff --git a/src/test/auxiliary/issue-18048-lib.rs b/src/test/auxiliary/issue-18048-lib.rs new file mode 100644 index 0000000000000..52cc216657b33 --- /dev/null +++ b/src/test/auxiliary/issue-18048-lib.rs @@ -0,0 +1,24 @@ +// Copyright 2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_type="lib"] +#![feature(associated_types)] + +pub trait Bar { + type T; + + fn get(x: Option) -> ::T; +} + +impl Bar for int { + type T = uint; + + fn get(_: Option) -> uint { 22 } +} diff --git a/src/test/run-pass/issue-18048.rs b/src/test/run-pass/issue-18048.rs new file mode 100644 index 0000000000000..7cd6e5eb0d5da --- /dev/null +++ b/src/test/run-pass/issue-18048.rs @@ -0,0 +1,28 @@ +// Copyright 2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:issue-18048-lib.rs + +// Test that we are able to reference cross-crate traits that employ +// associated types. + +#![feature(associated_types)] + +extern crate "issue-18048-lib" as bar; + +use bar::Bar; + +fn foo(b: B) -> ::T { + Bar::get(None::) +} + +fn main() { + println!("{}", foo(3i)); +} From 518ec1259a967142fcfbf7cb6dd2d4a3dd5610cf Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 30 Dec 2014 06:29:59 -0500 Subject: [PATCH 34/36] Normalize associated types in bounds too. Also, make the workaround for lack of impl-trait-for-trait just a bit more targeted (don't substitute err, just drop the troublesome bound for now) -- otherwise substituting false types leads us into trouble when we normalize etc. --- src/librustc/middle/ty.rs | 98 ++++++++++++++----- src/librustc_typeck/check/assoc.rs | 30 +++--- src/librustc_typeck/check/method/confirm.rs | 44 +++------ src/librustc_typeck/collect.rs | 2 +- .../associated-types-normalize-in-bounds.rs | 41 ++++++++ 5 files changed, 149 insertions(+), 66 deletions(-) create mode 100644 src/test/run-pass/associated-types-normalize-in-bounds.rs diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index caec56800c63a..d6ab0201d190a 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -6970,13 +6970,67 @@ pub trait HasProjectionTypes { fn has_projection_types(&self) -> bool; } +impl<'tcx> HasProjectionTypes for ty::GenericBounds<'tcx> { + fn has_projection_types(&self) -> bool { + self.predicates.iter().any(|p| p.has_projection_types()) + } +} + +impl<'tcx> HasProjectionTypes for Predicate<'tcx> { + fn has_projection_types(&self) -> bool { + match *self { + Predicate::Trait(ref data) => data.has_projection_types(), + Predicate::Equate(ref data) => data.has_projection_types(), + Predicate::RegionOutlives(ref data) => data.has_projection_types(), + Predicate::TypeOutlives(ref data) => data.has_projection_types(), + Predicate::Projection(ref data) => data.has_projection_types(), + } + } +} + +impl<'tcx> HasProjectionTypes for TraitPredicate<'tcx> { + fn has_projection_types(&self) -> bool { + self.trait_ref.has_projection_types() + } +} + +impl<'tcx> HasProjectionTypes for EquatePredicate<'tcx> { + fn has_projection_types(&self) -> bool { + self.0.has_projection_types() || self.1.has_projection_types() + } +} + +impl HasProjectionTypes for Region { + fn has_projection_types(&self) -> bool { + false + } +} + +impl HasProjectionTypes for OutlivesPredicate { + fn has_projection_types(&self) -> bool { + self.0.has_projection_types() || self.1.has_projection_types() + } +} + +impl<'tcx> HasProjectionTypes for ProjectionPredicate<'tcx> { + fn has_projection_types(&self) -> bool { + self.projection_ty.has_projection_types() || self.ty.has_projection_types() + } +} + +impl<'tcx> HasProjectionTypes for ProjectionTy<'tcx> { + fn has_projection_types(&self) -> bool { + self.trait_ref.has_projection_types() + } +} + impl<'tcx> HasProjectionTypes for Ty<'tcx> { fn has_projection_types(&self) -> bool { ty::type_has_projection(*self) } } -impl<'tcx> HasProjectionTypes for ty::TraitRef<'tcx> { +impl<'tcx> HasProjectionTypes for TraitRef<'tcx> { fn has_projection_types(&self) -> bool { self.substs.has_projection_types() } @@ -7012,7 +7066,7 @@ impl<'tcx,T> HasProjectionTypes for Box } } -impl HasProjectionTypes for ty::Binder +impl HasProjectionTypes for Binder where T : HasProjectionTypes { fn has_projection_types(&self) -> bool { @@ -7020,23 +7074,23 @@ impl HasProjectionTypes for ty::Binder } } -impl<'tcx> HasProjectionTypes for ty::FnOutput<'tcx> { +impl<'tcx> HasProjectionTypes for FnOutput<'tcx> { fn has_projection_types(&self) -> bool { match *self { - ty::FnConverging(t) => t.has_projection_types(), - ty::FnDiverging => false, + FnConverging(t) => t.has_projection_types(), + FnDiverging => false, } } } -impl<'tcx> HasProjectionTypes for ty::FnSig<'tcx> { +impl<'tcx> HasProjectionTypes for FnSig<'tcx> { fn has_projection_types(&self) -> bool { self.inputs.iter().any(|t| t.has_projection_types()) || self.output.has_projection_types() } } -impl<'tcx> HasProjectionTypes for ty::BareFnTy<'tcx> { +impl<'tcx> HasProjectionTypes for BareFnTy<'tcx> { fn has_projection_types(&self) -> bool { self.sig.has_projection_types() } @@ -7046,7 +7100,7 @@ pub trait ReferencesError { fn references_error(&self) -> bool; } -impl ReferencesError for ty::Binder { +impl ReferencesError for Binder { fn references_error(&self) -> bool { self.0.references_error() } @@ -7058,43 +7112,43 @@ impl ReferencesError for Rc { } } -impl<'tcx> ReferencesError for ty::TraitPredicate<'tcx> { +impl<'tcx> ReferencesError for TraitPredicate<'tcx> { fn references_error(&self) -> bool { self.trait_ref.references_error() } } -impl<'tcx> ReferencesError for ty::ProjectionPredicate<'tcx> { +impl<'tcx> ReferencesError for ProjectionPredicate<'tcx> { fn references_error(&self) -> bool { self.projection_ty.trait_ref.references_error() || self.ty.references_error() } } -impl<'tcx> ReferencesError for ty::TraitRef<'tcx> { +impl<'tcx> ReferencesError for TraitRef<'tcx> { fn references_error(&self) -> bool { self.input_types().iter().any(|t| t.references_error()) } } -impl<'tcx> ReferencesError for ty::Ty<'tcx> { +impl<'tcx> ReferencesError for Ty<'tcx> { fn references_error(&self) -> bool { - ty::type_is_error(*self) + type_is_error(*self) } } -impl<'tcx> ReferencesError for ty::Predicate<'tcx> { +impl<'tcx> ReferencesError for Predicate<'tcx> { fn references_error(&self) -> bool { match *self { - ty::Predicate::Trait(ref data) => data.references_error(), - ty::Predicate::Equate(ref data) => data.references_error(), - ty::Predicate::RegionOutlives(ref data) => data.references_error(), - ty::Predicate::TypeOutlives(ref data) => data.references_error(), - ty::Predicate::Projection(ref data) => data.references_error(), + Predicate::Trait(ref data) => data.references_error(), + Predicate::Equate(ref data) => data.references_error(), + Predicate::RegionOutlives(ref data) => data.references_error(), + Predicate::TypeOutlives(ref data) => data.references_error(), + Predicate::Projection(ref data) => data.references_error(), } } } -impl ReferencesError for ty::OutlivesPredicate +impl ReferencesError for OutlivesPredicate where A : ReferencesError, B : ReferencesError { fn references_error(&self) -> bool { @@ -7102,14 +7156,14 @@ impl ReferencesError for ty::OutlivesPredicate } } -impl<'tcx> ReferencesError for ty::EquatePredicate<'tcx> +impl<'tcx> ReferencesError for EquatePredicate<'tcx> { fn references_error(&self) -> bool { self.0.references_error() || self.1.references_error() } } -impl ReferencesError for ty::Region +impl ReferencesError for Region { fn references_error(&self) -> bool { false diff --git a/src/librustc_typeck/check/assoc.rs b/src/librustc_typeck/check/assoc.rs index c20dd5aebaddb..0d7ce2f871a6f 100644 --- a/src/librustc_typeck/check/assoc.rs +++ b/src/librustc_typeck/check/assoc.rs @@ -10,7 +10,7 @@ use middle::infer::InferCtxt; use middle::traits::{ObligationCause, ObligationCauseCode, FulfillmentContext}; -use middle::ty::{mod, HasProjectionTypes, Ty}; +use middle::ty::{mod, RegionEscape, HasProjectionTypes, Ty}; use middle::ty_fold::{mod, TypeFoldable, TypeFolder}; use syntax::ast; use syntax::codemap::Span; @@ -32,8 +32,7 @@ pub fn normalize_associated_types_in<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>, let mut normalizer = AssociatedTypeNormalizer { span: span, body_id: body_id, infcx: infcx, - fulfillment_cx: fulfillment_cx, - region_binders: 0 }; + fulfillment_cx: fulfillment_cx }; value.fold_with(&mut normalizer) } @@ -42,7 +41,6 @@ struct AssociatedTypeNormalizer<'a,'tcx:'a> { fulfillment_cx: &'a mut FulfillmentContext<'tcx>, span: Span, body_id: ast::NodeId, - region_binders: uint, } impl<'a,'tcx> TypeFolder<'tcx> for AssociatedTypeNormalizer<'a,'tcx> { @@ -50,14 +48,6 @@ impl<'a,'tcx> TypeFolder<'tcx> for AssociatedTypeNormalizer<'a,'tcx> { self.infcx.tcx } - fn enter_region_binder(&mut self) { - self.region_binders += 1; - } - - fn exit_region_binder(&mut self) { - self.region_binders -= 1; - } - fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { // We don't want to normalize associated types that occur inside of region // binders, because they may contain bound regions, and we can't cope with that. @@ -69,10 +59,22 @@ impl<'a,'tcx> TypeFolder<'tcx> for AssociatedTypeNormalizer<'a,'tcx> { // Instead of normalizing `>::A` here, we'll // normalize it when we instantiate those bound regions (which // should occur eventually). - let no_region_binders = self.region_binders == 0; match ty.sty { - ty::ty_projection(ref data) if no_region_binders => { + ty::ty_projection(ref data) if !data.has_escaping_regions() => { // (*) + + // (*) This is kind of hacky -- we need to be able to + // handle normalization within binders because + // otherwise we wind up a need to normalize when doing + // trait matching (since you can have a trait + // obligation like `for<'a> T::B : Fn(&'a int)`), but + // we can't normalize with bound regions in scope. So + // far now we just ignore binders but only normalize + // if all bound regions are gone (and then we still + // have to renormalize whenever we instantiate a + // binder). It would be better to normalize in a + // binding-aware fashion. + let cause = ObligationCause::new( self.span, diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 9704439c468b2..a189f780b0c27 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -42,12 +42,6 @@ struct InstantiatedMethodSig<'tcx> { /// the method. all_substs: subst::Substs<'tcx>, - /// Substitution to use when adding obligations from the method - /// bounds. Normally equal to `all_substs` except for object - /// receivers. See FIXME in instantiate_method_sig() for - /// explanation. - method_bounds_substs: subst::Substs<'tcx>, - /// Generic bounds on the method's parameters which must be added /// as pending obligations. method_bounds: ty::GenericBounds<'tcx>, @@ -103,7 +97,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { // Create the final signature for the method, replacing late-bound regions. let InstantiatedMethodSig { - method_sig, all_substs, method_bounds_substs, method_bounds + method_sig, all_substs, method_bounds } = self.instantiate_method_sig(&pick, all_substs); let method_self_ty = method_sig.inputs[0]; @@ -111,7 +105,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { self.unify_receivers(self_ty, method_self_ty); // Add any trait/regions obligations specified on the method's type parameters. - self.add_obligations(&pick, &method_bounds_substs, &method_bounds); + self.add_obligations(&pick, &all_substs, &method_bounds); // Create the final `MethodCallee`. let fty = ty::mk_bare_fn(self.tcx(), None, self.tcx().mk_bare_fn(ty::BareFnTy { @@ -403,24 +397,17 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { // type `Trait`, this leads to an obligation // `Trait:Trait`. Until such time we DST is fully implemented, // that obligation is not necessarily satisfied. (In the - // future, it would be.) - // - // To sidestep this, we overwrite the binding for `Self` with - // `err` (just for trait objects) when we generate the - // obligations. This causes us to generate the obligation - // `err:Trait`, and the error type is considered to implement - // all traits, so we're all good. Hack hack hack. - let method_bounds_substs = match pick.kind { + // future, it would be.) But we know that the true `Self` DOES implement + // the trait. So we just delete this requirement. Hack hack hack. + let mut method_bounds = pick.method_ty.generics.to_bounds(self.tcx(), &all_substs); + match pick.kind { probe::ObjectPick(..) => { - let mut temp_substs = all_substs.clone(); - temp_substs.types.get_mut_slice(subst::SelfSpace)[0] = self.tcx().types.err; - temp_substs + assert_eq!(method_bounds.predicates.get_slice(subst::SelfSpace).len(), 1); + method_bounds.predicates.pop(subst::SelfSpace); } - _ => { - all_substs.clone() - } - }; - let method_bounds = pick.method_ty.generics.to_bounds(self.tcx(), &method_bounds_substs); + _ => { } + } + let method_bounds = self.fcx.normalize_associated_types_in(self.span, &method_bounds); debug!("method_bounds after subst = {}", method_bounds.repr(self.tcx())); @@ -442,18 +429,17 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { InstantiatedMethodSig { method_sig: method_sig, all_substs: all_substs, - method_bounds_substs: method_bounds_substs, method_bounds: method_bounds, } } fn add_obligations(&mut self, pick: &probe::Pick<'tcx>, - method_bounds_substs: &subst::Substs<'tcx>, + all_substs: &subst::Substs<'tcx>, method_bounds: &ty::GenericBounds<'tcx>) { - debug!("add_obligations: pick={} method_bounds_substs={} method_bounds={}", + debug!("add_obligations: pick={} all_substs={} method_bounds={}", pick.repr(self.tcx()), - method_bounds_substs.repr(self.tcx()), + all_substs.repr(self.tcx()), method_bounds.repr(self.tcx())); self.fcx.add_obligations_for_parameters( @@ -461,7 +447,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { method_bounds); self.fcx.add_default_region_param_bounds( - method_bounds_substs, + all_substs, self.call_expr); } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 8f70966dd14c4..47473564254e1 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1071,7 +1071,7 @@ fn ty_generics_for_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, debug!("ty_generics_for_trait: assoc_predicates={}", assoc_predicates.repr(ccx.tcx)); for assoc_predicate in assoc_predicates.into_iter() { - generics.predicates.push(subst::SelfSpace, assoc_predicate); + generics.predicates.push(subst::TypeSpace, assoc_predicate); } return generics; diff --git a/src/test/run-pass/associated-types-normalize-in-bounds.rs b/src/test/run-pass/associated-types-normalize-in-bounds.rs new file mode 100644 index 0000000000000..f09c27029d7fa --- /dev/null +++ b/src/test/run-pass/associated-types-normalize-in-bounds.rs @@ -0,0 +1,41 @@ +// Copyright 2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that we normalize associated types that appear in bounds; if +// we didn't, the call to `self.split2()` fails to type check. + +#![feature(associated_types)] + +struct Splits<'a, T, P>; +struct SplitsN; + +trait SliceExt2 for Sized? { + type Item; + + fn split2<'a, P>(&'a self, pred: P) -> Splits<'a, Self::Item, P> + where P: FnMut(&Self::Item) -> bool; + fn splitn2<'a, P>(&'a self, n: uint, pred: P) -> SplitsN> + where P: FnMut(&Self::Item) -> bool; +} + +impl SliceExt2 for [T] { + type Item = T; + + fn split2

(&self, pred: P) -> Splits where P: FnMut(&T) -> bool { + loop {} + } + + fn splitn2

(&self, n: uint, pred: P) -> SplitsN> where P: FnMut(&T) -> bool { + self.split2(pred); + loop {} + } +} + +fn main() { } From 919975d0a5c90a25bf09a0a7c27fb7156d6aa2ad Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 30 Dec 2014 08:59:33 -0500 Subject: [PATCH 35/36] Address nits. --- src/librustc/middle/traits/fulfill.rs | 23 +++++++++++-------- src/librustc/middle/traits/mod.rs | 5 +++- src/librustc/middle/traits/project.rs | 22 +++++++----------- src/librustc/middle/traits/select.rs | 9 +++++++- src/librustc/middle/traits/util.rs | 11 +++++++-- src/librustc/middle/ty.rs | 20 +++++++++++++++- src/librustc_typeck/astconv.rs | 7 +----- src/librustc_typeck/check/assoc.rs | 6 ++--- src/librustc_typeck/check/mod.rs | 8 ++++--- ...8048-lib.rs => associated-types-cc-lib.rs} | 3 +++ ...{issue-18048.rs => associated-types-cc.rs} | 4 ++-- src/test/run-pass/issue-19081.rs | 2 +- 12 files changed, 75 insertions(+), 45 deletions(-) rename src/test/auxiliary/{issue-18048-lib.rs => associated-types-cc-lib.rs} (88%) rename src/test/run-pass/{issue-18048.rs => associated-types-cc.rs} (89%) diff --git a/src/librustc/middle/traits/fulfill.rs b/src/librustc/middle/traits/fulfill.rs index b55504da237af..7ec221fcfa903 100644 --- a/src/librustc/middle/traits/fulfill.rs +++ b/src/librustc/middle/traits/fulfill.rs @@ -14,7 +14,6 @@ use middle::ty::{mod, AsPredicate, RegionEscape, Ty, ToPolyTraitRef}; use std::collections::HashSet; use std::collections::hash_map::Entry::{Occupied, Vacant}; use std::default::Default; -use std::rc::Rc; use syntax::ast; use util::common::ErrorReported; use util::ppaux::Repr; @@ -102,26 +101,30 @@ impl<'tcx> FulfillmentContext<'tcx> { } } - pub fn normalize_associated_type<'a>(&mut self, + /// "Normalize" a projection type `::X` by + /// creating a fresh type variable `$0` as well as a projection + /// predicate `::X == $0`. When the + /// inference engine runs, it will attempt to find an impl of + /// `SomeTrait` or a where clause that lets us unify `$0` with + /// something concrete. If this fails, we'll unify `$0` with + /// `projection_ty` again. + pub fn normalize_projection_type<'a>(&mut self, infcx: &InferCtxt<'a,'tcx>, - trait_ref: Rc>, - item_name: ast::Name, + projection_ty: ty::ProjectionTy<'tcx>, cause: ObligationCause<'tcx>) -> Ty<'tcx> { - debug!("normalize_associated_type(trait_ref={}, item_name={})", - trait_ref.repr(infcx.tcx), - item_name.repr(infcx.tcx)); + debug!("normalize_associated_type(projection_ty={})", + projection_ty.repr(infcx.tcx)); - assert!(!trait_ref.has_escaping_regions()); + assert!(!projection_ty.has_escaping_regions()); // FIXME(#20304) -- cache let ty_var = infcx.next_ty_var(); let projection = ty::Binder(ty::ProjectionPredicate { - projection_ty: ty::ProjectionTy { trait_ref: trait_ref, - item_name: item_name }, + projection_ty: projection_ty, ty: ty_var }); let obligation = Obligation::new(cause, projection.as_predicate()); diff --git a/src/librustc/middle/traits/mod.rs b/src/librustc/middle/traits/mod.rs index d7febea8909b1..d4fa0c98ad5d1 100644 --- a/src/librustc/middle/traits/mod.rs +++ b/src/librustc/middle/traits/mod.rs @@ -117,7 +117,10 @@ pub enum ObligationCauseCode<'tcx> { #[deriving(Clone)] pub struct DerivedObligationCause<'tcx> { - /// Resolving this trait led to the current obligation + /// The trait reference of the parent obligation that led to the + /// current obligation. Note that only trait obligations lead to + /// derived obligations, so we just store the trait reference here + /// directly. parent_trait_ref: ty::PolyTraitRef<'tcx>, /// The parent trait had this cause diff --git a/src/librustc/middle/traits/project.rs b/src/librustc/middle/traits/project.rs index d319e44141519..435babf168e86 100644 --- a/src/librustc/middle/traits/project.rs +++ b/src/librustc/middle/traits/project.rs @@ -20,7 +20,6 @@ use super::VtableImplData; use middle::infer; use middle::subst::Subst; use middle::ty::{mod, AsPredicate, ToPolyTraitRef, Ty}; -use std::fmt; use util::ppaux::Repr; pub type PolyProjectionObligation<'tcx> = @@ -34,10 +33,17 @@ pub type ProjectionTyObligation<'tcx> = /// When attempting to resolve `::Name == U`... pub enum ProjectionError<'tcx> { + /// ...we could not find any helpful information on what `Name` + /// might be. This could occur, for example, if there is a where + /// clause `T : TraitRef` but not `T : TraitRef`. When + /// normalizing, this case is where we opt to normalize back to + /// the projection type `::Name`. NoCandidate, + + /// ...we found multiple sources of information and couldn't resolve the ambiguity. TooManyCandidates, - /// + /// ...`` ws resolved to some type `V` that failed to unify with `U` MismatchedTypes(MismatchedProjectionTypes<'tcx>), /// ...an error occurred matching `T : TraitRef` @@ -380,12 +386,6 @@ fn confirm_candidate<'cx,'tcx>( Ok(projected_ty) } -impl<'tcx> Repr<'tcx> for super::MismatchedProjectionTypes<'tcx> { - fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String { - self.err.repr(tcx) - } -} - impl<'tcx> Repr<'tcx> for ProjectionError<'tcx> { fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String { match *self { @@ -401,12 +401,6 @@ impl<'tcx> Repr<'tcx> for ProjectionError<'tcx> { } } -impl<'tcx> fmt::Show for super::MismatchedProjectionTypes<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "MismatchedProjectionTypes(..)") - } -} - impl<'tcx> Repr<'tcx> for ProjectionTyCandidate<'tcx> { fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String { match *self { diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index 755e50f13275e..ce5337a58e10c 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -150,8 +150,15 @@ enum SelectionCandidate<'tcx> { } struct SelectionCandidateSet<'tcx> { + // a list of candidates that definitely apply to the current + // obligation (meaning: types unify). vec: Vec>, - ambiguous: bool + + // if this is true, then there were candidates that might or might + // not have applied, but we couldn't tell. This occurs when some + // of the input types are type variables, in which case there are + // various "builtin" rules that might or might not trigger. + ambiguous: bool, } enum BuiltinBoundConditions<'tcx> { diff --git a/src/librustc/middle/traits/util.rs b/src/librustc/middle/traits/util.rs index ddf2c9d87fee2..109810fc7eec3 100644 --- a/src/librustc/middle/traits/util.rs +++ b/src/librustc/middle/traits/util.rs @@ -385,9 +385,16 @@ impl<'tcx> fmt::Show for super::FulfillmentErrorCode<'tcx> { } } -impl<'tcx> Repr<'tcx> for ty::type_err<'tcx> { +impl<'tcx> Repr<'tcx> for super::MismatchedProjectionTypes<'tcx> { fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String { - ty::type_err_to_str(tcx, self) + self.err.repr(tcx) } } +impl<'tcx> fmt::Show for super::MismatchedProjectionTypes<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "MismatchedProjectionTypes(..)") + } +} + + diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index d6ab0201d190a..ab39c761a3861 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -1791,7 +1791,8 @@ pub enum Predicate<'tcx> { /// where T : 'a TypeOutlives(PolyTypeOutlivesPredicate<'tcx>), - /// + /// where ::Name == X, approximately. + /// See `ProjectionPredicate` struct for details. Projection(PolyProjectionPredicate<'tcx>), } @@ -1857,9 +1858,14 @@ impl<'tcx> PolyProjectionPredicate<'tcx> { } } +/// Represents the projection of an associated type. In explicit UFCS +/// form this would be written `>::N`. #[deriving(Clone, PartialEq, Eq, Hash, Show)] pub struct ProjectionTy<'tcx> { + /// The trait reference `T as Trait<..>`. pub trait_ref: Rc>, + + /// The name `N` of the associated type. pub item_name: ast::Name, } @@ -2179,6 +2185,12 @@ impl<'tcx> ParameterEnvironment<'tcx> { /// - `generics`: the set of type parameters and their bounds /// - `ty`: the base types, which may reference the parameters defined /// in `generics` +/// +/// Note that TypeSchemes are also sometimes called "polytypes" (and +/// in fact this struct used to carry that name, so you may find some +/// stray references in a comment or something). We try to reserve the +/// "poly" prefix to refer to higher-ranked things, as in +/// `PolyTraitRef`. #[deriving(Clone, Show)] pub struct TypeScheme<'tcx> { pub generics: Generics<'tcx>, @@ -4680,6 +4692,12 @@ pub fn ty_sort_string<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> String { } } +impl<'tcx> Repr<'tcx> for ty::type_err<'tcx> { + fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String { + ty::type_err_to_str(tcx, self) + } +} + /// Explains the source of a type err in a short, human readable way. This is meant to be placed /// in parentheses after some larger message. You should also invoke `note_and_explain_type_err()` /// afterwards to present additional details, particularly when it comes to lifetime-related diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 82a023202097f..587a85cfcbac4 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -244,7 +244,6 @@ pub fn opt_ast_region_to_region<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( fn ast_path_substs_for_ty<'tcx,AC,RS>( this: &AC, rscope: &RS, - decl_def_id: ast::DefId, decl_generics: &ty::Generics<'tcx>, path: &ast::Path) -> Substs<'tcx> @@ -280,7 +279,6 @@ fn ast_path_substs_for_ty<'tcx,AC,RS>( create_substs_for_ast_path(this, rscope, path.span, - decl_def_id, decl_generics, None, types, @@ -291,7 +289,6 @@ fn create_substs_for_ast_path<'tcx,AC,RS>( this: &AC, rscope: &RS, span: Span, - _decl_def_id: ast::DefId, decl_generics: &ty::Generics<'tcx>, self_ty: Option>, types: Vec>, @@ -621,7 +618,6 @@ fn ast_path_to_trait_ref<'a,'tcx,AC,RS>( let substs = create_substs_for_ast_path(this, &shifted_rscope, path.span, - trait_def_id, &trait_def.generics, self_ty, types, @@ -705,7 +701,6 @@ pub fn ast_path_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( let substs = ast_path_substs_for_ty(this, rscope, - did, &generics, path); let ty = decl_ty.subst(tcx, &substs); @@ -747,7 +742,7 @@ pub fn ast_path_to_ty_relaxed<'tcx,AC,RS>( Substs::new(VecPerParamSpace::params_from_type(type_params), VecPerParamSpace::params_from_type(region_params)) } else { - ast_path_substs_for_ty(this, rscope, did, &generics, path) + ast_path_substs_for_ty(this, rscope, &generics, path) }; let ty = decl_ty.subst(tcx, &substs); diff --git a/src/librustc_typeck/check/assoc.rs b/src/librustc_typeck/check/assoc.rs index 0d7ce2f871a6f..081959a4efa4a 100644 --- a/src/librustc_typeck/check/assoc.rs +++ b/src/librustc_typeck/check/assoc.rs @@ -80,11 +80,9 @@ impl<'a,'tcx> TypeFolder<'tcx> for AssociatedTypeNormalizer<'a,'tcx> { self.span, self.body_id, ObligationCauseCode::MiscObligation); - let trait_ref = data.trait_ref.clone(); self.fulfillment_cx - .normalize_associated_type(self.infcx, - trait_ref, - data.item_name, + .normalize_projection_type(self.infcx, + data.clone(), cause) } _ => { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 7929a005af2c8..12ecfe6c2981c 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1758,9 +1758,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { traits::ObligationCauseCode::MiscObligation); self.inh.fulfillment_cx .borrow_mut() - .normalize_associated_type(self.infcx(), - trait_ref, - item_name, + .normalize_projection_type(self.infcx(), + ty::ProjectionTy { + trait_ref: trait_ref, + item_name: item_name, + }, cause) } diff --git a/src/test/auxiliary/issue-18048-lib.rs b/src/test/auxiliary/associated-types-cc-lib.rs similarity index 88% rename from src/test/auxiliary/issue-18048-lib.rs rename to src/test/auxiliary/associated-types-cc-lib.rs index 52cc216657b33..17b2a0751fe29 100644 --- a/src/test/auxiliary/issue-18048-lib.rs +++ b/src/test/auxiliary/associated-types-cc-lib.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// Helper for test issue-18048, which tests associated types in a +// cross-crate scenario. + #![crate_type="lib"] #![feature(associated_types)] diff --git a/src/test/run-pass/issue-18048.rs b/src/test/run-pass/associated-types-cc.rs similarity index 89% rename from src/test/run-pass/issue-18048.rs rename to src/test/run-pass/associated-types-cc.rs index 7cd6e5eb0d5da..c0cf917aa4117 100644 --- a/src/test/run-pass/issue-18048.rs +++ b/src/test/run-pass/associated-types-cc.rs @@ -8,14 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// aux-build:issue-18048-lib.rs +// aux-build:associated-types-cc-lib.rs // Test that we are able to reference cross-crate traits that employ // associated types. #![feature(associated_types)] -extern crate "issue-18048-lib" as bar; +extern crate "associated-types-cc-lib" as bar; use bar::Bar; diff --git a/src/test/run-pass/issue-19081.rs b/src/test/run-pass/issue-19081.rs index aeb140874779d..57724ba91b02f 100644 --- a/src/test/run-pass/issue-19081.rs +++ b/src/test/run-pass/issue-19081.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty -- currently pretty prints as `Hash< Date: Tue, 30 Dec 2014 12:09:21 -0500 Subject: [PATCH 36/36] Fix rebase conflicts --- src/librustc_typeck/check/closure.rs | 4 +- src/librustc_typeck/check/mod.rs | 122 ++++++------------ src/librustc_typeck/collect.rs | 1 - src/librustdoc/clean/mod.rs | 2 +- .../trait-static-method-generic-inference.rs | 21 ++- 5 files changed, 48 insertions(+), 102 deletions(-) rename src/test/{run-pass => compile-fail}/trait-static-method-generic-inference.rs (69%) diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 85ead053d1d29..eba040e7ea8b6 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -48,7 +48,7 @@ pub fn check_expr_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, match expected_sig_and_kind { None => { // doesn't look like an unboxed closure let region = astconv::opt_ast_region_to_region(fcx, - fcx.infcx(), + fcx, expr.span, &None); @@ -117,7 +117,7 @@ fn check_unboxed_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, abi::RustCall, expected_sig); - let region = match fcx.infcx().anon_regions(expr.span, 1) { + let region = match fcx.anon_regions(expr.span, 1) { Err(_) => { fcx.ccx.tcx.sess.span_bug(expr.span, "can't make anon regions here?!") diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 12ecfe6c2981c..8069d00dda826 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1933,7 +1933,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } pub fn to_ty(&self, ast_t: &ast::Ty) -> Ty<'tcx> { - let t = ast_ty_to_ty(self, self.infcx(), ast_t); + let t = ast_ty_to_ty(self, self, ast_t); let mut bounds_checker = wf::BoundsChecker::new(self, ast_t.span, @@ -2123,18 +2123,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } -//impl<'a, 'tcx> RegionScope for infer::InferCtxt<'a, 'tcx> { -// fn default_region_bound(&self, span: Span) -> Option { -// Some(self.next_region_var(infer::MiscVariable(span))) -// } -// -// fn anon_regions(&self, span: Span, count: uint) -// -> Result, Option>> { -// Ok(Vec::from_fn(count, |_| { -// self.next_region_var(infer::MiscVariable(span)) -// })) -// } -//} +impl<'a, 'tcx> RegionScope for FnCtxt<'a, 'tcx> { + fn default_region_bound(&self, span: Span) -> Option { + Some(self.infcx().next_region_var(infer::MiscVariable(span))) + } + + fn anon_regions(&self, span: Span, count: uint) + -> Result, Option>> { + Ok(Vec::from_fn(count, |_| { + self.infcx().next_region_var(infer::MiscVariable(span)) + })) + } +} #[deriving(Copy, Show, PartialEq, Eq)] pub enum LvaluePreference { @@ -2347,58 +2347,6 @@ fn autoderef_for_index<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>, } } -/// Autoderefs `base_expr`, looking for a `Slice` impl. If it finds one, installs the relevant -/// method info and returns the result type (else None). -fn try_overloaded_slice<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, - method_call: MethodCall, - expr: &ast::Expr, - base_expr: &ast::Expr, - base_ty: Ty<'tcx>, - start_expr: &Option>, - end_expr: &Option>, - mutbl: ast::Mutability) - -> Option> // return type is result of slice -{ - let lvalue_pref = match mutbl { - ast::MutMutable => PreferMutLvalue, - ast::MutImmutable => NoPreference - }; - - let opt_method_ty = - autoderef_for_index(fcx, base_expr, base_ty, lvalue_pref, |adjusted_ty, autoderefref| { - try_overloaded_slice_step(fcx, method_call, expr, base_expr, - adjusted_ty, autoderefref, mutbl, - start_expr, end_expr) - }); - - // Regardless of whether the lookup succeeds, check the method arguments - // so that we have *some* type for each argument. - let method_ty_or_err = opt_method_ty.unwrap_or(fcx.tcx().types.err); - - let mut args = vec![]; - start_expr.as_ref().map(|x| args.push(x)); - end_expr.as_ref().map(|x| args.push(x)); - - check_method_argument_types(fcx, - expr.span, - method_ty_or_err, - expr, - args.as_slice(), - AutorefArgs::Yes, - DontTupleArguments); - - opt_method_ty.map(|method_ty| { - let result_ty = ty::ty_fn_ret(method_ty); - match result_ty { - ty::FnConverging(result_ty) => result_ty, - ty::FnDiverging => { - fcx.tcx().sess.span_bug(expr.span, - "slice trait does not define a `!` return") - } - } - }) -} - /// Checks for a `Slice` (or `SliceMut`) impl at the relevant level of autoderef. If it finds one, /// installs method info and returns type of method (else None). fn try_overloaded_slice_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, @@ -4327,7 +4275,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, let actual_structure_type = fcx.expr_ty(&*expr); if !ty::type_is_error(actual_structure_type) { let type_and_substs = astconv::ast_path_to_ty_relaxed(fcx, - fcx.infcx(), + fcx, struct_id, path); match fcx.mk_subty(false, @@ -4410,8 +4358,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, }, base_t, None); - fcx.write_ty(idx.id, ty::mk_err()); - fcx.write_ty(id, ty::mk_err()) + fcx.write_ty(idx.id, fcx.tcx().types.err); + fcx.write_ty(id, fcx.tcx().types.err); } } } @@ -4440,7 +4388,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, fcx.write_ty(id, element_ty); } _ => { - check_expr_has_type(fcx, &**idx, ty::mk_err()); + check_expr_has_type(fcx, &**idx, fcx.tcx().types.err); fcx.type_error_message( expr.span, |actual| { @@ -4449,7 +4397,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, }, base_t, None); - fcx.write_ty(id, ty::mk_err()) + fcx.write_ty(id, fcx.tcx().types.err); } } } @@ -4468,19 +4416,21 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, }); let idx_type = match (t_start, t_end) { - (Some(ty), None) | (None, Some(ty)) => Some(ty), - (Some(t_start), Some(t_end)) - if ty::type_is_error(t_start) || ty::type_is_error(t_end) => { - Some(ty::mk_err()) - } - (Some(t_start), Some(t_end)) => { - Some(infer::common_supertype(fcx.infcx(), - infer::RangeExpression(expr.span), - true, - t_start, - t_end)) - } - _ => None + (Some(ty), None) | (None, Some(ty)) => { + Some(ty) + } + (Some(t_start), Some(t_end)) if (ty::type_is_error(t_start) || + ty::type_is_error(t_end)) => { + Some(fcx.tcx().types.err) + } + (Some(t_start), Some(t_end)) => { + Some(infer::common_supertype(fcx.infcx(), + infer::RangeExpression(expr.span), + true, + t_start, + t_end)) + } + _ => None }; // Note that we don't check the type of start/end satisfy any @@ -4489,7 +4439,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, let range_type = match idx_type { Some(idx_type) if ty::type_is_error(idx_type) => { - ty::mk_err() + fcx.tcx().types.err } Some(idx_type) => { // Find the did from the appropriate lang item. @@ -4515,7 +4465,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, ty::mk_struct(tcx, did, tcx.mk_substs(substs)) } else { tcx.sess.span_err(expr.span, "No lang item for range syntax"); - ty::mk_err() + fcx.tcx().types.err } } None => { @@ -4525,7 +4475,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, ty::mk_struct(tcx, did, tcx.mk_substs(substs)) } else { tcx.sess.span_err(expr.span, "No lang item for range syntax"); - ty::mk_err() + fcx.tcx().types.err } } }; diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 47473564254e1..9e184db3b84fe 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1098,7 +1098,6 @@ fn ty_generics_for_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let bounds = compute_bounds(ccx, assoc_ty, assoc_type_def.bounds.as_slice(), - &assoc_type_def.unbound, assoc_type_def.span); ty::predicates(ccx.tcx, assoc_ty, &bounds).into_iter() diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 467f34261ba78..1fbfbe7eb1ab5 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1474,7 +1474,7 @@ impl<'tcx> Clean for ty::Ty<'tcx> { ty::ty_projection(ref data) => { let trait_ref = match data.trait_ref.clean(cx) { - TyParamBound::TraitBound(t) => t.trait_, + TyParamBound::TraitBound(t, _) => t.trait_, TyParamBound::RegionBound(_) => panic!("cleaning a trait got a region??"), }; Type::QPath { diff --git a/src/test/run-pass/trait-static-method-generic-inference.rs b/src/test/compile-fail/trait-static-method-generic-inference.rs similarity index 69% rename from src/test/run-pass/trait-static-method-generic-inference.rs rename to src/test/compile-fail/trait-static-method-generic-inference.rs index 4151ad6530ef4..651f663fc9913 100644 --- a/src/test/run-pass/trait-static-method-generic-inference.rs +++ b/src/test/compile-fail/trait-static-method-generic-inference.rs @@ -8,6 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// Issue #3902. We are (at least currently) unable to infer `Self` +// based on `T`, even though there is only a single impl, because of +// the possibility of associated types and other things (basically: no +// constraints on `Self` here at all). + mod base { pub trait HasNew { fn new() -> T; @@ -22,19 +27,11 @@ mod base { Foo { dummy: () } } } - - pub struct Bar { - dummy: (), - } - - impl HasNew for Bar { - fn new() -> Bar { - Bar { dummy: () } - } - } } -pub fn main() { +pub fn foo() { let _f: base::Foo = base::HasNew::new(); - let _b: base::Bar = base::HasNew::new(); + //~^ ERROR type annotations required } + +fn main() { }