Require that objects can only be made from Sized types. Fixes #18333.
This commit is contained in:
parent
dd5ce5ae2f
commit
7a372e23cb
6 changed files with 59 additions and 5 deletions
|
|
@ -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>>;
|
||||
|
|
|
|||
|
|
@ -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`:
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
30
src/test/compile-fail/dst-object-from-unsized-type.rs
Normal file
30
src/test/compile-fail/dst-object-from-unsized-type.rs
Normal file
|
|
@ -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`
|
||||
}
|
||||
|
|
@ -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`
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue