diff options
| author | Niko Matsakis <niko@alum.mit.edu> | 2014-11-07 16:26:26 -0500 |
|---|---|---|
| committer | Niko Matsakis <niko@alum.mit.edu> | 2014-11-20 09:16:20 -0500 |
| commit | 7a372e23cbab0be6abd3fbd321d0548640568920 (patch) | |
| tree | 8a7ccd1dbf4b3e462e679ebb3eb4a69f5c8261ab | |
| parent | dd5ce5ae2f254cc42763518909f6e7c486d9502a (diff) | |
| download | rust-7a372e23cbab0be6abd3fbd321d0548640568920.tar.gz rust-7a372e23cbab0be6abd3fbd321d0548640568920.zip | |
Require that objects can only be made from Sized types. Fixes #18333.
| -rw-r--r-- | src/librustc/middle/traits/mod.rs | 3 | ||||
| -rw-r--r-- | src/librustc/middle/typeck/check/mod.rs | 7 | ||||
| -rw-r--r-- | src/librustc/middle/typeck/check/vtable.rs | 19 | ||||
| -rw-r--r-- | src/librustc/util/common.rs | 3 | ||||
| -rw-r--r-- | src/test/compile-fail/dst-object-from-unsized-type.rs | 30 | ||||
| -rw-r--r-- | src/test/compile-fail/issue-14366.rs | 2 |
6 files changed, 59 insertions, 5 deletions
diff --git a/src/librustc/middle/traits/mod.rs b/src/librustc/middle/traits/mod.rs index d34d413225e..0a47d647890 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<Obligation<'tcx>>; diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 553d80852c2..704168da158 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 99ffe898622..1619a4224f9 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<ty::TraitRef<'tcx>> { + // 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 cdbe107e11c..e2fa02584f4 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 00000000000..e40cc342c0b --- /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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<Sized? T: Foo>(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 a0eca1d49dc..01a15023fba 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` } |
