From 9fca13dfb876947ad3f827a7b84da13d2e63d1e2 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Wed, 12 Dec 2012 16:36:51 -0800 Subject: [PATCH] Auto-borrow trait types Allow @A to be used where &A is expected, if A is a trait. As per issue 3794 --- src/librustc/middle/borrowck/gather_loans.rs | 5 ++ src/librustc/middle/trans/expr.rs | 5 +- src/librustc/middle/ty.rs | 75 ++++++++++++------- .../middle/typeck/infer/assignment.rs | 8 ++ src/test/run-pass/issue-3794.rs | 1 - 5 files changed, 65 insertions(+), 29 deletions(-) diff --git a/src/librustc/middle/borrowck/gather_loans.rs b/src/librustc/middle/borrowck/gather_loans.rs index eafbe8b16abc..537ecf143cce 100644 --- a/src/librustc/middle/borrowck/gather_loans.rs +++ b/src/librustc/middle/borrowck/gather_loans.rs @@ -307,6 +307,11 @@ impl gather_loan_ctxt { autoref.mutbl, autoref.region) } + ty::AutoBorrowTrait => { + self.guarantee_valid(cmt, + autoref.mutbl, + autoref.region); + } } } } diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs index 59a1206bd0d0..ffd28d8f40ca 100644 --- a/src/librustc/middle/trans/expr.rs +++ b/src/librustc/middle/trans/expr.rs @@ -119,7 +119,8 @@ use base::*; use syntax::print::pprust::{expr_to_str}; use util::ppaux::ty_to_str; use util::common::indenter; -use ty::{AutoPtr, AutoBorrowVec, AutoBorrowVecRef, AutoBorrowFn}; +use ty::{AutoPtr, AutoBorrowVec, AutoBorrowVecRef, AutoBorrowFn, + AutoBorrowTrait}; use callee::{AutorefArg, DoAutorefArg, DontAutorefArg}; use middle::ty::MoveValue; @@ -196,7 +197,7 @@ fn trans_to_datum(bcx: block, expr: @ast::expr) -> DatumBlock { None => datum, Some(ref autoref) => { match autoref.kind { - AutoPtr => { + AutoPtr | AutoBorrowTrait => { unpack_datum!(bcx, auto_ref(bcx, datum)) } AutoBorrowVec => { diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 1ef91bfda880..7fd43865405f 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -216,6 +216,7 @@ export trait_supertraits; export AutoAdjustment; export AutoRef; export AutoRefKind, AutoPtr, AutoBorrowVec, AutoBorrowVecRef, AutoBorrowFn; +export AutoBorrowTrait; export iter_bound_traits_and_supertraits; export count_traits_and_supertraits; @@ -354,6 +355,9 @@ enum AutoRefKind { /// Convert from @fn()/~fn() to &fn() AutoBorrowFn, + + /// Convert from @T to &T where T is a trait + AutoBorrowTrait, } // Stores information about provided methods (a.k.a. default methods) in @@ -1024,7 +1028,13 @@ fn mk_t_with_id(cx: ctxt, +st: sty, o_def_id: Option) -> t { ty_self => flags |= has_self as uint, ty_enum(_, ref substs) | ty_struct(_, ref substs) | ty_trait(_, ref substs, _) => { - flags |= sflags(substs); + flags |= sflags(substs); + match st { + ty_trait(_, _, vstore_slice(r)) => { + flags |= rflags(r); + } + _ => () + } } ty_box(m) | ty_uniq(m) | ty_evec(m, _) | ty_ptr(m) | ty_unboxed_vec(m) => { @@ -1233,6 +1243,7 @@ fn default_arg_mode_for_ty(tcx: ctxt, ty: ty::t) -> ast::rmode { ty::ty_rptr(*) => true, ty_evec(_, vstore_slice(_)) => true, ty_estr(vstore_slice(_)) => true, + ty_trait(_, _, vstore_slice(_)) => true, // technically, we prob ought to include // &fn(), but that is treated specially due to #2202 @@ -1412,7 +1423,11 @@ fn fold_regions_and_ty( ty::mk_struct(cx, def_id, fold_substs(substs, fldr, fldt)) } ty_trait(def_id, ref substs, vst) => { - ty::mk_trait(cx, def_id, fold_substs(substs, fldr, fldt), vst) + let m_vst = match vst { + vstore_slice(r) => vstore_slice(fldr(r)), + _ => vst + }; + ty::mk_trait(cx, def_id, fold_substs(substs, fldr, fldt), m_vst) } ty_fn(ref f) => { let new_region = fldr(f.meta.region); @@ -1483,30 +1498,35 @@ fn fold_region(cx: ctxt, t0: t, fldop: fn(Region, bool) -> Region) -> t { let tb = get(t0); if !tbox_has_flag(tb, has_regions) { return t0; } match tb.sty { - ty_rptr(r, {ty: t1, mutbl: m}) => { - let m_r = fldop(r, under_r); - let m_t1 = do_fold(cx, t1, true, fldop); - ty::mk_rptr(cx, m_r, {ty: m_t1, mutbl: m}) - } - ty_estr(vstore_slice(r)) => { - let m_r = fldop(r, under_r); - ty::mk_estr(cx, vstore_slice(m_r)) - } - ty_evec({ty: t1, mutbl: m}, vstore_slice(r)) => { - let m_r = fldop(r, under_r); - let m_t1 = do_fold(cx, t1, true, fldop); - ty::mk_evec(cx, {ty: m_t1, mutbl: m}, vstore_slice(m_r)) - } - ty_fn(_) => { - // do not recurse into functions, which introduce fresh bindings - t0 - } - ref sty => { - do fold_sty_to_ty(cx, sty) |t| { - do_fold(cx, t, under_r, fldop) + ty_rptr(r, {ty: t1, mutbl: m}) => { + let m_r = fldop(r, under_r); + let m_t1 = do_fold(cx, t1, true, fldop); + ty::mk_rptr(cx, m_r, {ty: m_t1, mutbl: m}) } - } - } + ty_estr(vstore_slice(r)) => { + let m_r = fldop(r, under_r); + ty::mk_estr(cx, vstore_slice(m_r)) + } + ty_evec({ty: t1, mutbl: m}, vstore_slice(r)) => { + let m_r = fldop(r, under_r); + let m_t1 = do_fold(cx, t1, true, fldop); + ty::mk_evec(cx, {ty: m_t1, mutbl: m}, vstore_slice(m_r)) + } + ty_fn(_) => { + // do not recurse into functions, which introduce fresh + // bindings + t0 + } + ty_trait(id, substs, vstore_slice(r)) => { + let m_r = fldop(r, under_r); + ty::mk_trait(cx, id, substs, vstore_slice(m_r)) + } + ref sty => { + do fold_sty_to_ty(cx, sty) |t| { + do_fold(cx, t, under_r, fldop) + } + } + } } do_fold(cx, t0, false, fldop) @@ -1693,7 +1713,8 @@ pure fn type_is_region_ptr(ty: t) -> bool { pure fn type_is_slice(ty: t) -> bool { match get(ty).sty { - ty_evec(_, vstore_slice(_)) | ty_estr(vstore_slice(_)) => true, + ty_evec(_, vstore_slice(_)) | ty_estr(vstore_slice(_)) + | ty_trait(_, _, vstore_slice(_)) => true, _ => return false } } @@ -1725,6 +1746,8 @@ pure fn type_is_unique(ty: t) -> bool { ty_uniq(_) => return true, ty_evec(_, vstore_uniq) => true, ty_estr(vstore_uniq) => true, +// Note that ~Trait is *not* considered unique. If it is, +// casts to ~Trait get treated like immediate casts. _ => return false } } diff --git a/src/librustc/middle/typeck/infer/assignment.rs b/src/librustc/middle/typeck/infer/assignment.rs index 2ceff545eb73..1d0bde118133 100644 --- a/src/librustc/middle/typeck/infer/assignment.rs +++ b/src/librustc/middle/typeck/infer/assignment.rs @@ -194,6 +194,14 @@ priv impl Assign { a, nr_b, m_imm, b_f.meta.region) } + (ty::ty_trait(_, _, vs_1), + ty::ty_trait(t_2, s_2, ty::vstore_slice(r_b))) => { + let nr_b = ty::mk_trait(self.infcx.tcx, t_2, s_2, + vs_1); + self.try_assign(0, ty::AutoBorrowTrait, a, nr_b, + m_const, r_b) + } + // check for &T being assigned to *T: (ty::ty_rptr(_, ref a_t), ty::ty_ptr(ref b_t)) => { match Sub(*self).mts(*a_t, *b_t) { diff --git a/src/test/run-pass/issue-3794.rs b/src/test/run-pass/issue-3794.rs index 9d39d59b24f8..c88ea36aa33f 100644 --- a/src/test/run-pass/issue-3794.rs +++ b/src/test/run-pass/issue-3794.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// xfail-test trait T { fn print(&self); }