From bdfeb65585a5d6aa4bda0f73f12d4d57d167f322 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 28 Aug 2014 18:50:00 +1200 Subject: [PATCH 1/2] 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 77e73c46c402c..2698ac94a99c6 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 b96a75cba9480..ee2d73dda9523 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 0000000000000..e0a929dcf4f8c --- /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` +} From cc598e6f8e3d7eb88b4f7867484a1a4d503efc38 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 1 Sep 2014 09:48:19 +1200 Subject: [PATCH 2/2] Second approach - using type contents --- src/librustc/diagnostics.rs | 3 +-- src/librustc/middle/kind.rs | 20 ++------------------ src/librustc/middle/ty.rs | 2 +- src/test/compile-fail/bad-sized.rs | 14 +++++++------- 4 files changed, 11 insertions(+), 28 deletions(-) diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index 2698ac94a99c6..77e73c46c402c 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -167,6 +167,5 @@ register_diagnostics!( E0155, E0156, E0157, - E0158, - E0159 + E0158 ) diff --git a/src/librustc/middle/kind.rs b/src/librustc/middle/kind.rs index ee2d73dda9523..c3a001116b34c 100644 --- a/src/librustc/middle/kind.rs +++ b/src/librustc/middle/kind.rs @@ -596,8 +596,8 @@ fn check_ty(cx: &mut Context, aty: &Ty) { Some(ref item_substs) => { let def_map = cx.tcx.def_map.borrow(); let did = def_map.get_copy(&id).def_id(); - let ty = ty::lookup_item_type(cx.tcx, did); - for def in ty.generics.types.iter() { + let generics = ty::lookup_item_type(cx.tcx, did).generics; + for def in generics.types.iter() { let ty = *item_substs.substs.types.get(def.space, def.index); check_typaram_bounds(cx, aty.span, ty, def); @@ -644,20 +644,6 @@ 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) { @@ -688,7 +674,6 @@ fn check_bounds_on_structs_or_enums_in_type_if_possible(cx: &mut Context, .types .iter()) { check_typaram_bounds(cx, span, *ty, type_param_def); - check_false_sized(cx, span, *ty); } // Check trait bounds. @@ -716,7 +701,6 @@ 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/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 2d3096d13eae0..2cd76404ecbac 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -2362,7 +2362,7 @@ pub fn type_contents(cx: &ctxt, ty: t) -> TypeContents { } ty_trait(box ty::TyTrait { bounds, .. }) => { - object_contents(cx, bounds) | TC::ReachesFfiUnsafe + object_contents(cx, bounds) | TC::ReachesFfiUnsafe | TC::Nonsized } ty_ptr(ref mt) => { diff --git a/src/test/compile-fail/bad-sized.rs b/src/test/compile-fail/bad-sized.rs index e0a929dcf4f8c..fb9a060cb602a 100644 --- a/src/test/compile-fail/bad-sized.rs +++ b/src/test/compile-fail/bad-sized.rs @@ -8,18 +8,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-tidy-linelength + 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` + //~^ ERROR instantiating a type parameter with an incompatible type `Trait+Sized`, which does not fulfill `Sized` + //~^^ ERROR instantiating a type parameter with an incompatible type `Trait+Sized`, which does not fulfill `Sized` + //~^^^ ERROR instantiating a type parameter with an incompatible type `Trait+Sized`, which does not fulfill `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` + //~^ ERROR instantiating a type parameter with an incompatible type `Trait+Sized`, which does not fulfill `Sized` + //~^^ ERROR instantiating a type parameter with an incompatible type `Trait+Sized`, which does not fulfill `Sized` }