From 0ad4c6f85022642ddbb3fc10f1743eb4e16abef0 Mon Sep 17 00:00:00 2001 From: Masaki Hara Date: Mon, 10 Sep 2018 22:54:48 +0900 Subject: [PATCH 01/19] Add InstanceDef::VtableShim. --- src/librustc/ich/impls_ty.rs | 3 +++ src/librustc/ty/instance.rs | 7 +++++++ src/librustc/ty/mod.rs | 1 + src/librustc/ty/structural_impls.rs | 5 ++++- src/librustc_mir/interpret/terminator.rs | 1 + src/librustc_mir/monomorphize/collector.rs | 2 ++ src/librustc_mir/monomorphize/partitioning.rs | 3 +++ src/librustc_mir/shim.rs | 3 +++ 8 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index 642eb11006649..e65f4fc57e632 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -1011,6 +1011,9 @@ impl<'a, 'gcx> HashStable> for ty::InstanceDef<'gcx> { ty::InstanceDef::Item(def_id) => { def_id.hash_stable(hcx, hasher); } + ty::InstanceDef::VtableShim(def_id) => { + def_id.hash_stable(hcx, hasher); + } ty::InstanceDef::Intrinsic(def_id) => { def_id.hash_stable(hcx, hasher); } diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index 3d205215d64c6..9410bea2182be 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -27,6 +27,9 @@ pub enum InstanceDef<'tcx> { Item(DefId), Intrinsic(DefId), + /// `::method` where `method` receives unsizeable `self: Self`. + VtableShim(DefId), + /// \::call_* /// def-id is FnTrait::call_* FnPtrShim(DefId, Ty<'tcx>), @@ -63,6 +66,7 @@ impl<'tcx> InstanceDef<'tcx> { pub fn def_id(&self) -> DefId { match *self { InstanceDef::Item(def_id) | + InstanceDef::VtableShim(def_id) | InstanceDef::FnPtrShim(def_id, _) | InstanceDef::Virtual(def_id, _) | InstanceDef::Intrinsic(def_id, ) | @@ -120,6 +124,9 @@ impl<'tcx> fmt::Display for Instance<'tcx> { ppaux::parameterized(f, self.substs, self.def_id(), &[])?; match self.def { InstanceDef::Item(_) => Ok(()), + InstanceDef::VtableShim(_) => { + write!(f, " - shim(vtable)") + } InstanceDef::Intrinsic(_) => { write!(f, " - intrinsic") } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index bb9346f2f468d..4f3d96006fcc8 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2759,6 +2759,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { ty::InstanceDef::Item(did) => { self.optimized_mir(did) } + ty::InstanceDef::VtableShim(..) | ty::InstanceDef::Intrinsic(..) | ty::InstanceDef::FnPtrShim(..) | ty::InstanceDef::Virtual(..) | diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 273799bd4bd34..46fe4e57c1e6e 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -624,6 +624,8 @@ impl<'a, 'tcx> Lift<'tcx> for ty::InstanceDef<'a> { match *self { ty::InstanceDef::Item(def_id) => Some(ty::InstanceDef::Item(def_id)), + ty::InstanceDef::VtableShim(def_id) => + Some(ty::InstanceDef::VtableShim(def_id)), ty::InstanceDef::Intrinsic(def_id) => Some(ty::InstanceDef::Intrinsic(def_id)), ty::InstanceDef::FnPtrShim(def_id, ref ty) => @@ -793,6 +795,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::instance::Instance<'tcx> { substs: self.substs.fold_with(folder), def: match self.def { Item(did) => Item(did.fold_with(folder)), + VtableShim(did) => VtableShim(did.fold_with(folder)), Intrinsic(did) => Intrinsic(did.fold_with(folder)), FnPtrShim(did, ty) => FnPtrShim( did.fold_with(folder), @@ -821,7 +824,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::instance::Instance<'tcx> { use ty::InstanceDef::*; self.substs.visit_with(visitor) || match self.def { - Item(did) | Intrinsic(did) | Virtual(did, _) => { + Item(did) | VtableShim(did) | Intrinsic(did) | Virtual(did, _) => { did.visit_with(visitor) }, FnPtrShim(did, ty) | CloneShim(did, ty) => { diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs index faeeb24c6c267..ee84e49022f1b 100644 --- a/src/librustc_mir/interpret/terminator.rs +++ b/src/librustc_mir/interpret/terminator.rs @@ -256,6 +256,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> self.dump_place(*dest); Ok(()) } + ty::InstanceDef::VtableShim(..) | ty::InstanceDef::ClosureOnceShim { .. } | ty::InstanceDef::FnPtrShim(..) | ty::InstanceDef::DropGlue(..) | diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 6b60b5340eee7..66bf1b628ce5b 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -705,6 +705,7 @@ fn visit_instance_use<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, bug!("intrinsic {:?} being reified", def_id); } } + ty::InstanceDef::VtableShim(..) | ty::InstanceDef::Virtual(..) | ty::InstanceDef::DropGlue(_, None) => { // don't need to emit shim if we are calling directly. @@ -731,6 +732,7 @@ fn should_monomorphize_locally<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: -> bool { let def_id = match instance.def { ty::InstanceDef::Item(def_id) => def_id, + ty::InstanceDef::VtableShim(..) | ty::InstanceDef::ClosureOnceShim { .. } | ty::InstanceDef::Virtual(..) | ty::InstanceDef::FnPtrShim(..) | diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs index 3a1108bb16983..f0a35ca7adbd2 100644 --- a/src/librustc_mir/monomorphize/partitioning.rs +++ b/src/librustc_mir/monomorphize/partitioning.rs @@ -180,6 +180,7 @@ pub trait CodegenUnitExt<'tcx> { InstanceDef::Item(def_id) => { tcx.hir.as_local_node_id(def_id) } + InstanceDef::VtableShim(..) | InstanceDef::Intrinsic(..) | InstanceDef::FnPtrShim(..) | InstanceDef::Virtual(..) | @@ -422,6 +423,7 @@ fn mono_item_visibility( InstanceDef::Item(def_id) => def_id, // These are all compiler glue and such, never exported, always hidden. + InstanceDef::VtableShim(..) | InstanceDef::FnPtrShim(..) | InstanceDef::Virtual(..) | InstanceDef::Intrinsic(..) | @@ -756,6 +758,7 @@ fn characteristic_def_id_of_mono_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, MonoItem::Fn(instance) => { let def_id = match instance.def { ty::InstanceDef::Item(def_id) => def_id, + ty::InstanceDef::VtableShim(..) | ty::InstanceDef::FnPtrShim(..) | ty::InstanceDef::ClosureOnceShim { .. } | ty::InstanceDef::Intrinsic(..) | diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 4b26094b9fc28..867b630bb666b 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -43,6 +43,9 @@ fn make_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let mut result = match instance { ty::InstanceDef::Item(..) => bug!("item {:?} passed to make_shim", instance), + ty::InstanceDef::VtableShim(..) => { + unimplemented!("make_shim({:?})", instance); + } ty::InstanceDef::FnPtrShim(def_id, ty) => { let trait_ = tcx.trait_of_item(def_id).unwrap(); let adjustment = match tcx.lang_items().fn_trait_kind(trait_) { From 6fd914a1afc3d0d0f86e8a9a1bfacd55be053d58 Mon Sep 17 00:00:00 2001 From: Masaki Hara Date: Mon, 10 Sep 2018 23:00:50 +0900 Subject: [PATCH 02/19] Add vtable-shim helper methods for Instance. --- src/librustc/ty/instance.rs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index 9410bea2182be..83029df0fe72f 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -237,6 +237,25 @@ impl<'a, 'b, 'tcx> Instance<'tcx> { result } + pub fn resolve_for_vtable(tcx: TyCtxt<'a, 'tcx, 'tcx>, + param_env: ty::ParamEnv<'tcx>, + def_id: DefId, + substs: &'tcx Substs<'tcx>) -> Option> { + debug!("resolve(def_id={:?}, substs={:?})", def_id, substs); + let fn_sig = tcx.fn_sig(def_id); + let is_vtable_shim = + fn_sig.inputs().skip_binder().len() > 0 && fn_sig.input(0).skip_binder().is_self(); + if is_vtable_shim { + debug!(" => associated item with unsizeable self: Self"); + Some(Instance { + def: InstanceDef::VtableShim(def_id), + substs, + }) + } else { + Instance::resolve(tcx, param_env, def_id, substs) + } + } + pub fn resolve_closure( tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, @@ -251,6 +270,14 @@ impl<'a, 'b, 'tcx> Instance<'tcx> { _ => Instance::new(def_id, substs.substs) } } + + pub fn is_vtable_shim(&self) -> bool { + if let InstanceDef::VtableShim(..) = self.def { + true + } else { + false + } + } } fn resolve_associated_item<'a, 'tcx>( From 824315a7220895b0e21783726eb2b7856bc27406 Mon Sep 17 00:00:00 2001 From: Masaki Hara Date: Mon, 10 Sep 2018 23:01:46 +0900 Subject: [PATCH 03/19] Distinguish vtable shims in symbol paths. --- src/librustc_codegen_utils/symbol_names.rs | 11 ++++++++++- src/test/ui/symbol-names/basic.stderr | 2 +- src/test/ui/symbol-names/impl1.stderr | 4 ++-- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs index c1e80234a7750..27700bab24550 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -219,6 +219,9 @@ fn get_symbol_hash<'a, 'tcx>( .hash_stable(&mut hcx, &mut hasher); (&tcx.crate_disambiguator(instantiating_crate)).hash_stable(&mut hcx, &mut hasher); } + + let is_vtable_shim = instance.is_vtable_shim(); + is_vtable_shim.hash_stable(&mut hcx, &mut hasher); }); // 64 bits should be enough to avoid collisions. @@ -322,7 +325,13 @@ fn compute_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: Instance let hash = get_symbol_hash(tcx, def_id, instance, instance_ty, substs); - SymbolPathBuffer::from_interned(tcx.def_symbol_name(def_id)).finish(hash) + let mut buf = SymbolPathBuffer::from_interned(tcx.def_symbol_name(def_id)); + + if instance.is_vtable_shim() { + buf.push("{{vtable-shim}}"); + } + + buf.finish(hash) } // Follow C++ namespace-mangling style, see diff --git a/src/test/ui/symbol-names/basic.stderr b/src/test/ui/symbol-names/basic.stderr index eeeb1b5e34d8b..5e910caf3c08f 100644 --- a/src/test/ui/symbol-names/basic.stderr +++ b/src/test/ui/symbol-names/basic.stderr @@ -1,4 +1,4 @@ -error: symbol-name(_ZN5basic4main17h2138d548fb9814b6E) +error: symbol-name(_ZN5basic4main17h6ab1850bb0b9f417E) --> $DIR/basic.rs:13:1 | LL | #[rustc_symbol_name] //~ ERROR _ZN5basic4main diff --git a/src/test/ui/symbol-names/impl1.stderr b/src/test/ui/symbol-names/impl1.stderr index edce692969556..46e260bc28cc5 100644 --- a/src/test/ui/symbol-names/impl1.stderr +++ b/src/test/ui/symbol-names/impl1.stderr @@ -1,4 +1,4 @@ -error: symbol-name(_ZN5impl13foo3Foo3bar17h8da62e6147ff602fE) +error: symbol-name(_ZN5impl13foo3Foo3bar17h99c48478d64a0eb0E) --> $DIR/impl1.rs:18:9 | LL | #[rustc_symbol_name] //~ ERROR _ZN5impl13foo3Foo3bar @@ -10,7 +10,7 @@ error: item-path(foo::Foo::bar) LL | #[rustc_item_path] //~ ERROR item-path(foo::Foo::bar) | ^^^^^^^^^^^^^^^^^^ -error: symbol-name(_ZN5impl13bar33_$LT$impl$u20$impl1..foo..Foo$GT$3baz17h374cb8f6185db9b4E) +error: symbol-name(_ZN5impl13bar33_$LT$impl$u20$impl1..foo..Foo$GT$3baz17hebf13830acf865d9E) --> $DIR/impl1.rs:28:9 | LL | #[rustc_symbol_name] //~ ERROR _ZN5impl13bar33_$LT$impl$u20$impl1..foo..Foo$GT$3baz From fe3f606cda083aec9564add4f7ff6ed4c4a0fff7 Mon Sep 17 00:00:00 2001 From: Masaki Hara Date: Tue, 11 Sep 2018 23:26:38 +0900 Subject: [PATCH 04/19] Add ty_fn_sig_vtable for getting adjusted signature for vtable shims. --- src/librustc_codegen_llvm/base.rs | 2 +- src/librustc_codegen_llvm/callee.rs | 2 +- src/librustc_codegen_llvm/common.rs | 19 +++++++++++++++++++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/librustc_codegen_llvm/base.rs b/src/librustc_codegen_llvm/base.rs index 614a562846e86..501a0b8af76bb 100644 --- a/src/librustc_codegen_llvm/base.rs +++ b/src/librustc_codegen_llvm/base.rs @@ -492,7 +492,7 @@ pub fn codegen_instance<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, instance: Instance<' info!("codegen_instance({})", instance); let fn_ty = instance.ty(cx.tcx); - let sig = common::ty_fn_sig(cx, fn_ty); + let sig = common::ty_fn_sig_vtable(cx, fn_ty, instance.is_vtable_shim()); let sig = cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig); let lldecl = cx.instances.borrow().get(&instance).cloned().unwrap_or_else(|| diff --git a/src/librustc_codegen_llvm/callee.rs b/src/librustc_codegen_llvm/callee.rs index 4b4ccb3b600b3..972cccd5d68e0 100644 --- a/src/librustc_codegen_llvm/callee.rs +++ b/src/librustc_codegen_llvm/callee.rs @@ -56,7 +56,7 @@ pub fn get_fn( debug!("get_fn({:?}: {:?}) => {}", instance, fn_ty, sym); // Create a fn pointer with the substituted signature. - let fn_ptr_ty = tcx.mk_fn_ptr(common::ty_fn_sig(cx, fn_ty)); + let fn_ptr_ty = tcx.mk_fn_ptr(common::ty_fn_sig_vtable(cx, fn_ty, instance.is_vtable_shim())); let llptrty = cx.layout_of(fn_ptr_ty).llvm_type(cx); let llfn = if let Some(llfn) = declare::get_declared_value(cx, &sym) { diff --git a/src/librustc_codegen_llvm/common.rs b/src/librustc_codegen_llvm/common.rs index c08937fa9b916..df91f75837422 100644 --- a/src/librustc_codegen_llvm/common.rs +++ b/src/librustc_codegen_llvm/common.rs @@ -453,3 +453,22 @@ pub fn ty_fn_sig<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, _ => bug!("unexpected type {:?} to ty_fn_sig", ty) } } + +pub fn ty_fn_sig_vtable<'a, 'tcx>( + cx: &CodegenCx<'a, 'tcx>, + ty: Ty<'tcx>, + is_vtable_shim: bool + ) -> ty::PolyFnSig<'tcx> +{ + let mut fn_sig = ty_fn_sig(cx, ty); + if is_vtable_shim { + // Modify fn(self, ...) to fn(self: *mut Self, ...) + fn_sig = fn_sig.map_bound(|mut fn_sig| { + let mut inputs_and_output = fn_sig.inputs_and_output.to_vec(); + inputs_and_output[0] = cx.tcx.mk_mut_ptr(inputs_and_output[0]); + fn_sig.inputs_and_output = cx.tcx.intern_type_list(&inputs_and_output); + fn_sig + }); + } + fn_sig +} From 1fb085511e61c3d97f020c9d8d28e567f7cb1694 Mon Sep 17 00:00:00 2001 From: Masaki Hara Date: Tue, 11 Sep 2018 23:30:16 +0900 Subject: [PATCH 05/19] Make declare_fn aware of vtable shims. --- src/librustc_codegen_llvm/callee.rs | 2 +- src/librustc_codegen_llvm/context.rs | 2 +- src/librustc_codegen_llvm/declare.rs | 8 +++++--- src/librustc_codegen_llvm/mono_item.rs | 2 +- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/librustc_codegen_llvm/callee.rs b/src/librustc_codegen_llvm/callee.rs index 972cccd5d68e0..82d85b6ead485 100644 --- a/src/librustc_codegen_llvm/callee.rs +++ b/src/librustc_codegen_llvm/callee.rs @@ -91,7 +91,7 @@ pub fn get_fn( llfn } } else { - let llfn = declare::declare_fn(cx, &sym, fn_ty); + let llfn = declare::declare_fn(cx, &sym, fn_ty, instance.is_vtable_shim()); assert_eq!(common::val_ty(llfn), llptrty); debug!("get_fn: not casting pointer!"); diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs index 826df82193a31..8087f130afaa0 100644 --- a/src/librustc_codegen_llvm/context.rs +++ b/src/librustc_codegen_llvm/context.rs @@ -412,7 +412,7 @@ impl<'b, 'tcx> CodegenCx<'b, 'tcx> { Abi::C ))); - let llfn = declare::declare_fn(self, "rust_eh_unwind_resume", ty); + let llfn = declare::declare_fn(self, "rust_eh_unwind_resume", ty, false); attributes::unwind(llfn, true); attributes::apply_target_cpu_attr(self, llfn); unwresume.set(Some(llfn)); diff --git a/src/librustc_codegen_llvm/declare.rs b/src/librustc_codegen_llvm/declare.rs index 26969e24f0883..0d01e9ef7ddab 100644 --- a/src/librustc_codegen_llvm/declare.rs +++ b/src/librustc_codegen_llvm/declare.rs @@ -130,9 +130,11 @@ pub fn declare_fn( cx: &CodegenCx<'ll, 'tcx>, name: &str, fn_type: Ty<'tcx>, + is_vtable_shim: bool, ) -> &'ll Value { - debug!("declare_rust_fn(name={:?}, fn_type={:?})", name, fn_type); - let sig = common::ty_fn_sig(cx, fn_type); + debug!("declare_rust_fn(name={:?}, fn_type={:?}, is_vtable_shim={:?})", + name, fn_type, is_vtable_shim); + let sig = common::ty_fn_sig_vtable(cx, fn_type, is_vtable_shim); let sig = cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig); debug!("declare_rust_fn (after region erasure) sig={:?}", sig); @@ -189,7 +191,7 @@ pub fn define_fn( if get_defined_value(cx, name).is_some() { cx.sess().fatal(&format!("symbol `{}` already defined", name)) } else { - declare_fn(cx, name, fn_type) + declare_fn(cx, name, fn_type, false) } } diff --git a/src/librustc_codegen_llvm/mono_item.rs b/src/librustc_codegen_llvm/mono_item.rs index dab9b147cc070..aab8613b75619 100644 --- a/src/librustc_codegen_llvm/mono_item.rs +++ b/src/librustc_codegen_llvm/mono_item.rs @@ -155,7 +155,7 @@ fn predefine_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, let mono_ty = instance.ty(cx.tcx); let attrs = cx.tcx.codegen_fn_attrs(instance.def_id()); - let lldecl = declare::declare_fn(cx, symbol_name, mono_ty); + let lldecl = declare::declare_fn(cx, symbol_name, mono_ty, instance.is_vtable_shim()); unsafe { llvm::LLVMRustSetLinkage(lldecl, base::linkage_to_llvm(linkage)) }; base::set_link_section(lldecl, &attrs); if linkage == Linkage::LinkOnceODR || From 250979c0ae90aa9c309efc9dcdac9e559b72b74d Mon Sep 17 00:00:00 2001 From: Masaki Hara Date: Tue, 11 Sep 2018 23:31:48 +0900 Subject: [PATCH 06/19] Implement vtable shim generation. --- src/librustc_mir/shim.rs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 867b630bb666b..4618c44cdde2a 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -43,8 +43,14 @@ fn make_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let mut result = match instance { ty::InstanceDef::Item(..) => bug!("item {:?} passed to make_shim", instance), - ty::InstanceDef::VtableShim(..) => { - unimplemented!("make_shim({:?})", instance); + ty::InstanceDef::VtableShim(def_id) => { + build_call_shim( + tcx, + def_id, + Adjustment::DerefMove, + CallKind::Direct(def_id), + None, + ) } ty::InstanceDef::FnPtrShim(def_id, ty) => { let trait_ = tcx.trait_of_item(def_id).unwrap(); @@ -131,6 +137,7 @@ fn make_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, enum Adjustment { Identity, Deref, + DerefMove, RefMut, } @@ -704,6 +711,14 @@ fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let rcvr = match rcvr_adjustment { Adjustment::Identity => Operand::Move(rcvr_l), Adjustment::Deref => Operand::Copy(rcvr_l.deref()), + Adjustment::DerefMove => { + // fn(Self, ...) -> fn(*mut Self, ...) + let arg_ty = local_decls[rcvr_arg].ty; + assert!(arg_ty.is_self()); + local_decls[rcvr_arg].ty = tcx.mk_mut_ptr(arg_ty); + + Operand::Copy(rcvr_l.deref()) + } Adjustment::RefMut => { // let rcvr = &mut rcvr; let ref_rcvr = local_decls.push(temp_decl( From f2ef005d1d9bfb6a594dc08805eef271fb9bbcd4 Mon Sep 17 00:00:00 2001 From: Masaki Hara Date: Tue, 11 Sep 2018 23:30:55 +0900 Subject: [PATCH 07/19] Resolve to Instance::VtableShim when necessary. --- src/librustc_codegen_llvm/callee.rs | 16 ++++++++++++++++ src/librustc_codegen_llvm/meth.rs | 2 +- src/librustc_mir/monomorphize/collector.rs | 2 +- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/librustc_codegen_llvm/callee.rs b/src/librustc_codegen_llvm/callee.rs index 82d85b6ead485..153e300a5232e 100644 --- a/src/librustc_codegen_llvm/callee.rs +++ b/src/librustc_codegen_llvm/callee.rs @@ -220,3 +220,19 @@ pub fn resolve_and_get_fn( ).unwrap() ) } + +pub fn resolve_and_get_fn_for_vtable( + cx: &CodegenCx<'ll, 'tcx>, + def_id: DefId, + substs: &'tcx Substs<'tcx>, +) -> &'ll Value { + get_fn( + cx, + ty::Instance::resolve_for_vtable( + cx.tcx, + ty::ParamEnv::reveal_all(), + def_id, + substs + ).unwrap() + ) +} diff --git a/src/librustc_codegen_llvm/meth.rs b/src/librustc_codegen_llvm/meth.rs index 29c2e71960c2c..d38f343d01f34 100644 --- a/src/librustc_codegen_llvm/meth.rs +++ b/src/librustc_codegen_llvm/meth.rs @@ -89,7 +89,7 @@ pub fn get_vtable( let methods = tcx.vtable_methods(trait_ref.with_self_ty(tcx, ty)); let methods = methods.iter().cloned().map(|opt_mth| { opt_mth.map_or(nullptr, |(def_id, substs)| { - callee::resolve_and_get_fn(cx, def_id, substs) + callee::resolve_and_get_fn_for_vtable(cx, def_id, substs) }) }); diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 66bf1b628ce5b..6062131c9d217 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -915,7 +915,7 @@ fn create_mono_items_for_vtable_methods<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Walk all methods of the trait, including those of its supertraits let methods = tcx.vtable_methods(poly_trait_ref); let methods = methods.iter().cloned().filter_map(|method| method) - .map(|(def_id, substs)| ty::Instance::resolve( + .map(|(def_id, substs)| ty::Instance::resolve_for_vtable( tcx, ty::ParamEnv::reveal_all(), def_id, From 5eceab02ec2fcb53f855373929ea2364c12396b4 Mon Sep 17 00:00:00 2001 From: Masaki Hara Date: Tue, 11 Sep 2018 23:32:18 +0900 Subject: [PATCH 08/19] Implement by-value trait object method call. --- src/librustc_codegen_llvm/abi.rs | 16 ++++++++-------- src/librustc_codegen_llvm/mir/block.rs | 6 ++++++ 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/librustc_codegen_llvm/abi.rs b/src/librustc_codegen_llvm/abi.rs index 7b93d3e795ed8..72daa0beb0982 100644 --- a/src/librustc_codegen_llvm/abi.rs +++ b/src/librustc_codegen_llvm/abi.rs @@ -305,17 +305,17 @@ impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> { // Don't pass the vtable, it's not an argument of the virtual fn. // Instead, pass just the (thin pointer) first field of `*dyn Trait`. if arg_idx == Some(0) { - if layout.is_unsized() { - unimplemented!("by-value trait object is not \ - yet implemented in #![feature(unsized_locals)]"); - } // FIXME(eddyb) `layout.field(cx, 0)` is not enough because e.g. // `Box` has a few newtype wrappers around the raw // pointer, so we'd have to "dig down" to find `*dyn Trait`. - let pointee = layout.ty.builtin_deref(true) - .unwrap_or_else(|| { - bug!("FnType::new_vtable: non-pointer self {:?}", layout) - }).ty; + let pointee = if layout.is_unsized() { + layout.ty + } else { + layout.ty.builtin_deref(true) + .unwrap_or_else(|| { + bug!("FnType::new_vtable: non-pointer self {:?}", layout) + }).ty + }; let fat_ptr_ty = cx.tcx.mk_mut_ptr(pointee); layout = cx.layout_of(fat_ptr_ty).field(cx, 0); } diff --git a/src/librustc_codegen_llvm/mir/block.rs b/src/librustc_codegen_llvm/mir/block.rs index 68e30227185c0..fc97e350ad243 100644 --- a/src/librustc_codegen_llvm/mir/block.rs +++ b/src/librustc_codegen_llvm/mir/block.rs @@ -651,6 +651,12 @@ impl FunctionCx<'a, 'll, 'tcx> { .get_fn(&bx, meta, &fn_ty)); llargs.push(data_ptr); continue; + } else if let Ref(data_ptr, Some(meta), _) = op.val { + // by-value dynamic dispatch + llfn = Some(meth::VirtualIndex::from_index(idx) + .get_fn(&bx, meta, &fn_ty)); + llargs.push(data_ptr); + continue; } } From 4ce35fdd349927c3cf1143421c71e4e75acb34e9 Mon Sep 17 00:00:00 2001 From: Masaki Hara Date: Wed, 12 Sep 2018 00:19:09 +0900 Subject: [PATCH 09/19] Add tests for unsized-locals. --- .../by-value-trait-object-safety.rs | 30 +++++++ .../by-value-trait-objects-rust-call.rs | 65 +++++++++++++++ .../by-value-trait-objects-rust-call2.rs | 79 +++++++++++++++++++ .../unsized-locals/by-value-trait-objects.rs | 59 ++++++++++++++ ...y-value-trait-object-safety-withdefault.rs | 27 +++++++ .../by-value-trait-object-safety.rs | 29 +++++++ 6 files changed, 289 insertions(+) create mode 100644 src/test/compile-fail/unsized-locals/by-value-trait-object-safety.rs create mode 100644 src/test/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call.rs create mode 100644 src/test/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call2.rs create mode 100644 src/test/run-pass-valgrind/unsized-locals/by-value-trait-objects.rs create mode 100644 src/test/run-pass/unsized-locals/by-value-trait-object-safety-withdefault.rs create mode 100644 src/test/run-pass/unsized-locals/by-value-trait-object-safety.rs diff --git a/src/test/compile-fail/unsized-locals/by-value-trait-object-safety.rs b/src/test/compile-fail/unsized-locals/by-value-trait-object-safety.rs new file mode 100644 index 0000000000000..9ac67da24431e --- /dev/null +++ b/src/test/compile-fail/unsized-locals/by-value-trait-object-safety.rs @@ -0,0 +1,30 @@ +// Copyright 2018 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(unsized_locals)] + +pub trait Foo { + fn foo(self) -> String where Self: Sized; +} + +struct A; + +impl Foo for A { + fn foo(self) -> String { + format!("hello") + } +} + + +fn main() { + let x = *(Box::new(A) as Box); + x.foo(); + //~^ERROR the `foo` method cannot be invoked on a trait object +} diff --git a/src/test/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call.rs b/src/test/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call.rs new file mode 100644 index 0000000000000..23b1c72a5bf95 --- /dev/null +++ b/src/test/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call.rs @@ -0,0 +1,65 @@ +// Copyright 2018 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(unsized_locals)] +#![feature(unboxed_closures)] + +pub trait FnOnce { + type Output; + extern "rust-call" fn call_once(self, args: Args) -> Self::Output; +} + +struct A; + +impl FnOnce<()> for A { + type Output = String; + extern "rust-call" fn call_once(self, (): ()) -> Self::Output { + format!("hello") + } +} + +struct B(i32); + +impl FnOnce<()> for B { + type Output = String; + extern "rust-call" fn call_once(self, (): ()) -> Self::Output { + format!("{}", self.0) + } +} + +struct C(String); + +impl FnOnce<()> for C { + type Output = String; + extern "rust-call" fn call_once(self, (): ()) -> Self::Output { + self.0 + } +} + +struct D(Box); + +impl FnOnce<()> for D { + type Output = String; + extern "rust-call" fn call_once(self, (): ()) -> Self::Output { + *self.0 + } +} + + +fn main() { + let x = *(Box::new(A) as Box>); + assert_eq!(x.call_once(()), format!("hello")); + let x = *(Box::new(B(42)) as Box>); + assert_eq!(x.call_once(()), format!("42")); + let x = *(Box::new(C(format!("jumping fox"))) as Box>); + assert_eq!(x.call_once(()), format!("jumping fox")); + let x = *(Box::new(D(Box::new(format!("lazy dog")))) as Box>); + assert_eq!(x.call_once(()), format!("lazy dog")); +} diff --git a/src/test/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call2.rs b/src/test/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call2.rs new file mode 100644 index 0000000000000..f5d1c7e84d212 --- /dev/null +++ b/src/test/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call2.rs @@ -0,0 +1,79 @@ +// Copyright 2018 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(unsized_locals)] +#![feature(unboxed_closures)] + +pub trait FnOnce { + type Output; + extern "rust-call" fn call_once(self, args: Args) -> Self::Output; +} + +struct A; + +impl FnOnce<(String, Box)> for A { + type Output = String; + extern "rust-call" fn call_once(self, (s1, s2): (String, Box)) -> Self::Output { + assert_eq!(&s1 as &str, "s1"); + assert_eq!(&s2 as &str, "s2"); + format!("hello") + } +} + +struct B(i32); + +impl FnOnce<(String, Box)> for B { + type Output = String; + extern "rust-call" fn call_once(self, (s1, s2): (String, Box)) -> Self::Output { + assert_eq!(&s1 as &str, "s1"); + assert_eq!(&s2 as &str, "s2"); + format!("{}", self.0) + } +} + +struct C(String); + +impl FnOnce<(String, Box)> for C { + type Output = String; + extern "rust-call" fn call_once(self, (s1, s2): (String, Box)) -> Self::Output { + assert_eq!(&s1 as &str, "s1"); + assert_eq!(&s2 as &str, "s2"); + self.0 + } +} + +struct D(Box); + +impl FnOnce<(String, Box)> for D { + type Output = String; + extern "rust-call" fn call_once(self, (s1, s2): (String, Box)) -> Self::Output { + assert_eq!(&s1 as &str, "s1"); + assert_eq!(&s2 as &str, "s2"); + *self.0 + } +} + + +fn main() { + let (s1, s2) = (format!("s1"), format!("s2").into_boxed_str()); + let x = *(Box::new(A) as Box), Output = String>>); + assert_eq!(x.call_once((s1, s2)), format!("hello")); + let (s1, s2) = (format!("s1"), format!("s2").into_boxed_str()); + let x = *(Box::new(B(42)) as Box), Output = String>>); + assert_eq!(x.call_once((s1, s2)), format!("42")); + let (s1, s2) = (format!("s1"), format!("s2").into_boxed_str()); + let x = *(Box::new(C(format!("jumping fox"))) + as Box), Output = String>>); + assert_eq!(x.call_once((s1, s2)), format!("jumping fox")); + let (s1, s2) = (format!("s1"), format!("s2").into_boxed_str()); + let x = *(Box::new(D(Box::new(format!("lazy dog")))) + as Box), Output = String>>); + assert_eq!(x.call_once((s1, s2)), format!("lazy dog")); +} diff --git a/src/test/run-pass-valgrind/unsized-locals/by-value-trait-objects.rs b/src/test/run-pass-valgrind/unsized-locals/by-value-trait-objects.rs new file mode 100644 index 0000000000000..688dcaed81590 --- /dev/null +++ b/src/test/run-pass-valgrind/unsized-locals/by-value-trait-objects.rs @@ -0,0 +1,59 @@ +// Copyright 2018 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(unsized_locals)] + +pub trait Foo { + fn foo(self) -> String; +} + +struct A; + +impl Foo for A { + fn foo(self) -> String { + format!("hello") + } +} + +struct B(i32); + +impl Foo for B { + fn foo(self) -> String { + format!("{}", self.0) + } +} + +struct C(String); + +impl Foo for C { + fn foo(self) -> String { + self.0 + } +} + +struct D(Box); + +impl Foo for D { + fn foo(self) -> String { + *self.0 + } +} + + +fn main() { + let x = *(Box::new(A) as Box); + assert_eq!(x.foo(), format!("hello")); + let x = *(Box::new(B(42)) as Box); + assert_eq!(x.foo(), format!("42")); + let x = *(Box::new(C(format!("jumping fox"))) as Box); + assert_eq!(x.foo(), format!("jumping fox")); + let x = *(Box::new(D(Box::new(format!("lazy dog")))) as Box); + assert_eq!(x.foo(), format!("lazy dog")); +} diff --git a/src/test/run-pass/unsized-locals/by-value-trait-object-safety-withdefault.rs b/src/test/run-pass/unsized-locals/by-value-trait-object-safety-withdefault.rs new file mode 100644 index 0000000000000..b2d228b4da301 --- /dev/null +++ b/src/test/run-pass/unsized-locals/by-value-trait-object-safety-withdefault.rs @@ -0,0 +1,27 @@ +// Copyright 2018 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(unsized_locals)] + +pub trait Foo { + fn foo(self) -> String { + format!("hello") + } +} + +struct A; + +impl Foo for A {} + + +fn main() { + let x = *(Box::new(A) as Box); + assert_eq!(x.foo(), format!("hello")); +} diff --git a/src/test/run-pass/unsized-locals/by-value-trait-object-safety.rs b/src/test/run-pass/unsized-locals/by-value-trait-object-safety.rs new file mode 100644 index 0000000000000..2912df7ce075e --- /dev/null +++ b/src/test/run-pass/unsized-locals/by-value-trait-object-safety.rs @@ -0,0 +1,29 @@ +// Copyright 2018 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(unsized_locals)] + +pub trait Foo { + fn foo(self) -> String; +} + +struct A; + +impl Foo for A { + fn foo(self) -> String { + format!("hello") + } +} + + +fn main() { + let x = *(Box::new(A) as Box); + assert_eq!(x.foo(), format!("hello")); +} From 7ccf66152400403da56ef56d29a454c981c85d3a Mon Sep 17 00:00:00 2001 From: Masaki Hara Date: Thu, 13 Sep 2018 22:24:19 +0900 Subject: [PATCH 10/19] Reflect by-value object safety in the unstable book. --- .../unstable-book/src/language-features/unsized-locals.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/doc/unstable-book/src/language-features/unsized-locals.md b/src/doc/unstable-book/src/language-features/unsized-locals.md index 7a5fe5b7f28cd..6f7cf754ae083 100644 --- a/src/doc/unstable-book/src/language-features/unsized-locals.md +++ b/src/doc/unstable-book/src/language-features/unsized-locals.md @@ -101,9 +101,9 @@ fn main() { } ``` -And `Foo` will also be object-safe. However, this object-safety is not yet implemented. +And `Foo` will also be object-safe. -```rust,ignore +```rust #![feature(unsized_locals)] trait Foo { @@ -119,8 +119,6 @@ fn main () { } ``` -Unfortunately, this is not implemented yet. - One of the objectives of this feature is to allow `Box`, instead of `Box` in the future. See [#28796] for details. [#28796]: https://github.com/rust-lang/rust/issues/28796 From 7c965e3e6594d2838a59fa46f7f73289588c3037 Mon Sep 17 00:00:00 2001 From: Masaki Hara Date: Wed, 26 Sep 2018 23:03:09 +0900 Subject: [PATCH 11/19] Prefer Move over Copy when dereferencing rvalue objects. --- src/librustc_mir/shim.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 4618c44cdde2a..8ca2381b37a3a 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -717,7 +717,7 @@ fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, assert!(arg_ty.is_self()); local_decls[rcvr_arg].ty = tcx.mk_mut_ptr(arg_ty); - Operand::Copy(rcvr_l.deref()) + Operand::Move(rcvr_l.deref()) } Adjustment::RefMut => { // let rcvr = &mut rcvr; From 609cc26d3194f8198b1c500b33190c6213e28a89 Mon Sep 17 00:00:00 2001 From: Masaki Hara Date: Wed, 26 Sep 2018 23:03:56 +0900 Subject: [PATCH 12/19] Ensure virtual call receiver PassMode. --- src/librustc_codegen_llvm/mir/block.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/librustc_codegen_llvm/mir/block.rs b/src/librustc_codegen_llvm/mir/block.rs index fc97e350ad243..9fab362f7e2ff 100644 --- a/src/librustc_codegen_llvm/mir/block.rs +++ b/src/librustc_codegen_llvm/mir/block.rs @@ -657,6 +657,8 @@ impl FunctionCx<'a, 'll, 'tcx> { .get_fn(&bx, meta, &fn_ty)); llargs.push(data_ptr); continue; + } else { + span_bug!(span, "can't codegen a virtual call on {:?}", op); } } From 207531606476a1fa03de815c2a112f3909cda48a Mon Sep 17 00:00:00 2001 From: Masaki Hara Date: Thu, 27 Sep 2018 00:14:38 +0900 Subject: [PATCH 13/19] Include InstanceDef's discriminant in the symbol hash. --- src/librustc_codegen_utils/symbol_names.rs | 6 ++++-- src/test/ui/symbol-names/basic.stderr | 2 +- src/test/ui/symbol-names/impl1.stderr | 4 ++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs index 27700bab24550..0d95b0c7bbc0c 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -114,6 +114,7 @@ use rustc_mir::monomorphize::Instance; use syntax_pos::symbol::Symbol; use std::fmt::Write; +use std::mem::discriminant; pub fn provide(providers: &mut Providers) { *providers = Providers { @@ -220,8 +221,9 @@ fn get_symbol_hash<'a, 'tcx>( (&tcx.crate_disambiguator(instantiating_crate)).hash_stable(&mut hcx, &mut hasher); } - let is_vtable_shim = instance.is_vtable_shim(); - is_vtable_shim.hash_stable(&mut hcx, &mut hasher); + // We want to avoid accidental collision between different types of instances. + // Especially, VtableShim may overlap with its original instance without this. + discriminant(&instance.def).hash_stable(&mut hcx, &mut hasher); }); // 64 bits should be enough to avoid collisions. diff --git a/src/test/ui/symbol-names/basic.stderr b/src/test/ui/symbol-names/basic.stderr index 5e910caf3c08f..551c5bb4a7591 100644 --- a/src/test/ui/symbol-names/basic.stderr +++ b/src/test/ui/symbol-names/basic.stderr @@ -1,4 +1,4 @@ -error: symbol-name(_ZN5basic4main17h6ab1850bb0b9f417E) +error: symbol-name(_ZN5basic4main17h08bcaf310214ed52E) --> $DIR/basic.rs:13:1 | LL | #[rustc_symbol_name] //~ ERROR _ZN5basic4main diff --git a/src/test/ui/symbol-names/impl1.stderr b/src/test/ui/symbol-names/impl1.stderr index 46e260bc28cc5..73c8d7b9721c6 100644 --- a/src/test/ui/symbol-names/impl1.stderr +++ b/src/test/ui/symbol-names/impl1.stderr @@ -1,4 +1,4 @@ -error: symbol-name(_ZN5impl13foo3Foo3bar17h99c48478d64a0eb0E) +error: symbol-name(_ZN5impl13foo3Foo3bar17hc487d6ec13fe9124E) --> $DIR/impl1.rs:18:9 | LL | #[rustc_symbol_name] //~ ERROR _ZN5impl13foo3Foo3bar @@ -10,7 +10,7 @@ error: item-path(foo::Foo::bar) LL | #[rustc_item_path] //~ ERROR item-path(foo::Foo::bar) | ^^^^^^^^^^^^^^^^^^ -error: symbol-name(_ZN5impl13bar33_$LT$impl$u20$impl1..foo..Foo$GT$3baz17hebf13830acf865d9E) +error: symbol-name(_ZN5impl13bar33_$LT$impl$u20$impl1..foo..Foo$GT$3baz17h38577281258e1527E) --> $DIR/impl1.rs:28:9 | LL | #[rustc_symbol_name] //~ ERROR _ZN5impl13bar33_$LT$impl$u20$impl1..foo..Foo$GT$3baz From 06b6b1c79088a2697c38cd1719ebe0ce13e67d0b Mon Sep 17 00:00:00 2001 From: Masaki Hara Date: Sat, 6 Oct 2018 22:58:36 +0900 Subject: [PATCH 14/19] Make declare_fn accept PolyFnSig instead of Ty. --- src/librustc_codegen_llvm/callee.rs | 2 +- src/librustc_codegen_llvm/context.rs | 6 +++--- src/librustc_codegen_llvm/declare.rs | 18 +++++++----------- src/librustc_codegen_llvm/intrinsic.rs | 6 +++--- src/librustc_codegen_llvm/mono_item.rs | 4 +++- 5 files changed, 17 insertions(+), 19 deletions(-) diff --git a/src/librustc_codegen_llvm/callee.rs b/src/librustc_codegen_llvm/callee.rs index 153e300a5232e..fff0177c94842 100644 --- a/src/librustc_codegen_llvm/callee.rs +++ b/src/librustc_codegen_llvm/callee.rs @@ -91,7 +91,7 @@ pub fn get_fn( llfn } } else { - let llfn = declare::declare_fn(cx, &sym, fn_ty, instance.is_vtable_shim()); + let llfn = declare::declare_fn(cx, &sym, common::ty_fn_sig_vtable(cx, fn_ty, instance.is_vtable_shim())); assert_eq!(common::val_ty(llfn), llptrty); debug!("get_fn: not casting pointer!"); diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs index 8087f130afaa0..241f7989e1681 100644 --- a/src/librustc_codegen_llvm/context.rs +++ b/src/librustc_codegen_llvm/context.rs @@ -404,15 +404,15 @@ impl<'b, 'tcx> CodegenCx<'b, 'tcx> { return llfn; } - let ty = tcx.mk_fn_ptr(ty::Binder::bind(tcx.mk_fn_sig( + let sig = ty::Binder::bind(tcx.mk_fn_sig( iter::once(tcx.mk_mut_ptr(tcx.types.u8)), tcx.types.never, false, hir::Unsafety::Unsafe, Abi::C - ))); + )); - let llfn = declare::declare_fn(self, "rust_eh_unwind_resume", ty, false); + let llfn = declare::declare_fn(self, "rust_eh_unwind_resume", sig); attributes::unwind(llfn, true); attributes::apply_target_cpu_attr(self, llfn); unwresume.set(Some(llfn)); diff --git a/src/librustc_codegen_llvm/declare.rs b/src/librustc_codegen_llvm/declare.rs index 0d01e9ef7ddab..f4aede55ce1a6 100644 --- a/src/librustc_codegen_llvm/declare.rs +++ b/src/librustc_codegen_llvm/declare.rs @@ -22,7 +22,7 @@ use llvm; use llvm::AttributePlace::Function; -use rustc::ty::{self, Ty}; +use rustc::ty::{self, PolyFnSig}; use rustc::ty::layout::LayoutOf; use rustc::session::config::Sanitizer; use rustc_data_structures::small_c_str::SmallCStr; @@ -30,7 +30,6 @@ use rustc_target::spec::PanicStrategy; use abi::{Abi, FnType, FnTypeExt}; use attributes; use context::CodegenCx; -use common; use type_::Type; use value::Value; @@ -129,12 +128,9 @@ pub fn declare_cfn(cx: &CodegenCx<'ll, '_>, name: &str, fn_type: &'ll Type) -> & pub fn declare_fn( cx: &CodegenCx<'ll, 'tcx>, name: &str, - fn_type: Ty<'tcx>, - is_vtable_shim: bool, + sig: PolyFnSig<'tcx>, ) -> &'ll Value { - debug!("declare_rust_fn(name={:?}, fn_type={:?}, is_vtable_shim={:?})", - name, fn_type, is_vtable_shim); - let sig = common::ty_fn_sig_vtable(cx, fn_type, is_vtable_shim); + debug!("declare_rust_fn(name={:?}, sig={:?})", name, sig); let sig = cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig); debug!("declare_rust_fn (after region erasure) sig={:?}", sig); @@ -186,12 +182,12 @@ pub fn define_private_global(cx: &CodegenCx<'ll, '_>, ty: &'ll Type) -> &'ll Val pub fn define_fn( cx: &CodegenCx<'ll, 'tcx>, name: &str, - fn_type: Ty<'tcx>, + fn_sig: PolyFnSig<'tcx>, ) -> &'ll Value { if get_defined_value(cx, name).is_some() { cx.sess().fatal(&format!("symbol `{}` already defined", name)) } else { - declare_fn(cx, name, fn_type, false) + declare_fn(cx, name, fn_sig) } } @@ -203,9 +199,9 @@ pub fn define_fn( pub fn define_internal_fn( cx: &CodegenCx<'ll, 'tcx>, name: &str, - fn_type: Ty<'tcx>, + fn_sig: PolyFnSig<'tcx>, ) -> &'ll Value { - let llfn = define_fn(cx, name, fn_type); + let llfn = define_fn(cx, name, fn_sig); unsafe { llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::InternalLinkage) }; llfn } diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index 272196afa6f92..03244c18ac3e4 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -933,14 +933,14 @@ fn gen_fn<'ll, 'tcx>( output: Ty<'tcx>, codegen: &mut dyn FnMut(Builder<'_, 'll, 'tcx>), ) -> &'ll Value { - let rust_fn_ty = cx.tcx.mk_fn_ptr(ty::Binder::bind(cx.tcx.mk_fn_sig( + let rust_fn_sig = ty::Binder::bind(cx.tcx.mk_fn_sig( inputs.into_iter(), output, false, hir::Unsafety::Unsafe, Abi::Rust - ))); - let llfn = declare::define_internal_fn(cx, name, rust_fn_ty); + )); + let llfn = declare::define_internal_fn(cx, name, rust_fn_sig); attributes::from_fn_attrs(cx, llfn, None); let bx = Builder::new_block(cx, llfn, "entry-block"); codegen(bx); diff --git a/src/librustc_codegen_llvm/mono_item.rs b/src/librustc_codegen_llvm/mono_item.rs index aab8613b75619..d160f114d4ccd 100644 --- a/src/librustc_codegen_llvm/mono_item.rs +++ b/src/librustc_codegen_llvm/mono_item.rs @@ -17,6 +17,7 @@ use asm; use attributes; use base; +use common; use consts; use context::CodegenCx; use declare; @@ -154,8 +155,9 @@ fn predefine_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, !instance.substs.has_param_types()); let mono_ty = instance.ty(cx.tcx); + let mono_sig = common::ty_fn_sig_vtable(cx, mono_ty, instance.is_vtable_shim()); let attrs = cx.tcx.codegen_fn_attrs(instance.def_id()); - let lldecl = declare::declare_fn(cx, symbol_name, mono_ty, instance.is_vtable_shim()); + let lldecl = declare::declare_fn(cx, symbol_name, mono_sig); unsafe { llvm::LLVMRustSetLinkage(lldecl, base::linkage_to_llvm(linkage)) }; base::set_link_section(lldecl, &attrs); if linkage == Linkage::LinkOnceODR || From e568e98063bea3864162cdcfda7bc200c7f09669 Mon Sep 17 00:00:00 2001 From: Masaki Hara Date: Sat, 6 Oct 2018 23:00:35 +0900 Subject: [PATCH 15/19] Move codegen_llvm::common::ty_fn_sig into rustc::ty::Instance. --- src/librustc/ty/instance.rs | 63 ++++++++++++++++++++++- src/librustc_codegen_llvm/abi.rs | 5 +- src/librustc_codegen_llvm/base.rs | 5 +- src/librustc_codegen_llvm/callee.rs | 8 +-- src/librustc_codegen_llvm/common.rs | 70 -------------------------- src/librustc_codegen_llvm/mir/block.rs | 3 +- src/librustc_codegen_llvm/mono_item.rs | 6 +-- 7 files changed, 73 insertions(+), 87 deletions(-) diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index 83029df0fe72f..041565c8b5a07 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -8,13 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use hir::Unsafety; use hir::def_id::DefId; -use ty::{self, Ty, TypeFoldable, Substs, TyCtxt}; +use ty::{self, Ty, PolyFnSig, TypeFoldable, Substs, TyCtxt}; use traits; use rustc_target::spec::abi::Abi; use util::ppaux; use std::fmt; +use std::iter; #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] pub struct Instance<'tcx> { @@ -59,6 +61,65 @@ impl<'a, 'tcx> Instance<'tcx> { &ty, ) } + + fn fn_sig_noadjust(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> PolyFnSig<'tcx> { + let ty = self.ty(tcx); + match ty.sty { + ty::FnDef(..) | + // Shims currently have type FnPtr. Not sure this should remain. + ty::FnPtr(_) => ty.fn_sig(tcx), + ty::Closure(def_id, substs) => { + let sig = substs.closure_sig(def_id, tcx); + + let env_ty = tcx.closure_env_ty(def_id, substs).unwrap(); + sig.map_bound(|sig| tcx.mk_fn_sig( + iter::once(*env_ty.skip_binder()).chain(sig.inputs().iter().cloned()), + sig.output(), + sig.variadic, + sig.unsafety, + sig.abi + )) + } + ty::Generator(def_id, substs, _) => { + let sig = substs.poly_sig(def_id, tcx); + + let env_region = ty::ReLateBound(ty::INNERMOST, ty::BrEnv); + let env_ty = tcx.mk_mut_ref(tcx.mk_region(env_region), ty); + + sig.map_bound(|sig| { + let state_did = tcx.lang_items().gen_state().unwrap(); + let state_adt_ref = tcx.adt_def(state_did); + let state_substs = tcx.intern_substs(&[ + sig.yield_ty.into(), + sig.return_ty.into(), + ]); + let ret_ty = tcx.mk_adt(state_adt_ref, state_substs); + + tcx.mk_fn_sig(iter::once(env_ty), + ret_ty, + false, + Unsafety::Normal, + Abi::Rust + ) + }) + } + _ => bug!("unexpected type {:?} in Instance::fn_sig_noadjust", ty) + } + } + + pub fn fn_sig(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ty::PolyFnSig<'tcx> { + let mut fn_sig = self.fn_sig_noadjust(tcx); + if let InstanceDef::VtableShim(..) = self.def { + // Modify fn(self, ...) to fn(self: *mut Self, ...) + fn_sig = fn_sig.map_bound(|mut fn_sig| { + let mut inputs_and_output = fn_sig.inputs_and_output.to_vec(); + inputs_and_output[0] = tcx.mk_mut_ptr(inputs_and_output[0]); + fn_sig.inputs_and_output = tcx.intern_type_list(&inputs_and_output); + fn_sig + }); + } + fn_sig + } } impl<'tcx> InstanceDef<'tcx> { diff --git a/src/librustc_codegen_llvm/abi.rs b/src/librustc_codegen_llvm/abi.rs index 72daa0beb0982..7c7662a88de53 100644 --- a/src/librustc_codegen_llvm/abi.rs +++ b/src/librustc_codegen_llvm/abi.rs @@ -11,7 +11,7 @@ use llvm::{self, AttributePlace}; use base; use builder::{Builder, MemFlags}; -use common::{ty_fn_sig, C_usize}; +use common::C_usize; use context::CodegenCx; use mir::place::PlaceRef; use mir::operand::OperandValue; @@ -283,8 +283,7 @@ pub trait FnTypeExt<'tcx> { impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> { fn of_instance(cx: &CodegenCx<'ll, 'tcx>, instance: &ty::Instance<'tcx>) -> Self { - let fn_ty = instance.ty(cx.tcx); - let sig = ty_fn_sig(cx, fn_ty); + let sig = instance.fn_sig(cx.tcx); let sig = cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig); FnType::new(cx, sig, &[]) } diff --git a/src/librustc_codegen_llvm/base.rs b/src/librustc_codegen_llvm/base.rs index 501a0b8af76bb..0932ceec9060f 100644 --- a/src/librustc_codegen_llvm/base.rs +++ b/src/librustc_codegen_llvm/base.rs @@ -56,7 +56,7 @@ use callee; use common::{C_bool, C_bytes_in_context, C_i32, C_usize}; use rustc_mir::monomorphize::collector::{self, MonoItemCollectionMode}; use rustc_mir::monomorphize::item::DefPathBasedNames; -use common::{self, C_struct_in_context, C_array, val_ty}; +use common::{C_struct_in_context, C_array, val_ty}; use consts; use context::CodegenCx; use debuginfo; @@ -491,8 +491,7 @@ pub fn codegen_instance<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, instance: Instance<' // release builds. info!("codegen_instance({})", instance); - let fn_ty = instance.ty(cx.tcx); - let sig = common::ty_fn_sig_vtable(cx, fn_ty, instance.is_vtable_shim()); + let sig = instance.fn_sig(cx.tcx); let sig = cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig); let lldecl = cx.instances.borrow().get(&instance).cloned().unwrap_or_else(|| diff --git a/src/librustc_codegen_llvm/callee.rs b/src/librustc_codegen_llvm/callee.rs index fff0177c94842..7300bac96182b 100644 --- a/src/librustc_codegen_llvm/callee.rs +++ b/src/librustc_codegen_llvm/callee.rs @@ -47,16 +47,16 @@ pub fn get_fn( assert!(!instance.substs.has_escaping_regions()); assert!(!instance.substs.has_param_types()); - let fn_ty = instance.ty(cx.tcx); + let sig = instance.fn_sig(cx.tcx); if let Some(&llfn) = cx.instances.borrow().get(&instance) { return llfn; } let sym = tcx.symbol_name(instance).as_str(); - debug!("get_fn({:?}: {:?}) => {}", instance, fn_ty, sym); + debug!("get_fn({:?}: {:?}) => {}", instance, sig, sym); // Create a fn pointer with the substituted signature. - let fn_ptr_ty = tcx.mk_fn_ptr(common::ty_fn_sig_vtable(cx, fn_ty, instance.is_vtable_shim())); + let fn_ptr_ty = tcx.mk_fn_ptr(sig); let llptrty = cx.layout_of(fn_ptr_ty).llvm_type(cx); let llfn = if let Some(llfn) = declare::get_declared_value(cx, &sym) { @@ -91,7 +91,7 @@ pub fn get_fn( llfn } } else { - let llfn = declare::declare_fn(cx, &sym, common::ty_fn_sig_vtable(cx, fn_ty, instance.is_vtable_shim())); + let llfn = declare::declare_fn(cx, &sym, sig); assert_eq!(common::val_ty(llfn), llptrty); debug!("get_fn: not casting pointer!"); diff --git a/src/librustc_codegen_llvm/common.rs b/src/librustc_codegen_llvm/common.rs index df91f75837422..c9b464fd8f3dd 100644 --- a/src/librustc_codegen_llvm/common.rs +++ b/src/librustc_codegen_llvm/common.rs @@ -30,9 +30,7 @@ use rustc::ty::layout::{HasDataLayout, LayoutOf}; use rustc::hir; use libc::{c_uint, c_char}; -use std::iter; -use rustc_target::spec::abi::Abi; use syntax::symbol::LocalInternedString; use syntax_pos::{Span, DUMMY_SP}; @@ -404,71 +402,3 @@ pub fn shift_mask_val( _ => bug!("shift_mask_val: expected Integer or Vector, found {:?}", kind), } } - -pub fn ty_fn_sig<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - ty: Ty<'tcx>) - -> ty::PolyFnSig<'tcx> -{ - match ty.sty { - ty::FnDef(..) | - // Shims currently have type FnPtr. Not sure this should remain. - ty::FnPtr(_) => ty.fn_sig(cx.tcx), - ty::Closure(def_id, substs) => { - let tcx = cx.tcx; - let sig = substs.closure_sig(def_id, tcx); - - let env_ty = tcx.closure_env_ty(def_id, substs).unwrap(); - sig.map_bound(|sig| tcx.mk_fn_sig( - iter::once(*env_ty.skip_binder()).chain(sig.inputs().iter().cloned()), - sig.output(), - sig.variadic, - sig.unsafety, - sig.abi - )) - } - ty::Generator(def_id, substs, _) => { - let tcx = cx.tcx; - let sig = substs.poly_sig(def_id, cx.tcx); - - let env_region = ty::ReLateBound(ty::INNERMOST, ty::BrEnv); - let env_ty = tcx.mk_mut_ref(tcx.mk_region(env_region), ty); - - sig.map_bound(|sig| { - let state_did = tcx.lang_items().gen_state().unwrap(); - let state_adt_ref = tcx.adt_def(state_did); - let state_substs = tcx.intern_substs(&[ - sig.yield_ty.into(), - sig.return_ty.into(), - ]); - let ret_ty = tcx.mk_adt(state_adt_ref, state_substs); - - tcx.mk_fn_sig(iter::once(env_ty), - ret_ty, - false, - hir::Unsafety::Normal, - Abi::Rust - ) - }) - } - _ => bug!("unexpected type {:?} to ty_fn_sig", ty) - } -} - -pub fn ty_fn_sig_vtable<'a, 'tcx>( - cx: &CodegenCx<'a, 'tcx>, - ty: Ty<'tcx>, - is_vtable_shim: bool - ) -> ty::PolyFnSig<'tcx> -{ - let mut fn_sig = ty_fn_sig(cx, ty); - if is_vtable_shim { - // Modify fn(self, ...) to fn(self: *mut Self, ...) - fn_sig = fn_sig.map_bound(|mut fn_sig| { - let mut inputs_and_output = fn_sig.inputs_and_output.to_vec(); - inputs_and_output[0] = cx.tcx.mk_mut_ptr(inputs_and_output[0]); - fn_sig.inputs_and_output = cx.tcx.intern_type_list(&inputs_and_output); - fn_sig - }); - } - fn_sig -} diff --git a/src/librustc_codegen_llvm/mir/block.rs b/src/librustc_codegen_llvm/mir/block.rs index 9fab362f7e2ff..d98b7869ae98e 100644 --- a/src/librustc_codegen_llvm/mir/block.rs +++ b/src/librustc_codegen_llvm/mir/block.rs @@ -298,8 +298,7 @@ impl FunctionCx<'a, 'll, 'tcx> { }; let (drop_fn, fn_ty) = match ty.sty { ty::Dynamic(..) => { - let fn_ty = drop_fn.ty(bx.cx.tcx); - let sig = common::ty_fn_sig(bx.cx, fn_ty); + let sig = drop_fn.fn_sig(bx.cx.tcx); let sig = bx.tcx().normalize_erasing_late_bound_regions( ty::ParamEnv::reveal_all(), &sig, diff --git a/src/librustc_codegen_llvm/mono_item.rs b/src/librustc_codegen_llvm/mono_item.rs index d160f114d4ccd..91c1ccbe00213 100644 --- a/src/librustc_codegen_llvm/mono_item.rs +++ b/src/librustc_codegen_llvm/mono_item.rs @@ -17,7 +17,6 @@ use asm; use attributes; use base; -use common; use consts; use context::CodegenCx; use declare; @@ -154,8 +153,7 @@ fn predefine_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, assert!(!instance.substs.needs_infer() && !instance.substs.has_param_types()); - let mono_ty = instance.ty(cx.tcx); - let mono_sig = common::ty_fn_sig_vtable(cx, mono_ty, instance.is_vtable_shim()); + let mono_sig = instance.fn_sig(cx.tcx); let attrs = cx.tcx.codegen_fn_attrs(instance.def_id()); let lldecl = declare::declare_fn(cx, symbol_name, mono_sig); unsafe { llvm::LLVMRustSetLinkage(lldecl, base::linkage_to_llvm(linkage)) }; @@ -180,7 +178,7 @@ fn predefine_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, } } - debug!("predefine_fn: mono_ty = {:?} instance = {:?}", mono_ty, instance); + debug!("predefine_fn: mono_sig = {:?} instance = {:?}", mono_sig, instance); if instance.def.is_inline(cx.tcx) { attributes::inline(cx, lldecl, attributes::InlineAttr::Hint); } From b3dce87a8694381e4e96fd4a7183487ffa100e22 Mon Sep 17 00:00:00 2001 From: Masaki Hara Date: Wed, 24 Oct 2018 22:10:17 +0900 Subject: [PATCH 16/19] Move compile-fail/unsized-locals under ui as per #44844. --- .../by-value-trait-object-safety.rs | 0 .../by-value-trait-object-safety.stderr | 8 ++++++ .../unsized-locals/unsized-exprs.rs | 0 .../ui/unsized-locals/unsized-exprs.stderr | 25 +++++++++++++++++++ .../unsized-locals/unsized-exprs2.nll.stderr | 19 ++++++++++++++ .../unsized-locals/unsized-exprs2.rs | 0 .../ui/unsized-locals/unsized-exprs2.stderr | 9 +++++++ 7 files changed, 61 insertions(+) rename src/test/{compile-fail => ui}/unsized-locals/by-value-trait-object-safety.rs (100%) create mode 100644 src/test/ui/unsized-locals/by-value-trait-object-safety.stderr rename src/test/{compile-fail => ui}/unsized-locals/unsized-exprs.rs (100%) create mode 100644 src/test/ui/unsized-locals/unsized-exprs.stderr create mode 100644 src/test/ui/unsized-locals/unsized-exprs2.nll.stderr rename src/test/{compile-fail => ui}/unsized-locals/unsized-exprs2.rs (100%) create mode 100644 src/test/ui/unsized-locals/unsized-exprs2.stderr diff --git a/src/test/compile-fail/unsized-locals/by-value-trait-object-safety.rs b/src/test/ui/unsized-locals/by-value-trait-object-safety.rs similarity index 100% rename from src/test/compile-fail/unsized-locals/by-value-trait-object-safety.rs rename to src/test/ui/unsized-locals/by-value-trait-object-safety.rs diff --git a/src/test/ui/unsized-locals/by-value-trait-object-safety.stderr b/src/test/ui/unsized-locals/by-value-trait-object-safety.stderr new file mode 100644 index 0000000000000..885944b2019c6 --- /dev/null +++ b/src/test/ui/unsized-locals/by-value-trait-object-safety.stderr @@ -0,0 +1,8 @@ +error: the `foo` method cannot be invoked on a trait object + --> $DIR/by-value-trait-object-safety.rs:28:7 + | +LL | x.foo(); + | ^^^ + +error: aborting due to previous error + diff --git a/src/test/compile-fail/unsized-locals/unsized-exprs.rs b/src/test/ui/unsized-locals/unsized-exprs.rs similarity index 100% rename from src/test/compile-fail/unsized-locals/unsized-exprs.rs rename to src/test/ui/unsized-locals/unsized-exprs.rs diff --git a/src/test/ui/unsized-locals/unsized-exprs.stderr b/src/test/ui/unsized-locals/unsized-exprs.stderr new file mode 100644 index 0000000000000..42a9d622e0dab --- /dev/null +++ b/src/test/ui/unsized-locals/unsized-exprs.stderr @@ -0,0 +1,25 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/unsized-exprs.rs:32:26 + | +LL | udrop::<(i32, [u8])>((42, *foo())); + | ^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: within `({integer}, [u8])`, the trait `std::marker::Sized` is not implemented for `[u8]` + = note: to learn more, visit + = note: required because it appears within the type `({integer}, [u8])` + = note: tuples must have a statically known size to be initialized + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/unsized-exprs.rs:34:22 + | +LL | udrop::>(A { 0: *foo() }); + | ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: within `A<[u8]>`, the trait `std::marker::Sized` is not implemented for `[u8]` + = note: to learn more, visit + = note: required because it appears within the type `A<[u8]>` + = note: structs must have a statically known size to be initialized + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/unsized-locals/unsized-exprs2.nll.stderr b/src/test/ui/unsized-locals/unsized-exprs2.nll.stderr new file mode 100644 index 0000000000000..21541fb8b8772 --- /dev/null +++ b/src/test/ui/unsized-locals/unsized-exprs2.nll.stderr @@ -0,0 +1,19 @@ +error[E0508]: cannot move out of type `[u8]`, a non-copy slice + --> $DIR/unsized-exprs2.rs:32:19 + | +LL | udrop::<[u8]>(foo()[..]); + | ^^^^^^^^^ cannot move out of here + +error[E0507]: cannot move out of data in a `&` reference + --> $DIR/unsized-exprs2.rs:32:19 + | +LL | udrop::<[u8]>(foo()[..]); + | ^^^^^^^^^ + | | + | cannot move out of data in a `&` reference + | cannot move + +error: aborting due to 2 previous errors + +Some errors occurred: E0507, E0508. +For more information about an error, try `rustc --explain E0507`. diff --git a/src/test/compile-fail/unsized-locals/unsized-exprs2.rs b/src/test/ui/unsized-locals/unsized-exprs2.rs similarity index 100% rename from src/test/compile-fail/unsized-locals/unsized-exprs2.rs rename to src/test/ui/unsized-locals/unsized-exprs2.rs diff --git a/src/test/ui/unsized-locals/unsized-exprs2.stderr b/src/test/ui/unsized-locals/unsized-exprs2.stderr new file mode 100644 index 0000000000000..30a6d5473dfc9 --- /dev/null +++ b/src/test/ui/unsized-locals/unsized-exprs2.stderr @@ -0,0 +1,9 @@ +error[E0507]: cannot move out of indexed content + --> $DIR/unsized-exprs2.rs:32:19 + | +LL | udrop::<[u8]>(foo()[..]); + | ^^^^^^^^^ cannot move out of indexed content + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`. From 4fd895a6b835c2d0ef6292ef39f3fb13f6f14650 Mon Sep 17 00:00:00 2001 From: Masaki Hara Date: Wed, 24 Oct 2018 23:18:15 +0900 Subject: [PATCH 17/19] Add autoderef tests for by-value trait objects. --- .../by-value-trait-object-safety-withdefault.rs | 4 ++++ .../run-pass/unsized-locals/by-value-trait-object-safety.rs | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/test/run-pass/unsized-locals/by-value-trait-object-safety-withdefault.rs b/src/test/run-pass/unsized-locals/by-value-trait-object-safety-withdefault.rs index b2d228b4da301..9fcc4292a8a45 100644 --- a/src/test/run-pass/unsized-locals/by-value-trait-object-safety-withdefault.rs +++ b/src/test/run-pass/unsized-locals/by-value-trait-object-safety-withdefault.rs @@ -24,4 +24,8 @@ impl Foo for A {} fn main() { let x = *(Box::new(A) as Box); assert_eq!(x.foo(), format!("hello")); + + // I'm not sure whether we want this to work + let x = Box::new(A) as Box; + assert_eq!(x.foo(), format!("hello")); } diff --git a/src/test/run-pass/unsized-locals/by-value-trait-object-safety.rs b/src/test/run-pass/unsized-locals/by-value-trait-object-safety.rs index 2912df7ce075e..0dd2d14a7a92f 100644 --- a/src/test/run-pass/unsized-locals/by-value-trait-object-safety.rs +++ b/src/test/run-pass/unsized-locals/by-value-trait-object-safety.rs @@ -26,4 +26,8 @@ impl Foo for A { fn main() { let x = *(Box::new(A) as Box); assert_eq!(x.foo(), format!("hello")); + + // I'm not sure whether we want this to work + let x = Box::new(A) as Box; + assert_eq!(x.foo(), format!("hello")); } From 1c4864708f5b16cb80ce656326f9f8637204b3df Mon Sep 17 00:00:00 2001 From: Masaki Hara Date: Wed, 24 Oct 2018 23:27:17 +0900 Subject: [PATCH 18/19] Remove license headers from unsized-locals tests. --- .../unsized-locals/by-value-trait-objects-rust-call.rs | 10 ---------- .../by-value-trait-objects-rust-call2.rs | 10 ---------- .../unsized-locals/by-value-trait-objects.rs | 10 ---------- .../unsized-locals/long-live-the-unsized-temporary.rs | 10 ---------- .../by-value-trait-object-safety-withdefault.rs | 10 ---------- .../unsized-locals/by-value-trait-object-safety.rs | 10 ---------- .../unsized-locals/reference-unsized-locals.rs | 10 ---------- .../run-pass/unsized-locals/simple-unsized-locals.rs | 10 ---------- src/test/run-pass/unsized-locals/unsized-exprs.rs | 10 ---------- src/test/run-pass/unsized-locals/unsized-parameters.rs | 10 ---------- .../ui/unsized-locals/by-value-trait-object-safety.rs | 10 ---------- .../unsized-locals/by-value-trait-object-safety.stderr | 2 +- src/test/ui/unsized-locals/unsized-exprs.rs | 10 ---------- src/test/ui/unsized-locals/unsized-exprs.stderr | 4 ++-- src/test/ui/unsized-locals/unsized-exprs2.nll.stderr | 4 ++-- src/test/ui/unsized-locals/unsized-exprs2.rs | 10 ---------- src/test/ui/unsized-locals/unsized-exprs2.stderr | 2 +- 17 files changed, 6 insertions(+), 136 deletions(-) diff --git a/src/test/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call.rs b/src/test/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call.rs index 23b1c72a5bf95..7f365ce2bbaf3 100644 --- a/src/test/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call.rs +++ b/src/test/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call.rs @@ -1,13 +1,3 @@ -// Copyright 2018 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(unsized_locals)] #![feature(unboxed_closures)] diff --git a/src/test/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call2.rs b/src/test/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call2.rs index f5d1c7e84d212..a78b897d19414 100644 --- a/src/test/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call2.rs +++ b/src/test/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call2.rs @@ -1,13 +1,3 @@ -// Copyright 2018 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(unsized_locals)] #![feature(unboxed_closures)] diff --git a/src/test/run-pass-valgrind/unsized-locals/by-value-trait-objects.rs b/src/test/run-pass-valgrind/unsized-locals/by-value-trait-objects.rs index 688dcaed81590..3d67101e734c7 100644 --- a/src/test/run-pass-valgrind/unsized-locals/by-value-trait-objects.rs +++ b/src/test/run-pass-valgrind/unsized-locals/by-value-trait-objects.rs @@ -1,13 +1,3 @@ -// Copyright 2018 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(unsized_locals)] pub trait Foo { diff --git a/src/test/run-pass-valgrind/unsized-locals/long-live-the-unsized-temporary.rs b/src/test/run-pass-valgrind/unsized-locals/long-live-the-unsized-temporary.rs index e1fda427b4e73..2f275f88d963e 100644 --- a/src/test/run-pass-valgrind/unsized-locals/long-live-the-unsized-temporary.rs +++ b/src/test/run-pass-valgrind/unsized-locals/long-live-the-unsized-temporary.rs @@ -1,13 +1,3 @@ -// Copyright 2018 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(unsized_locals)] use std::fmt; diff --git a/src/test/run-pass/unsized-locals/by-value-trait-object-safety-withdefault.rs b/src/test/run-pass/unsized-locals/by-value-trait-object-safety-withdefault.rs index 9fcc4292a8a45..e6e363f55a1a6 100644 --- a/src/test/run-pass/unsized-locals/by-value-trait-object-safety-withdefault.rs +++ b/src/test/run-pass/unsized-locals/by-value-trait-object-safety-withdefault.rs @@ -1,13 +1,3 @@ -// Copyright 2018 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(unsized_locals)] pub trait Foo { diff --git a/src/test/run-pass/unsized-locals/by-value-trait-object-safety.rs b/src/test/run-pass/unsized-locals/by-value-trait-object-safety.rs index 0dd2d14a7a92f..f19ff5b8de462 100644 --- a/src/test/run-pass/unsized-locals/by-value-trait-object-safety.rs +++ b/src/test/run-pass/unsized-locals/by-value-trait-object-safety.rs @@ -1,13 +1,3 @@ -// Copyright 2018 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(unsized_locals)] pub trait Foo { diff --git a/src/test/run-pass/unsized-locals/reference-unsized-locals.rs b/src/test/run-pass/unsized-locals/reference-unsized-locals.rs index 8b96c30940f07..1560d25d4b0de 100644 --- a/src/test/run-pass/unsized-locals/reference-unsized-locals.rs +++ b/src/test/run-pass/unsized-locals/reference-unsized-locals.rs @@ -1,13 +1,3 @@ -// Copyright 2018 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. - // run-pass #![feature(unsized_locals)] diff --git a/src/test/run-pass/unsized-locals/simple-unsized-locals.rs b/src/test/run-pass/unsized-locals/simple-unsized-locals.rs index 9643afaee6276..059559192456d 100644 --- a/src/test/run-pass/unsized-locals/simple-unsized-locals.rs +++ b/src/test/run-pass/unsized-locals/simple-unsized-locals.rs @@ -1,13 +1,3 @@ -// Copyright 2018 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. - // run-pass #![feature(unsized_locals)] diff --git a/src/test/run-pass/unsized-locals/unsized-exprs.rs b/src/test/run-pass/unsized-locals/unsized-exprs.rs index 06919a07c756b..4b988f1e72d5a 100644 --- a/src/test/run-pass/unsized-locals/unsized-exprs.rs +++ b/src/test/run-pass/unsized-locals/unsized-exprs.rs @@ -1,13 +1,3 @@ -// Copyright 2018 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. - // run-pass #![feature(unsized_tuple_coercion, unsized_locals)] diff --git a/src/test/run-pass/unsized-locals/unsized-parameters.rs b/src/test/run-pass/unsized-locals/unsized-parameters.rs index 82036c5797d79..3624154d5c44c 100644 --- a/src/test/run-pass/unsized-locals/unsized-parameters.rs +++ b/src/test/run-pass/unsized-locals/unsized-parameters.rs @@ -1,13 +1,3 @@ -// Copyright 2018 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. - // run-pass #![feature(unsized_locals)] diff --git a/src/test/ui/unsized-locals/by-value-trait-object-safety.rs b/src/test/ui/unsized-locals/by-value-trait-object-safety.rs index 9ac67da24431e..8b24328bd3854 100644 --- a/src/test/ui/unsized-locals/by-value-trait-object-safety.rs +++ b/src/test/ui/unsized-locals/by-value-trait-object-safety.rs @@ -1,13 +1,3 @@ -// Copyright 2018 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(unsized_locals)] pub trait Foo { diff --git a/src/test/ui/unsized-locals/by-value-trait-object-safety.stderr b/src/test/ui/unsized-locals/by-value-trait-object-safety.stderr index 885944b2019c6..7e9a2316be2bf 100644 --- a/src/test/ui/unsized-locals/by-value-trait-object-safety.stderr +++ b/src/test/ui/unsized-locals/by-value-trait-object-safety.stderr @@ -1,5 +1,5 @@ error: the `foo` method cannot be invoked on a trait object - --> $DIR/by-value-trait-object-safety.rs:28:7 + --> $DIR/by-value-trait-object-safety.rs:18:7 | LL | x.foo(); | ^^^ diff --git a/src/test/ui/unsized-locals/unsized-exprs.rs b/src/test/ui/unsized-locals/unsized-exprs.rs index a09ccbb407e98..0cf93c78c4abe 100644 --- a/src/test/ui/unsized-locals/unsized-exprs.rs +++ b/src/test/ui/unsized-locals/unsized-exprs.rs @@ -1,13 +1,3 @@ -// Copyright 2018 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(unsized_tuple_coercion, unsized_locals)] struct A(X); diff --git a/src/test/ui/unsized-locals/unsized-exprs.stderr b/src/test/ui/unsized-locals/unsized-exprs.stderr index 42a9d622e0dab..eb2016941770c 100644 --- a/src/test/ui/unsized-locals/unsized-exprs.stderr +++ b/src/test/ui/unsized-locals/unsized-exprs.stderr @@ -1,5 +1,5 @@ error[E0277]: the size for values of type `[u8]` cannot be known at compilation time - --> $DIR/unsized-exprs.rs:32:26 + --> $DIR/unsized-exprs.rs:22:26 | LL | udrop::<(i32, [u8])>((42, *foo())); | ^^^^^^^^^^^^ doesn't have a size known at compile-time @@ -10,7 +10,7 @@ LL | udrop::<(i32, [u8])>((42, *foo())); = note: tuples must have a statically known size to be initialized error[E0277]: the size for values of type `[u8]` cannot be known at compilation time - --> $DIR/unsized-exprs.rs:34:22 + --> $DIR/unsized-exprs.rs:24:22 | LL | udrop::>(A { 0: *foo() }); | ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time diff --git a/src/test/ui/unsized-locals/unsized-exprs2.nll.stderr b/src/test/ui/unsized-locals/unsized-exprs2.nll.stderr index 21541fb8b8772..675457b0db6bb 100644 --- a/src/test/ui/unsized-locals/unsized-exprs2.nll.stderr +++ b/src/test/ui/unsized-locals/unsized-exprs2.nll.stderr @@ -1,11 +1,11 @@ error[E0508]: cannot move out of type `[u8]`, a non-copy slice - --> $DIR/unsized-exprs2.rs:32:19 + --> $DIR/unsized-exprs2.rs:22:19 | LL | udrop::<[u8]>(foo()[..]); | ^^^^^^^^^ cannot move out of here error[E0507]: cannot move out of data in a `&` reference - --> $DIR/unsized-exprs2.rs:32:19 + --> $DIR/unsized-exprs2.rs:22:19 | LL | udrop::<[u8]>(foo()[..]); | ^^^^^^^^^ diff --git a/src/test/ui/unsized-locals/unsized-exprs2.rs b/src/test/ui/unsized-locals/unsized-exprs2.rs index 40d6e54bd892f..ae69893a83577 100644 --- a/src/test/ui/unsized-locals/unsized-exprs2.rs +++ b/src/test/ui/unsized-locals/unsized-exprs2.rs @@ -1,13 +1,3 @@ -// Copyright 2018 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(unsized_tuple_coercion, unsized_locals)] struct A(X); diff --git a/src/test/ui/unsized-locals/unsized-exprs2.stderr b/src/test/ui/unsized-locals/unsized-exprs2.stderr index 30a6d5473dfc9..d7cb4bffb483d 100644 --- a/src/test/ui/unsized-locals/unsized-exprs2.stderr +++ b/src/test/ui/unsized-locals/unsized-exprs2.stderr @@ -1,5 +1,5 @@ error[E0507]: cannot move out of indexed content - --> $DIR/unsized-exprs2.rs:32:19 + --> $DIR/unsized-exprs2.rs:22:19 | LL | udrop::<[u8]>(foo()[..]); | ^^^^^^^^^ cannot move out of indexed content From 2f7ea4a8725d433db4f34fca87eb7f61afb7ef9a Mon Sep 17 00:00:00 2001 From: Masaki Hara Date: Sat, 27 Oct 2018 17:17:24 +0900 Subject: [PATCH 19/19] Add more tests on unsized locals autoderef and borrowck. --- src/test/run-pass/unsized-locals/autoderef.rs | 47 ++++++++++++++ .../borrow-after-move.nll.stderr | 51 +++++++++++++++ .../ui/unsized-locals/borrow-after-move.rs | 42 +++++++++++++ .../unsized-locals/borrow-after-move.stderr | 57 +++++++++++++++++ .../ui/unsized-locals/double-move.nll.stderr | 55 ++++++++++++++++ src/test/ui/unsized-locals/double-move.rs | 53 ++++++++++++++++ src/test/ui/unsized-locals/double-move.stderr | 63 +++++++++++++++++++ 7 files changed, 368 insertions(+) create mode 100644 src/test/run-pass/unsized-locals/autoderef.rs create mode 100644 src/test/ui/unsized-locals/borrow-after-move.nll.stderr create mode 100644 src/test/ui/unsized-locals/borrow-after-move.rs create mode 100644 src/test/ui/unsized-locals/borrow-after-move.stderr create mode 100644 src/test/ui/unsized-locals/double-move.nll.stderr create mode 100644 src/test/ui/unsized-locals/double-move.rs create mode 100644 src/test/ui/unsized-locals/double-move.stderr diff --git a/src/test/run-pass/unsized-locals/autoderef.rs b/src/test/run-pass/unsized-locals/autoderef.rs new file mode 100644 index 0000000000000..885cd2b836080 --- /dev/null +++ b/src/test/run-pass/unsized-locals/autoderef.rs @@ -0,0 +1,47 @@ +#![feature(unsized_locals)] + +pub trait Foo { + fn foo(self) -> String; +} + +impl Foo for [char] { + fn foo(self) -> String { + self.iter().collect() + } +} + +impl Foo for str { + fn foo(self) -> String { + self.to_owned() + } +} + +impl Foo for dyn FnMut() -> String { + fn foo(mut self) -> String { + self() + } +} + + +fn main() { + let x = *(Box::new(['h', 'e', 'l', 'l', 'o']) as Box<[char]>); + assert_eq!(&x.foo() as &str, "hello"); + + let x = Box::new(['h', 'e', 'l', 'l', 'o']) as Box<[char]>; + assert_eq!(&x.foo() as &str, "hello"); + + let x = "hello".to_owned().into_boxed_str(); + assert_eq!(&x.foo() as &str, "hello"); + + let x = *("hello".to_owned().into_boxed_str()); + assert_eq!(&x.foo() as &str, "hello"); + + let x = "hello".to_owned().into_boxed_str(); + assert_eq!(&x.foo() as &str, "hello"); + + let x = *(Box::new(|| "hello".to_owned()) as Box String>); + assert_eq!(&x.foo() as &str, "hello"); + + let x = Box::new(|| "hello".to_owned()) as Box String>; + assert_eq!(&x.foo() as &str, "hello"); +} diff --git a/src/test/ui/unsized-locals/borrow-after-move.nll.stderr b/src/test/ui/unsized-locals/borrow-after-move.nll.stderr new file mode 100644 index 0000000000000..a3cfcc8921766 --- /dev/null +++ b/src/test/ui/unsized-locals/borrow-after-move.nll.stderr @@ -0,0 +1,51 @@ +error[E0382]: borrow of moved value: `x` + --> $DIR/borrow-after-move.rs:20:24 + | +LL | let y = *x; + | -- value moved here +LL | drop_unsized(y); +LL | println!("{}", &x); + | ^^ value borrowed here after move + +error[E0382]: borrow of moved value: `y` + --> $DIR/borrow-after-move.rs:22:24 + | +LL | drop_unsized(y); + | - value moved here +... +LL | println!("{}", &y); + | ^^ value borrowed here after move + | + = note: move occurs because `y` has type `str`, which does not implement the `Copy` trait + +error[E0382]: borrow of moved value: `x` + --> $DIR/borrow-after-move.rs:30:24 + | +LL | let y = *x; + | -- value moved here +LL | y.foo(); +LL | println!("{}", &x); + | ^^ value borrowed here after move + +error[E0382]: borrow of moved value: `y` + --> $DIR/borrow-after-move.rs:32:24 + | +LL | y.foo(); + | - value moved here +... +LL | println!("{}", &y); + | ^^ value borrowed here after move + | + = note: move occurs because `y` has type `str`, which does not implement the `Copy` trait + +error[E0382]: borrow of moved value: `x` + --> $DIR/borrow-after-move.rs:39:24 + | +LL | x.foo(); + | - value moved here +LL | println!("{}", &x); + | ^^ value borrowed here after move + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/unsized-locals/borrow-after-move.rs b/src/test/ui/unsized-locals/borrow-after-move.rs new file mode 100644 index 0000000000000..587a2180c1558 --- /dev/null +++ b/src/test/ui/unsized-locals/borrow-after-move.rs @@ -0,0 +1,42 @@ +#![feature(unsized_locals)] + +pub trait Foo { + fn foo(self) -> String; +} + +impl Foo for str { + fn foo(self) -> String { + self.to_owned() + } +} + +fn drop_unsized(_: T) {} + +fn main() { + { + let x = "hello".to_owned().into_boxed_str(); + let y = *x; + drop_unsized(y); + println!("{}", &x); + //~^ERROR use of moved value + println!("{}", &y); + //~^ERROR use of moved value + } + + { + let x = "hello".to_owned().into_boxed_str(); + let y = *x; + y.foo(); + println!("{}", &x); + //~^ERROR use of moved value + println!("{}", &y); + //~^ERROR use of moved value + } + + { + let x = "hello".to_owned().into_boxed_str(); + x.foo(); + println!("{}", &x); + //~^ERROR use of moved value + } +} diff --git a/src/test/ui/unsized-locals/borrow-after-move.stderr b/src/test/ui/unsized-locals/borrow-after-move.stderr new file mode 100644 index 0000000000000..8eea01f25c865 --- /dev/null +++ b/src/test/ui/unsized-locals/borrow-after-move.stderr @@ -0,0 +1,57 @@ +error[E0382]: use of moved value: `x` + --> $DIR/borrow-after-move.rs:20:25 + | +LL | let y = *x; + | - value moved here +LL | drop_unsized(y); +LL | println!("{}", &x); + | ^ value used here after move + | + = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait + +error[E0382]: use of moved value: `y` + --> $DIR/borrow-after-move.rs:22:25 + | +LL | drop_unsized(y); + | - value moved here +... +LL | println!("{}", &y); + | ^ value used here after move + | + = note: move occurs because `y` has type `str`, which does not implement the `Copy` trait + +error[E0382]: use of moved value: `x` + --> $DIR/borrow-after-move.rs:30:25 + | +LL | let y = *x; + | - value moved here +LL | y.foo(); +LL | println!("{}", &x); + | ^ value used here after move + | + = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait + +error[E0382]: use of moved value: `y` + --> $DIR/borrow-after-move.rs:32:25 + | +LL | y.foo(); + | - value moved here +... +LL | println!("{}", &y); + | ^ value used here after move + | + = note: move occurs because `y` has type `str`, which does not implement the `Copy` trait + +error[E0382]: use of moved value: `x` + --> $DIR/borrow-after-move.rs:39:25 + | +LL | x.foo(); + | - value moved here +LL | println!("{}", &x); + | ^ value used here after move + | + = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/unsized-locals/double-move.nll.stderr b/src/test/ui/unsized-locals/double-move.nll.stderr new file mode 100644 index 0000000000000..0555a8944bf94 --- /dev/null +++ b/src/test/ui/unsized-locals/double-move.nll.stderr @@ -0,0 +1,55 @@ +error[E0382]: use of moved value: `y` + --> $DIR/double-move.rs:20:22 + | +LL | drop_unsized(y); + | - value moved here +LL | drop_unsized(y); //~ERROR use of moved value + | ^ value used here after move + | + = note: move occurs because `y` has type `str`, which does not implement the `Copy` trait + +error[E0382]: use of moved value: `x` + --> $DIR/double-move.rs:26:22 + | +LL | let _y = *x; + | -- value moved here +LL | drop_unsized(x); //~ERROR use of moved value + | ^ value used here after move + +error[E0382]: use of moved value: `*x` + --> $DIR/double-move.rs:32:18 + | +LL | drop_unsized(x); + | - value moved here +LL | let _y = *x; //~ERROR use of moved value + | ^^ value used here after move + +error[E0382]: use of moved value: `y` + --> $DIR/double-move.rs:39:9 + | +LL | y.foo(); + | - value moved here +LL | y.foo(); //~ERROR use of moved value + | ^ value used here after move + | + = note: move occurs because `y` has type `str`, which does not implement the `Copy` trait + +error[E0382]: use of moved value: `*x` + --> $DIR/double-move.rs:45:9 + | +LL | let _y = *x; + | -- value moved here +LL | x.foo(); //~ERROR use of moved value + | ^ value used here after move + +error[E0382]: use of moved value: `*x` + --> $DIR/double-move.rs:51:18 + | +LL | x.foo(); + | - value moved here +LL | let _y = *x; //~ERROR use of moved value + | ^^ value used here after move + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/unsized-locals/double-move.rs b/src/test/ui/unsized-locals/double-move.rs new file mode 100644 index 0000000000000..c3a50341bc962 --- /dev/null +++ b/src/test/ui/unsized-locals/double-move.rs @@ -0,0 +1,53 @@ +#![feature(unsized_locals)] + +pub trait Foo { + fn foo(self) -> String; +} + +impl Foo for str { + fn foo(self) -> String { + self.to_owned() + } +} + +fn drop_unsized(_: T) {} + +fn main() { + { + let x = "hello".to_owned().into_boxed_str(); + let y = *x; + drop_unsized(y); + drop_unsized(y); //~ERROR use of moved value + } + + { + let x = "hello".to_owned().into_boxed_str(); + let _y = *x; + drop_unsized(x); //~ERROR use of moved value + } + + { + let x = "hello".to_owned().into_boxed_str(); + drop_unsized(x); + let _y = *x; //~ERROR use of moved value + } + + { + let x = "hello".to_owned().into_boxed_str(); + let y = *x; + y.foo(); + y.foo(); //~ERROR use of moved value + } + + { + let x = "hello".to_owned().into_boxed_str(); + let _y = *x; + x.foo(); //~ERROR use of moved value + } + + { + let x = "hello".to_owned().into_boxed_str(); + x.foo(); + let _y = *x; //~ERROR use of moved value + } +} diff --git a/src/test/ui/unsized-locals/double-move.stderr b/src/test/ui/unsized-locals/double-move.stderr new file mode 100644 index 0000000000000..1009e913b7b67 --- /dev/null +++ b/src/test/ui/unsized-locals/double-move.stderr @@ -0,0 +1,63 @@ +error[E0382]: use of moved value: `y` + --> $DIR/double-move.rs:20:22 + | +LL | drop_unsized(y); + | - value moved here +LL | drop_unsized(y); //~ERROR use of moved value + | ^ value used here after move + | + = note: move occurs because `y` has type `str`, which does not implement the `Copy` trait + +error[E0382]: use of moved value: `x` + --> $DIR/double-move.rs:26:22 + | +LL | let _y = *x; + | -- value moved here +LL | drop_unsized(x); //~ERROR use of moved value + | ^ value used here after move + | + = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait + +error[E0382]: use of moved value: `*x` + --> $DIR/double-move.rs:32:13 + | +LL | drop_unsized(x); + | - value moved here +LL | let _y = *x; //~ERROR use of moved value + | ^^ value used here after move + | + = note: move occurs because `x` has type `std::boxed::Box`, which does not implement the `Copy` trait + +error[E0382]: use of moved value: `y` + --> $DIR/double-move.rs:39:9 + | +LL | y.foo(); + | - value moved here +LL | y.foo(); //~ERROR use of moved value + | ^ value used here after move + | + = note: move occurs because `y` has type `str`, which does not implement the `Copy` trait + +error[E0382]: use of moved value: `*x` + --> $DIR/double-move.rs:45:9 + | +LL | let _y = *x; + | -- value moved here +LL | x.foo(); //~ERROR use of moved value + | ^ value used here after move + | + = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait + +error[E0382]: use of moved value: `*x` + --> $DIR/double-move.rs:51:13 + | +LL | x.foo(); + | - value moved here +LL | let _y = *x; //~ERROR use of moved value + | ^^ value used here after move + | + = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0382`.