mirror of
https://github.com/rust-lang/rust.git
synced 2024-10-30 22:12:15 +00:00
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.
This commit is contained in:
parent
c121cbab35
commit
0eb17e3f31
@ -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
|
||||
|
@ -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<ty::t> =
|
||||
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));
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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 {} }
|
||||
|
||||
|
@ -13,8 +13,9 @@ enum A {
|
||||
C([Box<A>]),
|
||||
}
|
||||
|
||||
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() {}
|
||||
|
25
src/test/compile-fail/issue-18107.rs
Normal file
25
src/test/compile-fail/issue-18107.rs
Normal file
@ -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 <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.
|
||||
|
||||
|
||||
|
||||
pub trait AbstractRenderer {}
|
||||
|
||||
fn _create_render(_: &()) ->
|
||||
AbstractRenderer
|
||||
//~^ ERROR: the trait `core::kinds::Sized` is not implemented
|
||||
{
|
||||
match 0u {
|
||||
_ => unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
}
|
@ -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
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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() {}
|
||||
|
Loading…
Reference in New Issue
Block a user