more detailed tests around diverging type variables

This commit is contained in:
Niko Matsakis 2017-03-17 14:10:00 -04:00
parent 52e524a357
commit 5cd99aa167
5 changed files with 140 additions and 74 deletions

View File

@ -22,16 +22,6 @@ fn deserialize() -> Result<(), String> {
}
}
fn doit() -> Result<(), String> {
let _ = match Deserialize::deserialize() {
//~^ ERROR code relies on type
//~| WARNING previously accepted
Ok(x) => x,
Err(e) => return Err(e),
};
Ok(())
}
trait ImplementedForUnitButNotNever {}
impl ImplementedForUnitButNotNever for () {}
@ -46,6 +36,6 @@ fn smeg() {
}
fn main() {
let _ = doit();
smeg();
}

View File

@ -1,41 +0,0 @@
// Copyright 2015 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.
// Test that diverging types default to ! when feature(never_type) is enabled. This test is the
// same as run-pass/unit-fallback.rs except that ! is enabled.
#![feature(never_type)]
trait Balls: Sized {
fn smeg() -> Result<Self, ()>;
}
impl Balls for () {
fn smeg() -> Result<(), ()> { Ok(()) }
}
struct Flah;
impl Flah {
fn flah<T: Balls>(&self) -> Result<T, ()> {
T::smeg()
}
}
fn doit() -> Result<(), ()> {
// The type of _ is unconstrained here and should default to !
let _ = try!(Flah.flah()); //~ ERROR the trait bound
Ok(())
}
fn main() {
let _ = doit();
}

View File

@ -0,0 +1,106 @@
// Copyright 2015 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.
// Test various cases where we permit an unconstrained variable
// to fallback based on control-flow.
//
// These represent current behavior, but are pretty dubious. I would
// like to revisit these and potentially change them. --nmatsakis
#![feature(never_type)]
#![feature(loop_break_value)]
trait BadDefault {
fn default() -> Self;
}
impl BadDefault for u32 {
fn default() -> Self {
0
}
}
impl BadDefault for ! {
fn default() -> ! {
panic!()
}
}
fn assignment() {
let x;
if true {
x = BadDefault::default();
} else {
x = return;
}
}
fn assignment_rev() {
let x;
if true {
x = return;
} else {
x = BadDefault::default();
}
}
fn if_then_else() {
let _x = if true {
BadDefault::default()
} else {
return;
};
}
fn if_then_else_rev() {
let _x = if true {
return;
} else {
BadDefault::default()
};
}
fn match_arm() {
let _x = match Ok(BadDefault::default()) {
Ok(v) => v,
Err(()) => return,
};
}
fn match_arm_rev() {
let _x = match Ok(BadDefault::default()) {
Err(()) => return,
Ok(v) => v,
};
}
fn loop_break() {
let _x = loop {
if false {
break return;
} else {
break BadDefault::default();
}
};
}
fn loop_break_rev() {
let _x = loop {
if false {
break return;
} else {
break BadDefault::default();
}
};
}
fn main() { }

View File

@ -8,31 +8,20 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Test that diverging types default to () (with feature(never_type) disabled).
// Test a regression found when building compiler. The `produce()`
// error type `T` winds up getting unified with result of `x.parse()`;
// the type of the closure given to `unwrap_or_else` needs to be
// inferred to `usize`.
trait Balls: Sized {
fn smeg() -> Result<Self, ()>;
}
use std::num::ParseIntError;
impl Balls for () {
fn smeg() -> Result<(), ()> { Ok(()) }
}
struct Flah;
impl Flah {
fn flah<T: Balls>(&self) -> Result<T, ()> {
T::smeg()
}
}
fn doit() -> Result<(), ()> {
// The type of _ is unconstrained here and should default to ()
let _ = try!(Flah.flah());
Ok(())
fn produce<T>() -> Result<&'static str, T> {
Ok("22")
}
fn main() {
let _ = doit();
let x: usize = produce()
.and_then(|x| x.parse())
.unwrap_or_else(|_| panic!());
println!("{}", x);
}

View File

@ -0,0 +1,22 @@
// 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 <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.
#![allow(warnings)]
// Here the type of `c` is `Option<?T>`, where `?T` is unconstrained.
// Because there is data-flow from the `{ return; }` block, which
// diverges and hence has type `!`, into `c`, we will default `?T` to
// `!`, and hence this code compiles rather than failing and requiring
// a type annotation.
fn main() {
let c = Some({ return; });
c.unwrap();
}