Adjust tests for inferenceGet more conservative about inference for now. Seems better to err on the side of being more correct rather than less. Fix a bug in typing index expressions that was exposed as a result, and add one type annotation that is not required. Delete some random tests that were relying on old behavior and don't seem to add anything anymore.
This commit is contained in:
parent
c197911c60
commit
05eb2eeb61
6 changed files with 100 additions and 23 deletions
|
@ -1366,7 +1366,7 @@ pub fn get_dylib_dependency_formats(cdata: Cmd)
|
|||
if spec.len() == 0 { continue }
|
||||
let cnum = spec.split(':').nth(0).unwrap();
|
||||
let link = spec.split(':').nth(1).unwrap();
|
||||
let cnum = cnum.parse().unwrap();
|
||||
let cnum: ast::CrateNum = cnum.parse().unwrap();
|
||||
let cnum = match cdata.cnum_map.get(&cnum) {
|
||||
Some(&n) => n,
|
||||
None => panic!("didn't find a crate in the cnum_map")
|
||||
|
|
|
@ -736,10 +736,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
let trait_def_id = match poly_trait_predicate.0.trait_ref.self_ty().sty {
|
||||
ty::ty_projection(ref data) => data.trait_ref.def_id,
|
||||
ty::ty_infer(ty::TyVar(_)) => {
|
||||
// TODO ignore potential ambiguity so that we can do
|
||||
// better inference, need to get our story
|
||||
// straight(er) here, I think.
|
||||
// candidates.ambiguous = true;
|
||||
// If the self-type is an inference variable, then it MAY wind up
|
||||
// being a projected type, so induce an ambiguity.
|
||||
//
|
||||
// FIXME(#20297) -- being strict about this can cause
|
||||
// inference failures with BorrowFrom, which is
|
||||
// unfortunate. Can we do better here?
|
||||
candidates.ambiguous = true;
|
||||
return;
|
||||
}
|
||||
_ => { return; }
|
||||
|
|
|
@ -10,7 +10,8 @@
|
|||
|
||||
use super::probe;
|
||||
|
||||
use check::{mod, FnCtxt, NoPreference, PreferMutLvalue, callee};
|
||||
use check::{mod, FnCtxt, NoPreference, PreferMutLvalue, callee, demand};
|
||||
use middle::mem_categorization::Typer;
|
||||
use middle::subst::{mod};
|
||||
use middle::traits;
|
||||
use middle::ty::{mod, Ty};
|
||||
|
@ -540,7 +541,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
|
|||
// Don't retry the first one or we might infinite loop!
|
||||
if i != 0 {
|
||||
match expr.node {
|
||||
ast::ExprIndex(ref base_expr, _) => {
|
||||
ast::ExprIndex(ref base_expr, ref index_expr) => {
|
||||
let mut base_adjustment =
|
||||
match self.fcx.inh.adjustments.borrow().get(&base_expr.id) {
|
||||
Some(&ty::AdjustDerefRef(ref adr)) => (*adr).clone(),
|
||||
|
@ -576,7 +577,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
|
|||
&**base_expr,
|
||||
Some(&ty::AdjustDerefRef(base_adjustment.clone())));
|
||||
|
||||
check::try_index_step(
|
||||
let result = check::try_index_step(
|
||||
self.fcx,
|
||||
MethodCall::expr(expr.id),
|
||||
*expr,
|
||||
|
@ -584,6 +585,14 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
|
|||
adjusted_base_ty,
|
||||
base_adjustment,
|
||||
PreferMutLvalue);
|
||||
|
||||
if let Some((input_ty, return_ty)) = result {
|
||||
let index_expr_ty = self.fcx.expr_ty(&**index_expr);
|
||||
demand::suptype(self.fcx, index_expr.span, input_ty, index_expr_ty);
|
||||
|
||||
let expr_ty = self.fcx.expr_ty(&**expr);
|
||||
demand::suptype(self.fcx, expr.span, expr_ty, return_ty);
|
||||
}
|
||||
}
|
||||
ast::ExprUnary(ast::UnDeref, ref base_expr) => {
|
||||
// if this is an overloaded deref, then re-evaluate with
|
||||
|
|
|
@ -8,25 +8,32 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Test that we correctly infer that `E` must be `()` here. This is
|
||||
// known because there is just one impl that could apply where
|
||||
// `Self=()`.
|
||||
// Test equality constraints on associated types in a where clause.
|
||||
|
||||
pub trait FromError<E> {
|
||||
fn from_error(err: E) -> Self;
|
||||
#![feature(associated_types)]
|
||||
|
||||
pub trait ToInt {
|
||||
fn to_int(&self) -> int;
|
||||
}
|
||||
|
||||
impl<E> FromError<E> for E {
|
||||
fn from_error(err: E) -> E {
|
||||
err
|
||||
}
|
||||
pub trait GetToInt
|
||||
{
|
||||
type R;
|
||||
|
||||
fn get(&self) -> <Self as GetToInt>::R;
|
||||
}
|
||||
|
||||
fn test() -> Result<(), ()> {
|
||||
Err(FromError::from_error(()))
|
||||
fn foo<G>(g: G) -> int
|
||||
where G : GetToInt
|
||||
{
|
||||
ToInt::to_int(&g.get()) //~ ERROR not implemented
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let result = (|| Err(FromError::from_error(())))();
|
||||
let foo: () = result.unwrap_or(());
|
||||
fn bar<G : GetToInt>(g: G) -> int
|
||||
where G::R : ToInt
|
||||
{
|
||||
ToInt::to_int(&g.get()) // OK
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
}
|
|
@ -8,6 +8,11 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Test an example where we fail to infer the type parameter H. This
|
||||
// is because there is really nothing constraining it. At one time, we
|
||||
// would infer based on the where clauses in scope, but that no longer
|
||||
// works.
|
||||
|
||||
trait Hash<H> {
|
||||
fn hash2(&self, hasher: &H) -> u64;
|
||||
}
|
||||
|
@ -30,7 +35,7 @@ trait StreamHash<S: Stream, H: StreamHasher<S>>: Hash<H> {
|
|||
impl<S: Stream, H: StreamHasher<S>> Hash<H> for u8 {
|
||||
fn hash2(&self, hasher: &H) -> u64 {
|
||||
let mut stream = hasher.stream();
|
||||
self.input_stream(&mut stream);
|
||||
self.input_stream(&mut stream); //~ ERROR type annotations required
|
||||
stream.result()
|
||||
}
|
||||
}
|
53
src/test/run-pass/associated-types-bound.rs
Normal file
53
src/test/run-pass/associated-types-bound.rs
Normal file
|
@ -0,0 +1,53 @@
|
|||
// 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.
|
||||
|
||||
// Test equality constraints on associated types in a where clause.
|
||||
|
||||
#![feature(associated_types)]
|
||||
|
||||
pub trait ToInt {
|
||||
fn to_int(&self) -> int;
|
||||
}
|
||||
|
||||
impl ToInt for int {
|
||||
fn to_int(&self) -> int { *self }
|
||||
}
|
||||
|
||||
impl ToInt for uint {
|
||||
fn to_int(&self) -> int { *self as int }
|
||||
}
|
||||
|
||||
pub trait GetToInt
|
||||
{
|
||||
type R : ToInt;
|
||||
|
||||
fn get(&self) -> <Self as GetToInt>::R;
|
||||
}
|
||||
|
||||
impl GetToInt for int {
|
||||
type R = int;
|
||||
fn get(&self) -> int { *self }
|
||||
}
|
||||
|
||||
impl GetToInt for uint {
|
||||
type R = uint;
|
||||
fn get(&self) -> uint { *self }
|
||||
}
|
||||
|
||||
fn foo<G>(g: G) -> int
|
||||
where G : GetToInt
|
||||
{
|
||||
ToInt::to_int(&g.get())
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
assert_eq!(foo(22i), 22i);
|
||||
assert_eq!(foo(22u), 22i);
|
||||
}
|
Loading…
Reference in a new issue