diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index c189aed05ab..0a001d47504 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -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") diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index 4ca98a6de64..9670ebdb03c 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -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; } diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 1aa9adaf9ec..9704439c468 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -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 diff --git a/src/test/run-pass/multidispatch-infer-from-single-impl.rs b/src/test/compile-fail/associated-types-bound-failure.rs similarity index 51% rename from src/test/run-pass/multidispatch-infer-from-single-impl.rs rename to src/test/compile-fail/associated-types-bound-failure.rs index f4ca67548fd..7981fe31827 100644 --- a/src/test/run-pass/multidispatch-infer-from-single-impl.rs +++ b/src/test/compile-fail/associated-types-bound-failure.rs @@ -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 { - fn from_error(err: E) -> Self; +#![feature(associated_types)] + +pub trait ToInt { + fn to_int(&self) -> int; } -impl FromError for E { - fn from_error(err: E) -> E { - err - } +pub trait GetToInt +{ + type R; + + fn get(&self) -> ::R; } -fn test() -> Result<(), ()> { - Err(FromError::from_error(())) +fn foo(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: G) -> int + where G::R : ToInt +{ + ToInt::to_int(&g.get()) // OK +} + +pub fn main() { } diff --git a/src/test/run-pass/issue-12028.rs b/src/test/compile-fail/issue-12028.rs similarity index 79% rename from src/test/run-pass/issue-12028.rs rename to src/test/compile-fail/issue-12028.rs index dbfa330d33d..78502efdec5 100644 --- a/src/test/run-pass/issue-12028.rs +++ b/src/test/compile-fail/issue-12028.rs @@ -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 { fn hash2(&self, hasher: &H) -> u64; } @@ -30,7 +35,7 @@ trait StreamHash>: Hash { impl> Hash 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() } } diff --git a/src/test/run-pass/associated-types-bound.rs b/src/test/run-pass/associated-types-bound.rs new file mode 100644 index 00000000000..db5119132cc --- /dev/null +++ b/src/test/run-pass/associated-types-bound.rs @@ -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 or the MIT license +// , 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) -> ::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) -> int + where G : GetToInt +{ + ToInt::to_int(&g.get()) +} + +pub fn main() { + assert_eq!(foo(22i), 22i); + assert_eq!(foo(22u), 22i); +}