mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-01 09:33:26 +00:00
fix remaining bugs
This commit is contained in:
parent
c998057770
commit
4a16b562a8
@ -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 ...
|
||||
|
@ -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)]
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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})}
|
||||
|
46
src/test/run-pass/trait-copy-guessing.rs
Normal file
46
src/test/run-pass/trait-copy-guessing.rs
Normal 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);
|
||||
}
|
Loading…
Reference in New Issue
Block a user