This commit is contained in:
Nick Cameron 2015-04-10 12:25:40 +12:00
parent 4e8e64140f
commit 73c2e768d6
10 changed files with 56 additions and 72 deletions

View File

@ -70,7 +70,7 @@ use option::Option::{self, Some, None};
use marker::Sized;
use usize;
fn _assert_is_object_safe(_: &Iterator) {}
fn _assert_is_object_safe(_: &Iterator<Item=()>) {}
/// An interface for dealing with "external iterators". These types of iterators
/// can be resumed at any time as all state is stored internally as opposed to

View File

@ -799,18 +799,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
self.delegate_consume(expr.id, expr.span, cmt_unadjusted);
}
ty::AdjustDerefRef(ref adj) => {
self.walk_autoderefs(expr, adj.autoderefs);
if let Some(ref r) = adj.autoref {
self.walk_autoref(expr, r, adj.autoderefs);
} else if adj.unsize.is_some() {
assert!(adj.autoderefs == 0,
format!("Expected no derefs with \
unsize AutoRefs, found: {}",
adj.repr(self.tcx())));
let cmt_unadjusted =
return_if_err!(self.mc.cat_expr_unadjusted(expr));
self.delegate_consume(expr.id, expr.span, cmt_unadjusted);
}
self.walk_autoderefref(expr, adj);
}
}
}
@ -860,29 +849,29 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
self.walk_autoderefs(expr, adj.autoderefs);
// Weird hacky special case: AutoUnsizeUniq, which converts
// from a ~T to a ~Trait etc, always comes in a stylized
// from a Box<T> to a Box<Trait> etc, always comes in a stylized
// fashion. In particular, we want to consume the ~ pointer
// being dereferenced, not the dereferenced content (as the
// content is, at least for upcasts, unsized).
match adj.autoref {
Some(ty::AutoUnsizeUniq(_)) => {
assert!(adj.autoderefs == 1,
format!("Expected exactly 1 deref with Uniq AutoRefs, found: {}",
adj.autoderefs));
if let Some(ty) = adj.unsize {
if let ty::ty_uniq(_) = ty.sty {
assert!(adj.autoderefs == 0,
format!("Expected no derefs with unsize AutoRefs, found: {}",
adj.repr(self.tcx())));
let cmt_unadjusted =
return_if_err!(self.mc.cat_expr_unadjusted(expr));
self.delegate_consume(expr.id, expr.span, cmt_unadjusted);
return;
}
_ => { }
}
let autoref = adj.autoref.as_ref();
//let autoref = adj.autoref.as_ref();
let cmt_derefd = return_if_err!(
self.mc.cat_expr_autoderefd(expr, adj.autoderefs));
self.walk_autoref(expr, &cmt_derefd, autoref);
self.walk_autoref(expr, cmt_derefd, adj.autoref);
}
/// Walks the autoref `opt_autoref` applied to the autoderef'd
/// `expr`. `cmt_derefd` is the mem-categorized form of `expr`
/// after all relevant autoderefs have occurred. Because AutoRefs
@ -893,25 +882,25 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
/// autoref.
fn walk_autoref(&mut self,
expr: &ast::Expr,
cmt_derefd: &mc::cmt<'tcx>,
opt_autoref: Option<&ty::AutoRef<'tcx>>)
cmt_base: mc::cmt<'tcx>,
opt_autoref: Option<ty::AutoRef<'tcx>>)
-> mc::cmt<'tcx>
{
debug!("walk_autoref(expr.id={} cmt_derefd={} opt_autoref={:?})",
expr.id,
cmt_derefd.repr(self.tcx()),
cmt_base.repr(self.tcx()),
opt_autoref);
let cmt_base_ty = cmt_base.ty;
let autoref = match opt_autoref {
Some(autoref) => autoref,
Some(ref autoref) => autoref,
None => {
// No recursive step here, this is a base case.
return cmt_derefd.clone();
// No AutoRef.
return cmt_base;
}
};
let cmt_base = self.walk_autoref_recursively(expr, cmt_derefd, baseref);
debug!("walk_autoref: expr.id={} cmt_base={}",
expr.id,
cmt_base.repr(self.tcx()));
@ -920,15 +909,13 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
ty::AutoPtr(r, m) => {
self.delegate.borrow(expr.id,
expr.span,
cmt_derefd,
cmt_base,
*r,
ty::BorrowKind::from_mutbl(m),
AutoRef);
}
ty::AutoUnsafe(m, ref baseref) => {
let cmt_base = self.walk_autoref_recursively(expr, cmt_derefd, baseref);
ty::AutoUnsafe(m) => {
debug!("walk_autoref: expr.id={} cmt_base={}",
expr.id,
cmt_base.repr(self.tcx()));
@ -953,24 +940,12 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
let adj_ty =
ty::adjust_ty_for_autoref(self.tcx(),
expr.span,
cmt_derefd.ty,
cmt_base_ty,
opt_autoref);
self.mc.cat_rvalue_node(expr.id, expr.span, adj_ty)
}
fn walk_autoref_recursively(&mut self,
expr: &ast::Expr,
cmt_derefd: &mc::cmt<'tcx>,
autoref: &Option<Box<ty::AutoRef<'tcx>>>)
-> mc::cmt<'tcx>
{
// Shuffle from a ref to an optional box to an optional ref.
let autoref: Option<&ty::AutoRef<'tcx>> = autoref.as_ref().map(|b| &**b);
self.walk_autoref(expr, cmt_derefd, autoref)
}
// When this returns true, it means that the expression *is* a
// method-call (i.e. via the operator-overload). This true result

View File

@ -290,6 +290,12 @@ pub enum AutoAdjustment<'tcx> {
#[derive(Copy, Clone, Debug)]
pub struct AutoDerefRef<'tcx> {
// FIXME with more powerful date structures we could have a better design
// here. Some constraints:
// unsize => autoref
// unsize => autodefs == 0
/// Apply a number of dereferences, producing an lvalue.
pub autoderefs: usize,
@ -303,11 +309,11 @@ pub struct AutoDerefRef<'tcx> {
#[derive(Copy, Clone, PartialEq, Debug)]
pub enum AutoRef<'tcx> {
/// Convert from T to &T
/// Convert from T to &T.
AutoPtr(&'tcx Region, ast::Mutability),
/// Convert from T to *T
/// Value to thin pointer
/// Convert from T to *T.
/// Value to thin pointer.
AutoUnsafe(ast::Mutability),
}
@ -407,7 +413,7 @@ impl MethodCall {
}
}
pub fn autoderef(expr_id: ast::NodeId, autoderef: usize) -> MethodCall {
pub fn autoderef(expr_id: ast::NodeId, autoderef: u32) -> MethodCall {
MethodCall {
expr_id: expr_id,
autoderef: 1 + autoderef
@ -4487,8 +4493,8 @@ pub fn adjust_ty<'tcx, F>(cx: &ctxt<'tcx>,
let method_call = MethodCall::autoderef(expr_id, i as u32);
match method_type(method_call) {
Some(method_ty) => {
// overloaded deref operators have all late-bound
// regions fully instantiated and coverge
// Overloaded deref operators have all late-bound
// regions fully instantiated and coverge.
let fn_ret =
ty::no_late_bound_regions(cx,
&ty_fn_ret(method_ty)).unwrap();
@ -4501,8 +4507,7 @@ pub fn adjust_ty<'tcx, F>(cx: &ctxt<'tcx>,
None => {
cx.sess.span_bug(
span,
&format!("the {}th autoderef failed: \
{}",
&format!("the {}th autoderef failed: {}",
i,
ty_to_string(cx, adjusted_ty))
);

View File

@ -79,7 +79,6 @@ use syntax::ast;
struct Coerce<'a, 'tcx: 'a> {
fcx: &'a FnCtxt<'a, 'tcx>,
origin: infer::TypeOrigin,
trace: TypeTrace<'tcx>,
unsizing_obligation: Cell<Option<Ty<'tcx>>>
}
@ -266,7 +265,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
if let Some(target) = self.unsize_ty(mt_a.ty, mt_b.ty) {
try!(coerce_mutbls(mt_a.mutbl, mt_b.mutbl));
let coercion = Coercion(self.trace.clone());
let coercion = Coercion(self.origin.span());
let r_borrow = self.fcx.infcx().next_region_var(coercion);
let region = self.tcx().mk_region(r_borrow);
(Some(ty::AutoPtr(region, mt_b.mutbl)), target)
@ -293,7 +292,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
};
let target = ty::adjust_ty_for_autoref(self.tcx(), target, reborrow);
try!(self.fcx.infcx().try(|_| self.subtype(target, b)));
try!(self.subtype(target, b));
let adjustment = AutoDerefRef {
autoderefs: if reborrow.is_some() { 1 } else { 0 },
autoref: reborrow,
@ -374,7 +373,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
assert!(ty_substs_a.len() == ty_substs_b.len());
let tps = ty_substs_a.iter().zip(ty_substs_b.iter()).enumerate();
for (i, (&tp_a, &tp_b)) in tps {
for (i, (tp_a, tp_b)) in tps {
if self.subtype(*tp_a, *tp_b).is_ok() {
continue;
}
@ -498,12 +497,10 @@ pub fn mk_assignty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
-> RelateResult<'tcx, ()> {
debug!("mk_assignty({} -> {})", a.repr(fcx.tcx()), b.repr(fcx.tcx()));
let (adjustment, unsizing_obligation) = try!(indent(|| {
fcx.infcx().commit_if_ok(|| {
let origin = infer::ExprAssignable(expr.span);
fcx.infcx().commit_if_ok(|_| {
let coerce = Coerce {
fcx: fcx,
origin: infer::ExprAssignable(expr.span),
trace: infer::TypeTrace::types(origin, false, a, b),
unsizing_obligation: Cell::new(None)
};
Ok((try!(coerce.coerce(expr, a, b)),

View File

@ -313,9 +313,15 @@ fn lookup_op_method<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>,
let method = match trait_did {
Some(trait_did) => {
let noop = ty::AutoDerefRef { autoderefs: 0, autoref: None };
method::lookup_in_trait_adjusted(fcx, expr.span, Some(lhs_expr), opname,
trait_did, noop, lhs_ty, Some(other_tys))
method::lookup_in_trait_adjusted(fcx,
expr.span,
Some(lhs_expr),
opname,
trait_did,
0,
false,
lhs_ty,
Some(other_tys))
}
None => None
};

View File

@ -1134,7 +1134,7 @@ fn link_autoref(rcx: &Rcx,
ty::AutoUnsafe(m) => {
let r = ty::ReScope(CodeExtent::from_node_id(expr.id));
link_region(rcx, expr.span, r, ty::BorrowKind::from_mutbl(m), expr_cmt);
link_region(rcx, expr.span, &r, ty::BorrowKind::from_mutbl(m), expr_cmt);
}
}
}

View File

@ -13,7 +13,6 @@ use middle::traits::{self, ObjectSafetyViolation, MethodViolationCode};
use middle::traits::{Obligation, ObligationCause};
use middle::traits::report_fulfillment_errors;
use middle::ty::{self, Ty, AsPredicate};
use syntax::ast;
use syntax::codemap::Span;
use util::ppaux::{Repr, UserString};

View File

@ -34,8 +34,9 @@ fn dent<C:BoxCar>(c: C, color: C::Color) {
fn dent_object<COLOR>(c: BoxCar<Color=COLOR>) {
//~^ ERROR ambiguous associated type
//~| ERROR the associated type `Color` (from the trait `Box`) must be specified
//~| ERROR the associated type `Color` (from the trait `Vehicle`) must be specified
//~| ERROR the value of the associated type `Color` (from the trait `Vehicle`) must be specified
//~| NOTE could derive from `Vehicle`
//~| NOTE could derive from `Box`
}
fn paint<C:BoxCar>(c: C, d: C::Color) {

View File

@ -14,6 +14,7 @@ use std::ops::{Add, Sub};
type Test = Add +
//~^ ERROR the type parameter `RHS` must be explicitly specified in an object type because its default value `Self` references the type `Self`
//~^^ ERROR the value of the associated type `Output` (from the trait `core::ops::Add`) must be specified [E0191]
Sub;
//~^ ERROR only the builtin traits can be used as closure or object bounds

View File

@ -10,7 +10,7 @@
#![ crate_name = "test" ]
#![allow(unstable)]
#![feature(box_syntax, old_io, rustc_private, core)]
#![feature(box_syntax, old_io, rustc_private, core, zero_one)]
extern crate graphviz;
// A simple rust project
@ -25,7 +25,7 @@ use std::old_io::stdio::println;
use sub::sub2 as msalias;
use sub::sub2;
use sub::sub2::nested_struct as sub_struct;
use std::num::Float;
use std::num::One;
use std::num::cast;
use std::num::{from_int,from_i8,from_i32};
@ -42,7 +42,7 @@ fn test_alias<I: Iterator>(i: Option<<I as Iterator>::Item>) {
let s = sub_struct{ field2: 45, };
// import tests
fn foo(x: &Float) {}
fn foo(x: &One) {}
let _: Option<u8> = from_i32(45);
let x = 42;