// 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>>;
}
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`:
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>,
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 =
"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");
+ }
}
}
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;
--- /dev/null
+// 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`
+}
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`
}