From bdfeb65585a5d6aa4bda0f73f12d4d57d167f322 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 28 Aug 2014 18:50:00 +1200 Subject: [PATCH] Forbid the Sized bound on unsized types closes #16800 --- src/librustc/diagnostics.rs | 3 ++- src/librustc/middle/kind.rs | 27 +++++++++++++++++++++------ src/test/compile-fail/bad-sized.rs | 25 +++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 7 deletions(-) create mode 100644 src/test/compile-fail/bad-sized.rs diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index 77e73c46c40..2698ac94a99 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -167,5 +167,6 @@ register_diagnostics!( E0155, E0156, E0157, - E0158 + E0158, + E0159 ) diff --git a/src/librustc/middle/kind.rs b/src/librustc/middle/kind.rs index b96a75cba94..ee2d73dda95 100644 --- a/src/librustc/middle/kind.rs +++ b/src/librustc/middle/kind.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use middle::freevars::freevar_entry; use middle::freevars; use middle::subst; @@ -593,15 +592,15 @@ fn check_ty(cx: &mut Context, aty: &Ty) { match aty.node { TyPath(_, _, id) => { match cx.tcx.item_substs.borrow().find(&id) { - None => { } + None => {} Some(ref item_substs) => { let def_map = cx.tcx.def_map.borrow(); let did = def_map.get_copy(&id).def_id(); - let generics = ty::lookup_item_type(cx.tcx, did).generics; - for def in generics.types.iter() { + let ty = ty::lookup_item_type(cx.tcx, did); + for def in ty.generics.types.iter() { let ty = *item_substs.substs.types.get(def.space, def.index); - check_typaram_bounds(cx, aty.span, ty, def) + check_typaram_bounds(cx, aty.span, ty, def); } } } @@ -645,6 +644,20 @@ pub fn check_typaram_bounds(cx: &Context, }); } +// Check that the programmer has not added the `Sized` bound to a trait type +// which would fool the compiler into thinking that trait types are sized, when +// they are really unsized. +fn check_false_sized(cx: &Context, sp: Span, ty: ty::t) { + match ty::get(ty).sty { + ty::ty_trait(..) if ty::type_is_sized(cx.tcx, ty) => { + span_err!(cx.tcx.sess, sp, E0159, + "explicitly adding `Sized` bound to an unsized type `{}`", + ty_to_string(cx.tcx, ty)); + } + _ => {} + } +} + fn check_bounds_on_structs_or_enums_in_type_if_possible(cx: &mut Context, span: Span, ty: ty::t) { @@ -674,7 +687,8 @@ fn check_bounds_on_structs_or_enums_in_type_if_possible(cx: &mut Context, .zip(polytype.generics .types .iter()) { - check_typaram_bounds(cx, span, *ty, type_param_def) + check_typaram_bounds(cx, span, *ty, type_param_def); + check_false_sized(cx, span, *ty); } // Check trait bounds. @@ -702,6 +716,7 @@ fn check_bounds_on_structs_or_enums_in_type_if_possible(cx: &mut Context, cx.tcx)).as_slice()); }) } + ty::ty_uniq(ty) => check_false_sized(cx, span, ty), _ => {} } }); diff --git a/src/test/compile-fail/bad-sized.rs b/src/test/compile-fail/bad-sized.rs new file mode 100644 index 00000000000..e0a929dcf4f --- /dev/null +++ b/src/test/compile-fail/bad-sized.rs @@ -0,0 +1,25 @@ +// Copyright 2012 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::cell::RefCell; + +trait Trait {} + +pub fn main() { + let x: Vec = Vec::new(); + //~^ ERROR explicitly adding `Sized` bound to an unsized type `Trait+Sized` + //~^^ ERROR explicitly adding `Sized` bound to an unsized type `Trait+Sized` + let x: Vec> = Vec::new(); + //~^ ERROR explicitly adding `Sized` bound to an unsized type `Trait+Sized` + //~^^ ERROR explicitly adding `Sized` bound to an unsized type `Trait+Sized` + let x: Vec>> = Vec::new(); + //~^ ERROR explicitly adding `Sized` bound to an unsized type `Trait+Sized` + //~^^ ERROR explicitly adding `Sized` bound to an unsized type `Trait+Sized` +}