Skip to content

Forbid unsized rvalues #16933

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 8, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/librustc/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,5 +169,6 @@ register_diagnostics!(
E0157,
E0158,
E0159,
E0160
E0160,
E0161
)
3 changes: 3 additions & 0 deletions src/librustc/driver/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,9 @@ pub fn phase_3_run_analysis_passes(sess: Session,
time(time_passes, "borrow checking", (), |_|
middle::borrowck::check_crate(&ty_cx, krate));

time(time_passes, "rvalue checking", (), |_|
middle::check_rvalues::check_crate(&ty_cx, krate));

time(time_passes, "kind checking", (), |_|
kind::check_crate(&ty_cx, krate));

Expand Down
1 change: 1 addition & 0 deletions src/librustc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ pub mod middle {
pub mod check_const;
pub mod check_loop;
pub mod check_match;
pub mod check_rvalues;
pub mod check_static;
pub mod const_eval;
pub mod dataflow;
Expand Down
86 changes: 86 additions & 0 deletions src/librustc/middle/check_rvalues.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// 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.

// Checks that all rvalues in a crate have statically known size. check_crate
// is the public starting point.

use middle::expr_use_visitor as euv;
use middle::mem_categorization as mc;
use middle::ty;
use util::ppaux::ty_to_string;

use syntax::ast;
use syntax::codemap::Span;
use syntax::visit;

pub fn check_crate(tcx: &ty::ctxt,
krate: &ast::Crate) {
let mut rvcx = RvalueContext { tcx: tcx };
visit::walk_crate(&mut rvcx, krate, ());
}

struct RvalueContext<'a> {
tcx: &'a ty::ctxt
}

impl<'a> visit::Visitor<()> for RvalueContext<'a> {
fn visit_fn(&mut self,
_: &visit::FnKind,
fd: &ast::FnDecl,
b: &ast::Block,
_: Span,
_: ast::NodeId,
_: ()) {
let mut euv = euv::ExprUseVisitor::new(self, self.tcx);
euv.walk_fn(fd, b);
}
}

impl<'a> euv::Delegate for RvalueContext<'a> {
fn consume(&mut self,
_: ast::NodeId,
span: Span,
cmt: mc::cmt,
_: euv::ConsumeMode) {
debug!("consume; cmt: {:?}; type: {}", *cmt, ty_to_string(self.tcx, cmt.ty));
if !ty::type_is_sized(self.tcx, cmt.ty) {
span_err!(self.tcx.sess, span, E0161,
"cannot move a value of type {0}: the size of {0} cannot be statically determined",
ty_to_string(self.tcx, cmt.ty));
}
}

fn consume_pat(&mut self,
_consume_pat: &ast::Pat,
_cmt: mc::cmt,
_mode: euv::ConsumeMode) {
}

fn borrow(&mut self,
_borrow_id: ast::NodeId,
_borrow_span: Span,
_cmt: mc::cmt,
_loan_region: ty::Region,
_bk: ty::BorrowKind,
_loan_cause: euv::LoanCause) {
}

fn decl_without_init(&mut self,
_id: ast::NodeId,
_span: Span) {
}

fn mutate(&mut self,
_assignment_id: ast::NodeId,
_assignment_span: Span,
_assignee_cmt: mc::cmt,
_mode: euv::MutateMode) {
}
}
2 changes: 1 addition & 1 deletion src/librustc/middle/mem_categorization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ pub enum MutabilityCategory {
// like `*x`, the type of this deref node is the deref'd type (`T`),
// but in a pattern like `@x`, the `@x` pattern is again a
// dereference, but its type is the type *before* the dereference
// (`@T`). So use `cmt.type` to find the type of the value in a consistent
// (`@T`). So use `cmt.ty` to find the type of the value in a consistent
// fashion. For more details, see the method `cat_pattern`
#[deriving(Clone, PartialEq)]
pub struct cmt_ {
Expand Down
1 change: 1 addition & 0 deletions src/test/compile-fail/dst-bad-assign-2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,5 @@ pub fn main() {
let f5: &mut Fat<ToBar> = &mut Fat { f1: 5, f2: "some str", ptr: Bar1 {f :42} };
let z: Box<ToBar> = box Bar1 {f: 36};
f5.ptr = *z; //~ ERROR dynamically sized type on lhs of assignment
//~^ ERROR E0161
}
1 change: 1 addition & 0 deletions src/test/compile-fail/dst-bad-deep.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,5 @@ pub fn main() {
let g: &Fat<[int]> = &f;
let h: &Fat<Fat<[int]>> = &Fat { ptr: *g };
//~^ ERROR trying to initialise a dynamically sized struct
//~^^ ERROR E0161
}
20 changes: 20 additions & 0 deletions src/test/compile-fail/dst-rvalue.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// 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.

// Check that dynamically sized rvalues are forbidden

pub fn main() {
let _x: Box<str> = box *"hello world";
//~^ ERROR E0161

let array: &[int] = &[1, 2, 3];
let _x: Box<[int]> = box *array;
//~^ ERROR E0161
}
2 changes: 2 additions & 0 deletions src/test/compile-fail/issue-5883.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ struct Struct {
fn new_struct(r: A+'static) -> Struct {
//~^ ERROR variable `r` has dynamically sized type
Struct { r: r } //~ ERROR trying to initialise a dynamically sized struct
//~^ ERROR E0161
//~^^ ERROR E0161
}

trait Curve {}
Expand Down
6 changes: 4 additions & 2 deletions src/test/compile-fail/unsized3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,10 @@ fn f8<Sized? X>(x1: &S<X>, x2: &S<X>) {

// Test some tuples.
fn f9<Sized? X>(x1: Box<S<X>>, x2: Box<E<X>>) {
f5(&(*x1, 34i)); //~ERROR instantiating a type parameter with an incompatible type `(S<X>,int)`,
f5(&(32i, *x2)); //~ERROR instantiating a type parameter with an incompatible type `(int,E<X>)`,
f5(&(*x1, 34i)); //~ERROR E0161
//~^ ERROR instantiating a type parameter with an incompatible type
f5(&(32i, *x2)); //~ERROR E0161
//~^ ERROR instantiating a type parameter with an incompatible type
}

// I would like these to fail eventually.
Expand Down
2 changes: 2 additions & 0 deletions src/test/compile-fail/unsized6.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,13 @@ fn f3<Sized? X>(x1: Box<X>, x2: Box<X>, x3: Box<X>) {
let y: X = *x1; //~ERROR variable `y` has dynamically sized type `X`
let y = *x2; //~ERROR variable `y` has dynamically sized type `X`
let (y, z) = (*x3, 4i); //~ERROR variable `y` has dynamically sized type `X`
//~^ ERROR E0161
}
fn f4<Sized? X: T>(x1: Box<X>, x2: Box<X>, x3: Box<X>) {
let y: X = *x1; //~ERROR variable `y` has dynamically sized type `X`
let y = *x2; //~ERROR variable `y` has dynamically sized type `X`
let (y, z) = (*x3, 4i); //~ERROR variable `y` has dynamically sized type `X`
//~^ ERROR E0161
}

fn g1<Sized? X>(x: X) {} //~ERROR variable `x` has dynamically sized type `X`
Expand Down