]> git.lizzy.rs Git - rust.git/commitdiff
rollup merge of #18266 : nick29581/vtable2.rs
authorAlex Crichton <alex@alexcrichton.com>
Mon, 27 Oct 2014 16:07:13 +0000 (09:07 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Mon, 27 Oct 2014 19:53:02 +0000 (12:53 -0700)
src/librustc/middle/typeck/check/method.rs
src/librustc/middle/typeck/check/mod.rs
src/librustc/middle/typeck/check/regionck.rs
src/librustc/middle/typeck/check/vtable.rs [new file with mode: 0644]
src/librustc/middle/typeck/check/vtable2.rs [deleted file]
src/librustc/middle/typeck/check/wf.rs

index cb2f1e010ac6e6ed719557f56569a850b311a34f..b1684cae95d404d5a6dcb940fe2ee0a307c6baeb 100644 (file)
@@ -88,7 +88,7 @@ trait `ToString` imported, and I call `to_string()` on a value of type `T`,
 use middle::typeck::astconv::AstConv;
 use middle::typeck::check::{FnCtxt, NoPreference, PreferMutLvalue};
 use middle::typeck::check::{impl_self_ty};
-use middle::typeck::check::vtable2::select_fcx_obligations_where_possible;
+use middle::typeck::check::vtable::select_fcx_obligations_where_possible;
 use middle::typeck::check;
 use middle::typeck::infer;
 use middle::typeck::{MethodCall, MethodCallee};
index 5ad68544570d168646c5d6b7dbb66544028d718b..3d1385bac3bf52f369b315d9b036dec8c2b70a03 100644 (file)
 use syntax;
 
 pub mod _match;
-pub mod vtable2; // New trait code
+pub mod vtable;
 pub mod writeback;
 pub mod regionmanip;
 pub mod regionck;
@@ -409,7 +409,7 @@ fn check_bare_fn(ccx: &CrateCtxt,
             let fcx = check_fn(ccx, fn_ty.fn_style, id, &fn_ty.sig,
                                decl, id, body, &inh);
 
-            vtable2::select_all_fcx_obligations_or_error(&fcx);
+            vtable::select_all_fcx_obligations_or_error(&fcx);
             regionck::regionck_fn(&fcx, id, body);
             writeback::resolve_type_vars_in_fn(&fcx, decl, body);
         }
@@ -1372,7 +1372,7 @@ fn check_cast(fcx: &FnCtxt,
 
     if ty::type_is_trait(t_1) {
         // This will be looked up later on.
-        vtable2::check_object_cast(fcx, cast_expr, e, t_1);
+        vtable::check_object_cast(fcx, cast_expr, e, t_1);
         fcx.write_ty(id, t_1);
         return
     }
@@ -1677,7 +1677,7 @@ fn register_unsize_obligations(&self,
             ty::UnsizeVtable(ref ty_trait, self_ty) => {
                 // If the type is `Foo+'a`, ensures that the type
                 // being cast to `Foo+'a` implements `Foo`:
-                vtable2::register_object_cast_obligations(self,
+                vtable::register_object_cast_obligations(self,
                                                           span,
                                                           ty_trait,
                                                           self_ty);
@@ -2564,7 +2564,7 @@ fn check_argument_types<'a>(fcx: &FnCtxt,
         // an "opportunistic" vtable resolution of any trait
         // bounds on the call.
         if check_blocks {
-            vtable2::select_fcx_obligations_where_possible(fcx);
+            vtable::select_fcx_obligations_where_possible(fcx);
         }
 
         // For variadic functions, we don't have a declared type for all of
@@ -4036,7 +4036,7 @@ fn check_struct_fields_on_error(fcx: &FnCtxt,
       ast::ExprForLoop(ref pat, ref head, ref block, _) => {
         check_expr(fcx, &**head);
         let typ = lookup_method_for_for_loop(fcx, &**head, expr.id);
-        vtable2::select_fcx_obligations_where_possible(fcx);
+        vtable::select_fcx_obligations_where_possible(fcx);
 
         let pcx = pat_ctxt {
             fcx: fcx,
@@ -4743,7 +4743,7 @@ pub fn check_const_with_ty(fcx: &FnCtxt,
 
     check_expr_with_hint(fcx, e, declty);
     demand::coerce(fcx, e.span, declty, e);
-    vtable2::select_all_fcx_obligations_or_error(fcx);
+    vtable::select_all_fcx_obligations_or_error(fcx);
     regionck::regionck_expr(fcx, e);
     writeback::resolve_type_vars_in_expr(fcx, e);
 }
index 6d135c0c90e30a5ea7612d48cd97113865ff8102..029e66eab0f984d038f9c1f0d8e6776bd99a2264 100644 (file)
@@ -126,7 +126,7 @@ fn get_i(x: &'a Bar) -> &'a int {
 use middle::typeck::astconv::AstConv;
 use middle::typeck::check::FnCtxt;
 use middle::typeck::check::regionmanip;
-use middle::typeck::check::vtable2;
+use middle::typeck::check::vtable;
 use middle::typeck::infer::resolve_and_force_all_but_regions;
 use middle::typeck::infer::resolve_type;
 use middle::typeck::infer;
@@ -172,7 +172,7 @@ pub fn regionck_fn(fcx: &FnCtxt, id: ast::NodeId, blk: &ast::Block) {
 
     // Region checking a fn can introduce new trait obligations,
     // particularly around closure bounds.
-    vtable2::select_all_fcx_obligations_or_error(fcx);
+    vtable::select_all_fcx_obligations_or_error(fcx);
 
     fcx.infcx().resolve_regions_and_report_errors();
 }
diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs
new file mode 100644 (file)
index 0000000..d557a2b
--- /dev/null
@@ -0,0 +1,415 @@
+// 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.
+
+use middle::subst::{SelfSpace};
+use middle::traits;
+use middle::traits::{SelectionError, OutputTypeParameterMismatch, Overflow, Unimplemented};
+use middle::traits::{Obligation, obligation_for_builtin_bound};
+use middle::traits::{FulfillmentError, CodeSelectionError, CodeAmbiguity};
+use middle::traits::{ObligationCause};
+use middle::ty;
+use middle::typeck::check::{FnCtxt,
+                            structurally_resolved_type};
+use middle::typeck::infer;
+use std::rc::Rc;
+use syntax::ast;
+use syntax::codemap::Span;
+use util::ppaux::UserString;
+use util::ppaux::Repr;
+
+pub fn check_object_cast(fcx: &FnCtxt,
+                         cast_expr: &ast::Expr,
+                         source_expr: &ast::Expr,
+                         target_object_ty: ty::t)
+{
+    debug!("check_object_cast(cast_expr={}, target_object_ty={})",
+           cast_expr.repr(fcx.tcx()),
+           target_object_ty.repr(fcx.tcx()));
+
+    // Look up vtables for the type we're casting to,
+    // passing in the source and target type.  The source
+    // must be a pointer type suitable to the object sigil,
+    // e.g.: `&x as &Trait` or `box x as Box<Trait>`
+    let source_ty = fcx.expr_ty(source_expr);
+    let source_ty = structurally_resolved_type(fcx, source_expr.span, source_ty);
+    debug!("source_ty={}", source_ty.repr(fcx.tcx()));
+    match (&ty::get(source_ty).sty, &ty::get(target_object_ty).sty) {
+        (&ty::ty_uniq(referent_ty), &ty::ty_uniq(object_trait_ty)) => {
+            let object_trait = object_trait(&object_trait_ty);
+
+            // Ensure that if ~T is cast to ~Trait, then T : Trait
+            push_cast_obligation(fcx, cast_expr, object_trait, referent_ty);
+        }
+
+        (&ty::ty_rptr(referent_region, ty::mt { ty: referent_ty,
+                                                mutbl: referent_mutbl }),
+         &ty::ty_rptr(target_region, ty::mt { ty: object_trait_ty,
+                                              mutbl: target_mutbl })) =>
+        {
+            let object_trait = object_trait(&object_trait_ty);
+            if !mutability_allowed(referent_mutbl, target_mutbl) {
+                fcx.tcx().sess.span_err(source_expr.span,
+                                        "types differ in mutability");
+            } else {
+                // Ensure that if &'a T is cast to &'b Trait, then T : Trait
+                push_cast_obligation(fcx, cast_expr,
+                                     object_trait,
+                                     referent_ty);
+
+                // Ensure that if &'a T is cast to &'b Trait, then 'b <= 'a
+                infer::mk_subr(fcx.infcx(),
+                               infer::RelateObjectBound(source_expr.span),
+                               target_region,
+                               referent_region);
+            }
+        }
+
+        (_, &ty::ty_uniq(..)) => {
+            fcx.ccx.tcx.sess.span_err(
+                source_expr.span,
+                format!("can only cast an boxed pointer \
+                         to a boxed object, not a {}",
+                        ty::ty_sort_string(fcx.tcx(), source_ty)).as_slice());
+        }
+
+        (_, &ty::ty_rptr(..)) => {
+            fcx.ccx.tcx.sess.span_err(
+                source_expr.span,
+                format!("can only cast a &-pointer \
+                         to an &-object, not a {}",
+                        ty::ty_sort_string(fcx.tcx(), source_ty)).as_slice());
+        }
+
+        _ => {
+            fcx.tcx().sess.span_bug(
+                source_expr.span,
+                "expected object type");
+        }
+    }
+
+    // Because we currently give unsound lifetimes to the "t_box", I
+    // could have written &'static ty::TyTrait here, but it seems
+    // gratuitously unsafe.
+    fn object_trait<'a>(t: &'a ty::t) -> &'a ty::TyTrait {
+        match ty::get(*t).sty {
+            ty::ty_trait(ref ty_trait) => &**ty_trait,
+            _ => fail!("expected ty_trait")
+        }
+    }
+
+    fn mutability_allowed(a_mutbl: ast::Mutability,
+                          b_mutbl: ast::Mutability)
+                          -> bool {
+        a_mutbl == b_mutbl ||
+            (a_mutbl == ast::MutMutable && b_mutbl == ast::MutImmutable)
+    }
+
+    fn push_cast_obligation(fcx: &FnCtxt,
+                            cast_expr: &ast::Expr,
+                            object_trait: &ty::TyTrait,
+                            referent_ty: ty::t) {
+        let object_trait_ref =
+            register_object_cast_obligations(fcx,
+                                             cast_expr.span,
+                                             object_trait,
+                                             referent_ty);
+
+        // Finally record the object_trait_ref for use during trans
+        // (it would prob be better not to do this, but it's just kind
+        // of a pain to have to reconstruct it).
+        fcx.write_object_cast(cast_expr.id, object_trait_ref);
+    }
+}
+
+pub fn register_object_cast_obligations(fcx: &FnCtxt,
+                                        span: Span,
+                                        object_trait: &ty::TyTrait,
+                                        referent_ty: ty::t)
+                                        -> Rc<ty::TraitRef>
+{
+    // This is just for better error reporting. Kinda goofy. The object type stuff
+    // needs some refactoring so there is a more convenient type to pass around.
+    let object_trait_ty =
+        ty::mk_trait(fcx.tcx(),
+                     object_trait.def_id,
+                     object_trait.substs.clone(),
+                     object_trait.bounds);
+
+    debug!("register_object_cast_obligations: referent_ty={} object_trait_ty={}",
+           referent_ty.repr(fcx.tcx()),
+           object_trait_ty.repr(fcx.tcx()));
+
+    // Take the type parameters from the object type, but set
+    // the Self type (which is unknown, for the object type)
+    // to be the type we are casting from.
+    let mut object_substs = object_trait.substs.clone();
+    assert!(object_substs.self_ty().is_none());
+    object_substs.types.push(SelfSpace, referent_ty);
+
+    // Create the obligation for casting from T to Trait.
+    let object_trait_ref =
+        Rc::new(ty::TraitRef { def_id: object_trait.def_id,
+                               substs: object_substs });
+    let object_obligation =
+        Obligation::new(
+            ObligationCause::new(span,
+                                 traits::ObjectCastObligation(object_trait_ty)),
+            object_trait_ref.clone());
+    fcx.register_obligation(object_obligation);
+
+    // Create additional obligations for all the various builtin
+    // bounds attached to the object cast. (In other words, if the
+    // object type is Foo+Send, this would create an obligation
+    // for the Send check.)
+    for builtin_bound in object_trait.bounds.builtin_bounds.iter() {
+            let obligation = obligation_for_builtin_bound(
+                fcx.tcx(),
+                ObligationCause::new(span,
+                                     traits::ObjectCastObligation(object_trait_ty)),
+                referent_ty,
+                builtin_bound);
+            match obligation {
+                Ok(obligation) => fcx.register_obligation(obligation),
+                _ => {}
+            }
+    }
+
+    object_trait_ref
+}
+
+pub fn select_all_fcx_obligations_or_error(fcx: &FnCtxt) {
+    debug!("select_all_fcx_obligations_or_error");
+
+    let mut fulfillment_cx = fcx.inh.fulfillment_cx.borrow_mut();
+    let r = fulfillment_cx.select_all_or_error(fcx.infcx(),
+                                               &fcx.inh.param_env,
+                                               fcx);
+    match r {
+        Ok(()) => { }
+        Err(errors) => { report_fulfillment_errors(fcx, &errors); }
+    }
+}
+
+fn resolve_trait_ref(fcx: &FnCtxt, obligation: &Obligation)
+                     -> (ty::TraitRef, ty::t)
+{
+    let trait_ref =
+        fcx.infcx().resolve_type_vars_in_trait_ref_if_possible(
+            &*obligation.trait_ref);
+    let self_ty =
+        trait_ref.substs.self_ty().unwrap();
+    (trait_ref, self_ty)
+}
+
+pub fn report_fulfillment_errors(fcx: &FnCtxt,
+                                 errors: &Vec<FulfillmentError>) {
+    for error in errors.iter() {
+        report_fulfillment_error(fcx, error);
+    }
+}
+
+pub fn report_fulfillment_error(fcx: &FnCtxt,
+                                error: &FulfillmentError) {
+    match error.code {
+        CodeSelectionError(ref e) => {
+            report_selection_error(fcx, &error.obligation, e);
+        }
+        CodeAmbiguity => {
+            maybe_report_ambiguity(fcx, &error.obligation);
+        }
+    }
+}
+
+pub fn report_selection_error(fcx: &FnCtxt,
+                              obligation: &Obligation,
+                              error: &SelectionError)
+{
+    match *error {
+        Overflow => {
+            let (trait_ref, self_ty) = resolve_trait_ref(fcx, obligation);
+            fcx.tcx().sess.span_err(
+                obligation.cause.span,
+                format!(
+                    "overflow evaluating the trait `{}` for the type `{}`",
+                    trait_ref.user_string(fcx.tcx()),
+                    self_ty.user_string(fcx.tcx())).as_slice());
+            note_obligation_cause(fcx, obligation);
+        }
+        Unimplemented => {
+            let (trait_ref, self_ty) = resolve_trait_ref(fcx, obligation);
+            if !ty::type_is_error(self_ty) {
+                fcx.tcx().sess.span_err(
+                    obligation.cause.span,
+                    format!(
+                        "the trait `{}` is not implemented for the type `{}`",
+                        trait_ref.user_string(fcx.tcx()),
+                        self_ty.user_string(fcx.tcx())).as_slice());
+                note_obligation_cause(fcx, obligation);
+            }
+        }
+        OutputTypeParameterMismatch(ref expected_trait_ref, ref e) => {
+            let expected_trait_ref =
+                fcx.infcx().resolve_type_vars_in_trait_ref_if_possible(
+                    &**expected_trait_ref);
+            let (trait_ref, self_ty) = resolve_trait_ref(fcx, obligation);
+            if !ty::type_is_error(self_ty) {
+                fcx.tcx().sess.span_err(
+                    obligation.cause.span,
+                    format!(
+                        "type mismatch: the type `{}` implements the trait `{}`, \
+                         but the trait `{}` is required ({})",
+                        self_ty.user_string(fcx.tcx()),
+                        expected_trait_ref.user_string(fcx.tcx()),
+                        trait_ref.user_string(fcx.tcx()),
+                        ty::type_err_to_str(fcx.tcx(), e)).as_slice());
+                note_obligation_cause(fcx, obligation);
+            }
+        }
+    }
+}
+
+pub fn maybe_report_ambiguity(fcx: &FnCtxt, obligation: &Obligation) {
+    // Unable to successfully determine, probably means
+    // insufficient type information, but could mean
+    // ambiguous impls. The latter *ought* to be a
+    // coherence violation, so we don't report it here.
+    let (trait_ref, self_ty) = resolve_trait_ref(fcx, obligation);
+    debug!("maybe_report_ambiguity(trait_ref={}, self_ty={}, obligation={})",
+           trait_ref.repr(fcx.tcx()),
+           self_ty.repr(fcx.tcx()),
+           obligation.repr(fcx.tcx()));
+    let all_types = &trait_ref.substs.types;
+    if all_types.iter().any(|&t| ty::type_is_error(t)) {
+    } else if all_types.iter().any(|&t| ty::type_needs_infer(t)) {
+        // This is kind of a hack: it frequently happens that some earlier
+        // error prevents types from being fully inferred, and then we get
+        // a bunch of uninteresting errors saying something like "<generic
+        // #0> doesn't implement Sized".  It may even be true that we
+        // could just skip over all checks where the self-ty is an
+        // inference variable, but I was afraid that there might be an
+        // inference variable created, registered as an obligation, and
+        // then never forced by writeback, and hence by skipping here we'd
+        // be ignoring the fact that we don't KNOW the type works
+        // out. Though even that would probably be harmless, given that
+        // we're only talking about builtin traits, which are known to be
+        // inhabited. But in any case I just threw in this check for
+        // has_errors() to be sure that compilation isn't happening
+        // anyway. In that case, why inundate the user.
+        if !fcx.tcx().sess.has_errors() {
+            fcx.tcx().sess.span_err(
+                obligation.cause.span,
+                format!(
+                    "unable to infer enough type information to \
+                     locate the impl of the trait `{}` for \
+                     the type `{}`; type annotations required",
+                    trait_ref.user_string(fcx.tcx()),
+                    self_ty.user_string(fcx.tcx())).as_slice());
+            note_obligation_cause(fcx, obligation);
+        }
+    } else if !fcx.tcx().sess.has_errors() {
+         // Ambiguity. Coherence should have reported an error.
+        fcx.tcx().sess.span_bug(
+            obligation.cause.span,
+            format!(
+                "coherence failed to report ambiguity: \
+                 cannot locate the impl of the trait `{}` for \
+                 the type `{}`",
+                trait_ref.user_string(fcx.tcx()),
+                self_ty.user_string(fcx.tcx())).as_slice());
+    }
+}
+
+pub fn select_fcx_obligations_where_possible(fcx: &FnCtxt) {
+    /*! Select as many obligations as we can at present. */
+
+    match
+        fcx.inh.fulfillment_cx
+        .borrow_mut()
+        .select_where_possible(fcx.infcx(), &fcx.inh.param_env, fcx)
+    {
+        Ok(()) => { }
+        Err(errors) => { report_fulfillment_errors(fcx, &errors); }
+    }
+}
+
+fn note_obligation_cause(fcx: &FnCtxt,
+                         obligation: &Obligation) {
+    let tcx = fcx.tcx();
+    let trait_name = ty::item_path_str(tcx, obligation.trait_ref.def_id);
+    match obligation.cause.code {
+        traits::MiscObligation => { }
+        traits::ItemObligation(item_def_id) => {
+            let item_name = ty::item_path_str(tcx, item_def_id);
+            tcx.sess.span_note(
+                obligation.cause.span,
+                format!(
+                    "the trait `{}` must be implemented because it is required by `{}`",
+                    trait_name,
+                    item_name).as_slice());
+        }
+        traits::ObjectCastObligation(object_ty) => {
+            tcx.sess.span_note(
+                obligation.cause.span,
+                format!(
+                    "the trait `{}` must be implemented for the cast \
+                     to the object type `{}`",
+                    trait_name,
+                    fcx.infcx().ty_to_string(object_ty)).as_slice());
+        }
+        traits::RepeatVec => {
+            tcx.sess.span_note(
+                obligation.cause.span,
+                "the `Copy` trait is required because the \
+                 repeated element will be copied");
+        }
+        traits::VariableType(_) => {
+            tcx.sess.span_note(
+                obligation.cause.span,
+                "all local variables must have a statically known size");
+        }
+        traits::ReturnType => {
+            tcx.sess.span_note(
+                obligation.cause.span,
+                "the return type of a function must have a \
+                 statically known size");
+        }
+        traits::AssignmentLhsSized => {
+            tcx.sess.span_note(
+                obligation.cause.span,
+                "the left-hand-side of an assignment must have a statically known size");
+        }
+        traits::StructInitializerSized => {
+            tcx.sess.span_note(
+                obligation.cause.span,
+                "structs must have a statically known size to be initialized");
+        }
+        traits::DropTrait => {
+            span_note!(tcx.sess, obligation.cause.span,
+                      "cannot implement a destructor on a \
+                      structure or enumeration that does not satisfy Send");
+            span_note!(tcx.sess, obligation.cause.span,
+                       "use \"#[unsafe_destructor]\" on the implementation \
+                       to force the compiler to allow this");
+        }
+        traits::ClosureCapture(var_id, closure_span) => {
+            let name = ty::local_var_name_str(tcx, var_id);
+            span_note!(tcx.sess, closure_span,
+                       "the closure that captures `{}` requires that all captured variables \"
+                       implement the trait `{}`",
+                       name,
+                       trait_name);
+        }
+        traits::FieldSized => {
+            span_note!(tcx.sess, obligation.cause.span,
+                       "only the last field of a struct or enum variant \
+                       may have a dynamically sized type")
+        }
+    }
+}
diff --git a/src/librustc/middle/typeck/check/vtable2.rs b/src/librustc/middle/typeck/check/vtable2.rs
deleted file mode 100644 (file)
index d557a2b..0000000
+++ /dev/null
@@ -1,415 +0,0 @@
-// 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.
-
-use middle::subst::{SelfSpace};
-use middle::traits;
-use middle::traits::{SelectionError, OutputTypeParameterMismatch, Overflow, Unimplemented};
-use middle::traits::{Obligation, obligation_for_builtin_bound};
-use middle::traits::{FulfillmentError, CodeSelectionError, CodeAmbiguity};
-use middle::traits::{ObligationCause};
-use middle::ty;
-use middle::typeck::check::{FnCtxt,
-                            structurally_resolved_type};
-use middle::typeck::infer;
-use std::rc::Rc;
-use syntax::ast;
-use syntax::codemap::Span;
-use util::ppaux::UserString;
-use util::ppaux::Repr;
-
-pub fn check_object_cast(fcx: &FnCtxt,
-                         cast_expr: &ast::Expr,
-                         source_expr: &ast::Expr,
-                         target_object_ty: ty::t)
-{
-    debug!("check_object_cast(cast_expr={}, target_object_ty={})",
-           cast_expr.repr(fcx.tcx()),
-           target_object_ty.repr(fcx.tcx()));
-
-    // Look up vtables for the type we're casting to,
-    // passing in the source and target type.  The source
-    // must be a pointer type suitable to the object sigil,
-    // e.g.: `&x as &Trait` or `box x as Box<Trait>`
-    let source_ty = fcx.expr_ty(source_expr);
-    let source_ty = structurally_resolved_type(fcx, source_expr.span, source_ty);
-    debug!("source_ty={}", source_ty.repr(fcx.tcx()));
-    match (&ty::get(source_ty).sty, &ty::get(target_object_ty).sty) {
-        (&ty::ty_uniq(referent_ty), &ty::ty_uniq(object_trait_ty)) => {
-            let object_trait = object_trait(&object_trait_ty);
-
-            // Ensure that if ~T is cast to ~Trait, then T : Trait
-            push_cast_obligation(fcx, cast_expr, object_trait, referent_ty);
-        }
-
-        (&ty::ty_rptr(referent_region, ty::mt { ty: referent_ty,
-                                                mutbl: referent_mutbl }),
-         &ty::ty_rptr(target_region, ty::mt { ty: object_trait_ty,
-                                              mutbl: target_mutbl })) =>
-        {
-            let object_trait = object_trait(&object_trait_ty);
-            if !mutability_allowed(referent_mutbl, target_mutbl) {
-                fcx.tcx().sess.span_err(source_expr.span,
-                                        "types differ in mutability");
-            } else {
-                // Ensure that if &'a T is cast to &'b Trait, then T : Trait
-                push_cast_obligation(fcx, cast_expr,
-                                     object_trait,
-                                     referent_ty);
-
-                // Ensure that if &'a T is cast to &'b Trait, then 'b <= 'a
-                infer::mk_subr(fcx.infcx(),
-                               infer::RelateObjectBound(source_expr.span),
-                               target_region,
-                               referent_region);
-            }
-        }
-
-        (_, &ty::ty_uniq(..)) => {
-            fcx.ccx.tcx.sess.span_err(
-                source_expr.span,
-                format!("can only cast an boxed pointer \
-                         to a boxed object, not a {}",
-                        ty::ty_sort_string(fcx.tcx(), source_ty)).as_slice());
-        }
-
-        (_, &ty::ty_rptr(..)) => {
-            fcx.ccx.tcx.sess.span_err(
-                source_expr.span,
-                format!("can only cast a &-pointer \
-                         to an &-object, not a {}",
-                        ty::ty_sort_string(fcx.tcx(), source_ty)).as_slice());
-        }
-
-        _ => {
-            fcx.tcx().sess.span_bug(
-                source_expr.span,
-                "expected object type");
-        }
-    }
-
-    // Because we currently give unsound lifetimes to the "t_box", I
-    // could have written &'static ty::TyTrait here, but it seems
-    // gratuitously unsafe.
-    fn object_trait<'a>(t: &'a ty::t) -> &'a ty::TyTrait {
-        match ty::get(*t).sty {
-            ty::ty_trait(ref ty_trait) => &**ty_trait,
-            _ => fail!("expected ty_trait")
-        }
-    }
-
-    fn mutability_allowed(a_mutbl: ast::Mutability,
-                          b_mutbl: ast::Mutability)
-                          -> bool {
-        a_mutbl == b_mutbl ||
-            (a_mutbl == ast::MutMutable && b_mutbl == ast::MutImmutable)
-    }
-
-    fn push_cast_obligation(fcx: &FnCtxt,
-                            cast_expr: &ast::Expr,
-                            object_trait: &ty::TyTrait,
-                            referent_ty: ty::t) {
-        let object_trait_ref =
-            register_object_cast_obligations(fcx,
-                                             cast_expr.span,
-                                             object_trait,
-                                             referent_ty);
-
-        // Finally record the object_trait_ref for use during trans
-        // (it would prob be better not to do this, but it's just kind
-        // of a pain to have to reconstruct it).
-        fcx.write_object_cast(cast_expr.id, object_trait_ref);
-    }
-}
-
-pub fn register_object_cast_obligations(fcx: &FnCtxt,
-                                        span: Span,
-                                        object_trait: &ty::TyTrait,
-                                        referent_ty: ty::t)
-                                        -> Rc<ty::TraitRef>
-{
-    // This is just for better error reporting. Kinda goofy. The object type stuff
-    // needs some refactoring so there is a more convenient type to pass around.
-    let object_trait_ty =
-        ty::mk_trait(fcx.tcx(),
-                     object_trait.def_id,
-                     object_trait.substs.clone(),
-                     object_trait.bounds);
-
-    debug!("register_object_cast_obligations: referent_ty={} object_trait_ty={}",
-           referent_ty.repr(fcx.tcx()),
-           object_trait_ty.repr(fcx.tcx()));
-
-    // Take the type parameters from the object type, but set
-    // the Self type (which is unknown, for the object type)
-    // to be the type we are casting from.
-    let mut object_substs = object_trait.substs.clone();
-    assert!(object_substs.self_ty().is_none());
-    object_substs.types.push(SelfSpace, referent_ty);
-
-    // Create the obligation for casting from T to Trait.
-    let object_trait_ref =
-        Rc::new(ty::TraitRef { def_id: object_trait.def_id,
-                               substs: object_substs });
-    let object_obligation =
-        Obligation::new(
-            ObligationCause::new(span,
-                                 traits::ObjectCastObligation(object_trait_ty)),
-            object_trait_ref.clone());
-    fcx.register_obligation(object_obligation);
-
-    // Create additional obligations for all the various builtin
-    // bounds attached to the object cast. (In other words, if the
-    // object type is Foo+Send, this would create an obligation
-    // for the Send check.)
-    for builtin_bound in object_trait.bounds.builtin_bounds.iter() {
-            let obligation = obligation_for_builtin_bound(
-                fcx.tcx(),
-                ObligationCause::new(span,
-                                     traits::ObjectCastObligation(object_trait_ty)),
-                referent_ty,
-                builtin_bound);
-            match obligation {
-                Ok(obligation) => fcx.register_obligation(obligation),
-                _ => {}
-            }
-    }
-
-    object_trait_ref
-}
-
-pub fn select_all_fcx_obligations_or_error(fcx: &FnCtxt) {
-    debug!("select_all_fcx_obligations_or_error");
-
-    let mut fulfillment_cx = fcx.inh.fulfillment_cx.borrow_mut();
-    let r = fulfillment_cx.select_all_or_error(fcx.infcx(),
-                                               &fcx.inh.param_env,
-                                               fcx);
-    match r {
-        Ok(()) => { }
-        Err(errors) => { report_fulfillment_errors(fcx, &errors); }
-    }
-}
-
-fn resolve_trait_ref(fcx: &FnCtxt, obligation: &Obligation)
-                     -> (ty::TraitRef, ty::t)
-{
-    let trait_ref =
-        fcx.infcx().resolve_type_vars_in_trait_ref_if_possible(
-            &*obligation.trait_ref);
-    let self_ty =
-        trait_ref.substs.self_ty().unwrap();
-    (trait_ref, self_ty)
-}
-
-pub fn report_fulfillment_errors(fcx: &FnCtxt,
-                                 errors: &Vec<FulfillmentError>) {
-    for error in errors.iter() {
-        report_fulfillment_error(fcx, error);
-    }
-}
-
-pub fn report_fulfillment_error(fcx: &FnCtxt,
-                                error: &FulfillmentError) {
-    match error.code {
-        CodeSelectionError(ref e) => {
-            report_selection_error(fcx, &error.obligation, e);
-        }
-        CodeAmbiguity => {
-            maybe_report_ambiguity(fcx, &error.obligation);
-        }
-    }
-}
-
-pub fn report_selection_error(fcx: &FnCtxt,
-                              obligation: &Obligation,
-                              error: &SelectionError)
-{
-    match *error {
-        Overflow => {
-            let (trait_ref, self_ty) = resolve_trait_ref(fcx, obligation);
-            fcx.tcx().sess.span_err(
-                obligation.cause.span,
-                format!(
-                    "overflow evaluating the trait `{}` for the type `{}`",
-                    trait_ref.user_string(fcx.tcx()),
-                    self_ty.user_string(fcx.tcx())).as_slice());
-            note_obligation_cause(fcx, obligation);
-        }
-        Unimplemented => {
-            let (trait_ref, self_ty) = resolve_trait_ref(fcx, obligation);
-            if !ty::type_is_error(self_ty) {
-                fcx.tcx().sess.span_err(
-                    obligation.cause.span,
-                    format!(
-                        "the trait `{}` is not implemented for the type `{}`",
-                        trait_ref.user_string(fcx.tcx()),
-                        self_ty.user_string(fcx.tcx())).as_slice());
-                note_obligation_cause(fcx, obligation);
-            }
-        }
-        OutputTypeParameterMismatch(ref expected_trait_ref, ref e) => {
-            let expected_trait_ref =
-                fcx.infcx().resolve_type_vars_in_trait_ref_if_possible(
-                    &**expected_trait_ref);
-            let (trait_ref, self_ty) = resolve_trait_ref(fcx, obligation);
-            if !ty::type_is_error(self_ty) {
-                fcx.tcx().sess.span_err(
-                    obligation.cause.span,
-                    format!(
-                        "type mismatch: the type `{}` implements the trait `{}`, \
-                         but the trait `{}` is required ({})",
-                        self_ty.user_string(fcx.tcx()),
-                        expected_trait_ref.user_string(fcx.tcx()),
-                        trait_ref.user_string(fcx.tcx()),
-                        ty::type_err_to_str(fcx.tcx(), e)).as_slice());
-                note_obligation_cause(fcx, obligation);
-            }
-        }
-    }
-}
-
-pub fn maybe_report_ambiguity(fcx: &FnCtxt, obligation: &Obligation) {
-    // Unable to successfully determine, probably means
-    // insufficient type information, but could mean
-    // ambiguous impls. The latter *ought* to be a
-    // coherence violation, so we don't report it here.
-    let (trait_ref, self_ty) = resolve_trait_ref(fcx, obligation);
-    debug!("maybe_report_ambiguity(trait_ref={}, self_ty={}, obligation={})",
-           trait_ref.repr(fcx.tcx()),
-           self_ty.repr(fcx.tcx()),
-           obligation.repr(fcx.tcx()));
-    let all_types = &trait_ref.substs.types;
-    if all_types.iter().any(|&t| ty::type_is_error(t)) {
-    } else if all_types.iter().any(|&t| ty::type_needs_infer(t)) {
-        // This is kind of a hack: it frequently happens that some earlier
-        // error prevents types from being fully inferred, and then we get
-        // a bunch of uninteresting errors saying something like "<generic
-        // #0> doesn't implement Sized".  It may even be true that we
-        // could just skip over all checks where the self-ty is an
-        // inference variable, but I was afraid that there might be an
-        // inference variable created, registered as an obligation, and
-        // then never forced by writeback, and hence by skipping here we'd
-        // be ignoring the fact that we don't KNOW the type works
-        // out. Though even that would probably be harmless, given that
-        // we're only talking about builtin traits, which are known to be
-        // inhabited. But in any case I just threw in this check for
-        // has_errors() to be sure that compilation isn't happening
-        // anyway. In that case, why inundate the user.
-        if !fcx.tcx().sess.has_errors() {
-            fcx.tcx().sess.span_err(
-                obligation.cause.span,
-                format!(
-                    "unable to infer enough type information to \
-                     locate the impl of the trait `{}` for \
-                     the type `{}`; type annotations required",
-                    trait_ref.user_string(fcx.tcx()),
-                    self_ty.user_string(fcx.tcx())).as_slice());
-            note_obligation_cause(fcx, obligation);
-        }
-    } else if !fcx.tcx().sess.has_errors() {
-         // Ambiguity. Coherence should have reported an error.
-        fcx.tcx().sess.span_bug(
-            obligation.cause.span,
-            format!(
-                "coherence failed to report ambiguity: \
-                 cannot locate the impl of the trait `{}` for \
-                 the type `{}`",
-                trait_ref.user_string(fcx.tcx()),
-                self_ty.user_string(fcx.tcx())).as_slice());
-    }
-}
-
-pub fn select_fcx_obligations_where_possible(fcx: &FnCtxt) {
-    /*! Select as many obligations as we can at present. */
-
-    match
-        fcx.inh.fulfillment_cx
-        .borrow_mut()
-        .select_where_possible(fcx.infcx(), &fcx.inh.param_env, fcx)
-    {
-        Ok(()) => { }
-        Err(errors) => { report_fulfillment_errors(fcx, &errors); }
-    }
-}
-
-fn note_obligation_cause(fcx: &FnCtxt,
-                         obligation: &Obligation) {
-    let tcx = fcx.tcx();
-    let trait_name = ty::item_path_str(tcx, obligation.trait_ref.def_id);
-    match obligation.cause.code {
-        traits::MiscObligation => { }
-        traits::ItemObligation(item_def_id) => {
-            let item_name = ty::item_path_str(tcx, item_def_id);
-            tcx.sess.span_note(
-                obligation.cause.span,
-                format!(
-                    "the trait `{}` must be implemented because it is required by `{}`",
-                    trait_name,
-                    item_name).as_slice());
-        }
-        traits::ObjectCastObligation(object_ty) => {
-            tcx.sess.span_note(
-                obligation.cause.span,
-                format!(
-                    "the trait `{}` must be implemented for the cast \
-                     to the object type `{}`",
-                    trait_name,
-                    fcx.infcx().ty_to_string(object_ty)).as_slice());
-        }
-        traits::RepeatVec => {
-            tcx.sess.span_note(
-                obligation.cause.span,
-                "the `Copy` trait is required because the \
-                 repeated element will be copied");
-        }
-        traits::VariableType(_) => {
-            tcx.sess.span_note(
-                obligation.cause.span,
-                "all local variables must have a statically known size");
-        }
-        traits::ReturnType => {
-            tcx.sess.span_note(
-                obligation.cause.span,
-                "the return type of a function must have a \
-                 statically known size");
-        }
-        traits::AssignmentLhsSized => {
-            tcx.sess.span_note(
-                obligation.cause.span,
-                "the left-hand-side of an assignment must have a statically known size");
-        }
-        traits::StructInitializerSized => {
-            tcx.sess.span_note(
-                obligation.cause.span,
-                "structs must have a statically known size to be initialized");
-        }
-        traits::DropTrait => {
-            span_note!(tcx.sess, obligation.cause.span,
-                      "cannot implement a destructor on a \
-                      structure or enumeration that does not satisfy Send");
-            span_note!(tcx.sess, obligation.cause.span,
-                       "use \"#[unsafe_destructor]\" on the implementation \
-                       to force the compiler to allow this");
-        }
-        traits::ClosureCapture(var_id, closure_span) => {
-            let name = ty::local_var_name_str(tcx, var_id);
-            span_note!(tcx.sess, closure_span,
-                       "the closure that captures `{}` requires that all captured variables \"
-                       implement the trait `{}`",
-                       name,
-                       trait_name);
-        }
-        traits::FieldSized => {
-            span_note!(tcx.sess, obligation.cause.span,
-                       "only the last field of a struct or enum variant \
-                       may have a dynamically sized type")
-        }
-    }
-}
index dc79fd4aa328c151fdf75d200069f08f96ae2630..3c594fbf2d3661ea4277cdfe79dd34d41092b48e 100644 (file)
@@ -14,7 +14,7 @@
 use middle::ty;
 use middle::ty_fold::{TypeFolder, TypeFoldable};
 use middle::typeck::astconv::AstConv;
-use middle::typeck::check::{FnCtxt, Inherited, blank_fn_ctxt, vtable2, regionck};
+use middle::typeck::check::{FnCtxt, Inherited, blank_fn_ctxt, vtable, regionck};
 use middle::typeck::check::regionmanip::replace_late_bound_regions;
 use middle::typeck::CrateCtxt;
 use util::ppaux::Repr;
@@ -100,7 +100,7 @@ fn with_fcx(&mut self,
         let inh = Inherited::new(ccx.tcx, param_env);
         let fcx = blank_fn_ctxt(ccx, &inh, polytype.ty, item.id);
         f(self, &fcx);
-        vtable2::select_all_fcx_obligations_or_error(&fcx);
+        vtable::select_all_fcx_obligations_or_error(&fcx);
         regionck::regionck_item(&fcx, item);
     }