From e7073edaa72edf747f20f6d06daea21b3848ef06 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 27 Mar 2013 19:14:52 -0700 Subject: [PATCH 1/2] librustc: Implement coercion for traits. r=nmatsakis --- src/librustc/metadata/tydecode.rs | 10 + src/librustc/metadata/tyencode.rs | 2 +- src/librustc/middle/astencode.rs | 190 ++++++++++++++-- src/librustc/middle/borrowck/gather_loans.rs | 6 + src/librustc/middle/borrowck/mod.rs | 2 +- src/librustc/middle/mem_categorization.rs | 6 + src/librustc/middle/trans/consts.rs | 3 + src/librustc/middle/trans/expr.rs | 49 +++- src/librustc/middle/trans/meth.rs | 25 ++- src/librustc/middle/ty.rs | 32 ++- src/librustc/middle/typeck/check/regionck.rs | 46 ++++ src/librustc/middle/typeck/check/vtable.rs | 212 ++++++++++-------- src/librustc/middle/typeck/check/writeback.rs | 4 + src/librustc/middle/typeck/infer/coercion.rs | 90 ++++++++ .../trait-coercion-generic-bad.rs | 22 ++ .../trait-coercion-generic-regions.rs | 22 ++ src/test/run-pass/trait-coercion-generic.rs | 32 +++ src/test/run-pass/trait-coercion.rs | 32 +++ 18 files changed, 664 insertions(+), 121 deletions(-) create mode 100644 src/test/compile-fail/trait-coercion-generic-bad.rs create mode 100644 src/test/compile-fail/trait-coercion-generic-regions.rs create mode 100644 src/test/run-pass/trait-coercion-generic.rs create mode 100644 src/test/run-pass/trait-coercion.rs diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs index e37b3a963c4e8..7a5552c3d99c5 100644 --- a/src/librustc/metadata/tydecode.rs +++ b/src/librustc/metadata/tydecode.rs @@ -106,6 +106,16 @@ pub fn parse_ty_data(data: @~[u8], crate_num: int, pos: uint, tcx: ty::ctxt, parse_ty(st, conv) } +pub fn parse_substs_data(data: @~[u8], + crate_num: int, + pos: uint, + tcx: ty::ctxt, + conv: conv_did) + -> ty::substs { + let st = parse_state_from_data(data, crate_num, pos, tcx); + parse_substs(st, conv) +} + pub fn parse_arg_data(data: @~[u8], crate_num: int, pos: uint, tcx: ty::ctxt, conv: conv_did) -> ty::arg { let st = parse_state_from_data(data, crate_num, pos, tcx); diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs index 6734abb7e8075..a473c337cd347 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -132,7 +132,7 @@ fn enc_opt(w: @io::Writer, t: Option, enc_f: &fn(T)) { } } -fn enc_substs(w: @io::Writer, cx: @ctxt, substs: ty::substs) { +pub fn enc_substs(w: @io::Writer, cx: @ctxt, substs: ty::substs) { do enc_opt(w, substs.self_r) |r| { enc_region(w, cx, r) } do enc_opt(w, substs.self_ty) |t| { enc_ty(w, cx, t) } w.write_char('['); diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index c2692e9fa105d..fdd2d30a44954 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -443,18 +443,25 @@ impl tr for ast::def { // ______________________________________________________________________ // Encoding and decoding of adjustment information -impl tr for ty::AutoAdjustment { - fn tr(&self, xcx: @ExtendedDecodeContext) -> ty::AutoAdjustment { - match self { - &ty::AutoAddEnv(r, s) => { - ty::AutoAddEnv(r.tr(xcx), s) +impl tr for ty::SigilAndRegion { + fn tr(&self, xcx: @ExtendedDecodeContext) -> ty::SigilAndRegion { + match *self { + ty::BorrowedSigilAndRegion(ref region) => { + ty::BorrowedSigilAndRegion(region.tr(xcx)) } + ty::OwnedSigilAndRegion => ty::OwnedSigilAndRegion, + ty::ManagedSigilAndRegion => ty::ManagedSigilAndRegion, + } + } +} - &ty::AutoDerefRef(ref adr) => { - ty::AutoDerefRef(ty::AutoDerefRef { - autoderefs: adr.autoderefs, - autoref: adr.autoref.map(|ar| ar.tr(xcx)), - }) +impl tr for ty::AutoDerefRef { + fn tr(&self, xcx: @ExtendedDecodeContext) -> ty::AutoDerefRef { + ty::AutoDerefRef { + autoderefs: self.autoderefs, + autoref: match self.autoref { + None => None, + Some(ref autoref) => Some(autoref.tr(xcx)), } } } @@ -782,6 +789,10 @@ trait ebml_writer_helpers { fn emit_bounds(&self, ecx: @e::EncodeContext, bs: ty::param_bounds); fn emit_tpbt(&self, ecx: @e::EncodeContext, tpbt: ty::ty_param_bounds_and_ty); + fn emit_substs(&self, ecx: @e::EncodeContext, substs: &ty::substs); + fn emit_auto_adjustment(&self, + ecx: @e::EncodeContext, + adj: ty::AutoAdjustment); } impl ebml_writer_helpers for writer::Encoder { @@ -831,6 +842,51 @@ impl ebml_writer_helpers for writer::Encoder { } } } + + fn emit_substs(&self, ecx: @e::EncodeContext, substs: &ty::substs) { + do self.emit_opaque { + tyencode::enc_substs(self.writer, ecx.ty_str_ctxt(), *substs) + } + } + + fn emit_auto_adjustment(&self, + ecx: @e::EncodeContext, + adj: ty::AutoAdjustment) { + do self.emit_enum(~"AutoAdjustment") { + match adj { + ty::AutoAddEnv(region, sigil) => { + do self.emit_enum_variant(~"AutoAddEnv", 0, 2) { + do self.emit_enum_variant_arg(0) { + region.encode(self); + } + do self.emit_enum_variant_arg(1) { + sigil.encode(self); + } + } + } + ty::AutoDerefRef(ref auto_deref_ref) => { + do self.emit_enum_variant(~"AutoDerefRef", 1, 1) { + do self.emit_enum_variant_arg(0) { + auto_deref_ref.encode(self); + } + } + } + ty::AutoObject(ref sigil_and_region, def_id, ref substs) => { + do self.emit_enum_variant(~"AutoObject", 2, 3) { + do self.emit_enum_variant_arg(0) { + sigil_and_region.encode(self); + } + do self.emit_enum_variant_arg(1) { + def_id.encode(self); + } + do self.emit_enum_variant_arg(2) { + self.emit_substs(ecx, substs); + } + } + } + } + } + } } trait write_tag_and_id { @@ -985,7 +1041,7 @@ fn encode_side_tables_for_id(ecx: @e::EncodeContext, do ebml_w.tag(c::tag_table_adjustments) { ebml_w.id(id); do ebml_w.tag(c::tag_table_val) { - (**adj).encode(&ebml_w) + ebml_w.emit_auto_adjustment(ecx, ***adj); } } } @@ -1027,6 +1083,9 @@ trait ebml_decoder_decoder_helpers { fn read_bounds(&self, xcx: @ExtendedDecodeContext) -> @~[ty::param_bound]; fn read_ty_param_bounds_and_ty(&self, xcx: @ExtendedDecodeContext) -> ty::ty_param_bounds_and_ty; + fn read_substs(&self, xcx: @ExtendedDecodeContext) -> ty::substs; + fn read_auto_adjustment(&self, xcx: @ExtendedDecodeContext) + -> ty::AutoAdjustment; fn convert_def_id(&self, xcx: @ExtendedDecodeContext, source: DefIdSource, did: ast::def_id) -> ast::def_id; @@ -1099,6 +1158,111 @@ impl ebml_decoder_decoder_helpers for reader::Decoder { } } + fn read_substs(&self, xcx: @ExtendedDecodeContext) -> ty::substs { + do self.read_opaque |doc| { + tydecode::parse_substs_data(doc.data, + xcx.dcx.cdata.cnum, + doc.start, + xcx.dcx.tcx, + |s, a| self.convert_def_id(xcx, s, a)) + } + } + + #[cfg(stage0)] + fn read_auto_adjustment(&self, xcx: @ExtendedDecodeContext) + -> ty::AutoAdjustment { + do self.read_enum("AutoAdjustment") { + do self.read_enum_variant |i| { + match i { + 0 => { + let region: ty::Region = + do self.read_enum_variant_arg(0) { + Decodable::decode(self) + }; + let sigil: ast::Sigil = + do self.read_enum_variant_arg(1) { + Decodable::decode(self) + }; + ty::AutoAddEnv(region.tr(xcx), sigil) + } + 1 => { + let auto_deref_ref: ty::AutoDerefRef = + do self.read_enum_variant_arg(0) { + Decodable::decode(self) + }; + ty::AutoDerefRef(auto_deref_ref.tr(xcx)) + } + 2 => { + let sigil_and_region: ty::SigilAndRegion = + do self.read_enum_variant_arg(0) { + Decodable::decode(self) + }; + let def_id: ast::def_id = + do self.read_enum_variant_arg(1) { + Decodable::decode(self) + }; + let substs: ty::substs = + do self.read_enum_variant_arg(2) { + self.read_substs(xcx) + }; + ty::AutoObject(sigil_and_region.tr(xcx), + def_id, + substs) + } + _ => fail!(~"bad enum variant") + } + } + } + } + + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn read_auto_adjustment(&self, xcx: @ExtendedDecodeContext) + -> ty::AutoAdjustment { + do self.read_enum("AutoAdjustment") { + static variants: [ &'static str, ..3 ] = + [ "AutoAddEnv", "AutoDerefRef", "AutoObject" ]; + do self.read_enum_variant(variants) |i| { + match i { + 0 => { + let region: ty::Region = + do self.read_enum_variant_arg(0) { + Decodable::decode(self) + }; + let sigil: ast::Sigil = + do self.read_enum_variant_arg(1) { + Decodable::decode(self) + }; + ty::AutoAddEnv(region.tr(xcx), sigil) + } + 1 => { + let auto_deref_ref: ty::AutoDerefRef = + do self.read_enum_variant_arg(0) { + Decodable::decode(self) + }; + ty::AutoDerefRef(auto_deref_ref.tr(xcx)) + } + 2 => { + let sigil_and_region: ty::SigilAndRegion = + do self.read_enum_variant_arg(0) { + Decodable::decode(self) + }; + let def_id: ast::def_id = + do self.read_enum_variant_arg(1) { + Decodable::decode(self) + }; + let substs = self.read_substs(xcx); + ty::AutoObject(sigil_and_region.tr(xcx), + def_id, + substs) + } + _ => fail!(~"bad enum variant") + } + } + } + } + fn convert_def_id(&self, xcx: @ExtendedDecodeContext, source: tydecode::DefIdSource, did: ast::def_id) -> ast::def_id { @@ -1180,8 +1344,8 @@ fn decode_side_tables(xcx: @ExtendedDecodeContext, dcx.maps.vtable_map.insert(id, val_dsr.read_vtable_res(xcx)); } else if tag == (c::tag_table_adjustments as uint) { - let adj: @ty::AutoAdjustment = @Decodable::decode(val_dsr); - adj.tr(xcx); + let adj: @ty::AutoAdjustment = + @val_dsr.read_auto_adjustment(xcx); dcx.tcx.adjustments.insert(id, adj); } else if tag == (c::tag_table_capture_map as uint) { let cvars = diff --git a/src/librustc/middle/borrowck/gather_loans.rs b/src/librustc/middle/borrowck/gather_loans.rs index d18aa1c12dfae..5e9020b728cf0 100644 --- a/src/librustc/middle/borrowck/gather_loans.rs +++ b/src/librustc/middle/borrowck/gather_loans.rs @@ -292,6 +292,12 @@ pub impl GatherLoanCtxt { return; } + ty::AutoObject(*) => { + // NB: We need not do something now, but if this borrows + // `@Trait` to `&Trait` then this will need a guarantee. + return; + } + ty::AutoDerefRef( ty::AutoDerefRef { autoref: None, _ }) => { diff --git a/src/librustc/middle/borrowck/mod.rs b/src/librustc/middle/borrowck/mod.rs index cdec64b7b4c98..2c640476c001a 100644 --- a/src/librustc/middle/borrowck/mod.rs +++ b/src/librustc/middle/borrowck/mod.rs @@ -472,7 +472,7 @@ pub impl BorrowckCtxt { fn cat_expr_autoderefd(&self, expr: @ast::expr, adj: @ty::AutoAdjustment) -> cmt { match *adj { - ty::AutoAddEnv(*) => { + ty::AutoAddEnv(*) | ty::AutoObject(*) => { // no autoderefs cat_expr_unadjusted(self.tcx, self.method_map, expr) } diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index b7ec6208d5607..7868d15532d1c 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -359,6 +359,12 @@ pub impl mem_categorization_ctxt { self.cat_expr_unadjusted(expr) } + Some(&@ty::AutoObject(*)) => { + // Result is an rvalue. + let expr_ty = ty::expr_ty_adjusted(self.tcx, expr); + self.cat_rvalue(expr, expr_ty) + } + Some(&@ty::AutoAddEnv(*)) => { // Convert a bare fn to a closure by adding NULL env. // Result is an rvalue. diff --git a/src/librustc/middle/trans/consts.rs b/src/librustc/middle/trans/consts.rs index 050fc0dd334ad..a33001714221c 100644 --- a/src/librustc/middle/trans/consts.rs +++ b/src/librustc/middle/trans/consts.rs @@ -222,6 +222,9 @@ pub fn const_expr(cx: @CrateContext, e: @ast::expr) -> ValueRef { } } } + Some(&@ty::AutoObject(*)) => { + cx.sess.span_unimpl(e.span, ~"unimplemented const object"); + } } let ety_adjusted = ty::expr_ty_adjusted(cx.tcx, e); diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs index c6eec22ef2c1f..d32ade0c1d78b 100644 --- a/src/librustc/middle/trans/expr.rs +++ b/src/librustc/middle/trans/expr.rs @@ -146,8 +146,8 @@ use middle::trans::tvec; use middle::trans::type_of; use middle::ty; use middle::ty::struct_mutable_fields; -use middle::ty::{AutoPtr, AutoBorrowVec, AutoBorrowVecRef, AutoBorrowFn, - AutoDerefRef, AutoAddEnv}; +use middle::ty::{AutoPtr, AutoBorrowVec, AutoBorrowVecRef, AutoBorrowFn}; +use middle::ty::{AutoDerefRef, AutoAddEnv, AutoObject}; use util::common::indenter; use util::ppaux::ty_to_str; @@ -236,6 +236,29 @@ pub fn trans_to_datum(bcx: block, expr: @ast::expr) -> DatumBlock { return DatumBlock {bcx: bcx, datum: datum}; } + Some(&@AutoObject(sigil_and_region, trait_def_id, _)) => { + let mut bcx = bcx; + + let adjusted_ty = expr_ty_adjusted(bcx, expr); + let scratch = scratch_datum(bcx, adjusted_ty, false); + + let trait_store = match sigil_and_region { + ty::BorrowedSigilAndRegion(r) => ty::RegionTraitStore(r), + ty::OwnedSigilAndRegion => ty::UniqTraitStore, + ty::ManagedSigilAndRegion => ty::BoxTraitStore, + }; + + bcx = meth::trans_trait_cast(bcx, + expr, + expr.id, + SaveIn(scratch.val), + trait_store, + false); // no adjustments + + let scratch = scratch.to_appropriate_datum(bcx); + scratch.add_clean(bcx); + return DatumBlock { bcx: bcx, datum: scratch }; + } }; fn auto_ref(bcx: block, datum: Datum) -> DatumBlock { @@ -291,16 +314,27 @@ pub fn trans_to_datum(bcx: block, expr: @ast::expr) -> DatumBlock { } pub fn trans_into(bcx: block, expr: @ast::expr, dest: Dest) -> block { + debug!("checking adjustment for id %d", expr.id as int); if bcx.tcx().adjustments.contains_key(&expr.id) { // use trans_to_datum, which is mildly less efficient but // which will perform the adjustments: let datumblock = trans_to_datum(bcx, expr); + debug!("storing adjusted with llty %s into %s", + datumblock.datum.to_str(bcx.ccx()), + dest.to_str(bcx.ccx())); return match dest { Ignore => datumblock.bcx, SaveIn(lldest) => datumblock.store_to(expr.id, INIT, lldest) }; } + trans_into_unadjusted(bcx, expr, dest) +} + +pub fn trans_into_unadjusted(bcx: block, + expr: @ast::expr, + dest: Dest) + -> block { let ty = expr_ty(bcx, expr); debug!("trans_into_unadjusted(expr=%s, dest=%s)", @@ -323,6 +357,9 @@ pub fn trans_into(bcx: block, expr: @ast::expr, dest: Dest) -> block { return match kind { ty::LvalueExpr => { let datumblock = trans_lvalue_unadjusted(bcx, expr); + debug!("storing LvalueExpr with llty %s into %s", + datumblock.datum.to_str(bcx.ccx()), + dest.to_str(bcx.ccx())); match dest { Ignore => datumblock.bcx, SaveIn(lldest) => datumblock.store_to(expr.id, INIT, lldest) @@ -767,8 +804,12 @@ fn trans_rvalue_dps_unadjusted(bcx: block, expr: @ast::expr, ast::expr_cast(val, _) => { match ty::get(node_id_type(bcx, expr.id)).sty { ty::ty_trait(_, _, store) => { - return meth::trans_trait_cast(bcx, val, expr.id, dest, - store); + return meth::trans_trait_cast(bcx, + val, + expr.id, + dest, + store, + true); } _ => { bcx.tcx().sess.span_bug(expr.span, diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs index c37702e8d2b09..44d9d90766696 100644 --- a/src/librustc/middle/trans/meth.rs +++ b/src/librustc/middle/trans/meth.rs @@ -825,14 +825,18 @@ pub fn trans_trait_cast(bcx: block, val: @ast::expr, id: ast::node_id, dest: expr::Dest, - store: ty::TraitStore) + store: ty::TraitStore, + do_adjustments: bool) -> block { let mut bcx = bcx; let _icx = bcx.insn_ctxt("impl::trans_cast"); let lldest = match dest { Ignore => { - return expr::trans_into(bcx, val, Ignore); + if do_adjustments { + return expr::trans_into(bcx, val, Ignore); + } + return expr::trans_into_unadjusted(bcx, val, Ignore); } SaveIn(dest) => dest }; @@ -847,7 +851,13 @@ pub fn trans_trait_cast(bcx: block, llboxdest = PointerCast(bcx, llboxdest, T_ptr(type_of(bcx.ccx(), v_ty))); - bcx = expr::trans_into(bcx, val, SaveIn(llboxdest)); + if do_adjustments { + bcx = expr::trans_into(bcx, val, SaveIn(llboxdest)); + } else { + bcx = expr::trans_into_unadjusted(bcx, + val, + SaveIn(llboxdest)); + } } ty::UniqTraitStore => { // Translate the uniquely-owned value into the second element of @@ -856,7 +866,14 @@ pub fn trans_trait_cast(bcx: block, llvaldest = PointerCast(bcx, llvaldest, T_ptr(type_of(bcx.ccx(), v_ty))); - bcx = expr::trans_into(bcx, val, SaveIn(llvaldest)); + + if do_adjustments { + bcx = expr::trans_into(bcx, val, SaveIn(llvaldest)); + } else { + bcx = expr::trans_into_unadjusted(bcx, + val, + SaveIn(llvaldest)); + } // Get the type descriptor of the wrapped value and store it into // the third element of the triple as well. diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index d7f71bae85b93..2c43a7ec98ad8 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -165,11 +165,12 @@ pub type opt_region_variance = Option; #[deriving(Eq)] pub enum region_variance { rv_covariant, rv_invariant, rv_contravariant } -#[auto_encode] -#[auto_decode] pub enum AutoAdjustment { AutoAddEnv(ty::Region, ast::Sigil), - AutoDerefRef(AutoDerefRef) + AutoDerefRef(AutoDerefRef), + AutoObject(SigilAndRegion, + ast::def_id /* ID of trait */, + substs /* trait substitutions */), } #[auto_encode] @@ -179,6 +180,14 @@ pub struct AutoDerefRef { autoref: Option } +#[auto_encode] +#[auto_decode] +pub enum SigilAndRegion { + BorrowedSigilAndRegion(Region), + OwnedSigilAndRegion, + ManagedSigilAndRegion, +} + #[auto_encode] #[auto_decode] pub struct AutoRef { @@ -2932,6 +2941,10 @@ pub fn expr_ty_adjusted(cx: ctxt, expr: @ast::expr) -> t { } } } + + Some(&@AutoObject(ref sigil, def_id, ref substs)) => { + trait_adjustment_to_ty(cx, sigil, def_id, substs) + } }; fn borrow_vec(cx: ctxt, expr: @ast::expr, @@ -2976,6 +2989,19 @@ pub fn expr_ty_adjusted(cx: ctxt, expr: @ast::expr) -> t { } } +pub fn trait_adjustment_to_ty(cx: ctxt, + sigil: &SigilAndRegion, + def_id: ast::def_id, + substs: &substs) + -> t { + let trait_store = match *sigil { + BorrowedSigilAndRegion(region) => RegionTraitStore(region), + OwnedSigilAndRegion => UniqTraitStore, + ManagedSigilAndRegion => BoxTraitStore, + }; + mk_trait(cx, def_id, copy *substs, trait_store) +} + pub struct ParamsTy { params: ~[t], ty: t diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs index 02102110d9bc3..cce297379cd4c 100644 --- a/src/librustc/middle/typeck/check/regionck.rs +++ b/src/librustc/middle/typeck/check/regionck.rs @@ -187,6 +187,29 @@ pub fn visit_expr(expr: @ast::expr, &&rcx: @mut Rcx, v: rvt) { autoderefs: autoderefs, autoref: Some(ref autoref)}) => { guarantor::for_autoref(rcx, expr, autoderefs, autoref); } + @ty::AutoObject(ty::BorrowedSigilAndRegion(trait_region), + _, + _) => { + // Determine if we are casting `expr` to an trait + // instance. If so, we have to be sure that the type of + // the source obeys the trait's region bound. + // + // Note: there is a subtle point here concerning type + // parameters. It is possible that the type of `source` + // contains type parameters, which in turn may contain + // regions that are not visible to us (only the caller + // knows about them). The kind checker is ultimately + // responsible for guaranteeing region safety in that + // particular case. There is an extensive comment on the + // function check_cast_for_escaping_regions() in kind.rs + // explaining how it goes about doing that. + + let source_ty = rcx.fcx.expr_ty(expr); + constrain_regions_in_type(rcx, + trait_region, + expr.span, + source_ty); + } _ => {} } } @@ -727,6 +750,29 @@ pub mod guarantor { debug!("before adjustments, cat=%?", expr_ct.cat); match rcx.fcx.inh.adjustments.find(&expr.id) { + Some(&@ty::AutoObject(ty::BorrowedSigilAndRegion(region), + _, + _)) => { + expr_ct.cat = ExprCategorization { + guarantor: None, + pointer: BorrowedPointer(region), + }; + } + + Some(&@ty::AutoObject(ty::OwnedSigilAndRegion, _, _)) => { + expr_ct.cat = ExprCategorization { + guarantor: None, + pointer: OwnedPointer, + }; + } + + Some(&@ty::AutoObject(ty::ManagedSigilAndRegion, _, _)) => { + expr_ct.cat = ExprCategorization { + guarantor: None, + pointer: OtherPointer, + }; + } + Some(&@ty::AutoAddEnv(*)) => { // This is basically an rvalue, not a pointer, no regions // involved. diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs index 8146213d3be6e..96397c9855812 100644 --- a/src/librustc/middle/typeck/check/vtable.rs +++ b/src/librustc/middle/typeck/check/vtable.rs @@ -11,7 +11,7 @@ use core::prelude::*; use middle::resolve::Impl; -use middle::ty::{param_ty, substs}; +use middle::ty::{AutoAddEnv, AutoDerefRef, AutoObject, param_ty, substs}; use middle::ty; use middle::typeck::check::{FnCtxt, impl_self_ty}; use middle::typeck::check::{structurally_resolved_type}; @@ -509,6 +509,102 @@ pub fn early_resolve_expr(ex: @ast::expr, let _indent = indenter(); let cx = fcx.ccx; + let early_resolve_object_cast = |src: @ast::expr, target_ty: ty::t| { + match ty::get(target_ty).sty { + ty::ty_trait(_, _, store) => { + // Look up vtables for the type we're casting to, + // passing in the source and target type. The source + // must be a pointer type suitable to the object sigil, + // e.g.: `@x as @Trait`, `&x as &Trait` or `~x as ~Trait` + let ty = structurally_resolved_type(fcx, ex.span, + fcx.expr_ty(src)); + match (&ty::get(ty).sty, store) { + (&ty::ty_box(mt), ty::BoxTraitStore) | + // XXX: Bare trait store is deprecated. + (&ty::ty_uniq(mt), ty::UniqTraitStore) | + (&ty::ty_rptr(_, mt), ty::RegionTraitStore(*)) => { + let location_info = + &location_info_for_expr(ex); + let vcx = VtableContext { + ccx: fcx.ccx, + infcx: fcx.infcx() + }; + let vtable_opt = + lookup_vtable(&vcx, + location_info, + mt.ty, + target_ty, + is_early); + match vtable_opt { + Some(vtable) => { + // Map this expression to that + // vtable (that is: "ex has vtable + // ") + if !is_early { + insert_vtables(fcx, ex.id, @~[vtable]); + } + } + None => { + fcx.tcx().sess.span_err( + ex.span, + fmt!("failed to find an implementation \ + of trait %s for %s", + fcx.infcx().ty_to_str(target_ty), + fcx.infcx().ty_to_str(mt.ty))); + } + } + + // Now, if this is &trait, we need to link the + // regions. + match (&ty::get(ty).sty, store) { + (&ty::ty_rptr(ra, _), + ty::RegionTraitStore(rb)) => { + infer::mk_subr(fcx.infcx(), + false, + ex.span, + rb, + ra); + } + _ => {} + } + } + + (_, ty::BareTraitStore) => { + fcx.ccx.tcx.sess.span_err( + ex.span, + ~"a sigil (`@`, `~`, or `&`) must be specified \ + when casting to a trait"); + } + + (_, ty::BoxTraitStore) => { + fcx.ccx.tcx.sess.span_err( + ex.span, + fmt!("can only cast an @-pointer \ + to an @-object, not a %s", + ty::ty_sort_str(fcx.tcx(), ty))); + } + + (_, ty::UniqTraitStore) => { + fcx.ccx.tcx.sess.span_err( + ex.span, + fmt!("can only cast an ~-pointer \ + to a ~-object, not a %s", + ty::ty_sort_str(fcx.tcx(), ty))); + } + + (_, ty::RegionTraitStore(_)) => { + fcx.ccx.tcx.sess.span_err( + ex.span, + fmt!("can only cast an &-pointer \ + to an &-object, not a %s", + ty::ty_sort_str(fcx.tcx(), ty))); + } + } + } + _ => { /* not a cast to a trait; ignore */ } + } + }; + match ex.node { ast::expr_path(*) => { for fcx.opt_node_ty_substs(ex.id) |substs| { @@ -562,103 +658,29 @@ pub fn early_resolve_expr(ex: @ast::expr, } } ast::expr_cast(src, _) => { - let target_ty = fcx.expr_ty(ex); - match ty::get(target_ty).sty { - ty::ty_trait(_, _, store) => { - // Look up vtables for the type we're casting to, - // passing in the source and target type. The source - // must be a pointer type suitable to the object sigil, - // e.g.: `@x as @Trait`, `&x as &Trait` or `~x as ~Trait` - let ty = structurally_resolved_type(fcx, ex.span, - fcx.expr_ty(src)); - match (&ty::get(ty).sty, store) { - (&ty::ty_box(mt), ty::BoxTraitStore) | - // XXX: Bare trait store is deprecated. - (&ty::ty_uniq(mt), ty::UniqTraitStore) | - (&ty::ty_rptr(_, mt), ty::RegionTraitStore(*)) => { - let location_info = - &location_info_for_expr(ex); - let vcx = VtableContext { - ccx: fcx.ccx, - infcx: fcx.infcx() - }; - let vtable_opt = - lookup_vtable(&vcx, - location_info, - mt.ty, - target_ty, - is_early); - match vtable_opt { - Some(vtable) => { - // Map this expression to that - // vtable (that is: "ex has vtable - // ") - if !is_early { - insert_vtables(fcx, ex.id, @~[vtable]); - } - } - None => { - fcx.tcx().sess.span_err( - ex.span, - fmt!("failed to find an implementation \ - of trait %s for %s", - fcx.infcx().ty_to_str(target_ty), - fcx.infcx().ty_to_str(mt.ty))); - } - } - - // Now, if this is &trait, we need to link the - // regions. - match (&ty::get(ty).sty, store) { - (&ty::ty_rptr(ra, _), - ty::RegionTraitStore(rb)) => { - infer::mk_subr(fcx.infcx(), - false, - ex.span, - rb, - ra); - } - _ => {} - } - } - - (_, ty::BareTraitStore) => { - fcx.ccx.tcx.sess.span_err( - ex.span, - ~"a sigil (`@`, `~`, or `&`) must be specified \ - when casting to a trait"); - } - - (_, ty::BoxTraitStore) => { - fcx.ccx.tcx.sess.span_err( - ex.span, - fmt!("can only cast an @-pointer \ - to an @-object, not a %s", - ty::ty_sort_str(fcx.tcx(), ty))); - } - - (_, ty::UniqTraitStore) => { - fcx.ccx.tcx.sess.span_err( - ex.span, - fmt!("can only cast an ~-pointer \ - to a ~-object, not a %s", - ty::ty_sort_str(fcx.tcx(), ty))); - } - - (_, ty::RegionTraitStore(_)) => { - fcx.ccx.tcx.sess.span_err( - ex.span, - fmt!("can only cast an &-pointer \ - to an &-object, not a %s", - ty::ty_sort_str(fcx.tcx(), ty))); - } - } - } - _ => { /* not a cast to a trait; ignore */ } - } + let target_ty = fcx.expr_ty(ex); + early_resolve_object_cast(src, target_ty); } _ => () } + + // Search for auto-adjustments to find trait coercions. + match fcx.inh.adjustments.find(&ex.id) { + None => {} + Some(adjustment) => { + match **adjustment { + AutoAddEnv(_, _) => {} + AutoDerefRef(_) => {} + AutoObject(ref sigil, def_id, ref substs) => { + let object_ty = ty::trait_adjustment_to_ty(cx.tcx, + sigil, + def_id, + substs); + early_resolve_object_cast(ex, object_ty); + } + } + } + } } pub fn resolve_expr(ex: @ast::expr, diff --git a/src/librustc/middle/typeck/check/writeback.rs b/src/librustc/middle/typeck/check/writeback.rs index 9ba98a4d27f10..4b5251e7a4196 100644 --- a/src/librustc/middle/typeck/check/writeback.rs +++ b/src/librustc/middle/typeck/check/writeback.rs @@ -119,6 +119,10 @@ fn resolve_type_vars_for_node(wbcx: @mut WbCtxt, sp: span, id: ast::node_id) match fcx.inh.adjustments.find(&id) { None => (), + Some(&adjustment @ @ty::AutoObject(*)) => { + fcx.tcx().adjustments.insert(id, adjustment); + } + Some(&@ty::AutoAddEnv(r, s)) => { match resolve_region(fcx.infcx(), r, resolve_all | force_all) { Err(e) => { diff --git a/src/librustc/middle/typeck/infer/coercion.rs b/src/librustc/middle/typeck/infer/coercion.rs index 91c987acc6aa7..68fba78cd7407 100644 --- a/src/librustc/middle/typeck/infer/coercion.rs +++ b/src/librustc/middle/typeck/infer/coercion.rs @@ -128,6 +128,68 @@ pub impl Coerce { }; } + ty::ty_trait(def_id, ref substs, ty::BoxTraitStore) => { + let result = do self.unpack_actual_value(a) |sty_a| { + match *sty_a { + ty::ty_box(*) => { + self.coerce_object(a, + sty_a, + b, + def_id, + substs, + ty::BoxTraitStore) + } + _ => Err(ty::terr_mismatch) + } + }; + match result { + Ok(t) => return Ok(t), + Err(_) => {} + } + } + + ty::ty_trait(def_id, ref substs, ty::UniqTraitStore) => { + let result = do self.unpack_actual_value(a) |sty_a| { + match *sty_a { + ty::ty_uniq(*) => { + self.coerce_object(a, + sty_a, + b, + def_id, + substs, + ty::UniqTraitStore) + } + _ => Err(ty::terr_mismatch) + } + }; + match result { + Ok(t) => return Ok(t), + Err(_) => {} + } + } + + ty::ty_trait(def_id, + ref substs, + ty::RegionTraitStore(region)) => { + let result = do self.unpack_actual_value(a) |sty_a| { + match *sty_a { + ty::ty_rptr(*) => { + self.coerce_object(a, + sty_a, + b, + def_id, + substs, + ty::RegionTraitStore(region)) + } + _ => Err(ty::terr_mismatch) + } + }; + match result { + Ok(t) => return Ok(t), + Err(_) => {} + } + } + _ => {} } @@ -376,4 +438,32 @@ pub impl Coerce { let a_unsafe = ty::mk_ptr(self.infcx.tcx, mt_a); self.subtype(a_unsafe, b) } + + fn coerce_object(&self, + a: ty::t, + sty_a: &ty::sty, + b: ty::t, + trait_def_id: ast::def_id, + trait_substs: &ty::substs, + trait_store: ty::TraitStore) + -> CoerceResult { + debug!("coerce_object(a=%s, sty_a=%?, b=%s)", + a.inf_str(self.infcx), + sty_a, + b.inf_str(self.infcx)); + + let sigil_and_region = match trait_store { + ty::BareTraitStore => return Err(ty::terr_mismatch), + ty::BoxTraitStore => ty::ManagedSigilAndRegion, + ty::UniqTraitStore => ty::OwnedSigilAndRegion, + ty::RegionTraitStore(region) => { + ty::BorrowedSigilAndRegion(region) + } + }; + + let adjustment = @ty::AutoObject(sigil_and_region, + trait_def_id, + copy *trait_substs); + Ok(Some(adjustment)) + } } diff --git a/src/test/compile-fail/trait-coercion-generic-bad.rs b/src/test/compile-fail/trait-coercion-generic-bad.rs new file mode 100644 index 0000000000000..ad8bb071733b7 --- /dev/null +++ b/src/test/compile-fail/trait-coercion-generic-bad.rs @@ -0,0 +1,22 @@ +use core::io::println; + +struct Struct { + person: &'static str +} + +trait Trait { + fn f(&self, x: T); +} + +impl Trait<&'static str> for Struct { + fn f(&self, x: &'static str) { + println(fmt!("Hello, %s!", x)); + } +} + +fn main() { + let s: @Trait = @Struct { person: "Fred" }; //~ ERROR mismatched types + //~^ ERROR mismatched types + s.f(1); +} + diff --git a/src/test/compile-fail/trait-coercion-generic-regions.rs b/src/test/compile-fail/trait-coercion-generic-regions.rs new file mode 100644 index 0000000000000..0233d2535c07c --- /dev/null +++ b/src/test/compile-fail/trait-coercion-generic-regions.rs @@ -0,0 +1,22 @@ +use core::io::println; + +struct Struct { + person: &'static str +} + +trait Trait { + fn f(&self, x: T); +} + +impl Trait<&'static str> for Struct { + fn f(&self, x: &'static str) { + println(fmt!("Hello, %s!", x)); + } +} + +fn main() { + let person = ~"Fred"; + let person: &str = person; //~ ERROR illegal borrow + let s: @Trait<&'static str> = @Struct { person: person }; +} + diff --git a/src/test/run-pass/trait-coercion-generic.rs b/src/test/run-pass/trait-coercion-generic.rs new file mode 100644 index 0000000000000..d6379b1b8efaf --- /dev/null +++ b/src/test/run-pass/trait-coercion-generic.rs @@ -0,0 +1,32 @@ +use core::io::println; + +trait Trait { + fn f(&self, x: T); +} + +struct Struct { + x: int, + y: int, +} + +impl Trait<&'static str> for Struct { + fn f(&self, x: &'static str) { + println(~"Hi, " + x + ~"!"); + } +} + +fn f(x: @Trait<&'static str>) { + x.f("Sue"); +} + +fn main() { + let a = Struct { x: 1, y: 2 }; + let b: @Trait<&'static str> = @a; + b.f("Fred"); + let c: ~Trait<&'static str> = ~a; + c.f("Mary"); + let d: &Trait<&'static str> = &a; + d.f("Joe"); + f(@a); +} + diff --git a/src/test/run-pass/trait-coercion.rs b/src/test/run-pass/trait-coercion.rs new file mode 100644 index 0000000000000..4112c8527143a --- /dev/null +++ b/src/test/run-pass/trait-coercion.rs @@ -0,0 +1,32 @@ +use core::io::println; + +trait Trait { + fn f(&self); +} + +struct Struct { + x: int, + y: int, +} + +impl Trait for Struct { + fn f(&self) { + println("Hi!"); + } +} + +fn f(x: @Trait) { + x.f(); +} + +fn main() { + let a = Struct { x: 1, y: 2 }; + let b: @Trait = @a; + b.f(); + let c: ~Trait = ~a; + c.f(); + let d: &Trait = &a; + d.f(); + f(@a); +} + From 1944eab9d44cf38bd4787898024a6e944c8f402b Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 28 Mar 2013 18:04:38 -0700 Subject: [PATCH 2/2] test: Remove `as @Trait`, `as ~Trait`, and `as &Trait` from the test suite. --- src/test/auxiliary/issue-2380.rs | 3 ++- src/test/bench/shootout-mandelbrot.rs | 2 +- src/test/compile-fail/class-cast-to-trait.rs | 2 +- src/test/compile-fail/kindck-owned-trait-contains.rs | 2 +- src/test/compile-fail/kindck-owned-trait-scoped.rs | 6 +++--- src/test/compile-fail/kindck-owned-trait.rs | 4 ++-- src/test/compile-fail/regions-trait-1.rs | 3 ++- src/test/compile-fail/regions-trait-2.rs | 2 +- src/test/compile-fail/regions-trait-3.rs | 2 +- src/test/compile-fail/trait-test-2.rs | 3 ++- src/test/compile-fail/unique-object-noncopyable.rs | 2 +- src/test/run-fail/unwind-box-trait.rs | 2 +- src/test/run-pass/autoderef-method-on-trait.rs | 3 ++- src/test/run-pass/boxed-trait-with-vstore.rs | 2 +- src/test/run-pass/class-cast-to-trait-cross-crate-2.rs | 2 +- src/test/run-pass/class-cast-to-trait-multiple-types.rs | 4 ++-- src/test/run-pass/class-cast-to-trait.rs | 2 +- src/test/run-pass/class-separate-impl.rs | 2 +- src/test/run-pass/explicit-self-objects-box.rs | 2 +- src/test/run-pass/explicit-self-objects-simple.rs | 2 +- src/test/run-pass/explicit-self-objects-uniq.rs | 2 +- src/test/run-pass/generic-object.rs | 2 +- src/test/run-pass/issue-2288.rs | 2 +- src/test/run-pass/issue-2734.rs | 3 ++- src/test/run-pass/issue-2735.rs | 3 ++- src/test/run-pass/issue-2904.rs | 2 +- src/test/run-pass/issue-2935.rs | 3 ++- src/test/run-pass/issue-3794.rs | 2 +- src/test/run-pass/issue-4241.rs | 4 ++-- src/test/run-pass/kindck-owned-trait-contains-1.rs | 3 ++- src/test/run-pass/reflect-visit-data.rs | 4 ++-- src/test/run-pass/regions-trait.rs | 2 +- .../trait-inheritance-cast-without-call-to-supertrait.rs | 4 ++-- src/test/run-pass/trait-inheritance-cast.rs | 4 ++-- src/test/run-pass/trait-region-pointer-simple.rs | 2 +- src/test/run-pass/unique-object.rs | 2 +- 36 files changed, 52 insertions(+), 44 deletions(-) diff --git a/src/test/auxiliary/issue-2380.rs b/src/test/auxiliary/issue-2380.rs index bd1b9d84e0774..610f208dc8cbc 100644 --- a/src/test/auxiliary/issue-2380.rs +++ b/src/test/auxiliary/issue-2380.rs @@ -16,5 +16,6 @@ pub trait i { } pub fn f() -> @i { impl i for () { } - @() as @i + let i: @i = @(); + i } diff --git a/src/test/bench/shootout-mandelbrot.rs b/src/test/bench/shootout-mandelbrot.rs index 1764ef48412cc..59bda83c8247c 100644 --- a/src/test/bench/shootout-mandelbrot.rs +++ b/src/test/bench/shootout-mandelbrot.rs @@ -112,7 +112,7 @@ fn writer(path: ~str, pport: comm::Port, size: uint) { let cout: @io::Writer = match path { ~"" => { - @Devnull as @io::Writer + @Devnull } ~"-" => { io::stdout() diff --git a/src/test/compile-fail/class-cast-to-trait.rs b/src/test/compile-fail/class-cast-to-trait.rs index 0662736545166..80043512fecaa 100644 --- a/src/test/compile-fail/class-cast-to-trait.rs +++ b/src/test/compile-fail/class-cast-to-trait.rs @@ -58,6 +58,6 @@ fn cat(in_x : uint, in_y : int, in_name: ~str) -> cat { } fn main() { - let nyan : @noisy = @cat(0, 2, ~"nyan") as @noisy; + let nyan : @noisy = @cat(0, 2, ~"nyan"); nyan.eat(); //~ ERROR type `@noisy` does not implement any method in scope named `eat` } diff --git a/src/test/compile-fail/kindck-owned-trait-contains.rs b/src/test/compile-fail/kindck-owned-trait-contains.rs index dadc66b5029c7..8e1dd0e4017a8 100644 --- a/src/test/compile-fail/kindck-owned-trait-contains.rs +++ b/src/test/compile-fail/kindck-owned-trait-contains.rs @@ -16,7 +16,7 @@ impl repeat for @A { fn repeater(v: @A) -> @repeat { // Note: owned kind is not necessary as A appears in the trait type - @v as @repeat // No + @v // No } fn main() { diff --git a/src/test/compile-fail/kindck-owned-trait-scoped.rs b/src/test/compile-fail/kindck-owned-trait-scoped.rs index 34ceb67f24343..c22aaec23b18f 100644 --- a/src/test/compile-fail/kindck-owned-trait-scoped.rs +++ b/src/test/compile-fail/kindck-owned-trait-scoped.rs @@ -29,7 +29,7 @@ fn to_foo(t: T) { // the fn body itself. let v = &3; struct F { f: T } - let x = @F {f:t} as @foo; + let x: @foo = @F {f:t}; fail_unless!(x.foo(v) == 3); } @@ -37,14 +37,14 @@ fn to_foo_2(t: T) -> @foo { // Not OK---T may contain borrowed ptrs and it is going to escape // as part of the returned foo value struct F { f: T } - @F {f:t} as @foo //~ ERROR value may contain borrowed pointers; use `'static` bound + @F {f:t} //~ ERROR value may contain borrowed pointers; use `'static` bound } fn to_foo_3(t: T) -> @foo { // OK---T may escape as part of the returned foo value, but it is // owned and hence does not contain borrowed ptrs struct F { f: T } - @F {f:t} as @foo + @F {f:t} } fn main() { diff --git a/src/test/compile-fail/kindck-owned-trait.rs b/src/test/compile-fail/kindck-owned-trait.rs index c61bbc69be519..6565007379ed6 100644 --- a/src/test/compile-fail/kindck-owned-trait.rs +++ b/src/test/compile-fail/kindck-owned-trait.rs @@ -11,11 +11,11 @@ trait foo { fn foo(&self); } fn to_foo(t: T) -> @foo { - @t as @foo //~ ERROR value may contain borrowed pointers; use `'static` bound + @t //~ ERROR value may contain borrowed pointers; use `'static` bound } fn to_foo2(t: T) -> @foo { - @t as @foo + @t } fn main() {} diff --git a/src/test/compile-fail/regions-trait-1.rs b/src/test/compile-fail/regions-trait-1.rs index 2f455e89dff90..46e44f333c817 100644 --- a/src/test/compile-fail/regions-trait-1.rs +++ b/src/test/compile-fail/regions-trait-1.rs @@ -34,5 +34,6 @@ fn get_v(gc: @get_ctxt) -> uint { fn main() { let ctxt = ctxt { v: 22u }; let hc = has_ctxt { c: &ctxt }; - fail_unless!(get_v(@hc as @get_ctxt) == 22u); + let hc_as_get_ctxt: @get_ctxt = @hc; + fail_unless!(get_v(hc_as_get_ctxt) == 22u); } diff --git a/src/test/compile-fail/regions-trait-2.rs b/src/test/compile-fail/regions-trait-2.rs index 5811496cab451..1e6ac3ac20519 100644 --- a/src/test/compile-fail/regions-trait-2.rs +++ b/src/test/compile-fail/regions-trait-2.rs @@ -23,7 +23,7 @@ impl<'self> get_ctxt for has_ctxt<'self> { fn make_gc() -> @get_ctxt { let ctxt = ctxt { v: 22u }; let hc = has_ctxt { c: &ctxt }; - return @hc as @get_ctxt; + @hc } fn main() { diff --git a/src/test/compile-fail/regions-trait-3.rs b/src/test/compile-fail/regions-trait-3.rs index 072b0e83fdf58..6f062cc37c8dd 100644 --- a/src/test/compile-fail/regions-trait-3.rs +++ b/src/test/compile-fail/regions-trait-3.rs @@ -28,7 +28,7 @@ impl get_ctxt for Foo<'self> { } fn make_gc2<'a,'b>(foo: Foo<'a>) -> @get_ctxt<'b> { - return @foo as @get_ctxt; //~ ERROR cannot infer an appropriate lifetime + @foo //~ ERROR cannot infer an appropriate lifetime } fn main() { diff --git a/src/test/compile-fail/trait-test-2.rs b/src/test/compile-fail/trait-test-2.rs index ea04f74f078d4..391a314f1aa45 100644 --- a/src/test/compile-fail/trait-test-2.rs +++ b/src/test/compile-fail/trait-test-2.rs @@ -15,5 +15,6 @@ impl bar for uint { fn dup(&self) -> uint { *self } fn blah(&self) {} } fn main() { 10i.dup::(); //~ ERROR does not take type parameters 10i.blah::(); //~ ERROR incorrect number of type parameters - (@10 as @bar).dup(); //~ ERROR contains a self-type + let bar: @bar = @10; //~ ERROR contains a self-type + bar.dup(); } diff --git a/src/test/compile-fail/unique-object-noncopyable.rs b/src/test/compile-fail/unique-object-noncopyable.rs index edc8a47822d72..992c77dbff2ed 100644 --- a/src/test/compile-fail/unique-object-noncopyable.rs +++ b/src/test/compile-fail/unique-object-noncopyable.rs @@ -28,7 +28,7 @@ impl Foo for Bar { fn main() { let x = ~Bar { x: 10 }; - let y: ~Foo = x as ~Foo; + let y: ~Foo = x; let _z = copy y; //~ ERROR copying a value of non-copyable type } diff --git a/src/test/run-fail/unwind-box-trait.rs b/src/test/run-fail/unwind-box-trait.rs index 2ed3b39a44573..076bd9d133dbe 100644 --- a/src/test/run-fail/unwind-box-trait.rs +++ b/src/test/run-fail/unwind-box-trait.rs @@ -23,7 +23,7 @@ impl i for ~int { } fn main() { - let x = @~0 as @i; + let x: @i = @~0; failfn(); error!(x); } diff --git a/src/test/run-pass/autoderef-method-on-trait.rs b/src/test/run-pass/autoderef-method-on-trait.rs index 3fabb95f2a351..003c94c044d47 100644 --- a/src/test/run-pass/autoderef-method-on-trait.rs +++ b/src/test/run-pass/autoderef-method-on-trait.rs @@ -17,6 +17,7 @@ impl double for uint { } pub fn main() { - let x = @(@3u as @double); + let y: @double = @3u; + let x = @y; fail_unless!(x.double() == 6u); } diff --git a/src/test/run-pass/boxed-trait-with-vstore.rs b/src/test/run-pass/boxed-trait-with-vstore.rs index 1aac86238dc58..af894fb45ab70 100644 --- a/src/test/run-pass/boxed-trait-with-vstore.rs +++ b/src/test/run-pass/boxed-trait-with-vstore.rs @@ -19,7 +19,7 @@ impl Foo for int { } pub fn main() { - let x = @3 as @Foo; + let x: @Foo = @3; x.foo(); } diff --git a/src/test/run-pass/class-cast-to-trait-cross-crate-2.rs b/src/test/run-pass/class-cast-to-trait-cross-crate-2.rs index 5f3650d3aec25..e5372958bfb62 100644 --- a/src/test/run-pass/class-cast-to-trait-cross-crate-2.rs +++ b/src/test/run-pass/class-cast-to-trait-cross-crate-2.rs @@ -21,7 +21,7 @@ fn print_out(thing: @ToStr, expected: ~str) { } pub fn main() { - let nyan : @ToStr = @cat(0u, 2, ~"nyan") as @ToStr; + let nyan : @ToStr = @cat(0u, 2, ~"nyan"); print_out(nyan, ~"nyan"); } diff --git a/src/test/run-pass/class-cast-to-trait-multiple-types.rs b/src/test/run-pass/class-cast-to-trait-multiple-types.rs index eefa78cc3c9af..a4ac8578b0d8a 100644 --- a/src/test/run-pass/class-cast-to-trait-multiple-types.rs +++ b/src/test/run-pass/class-cast-to-trait-multiple-types.rs @@ -86,8 +86,8 @@ fn annoy_neighbors(critter: @noisy) { pub fn main() { let nyan : cat = cat(0u, 2, ~"nyan"); let whitefang : dog = dog(); - annoy_neighbors(@(copy nyan) as @noisy); - annoy_neighbors(@(copy whitefang) as @noisy); + annoy_neighbors(@(copy nyan)); + annoy_neighbors(@(copy whitefang)); fail_unless!((nyan.meow_count() == 10u)); fail_unless!((*whitefang.volume == 1)); } diff --git a/src/test/run-pass/class-cast-to-trait.rs b/src/test/run-pass/class-cast-to-trait.rs index a15afa60c7522..84db8452ad62c 100644 --- a/src/test/run-pass/class-cast-to-trait.rs +++ b/src/test/run-pass/class-cast-to-trait.rs @@ -56,6 +56,6 @@ fn cat(in_x : uint, in_y : int, in_name: ~str) -> cat { pub fn main() { - let mut nyan: @noisy = @cat(0u, 2, ~"nyan") as @noisy; + let mut nyan: @noisy = @cat(0u, 2, ~"nyan"); nyan.speak(); } diff --git a/src/test/run-pass/class-separate-impl.rs b/src/test/run-pass/class-separate-impl.rs index 168f2d872e737..3c290ebaaafc2 100644 --- a/src/test/run-pass/class-separate-impl.rs +++ b/src/test/run-pass/class-separate-impl.rs @@ -66,6 +66,6 @@ fn print_out(thing: @ToStr, expected: ~str) { } pub fn main() { - let mut nyan : @ToStr = @cat(0u, 2, ~"nyan") as @ToStr; + let mut nyan : @ToStr = @cat(0u, 2, ~"nyan"); print_out(nyan, ~"nyan"); } diff --git a/src/test/run-pass/explicit-self-objects-box.rs b/src/test/run-pass/explicit-self-objects-box.rs index 6c981a93d7ceb..af39ab5d79986 100644 --- a/src/test/run-pass/explicit-self-objects-box.rs +++ b/src/test/run-pass/explicit-self-objects-box.rs @@ -24,7 +24,7 @@ impl Foo for S { pub fn main() { let x = @S { x: 3 }; - let y = x as @Foo; + let y: @Foo = x; y.f(); y.f(); y.f(); diff --git a/src/test/run-pass/explicit-self-objects-simple.rs b/src/test/run-pass/explicit-self-objects-simple.rs index 1fa054a9060c9..7c0322d1ae269 100644 --- a/src/test/run-pass/explicit-self-objects-simple.rs +++ b/src/test/run-pass/explicit-self-objects-simple.rs @@ -24,7 +24,7 @@ impl Foo for S { pub fn main() { let x = @S { x: 3 }; - let y = x as @Foo; + let y: @Foo = x; y.f(); } diff --git a/src/test/run-pass/explicit-self-objects-uniq.rs b/src/test/run-pass/explicit-self-objects-uniq.rs index 2361df4f45751..badfae5697861 100644 --- a/src/test/run-pass/explicit-self-objects-uniq.rs +++ b/src/test/run-pass/explicit-self-objects-uniq.rs @@ -24,7 +24,7 @@ impl Foo for S { pub fn main() { let x = ~S { x: 3 }; - let y = x as ~Foo; + let y: ~Foo = x; y.f(); } diff --git a/src/test/run-pass/generic-object.rs b/src/test/run-pass/generic-object.rs index acdd3fc460089..aed96196c1716 100644 --- a/src/test/run-pass/generic-object.rs +++ b/src/test/run-pass/generic-object.rs @@ -24,7 +24,7 @@ impl Foo for S { pub fn main() { let x = @S { x: 1 }; - let y = x as @Foo; + let y: @Foo = x; fail_unless!(y.get() == 1); } diff --git a/src/test/run-pass/issue-2288.rs b/src/test/run-pass/issue-2288.rs index 9aef66fd35c59..c41ef556ebd64 100644 --- a/src/test/run-pass/issue-2288.rs +++ b/src/test/run-pass/issue-2288.rs @@ -33,6 +33,6 @@ fn f(x: @clam, a: A) { pub fn main() { let c = foo(42); - let d: @clam = @c as @clam; + let d: @clam = @c; f(d, c.x); } diff --git a/src/test/run-pass/issue-2734.rs b/src/test/run-pass/issue-2734.rs index 7125e89287cbd..19cd7f9b095b4 100644 --- a/src/test/run-pass/issue-2734.rs +++ b/src/test/run-pass/issue-2734.rs @@ -12,7 +12,8 @@ trait hax { } impl hax for A { } fn perform_hax(x: @T) -> @hax { - @x as @hax + let hax: @hax = @x; + hax } fn deadcode() { diff --git a/src/test/run-pass/issue-2735.rs b/src/test/run-pass/issue-2735.rs index 9a5a366c74473..96275eeaf39ac 100644 --- a/src/test/run-pass/issue-2735.rs +++ b/src/test/run-pass/issue-2735.rs @@ -12,7 +12,8 @@ trait hax { } impl hax for A { } fn perform_hax(x: @T) -> @hax { - @x as @hax + let hax: @hax = @x; + hax } fn deadcode() { diff --git a/src/test/run-pass/issue-2904.rs b/src/test/run-pass/issue-2904.rs index 84a4083a62860..83a8a54ef1898 100644 --- a/src/test/run-pass/issue-2904.rs +++ b/src/test/run-pass/issue-2904.rs @@ -60,7 +60,7 @@ fn square_from_char(c: char) -> square { } fn read_board_grid(+in: rdr) -> ~[~[square]] { - let in = @in as @io::Reader; + let in: @io::Reader = @in; let mut grid = ~[]; for in.each_line |line| { let mut row = ~[]; diff --git a/src/test/run-pass/issue-2935.rs b/src/test/run-pass/issue-2935.rs index c1f4e1e49aa08..b52ff74d0d7f5 100644 --- a/src/test/run-pass/issue-2935.rs +++ b/src/test/run-pass/issue-2935.rs @@ -25,7 +25,8 @@ pub fn main() { // let y = @({a: 4i}); // let z = @({a: 4i} as it); // let z = @({a: true} as it); - let z = @(@true as @it); + let it: @it = @true; + let z = @(it); // x.f(); // y.f(); // (*z).f(); diff --git a/src/test/run-pass/issue-3794.rs b/src/test/run-pass/issue-3794.rs index 1c1eb75c220c1..c8e7cca86538d 100644 --- a/src/test/run-pass/issue-3794.rs +++ b/src/test/run-pass/issue-3794.rs @@ -34,7 +34,7 @@ fn print_s(s: &S) { pub fn main() { let s: @S = @S { s: 5 }; print_s(s); - let t: @T = s as @T; + let t: @T = s; print_t(t); } diff --git a/src/test/run-pass/issue-4241.rs b/src/test/run-pass/issue-4241.rs index 32aa5a0c70afe..cbf97af44d28d 100644 --- a/src/test/run-pass/issue-4241.rs +++ b/src/test/run-pass/issue-4241.rs @@ -108,7 +108,7 @@ fn query(cmd: ~[~str], sb: TcpSocketBuf) -> Result { let cmd = cmd_to_str(cmd); //io::println(cmd); sb.write_str(cmd); - let res = parse_response(@sb as @io::Reader); + let res = parse_response(@sb); //io::println(fmt!("%?", res)); res } @@ -116,7 +116,7 @@ fn query(cmd: ~[~str], sb: TcpSocketBuf) -> Result { fn query2(cmd: ~[~str]) -> Result { let _cmd = cmd_to_str(cmd); do io::with_str_reader(~"$3\r\nXXX\r\n") |sb| { - let res = parse_response(@sb as @io::Reader); + let res = parse_response(@sb); io::println(fmt!("%?", res)); res } diff --git a/src/test/run-pass/kindck-owned-trait-contains-1.rs b/src/test/run-pass/kindck-owned-trait-contains-1.rs index 0a39472025d26..09ff7eecfa6ba 100644 --- a/src/test/run-pass/kindck-owned-trait-contains-1.rs +++ b/src/test/run-pass/kindck-owned-trait-contains-1.rs @@ -16,7 +16,8 @@ impl repeat for @A { fn repeater(v: @A) -> @repeat { // Note: owned kind is not necessary as A appears in the trait type - @v as @repeat // No + let repeat: @repeat = @v; // No + repeat } pub fn main() { diff --git a/src/test/run-pass/reflect-visit-data.rs b/src/test/run-pass/reflect-visit-data.rs index 8e363c3d5db53..7e3c4d211c88b 100644 --- a/src/test/run-pass/reflect-visit-data.rs +++ b/src/test/run-pass/reflect-visit-data.rs @@ -489,7 +489,7 @@ pub impl my_visitor { unsafe { let u = my_visitor(**self); let v = ptr_visit_adaptor::(Inner {inner: u}); - visit_tydesc(inner, @v as @TyVisitor); + visit_tydesc(inner, @v); true } } @@ -644,7 +644,7 @@ pub fn main() { let td = get_tydesc_for(r); unsafe { error!("tydesc sz: %u, align: %u", (*td).size, (*td).align); } - let v = @v as @TyVisitor; + let v: @TyVisitor = @v; visit_tydesc(td, v); for (u.vals.clone()).each |s| { diff --git a/src/test/run-pass/regions-trait.rs b/src/test/run-pass/regions-trait.rs index 92ef18967b361..88bec8b4acf19 100644 --- a/src/test/run-pass/regions-trait.rs +++ b/src/test/run-pass/regions-trait.rs @@ -30,5 +30,5 @@ pub fn main() { let ctxt = Ctxt { v: 22 }; let hc = HasCtxt { c: &ctxt }; - fail_unless!(get_v(@hc as @get_ctxt) == 22); + fail_unless!(get_v(@hc) == 22); } diff --git a/src/test/run-pass/trait-inheritance-cast-without-call-to-supertrait.rs b/src/test/run-pass/trait-inheritance-cast-without-call-to-supertrait.rs index 39565382118f9..0115bed7cce31 100644 --- a/src/test/run-pass/trait-inheritance-cast-without-call-to-supertrait.rs +++ b/src/test/run-pass/trait-inheritance-cast-without-call-to-supertrait.rs @@ -33,8 +33,8 @@ impl Bar for A { pub fn main() { let a = &A { x: 3 }; - let afoo = a as &Foo; - let abar = a as &Bar; + let afoo: &Foo = a; + let abar: &Bar = a; fail_unless!(afoo.f() == 10); fail_unless!(abar.g() == 20); } diff --git a/src/test/run-pass/trait-inheritance-cast.rs b/src/test/run-pass/trait-inheritance-cast.rs index d066f49c73225..bd481618a86a8 100644 --- a/src/test/run-pass/trait-inheritance-cast.rs +++ b/src/test/run-pass/trait-inheritance-cast.rs @@ -34,8 +34,8 @@ impl Bar for A { pub fn main() { let a = &A { x: 3 }; - let afoo = a as &Foo; - let abar = a as &Bar; + let afoo: &Foo = a; + let abar: &Bar = a; fail_unless!(afoo.f() == 10); fail_unless!(abar.g() == 20); fail_unless!(abar.f() == 10); diff --git a/src/test/run-pass/trait-region-pointer-simple.rs b/src/test/run-pass/trait-region-pointer-simple.rs index 1ce2cddc29b05..7a2e3c0e17f76 100644 --- a/src/test/run-pass/trait-region-pointer-simple.rs +++ b/src/test/run-pass/trait-region-pointer-simple.rs @@ -25,7 +25,7 @@ impl Foo for A { pub fn main() { let a = A { x: 3 }; - let b = (&a) as &Foo; + let b: &Foo = &a; fail_unless!(b.f() == 3); } diff --git a/src/test/run-pass/unique-object.rs b/src/test/run-pass/unique-object.rs index f2aab3bbb51df..5115c4c641ce3 100644 --- a/src/test/run-pass/unique-object.rs +++ b/src/test/run-pass/unique-object.rs @@ -24,7 +24,7 @@ impl Foo for Bar { pub fn main() { let x = ~Bar { x: 10 }; - let y = x as ~Foo; + let y: ~Foo = x; fail_unless!(y.f() == 10); }