Skip to content

Commit 7a372e2

Browse files
committed
Require that objects can only be made from Sized types. Fixes #18333.
1 parent dd5ce5a commit 7a372e2

File tree

6 files changed

+59
-5
lines changed

6 files changed

+59
-5
lines changed

src/librustc/middle/traits/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,9 @@ pub enum ObligationCauseCode<'tcx> {
9494

9595
// Types of fields (other than the last) in a struct must be sized.
9696
FieldSized,
97+
98+
// Only Sized types can be made into objects
99+
ObjectSized,
97100
}
98101

99102
pub type Obligations<'tcx> = subst::VecPerParamSpace<Obligation<'tcx>>;

src/librustc/middle/typeck/check/mod.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1771,12 +1771,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
17711771
}
17721772
ty::UnsizeVtable(ref ty_trait, self_ty) => {
17731773
vtable::check_object_safety(self.tcx(), ty_trait, span);
1774+
17741775
// If the type is `Foo+'a`, ensures that the type
17751776
// being cast to `Foo+'a` implements `Foo`:
17761777
vtable::register_object_cast_obligations(self,
1777-
span,
1778-
ty_trait,
1779-
self_ty);
1778+
span,
1779+
ty_trait,
1780+
self_ty);
17801781

17811782
// If the type is `Foo+'a`, ensures that the type
17821783
// being cast to `Foo+'a` outlives `'a`:

src/librustc/middle/typeck/check/vtable.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use middle::typeck::infer;
2121
use std::rc::Rc;
2222
use syntax::ast;
2323
use syntax::codemap::Span;
24+
use util::common::ErrorReported;
2425
use util::ppaux::{UserString, Repr, ty_to_string};
2526

2627
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>,
238239
referent_ty: Ty<'tcx>)
239240
-> Rc<ty::TraitRef<'tcx>>
240241
{
242+
// We can only make objects from sized types.
243+
let sized_obligation =
244+
traits::obligation_for_builtin_bound(
245+
fcx.tcx(),
246+
traits::ObligationCause::new(span, traits::ObjectSized),
247+
referent_ty,
248+
ty::BoundSized);
249+
match sized_obligation {
250+
Ok(sized_obligation) => {
251+
fcx.register_obligation(sized_obligation);
252+
}
253+
Err(ErrorReported) => { }
254+
}
255+
241256
// This is just for better error reporting. Kinda goofy. The object type stuff
242257
// needs some refactoring so there is a more convenient type to pass around.
243258
let object_trait_ty =
@@ -543,5 +558,9 @@ fn note_obligation_cause<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
543558
"only the last field of a struct or enum variant \
544559
may have a dynamically sized type")
545560
}
561+
traits::ObjectSized => {
562+
span_note!(tcx.sess, obligation.cause.span,
563+
"only sized types can be made into objects");
564+
}
546565
}
547566
}

src/librustc/util/common.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ use syntax::ast;
2020
use syntax::visit;
2121
use syntax::visit::Visitor;
2222

23-
// An error has already been reported to the user, so no need to continue checking.
23+
// Useful type to use with `Result<>` indicate that an error has already
24+
// been reported to the user, so no need to continue checking.
2425
#[deriving(Clone,Show)]
2526
pub struct ErrorReported;
2627

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Test that we cannot create objects from unsized types.
12+
13+
trait Foo for Sized? {}
14+
impl Foo for str {}
15+
16+
fn test<Sized? T: Foo>(t: &T) {
17+
let u: &Foo = t;
18+
//~^ ERROR `core::kinds::Sized` is not implemented for the type `T`
19+
20+
let v: &Foo = t as &Foo;
21+
//~^ ERROR `core::kinds::Sized` is not implemented for the type `T`
22+
}
23+
24+
fn main() {
25+
let _: &[&Foo] = &["hi"];
26+
//~^ ERROR `core::kinds::Sized` is not implemented for the type `str`
27+
28+
let _: &Foo = "hi" as &Foo;
29+
//~^ ERROR `core::kinds::Sized` is not implemented for the type `str`
30+
}

src/test/compile-fail/issue-14366.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,5 @@
1111
fn main() {
1212
let _x = "test" as &::std::any::Any;
1313
//~^ ERROR the trait `core::kinds::Sized` is not implemented for the type `str`
14-
//~^^ NOTE the trait `core::kinds::Sized` must be implemented for the cast to the object type
14+
//~^^ ERROR the trait `core::kinds::Sized` is not implemented for the type `str`
1515
}

0 commit comments

Comments
 (0)