fix remaining bugs

This commit is contained in:
Ariel Ben-Yehuda 2015-10-21 19:01:58 +03:00
parent c998057770
commit 4a16b562a8
6 changed files with 124 additions and 58 deletions

View File

@ -340,7 +340,6 @@ pub fn type_known_to_meet_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
ty,
bound);
if !ty.has_infer_types() && !ty.has_closure_types() {
let cause = ObligationCause::misc(span, ast::DUMMY_NODE_ID);
let obligation =
util::predicate_for_builtin_bound(infcx.tcx, cause, bound, 0, ty);
@ -352,8 +351,12 @@ pub fn type_known_to_meet_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
.evaluate_obligation_conservatively(&obligation);
debug!("type_known_to_meet_builtin_bound: ty={:?} bound={:?} => {:?}",
ty, bound, result);
return result;
}
if result && (ty.has_infer_types() || ty.has_closure_types()) {
// Because of inference "guessing", selection can sometimes claim
// to succeed while the success requires a guess. To ensure
// this function's result remains infallible, we must confirm
// that guess. While imperfect, I believe this is sound.
let mut fulfill_cx = FulfillmentContext::new(false);
@ -382,6 +385,9 @@ pub fn type_known_to_meet_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
false
}
}
} else {
result
}
}
// FIXME: this is gonna need to be removed ...

View File

@ -2851,18 +2851,37 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
-> Vec<PredicateObligation<'tcx>>
{
debug!("impl_or_trait_obligations(def_id={:?})", def_id);
let tcx = self.tcx();
let predicates = self.tcx().lookup_predicates(def_id);
let predicates = predicates.instantiate(self.tcx(), substs);
let predicates = normalize_with_depth(self, cause.clone(), recursion_depth, &predicates);
let predicates = self.infcx().plug_leaks(skol_map, snapshot, &predicates);
let mut obligations = predicates.obligations;
obligations.append(
&mut util::predicates_for_generics(cause,
recursion_depth,
&predicates.value));
obligations
// To allow for one-pass evaluation of the nested obligation,
// each predicate must be preceded by the obligations required
// to normalize it.
// for example, if we have:
// impl<U: Iterator, V: Iterator<Item=U>> Foo for V where U::Item: Copy
// the impl will have the following predicates:
// <V as Iterator>::Item = U,
// U: Iterator, U: Sized,
// V: Iterator, V: Sized,
// <U as Iterator>::Item: Copy
// When we substitute, say, `V => IntoIter<u32>, U => $0`, the last
// obligation will normalize to `<$0 as Iterator>::Item = $1` and
// `$1: Copy`, so we must ensure the obligations are emitted in
// that order.
let predicates = tcx
.lookup_predicates(def_id)
.predicates.iter()
.flat_map(|predicate| {
let predicate =
normalize_with_depth(self, cause.clone(), recursion_depth,
&predicate.subst(tcx, substs));
predicate.obligations.into_iter().chain(
Some(Obligation {
cause: cause.clone(),
recursion_depth: recursion_depth,
predicate: predicate.value
}))
}).collect();
self.infcx().plug_leaks(skol_map, snapshot, &predicates)
}
#[allow(unused_comparisons)]

View File

@ -37,6 +37,7 @@ fn main()
let f: f32 = 1.2;
let v = 0 as *const u8;
let fat_v : *const [u8] = unsafe { &*(0 as *const [u8; 1])};
let fat_sv : *const [i8] = unsafe { &*(0 as *const [i8; 1])};
let foo: &Foo = &f;
let _ = v as &u8; //~ ERROR non-scalar
@ -94,7 +95,7 @@ fn main()
let _ = main as *mut str; //~ ERROR casting
let _ = &f as *mut f32; //~ ERROR casting
let _ = &f as *const f64; //~ ERROR casting
let _ = fat_v as usize;
let _ = fat_sv as usize;
//~^ ERROR casting
//~^^ HELP through a thin pointer first
@ -106,7 +107,7 @@ fn main()
let _ = main.f as *const u32; //~ ERROR attempted access of field
let cf: *const Foo = &0;
let _ = cf as *const [u8];
let _ = cf as *const [u16];
//~^ ERROR casting
//~^^ NOTE vtable kinds
let _ = cf as *const Bar;

View File

@ -8,7 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//~^^^^^^^^^^ ERROR overflow
//
// We get an error message at the top of file (dummy span).
// This is not helpful, but also kind of annoying to prevent,
@ -32,6 +31,7 @@ impl<T:Clone> ToOpt for Option<T> {
}
fn function<T:ToOpt + Clone>(counter: usize, t: T) {
//~^ ERROR reached the recursion limit during monomorphization
if counter > 0 {
function(counter - 1, t.to_option());
// FIXME(#4287) Error message should be here. It should be

View File

@ -8,12 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//~^^^^^^^^^^ ERROR overflow
//
// We get an error message at the top of file (dummy span).
// This is not helpful, but also kind of annoying to prevent,
// so for now just live with it.
enum Nil {NilValue}
struct Cons<T> {head:isize, tail:T}
trait Dot {fn dot(&self, other:Self) -> isize;}
@ -26,7 +20,7 @@ impl<T:Dot> Dot for Cons<T> {
}
}
fn test<T:Dot> (n:isize, i:isize, first:T, second:T) ->isize {
match n { 0 => {first.dot(second)}
match n { 0 => {first.dot(second)} //~ ERROR overflow
// FIXME(#4287) Error message should be here. It should be
// a type error to instantiate `test` at a type other than T.
_ => {test (n-1, i+1, Cons {head:2*i+1, tail:first}, Cons{head:i*i, tail:second})}

View File

@ -0,0 +1,46 @@
// 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.
// "guessing" in trait selection can affect `copy_or_move`. Check that this
// is correctly handled. I am not sure what is the "correct" behaviour,
// but we should at least not ICE.
use std::mem;
struct U([u8; 1337]);
struct S<'a,T:'a>(&'a T);
impl<'a, T> Clone for S<'a, T> { fn clone(&self) -> Self { S(self.0) } }
/// This impl triggers inference "guessing" - S<_>: Copy => _ = U
impl<'a> Copy for S<'a, Option<U>> {}
fn assert_impls_fn<R,T: Fn()->R>(_: &T){}
fn main() {
let n = None;
let e = S(&n);
let f = || {
// S being copy is critical for this to work
drop(e);
mem::size_of_val(e.0)
};
assert_impls_fn(&f);
assert_eq!(f(), 1337+1);
assert_eq!((|| {
// S being Copy is not critical here, but
// we check it anyway.
let n = None;
let e = S(&n);
let ret = mem::size_of_val(e.0);
drop(e);
ret
})(), 1337+1);
}