From 0eb17e3f3134a7cf83f659d4f1b6e25aa6bcdde9 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Sat, 18 Oct 2014 23:12:02 +0300 Subject: [PATCH] Ensure that the return type of a function is Sized While no real rvalue of an unsized type can exist, a diverging function can still "return" a value of such a type, which causes an ICE. Fixes #18107. --- src/librustc/middle/traits/mod.rs | 1 + src/librustc/middle/typeck/check/mod.rs | 11 ++++----- src/librustc/middle/typeck/check/vtable2.rs | 11 ++++++--- src/test/auxiliary/lang-item-public.rs | 3 +++ src/test/compile-fail/issue-17025.rs | 5 +++-- src/test/compile-fail/issue-18107.rs | 25 +++++++++++++++++++++ src/test/compile-fail/issue-5883.rs | 3 ++- src/test/compile-fail/privacy4.rs | 4 +++- src/test/compile-fail/required-lang-item.rs | 3 +++ 9 files changed, 52 insertions(+), 14 deletions(-) create mode 100644 src/test/compile-fail/issue-18107.rs diff --git a/src/librustc/middle/traits/mod.rs b/src/librustc/middle/traits/mod.rs index fb267421245..f0282804540 100644 --- a/src/librustc/middle/traits/mod.rs +++ b/src/librustc/middle/traits/mod.rs @@ -77,6 +77,7 @@ pub enum ObligationCauseCode { AssignmentLhsSized, // L = X implies that L is Sized StructInitializerSized, // S { ... } must be Sized VariableType(ast::NodeId), // Type of each variable must be Sized + ReturnType, // Return type must be Sized RepeatVec, // [T,..n] --> T must be Copy // Captures of variable the given id by a closure (span is the diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 953ae0b9bd9..a9c4317b9ee 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -555,16 +555,12 @@ fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>, // Remember return type so that regionck can access it later. let fn_sig_tys: Vec = - arg_tys.iter() - .chain([ret_ty].iter()) - .map(|&ty| ty) - .collect(); + arg_tys.iter().chain([ret_ty].iter()).map(|&ty| ty).collect(); debug!("fn-sig-map: fn_id={} fn_sig_tys={}", fn_id, fn_sig_tys.repr(tcx)); - inherited.fn_sig_map - .borrow_mut() - .insert(fn_id, fn_sig_tys); + + inherited.fn_sig_map.borrow_mut().insert(fn_id, fn_sig_tys); { let mut visit = GatherLocalsVisitor { fcx: &fcx, }; @@ -591,6 +587,7 @@ fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>, visit.visit_block(body); } + fcx.require_type_is_sized(ret_ty, decl.output.span, traits::ReturnType); check_block_with_expected(&fcx, body, ExpectHasType(ret_ty)); diff --git a/src/librustc/middle/typeck/check/vtable2.rs b/src/librustc/middle/typeck/check/vtable2.rs index 546ad86bc36..d557a2b713b 100644 --- a/src/librustc/middle/typeck/check/vtable2.rs +++ b/src/librustc/middle/typeck/check/vtable2.rs @@ -366,15 +366,20 @@ fn note_obligation_cause(fcx: &FnCtxt, traits::RepeatVec => { tcx.sess.span_note( obligation.cause.span, - format!( - "the `Copy` trait is required because the \ - repeated element will be copied").as_slice()); + "the `Copy` trait is required because the \ + repeated element will be copied"); } traits::VariableType(_) => { tcx.sess.span_note( obligation.cause.span, "all local variables must have a statically known size"); } + traits::ReturnType => { + tcx.sess.span_note( + obligation.cause.span, + "the return type of a function must have a \ + statically known size"); + } traits::AssignmentLhsSized => { tcx.sess.span_note( obligation.cause.span, diff --git a/src/test/auxiliary/lang-item-public.rs b/src/test/auxiliary/lang-item-public.rs index 73bad011472..967f49924d4 100644 --- a/src/test/auxiliary/lang-item-public.rs +++ b/src/test/auxiliary/lang-item-public.rs @@ -11,6 +11,9 @@ #![no_std] #![feature(lang_items)] +#[lang="sized"] +pub trait Sized for Sized? {} + #[lang="fail"] fn fail(_: &(&'static str, &'static str, uint)) -> ! { loop {} } diff --git a/src/test/compile-fail/issue-17025.rs b/src/test/compile-fail/issue-17025.rs index 1efc78e13b8..5e076a0dfbb 100644 --- a/src/test/compile-fail/issue-17025.rs +++ b/src/test/compile-fail/issue-17025.rs @@ -13,8 +13,9 @@ enum A { C([Box]), } -fn c(c:char) -> A { - B(c) //~ ERROR cannot move a value of type A: the size of A cannot be statically determined +fn c(c:char) { + B(c); + //~^ ERROR cannot move a value of type A: the size of A cannot be statically determined } pub fn main() {} diff --git a/src/test/compile-fail/issue-18107.rs b/src/test/compile-fail/issue-18107.rs new file mode 100644 index 00000000000..6cebf7f9da1 --- /dev/null +++ b/src/test/compile-fail/issue-18107.rs @@ -0,0 +1,25 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + + +pub trait AbstractRenderer {} + +fn _create_render(_: &()) -> + AbstractRenderer +//~^ ERROR: the trait `core::kinds::Sized` is not implemented +{ + match 0u { + _ => unimplemented!() + } +} + +fn main() { +} diff --git a/src/test/compile-fail/issue-5883.rs b/src/test/compile-fail/issue-5883.rs index 71b1bcd69da..96088052e91 100644 --- a/src/test/compile-fail/issue-5883.rs +++ b/src/test/compile-fail/issue-5883.rs @@ -14,7 +14,8 @@ struct Struct { r: A+'static } -fn new_struct(r: A+'static) -> Struct { +fn new_struct(r: A+'static) + -> Struct { //~^ ERROR the trait `core::kinds::Sized` is not implemented //~^ ERROR the trait `core::kinds::Sized` is not implemented Struct { r: r } //~^ ERROR the trait `core::kinds::Sized` is not implemented diff --git a/src/test/compile-fail/privacy4.rs b/src/test/compile-fail/privacy4.rs index 65f4a0e950f..b65ad2a2e6a 100644 --- a/src/test/compile-fail/privacy4.rs +++ b/src/test/compile-fail/privacy4.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(globs)] +#![feature(globs, lang_items)] #![no_std] // makes debugging this test *a lot* easier (during resolve) +#[lang = "sized"] pub trait Sized for Sized? {} + // Test to make sure that private items imported through globs remain private // when they're used. diff --git a/src/test/compile-fail/required-lang-item.rs b/src/test/compile-fail/required-lang-item.rs index 4921c130010..dd11ec645b4 100644 --- a/src/test/compile-fail/required-lang-item.rs +++ b/src/test/compile-fail/required-lang-item.rs @@ -8,8 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(lang_items)] #![no_std] +#[lang="sized"] pub trait Sized for Sized? {} + // error-pattern:requires `start` lang_item fn main() {}