diff --git a/src/librustc/middle/traits/mod.rs b/src/librustc/middle/traits/mod.rs index d34d413225e80..0a47d64789038 100644 --- a/src/librustc/middle/traits/mod.rs +++ b/src/librustc/middle/traits/mod.rs @@ -94,6 +94,9 @@ pub enum ObligationCauseCode<'tcx> { // Types of fields (other than the last) in a struct must be sized. FieldSized, + + // Only Sized types can be made into objects + ObjectSized, } pub type Obligations<'tcx> = subst::VecPerParamSpace>; diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 553d80852c28f..704168da1582a 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -1771,12 +1771,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } ty::UnsizeVtable(ref ty_trait, self_ty) => { vtable::check_object_safety(self.tcx(), ty_trait, span); + // If the type is `Foo+'a`, ensures that the type // being cast to `Foo+'a` implements `Foo`: vtable::register_object_cast_obligations(self, - span, - ty_trait, - self_ty); + span, + ty_trait, + self_ty); // If the type is `Foo+'a`, ensures that the type // being cast to `Foo+'a` outlives `'a`: diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs index 99ffe89862229..1619a4224f9f0 100644 --- a/src/librustc/middle/typeck/check/vtable.rs +++ b/src/librustc/middle/typeck/check/vtable.rs @@ -21,6 +21,7 @@ use middle::typeck::infer; use std::rc::Rc; use syntax::ast; use syntax::codemap::Span; +use util::common::ErrorReported; use util::ppaux::{UserString, Repr, ty_to_string}; pub fn check_object_cast<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, @@ -238,6 +239,20 @@ pub fn register_object_cast_obligations<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, referent_ty: Ty<'tcx>) -> Rc> { + // We can only make objects from sized types. + let sized_obligation = + traits::obligation_for_builtin_bound( + fcx.tcx(), + traits::ObligationCause::new(span, traits::ObjectSized), + referent_ty, + ty::BoundSized); + match sized_obligation { + Ok(sized_obligation) => { + fcx.register_obligation(sized_obligation); + } + Err(ErrorReported) => { } + } + // This is just for better error reporting. Kinda goofy. The object type stuff // needs some refactoring so there is a more convenient type to pass around. let object_trait_ty = @@ -543,5 +558,9 @@ fn note_obligation_cause<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, "only the last field of a struct or enum variant \ may have a dynamically sized type") } + traits::ObjectSized => { + span_note!(tcx.sess, obligation.cause.span, + "only sized types can be made into objects"); + } } } diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs index cdbe107e11c95..e2fa02584f4fd 100644 --- a/src/librustc/util/common.rs +++ b/src/librustc/util/common.rs @@ -20,7 +20,8 @@ use syntax::ast; use syntax::visit; use syntax::visit::Visitor; -// An error has already been reported to the user, so no need to continue checking. +// Useful type to use with `Result<>` indicate that an error has already +// been reported to the user, so no need to continue checking. #[deriving(Clone,Show)] pub struct ErrorReported; diff --git a/src/test/compile-fail/dst-object-from-unsized-type.rs b/src/test/compile-fail/dst-object-from-unsized-type.rs new file mode 100644 index 0000000000000..e40cc342c0b49 --- /dev/null +++ b/src/test/compile-fail/dst-object-from-unsized-type.rs @@ -0,0 +1,30 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that we cannot create objects from unsized types. + +trait Foo for Sized? {} +impl Foo for str {} + +fn test(t: &T) { + let u: &Foo = t; + //~^ ERROR `core::kinds::Sized` is not implemented for the type `T` + + let v: &Foo = t as &Foo; + //~^ ERROR `core::kinds::Sized` is not implemented for the type `T` +} + +fn main() { + let _: &[&Foo] = &["hi"]; + //~^ ERROR `core::kinds::Sized` is not implemented for the type `str` + + let _: &Foo = "hi" as &Foo; + //~^ ERROR `core::kinds::Sized` is not implemented for the type `str` +} diff --git a/src/test/compile-fail/issue-14366.rs b/src/test/compile-fail/issue-14366.rs index a0eca1d49dcc9..01a15023fbaad 100644 --- a/src/test/compile-fail/issue-14366.rs +++ b/src/test/compile-fail/issue-14366.rs @@ -11,5 +11,5 @@ fn main() { let _x = "test" as &::std::any::Any; //~^ ERROR the trait `core::kinds::Sized` is not implemented for the type `str` -//~^^ NOTE the trait `core::kinds::Sized` must be implemented for the cast to the object type +//~^^ ERROR the trait `core::kinds::Sized` is not implemented for the type `str` }