*/
+pub use self::LvaluePreference::*;
+pub use self::DerefArgs::*;
+pub use self::Expectation::*;
+use self::IsBinopAssignment::*;
+use self::TupleArgumentsFlag::*;
-use driver::session::Session;
+use session::Session;
use middle::const_eval;
use middle::def;
use middle::lang_items::IteratorItem;
use middle::mem_categorization;
use middle::pat_util::pat_id_map;
use middle::pat_util;
+use middle::region::CodeExtent;
use middle::subst;
use middle::subst::{Subst, Substs, VecPerParamSpace, ParamSpace};
use middle::traits;
use middle::ty::{FnSig, VariantInfo};
use middle::ty::{Polytype};
use middle::ty::{Disr, ParamTy, ParameterEnvironment};
-use middle::ty;
+use middle::ty::{mod, Ty};
+use middle::ty::liberate_late_bound_regions;
use middle::ty_fold::TypeFolder;
use middle::typeck::astconv::AstConv;
use middle::typeck::astconv::{ast_region_to_region, ast_ty_to_ty};
use middle::typeck::astconv;
use middle::typeck::check::_match::pat_ctxt;
-use middle::typeck::check::method::{AutoderefReceiver};
-use middle::typeck::check::method::{CheckTraitsAndInherentMethods};
-use middle::typeck::check::regionmanip::replace_late_bound_regions;
use middle::typeck::CrateCtxt;
use middle::typeck::infer;
use middle::typeck::rscope::RegionScope;
pub mod demand;
pub mod method;
pub mod wf;
+mod closure;
/// Fields that are part of a `FnCtxt` which are inherited by
/// closures defined within the function. For example:
/// share the inherited fields.
pub struct Inherited<'a, 'tcx: 'a> {
infcx: infer::InferCtxt<'a, 'tcx>,
- locals: RefCell<NodeMap<ty::t>>,
- param_env: ty::ParameterEnvironment,
+ locals: RefCell<NodeMap<Ty<'tcx>>>,
+ param_env: ty::ParameterEnvironment<'tcx>,
// Temporary tables:
- node_types: RefCell<NodeMap<ty::t>>,
- item_substs: RefCell<NodeMap<ty::ItemSubsts>>,
- adjustments: RefCell<NodeMap<ty::AutoAdjustment>>,
- method_map: MethodMap,
+ node_types: RefCell<NodeMap<Ty<'tcx>>>,
+ item_substs: RefCell<NodeMap<ty::ItemSubsts<'tcx>>>,
+ adjustments: RefCell<NodeMap<ty::AutoAdjustment<'tcx>>>,
+ method_map: MethodMap<'tcx>,
upvar_borrow_map: RefCell<ty::UpvarBorrowMap>,
- unboxed_closures: RefCell<DefIdMap<ty::UnboxedClosure>>,
- object_cast_map: ObjectCastMap,
+ unboxed_closures: RefCell<DefIdMap<ty::UnboxedClosure<'tcx>>>,
+ object_cast_map: ObjectCastMap<'tcx>,
// A mapping from each fn's id to its signature, with all bound
// regions replaced with free ones. Unlike the other tables, this
// one is never copied into the tcx: it is only used by regionck.
- fn_sig_map: RefCell<NodeMap<Vec<ty::t>>>,
+ fn_sig_map: RefCell<NodeMap<Vec<Ty<'tcx>>>>,
// A set of constraints that regionck must validate. Each
// constraint has the form `T:'a`, meaning "some type `T` must
// regionck to be sure that it has found *all* the region
// obligations (otherwise, it's easy to fail to walk to a
// particular node-id).
- region_obligations: RefCell<NodeMap<Vec<RegionObligation>>>,
+ region_obligations: RefCell<NodeMap<Vec<RegionObligation<'tcx>>>>,
// Tracks trait obligations incurred during this function body.
- fulfillment_cx: RefCell<traits::FulfillmentContext>,
+ fulfillment_cx: RefCell<traits::FulfillmentContext<'tcx>>,
}
-struct RegionObligation {
+struct RegionObligation<'tcx> {
sub_region: ty::Region,
- sup_type: ty::t,
- origin: infer::SubregionOrigin,
+ sup_type: Ty<'tcx>,
+ origin: infer::SubregionOrigin<'tcx>,
}
/// When type-checking an expression, we propagate downward
/// whatever type hint we are able in the form of an `Expectation`.
-enum Expectation {
+enum Expectation<'tcx> {
/// We know nothing about what type this expression should have.
NoExpectation,
/// This expression should have the type given (or some subtype)
- ExpectHasType(ty::t),
+ ExpectHasType(Ty<'tcx>),
- /// This expression will be cast to the `ty::t`
- ExpectCastableToType(ty::t),
+ /// This expression will be cast to the `Ty`
+ ExpectCastableToType(Ty<'tcx>),
}
#[deriving(Clone)]
// expects the types within the function to be consistent.
err_count_on_creation: uint,
- ret_ty: ty::FnOutput,
+ ret_ty: ty::FnOutput<'tcx>,
ps: RefCell<FnStyleState>,
fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> {
self.ccx.tcx
}
- fn node_ty(&self, id: ast::NodeId) -> McResult<ty::t> {
+ fn node_ty(&self, id: ast::NodeId) -> McResult<Ty<'tcx>> {
Ok(self.node_ty(id))
}
fn node_method_ty(&self, method_call: typeck::MethodCall)
- -> Option<ty::t> {
+ -> Option<Ty<'tcx>> {
self.inh.method_map.borrow().get(&method_call).map(|m| m.ty)
}
- fn adjustments<'a>(&'a self) -> &'a RefCell<NodeMap<ty::AutoAdjustment>> {
+ fn adjustments<'a>(&'a self) -> &'a RefCell<NodeMap<ty::AutoAdjustment<'tcx>>> {
&self.inh.adjustments
}
fn is_method_call(&self, id: ast::NodeId) -> bool {
self.inh.method_map.borrow().contains_key(&typeck::MethodCall::expr(id))
}
- fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<ast::NodeId> {
+ fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<CodeExtent> {
self.tcx().temporary_scope(rvalue_id)
}
fn upvar_borrow(&self, upvar_id: ty::UpvarId) -> ty::UpvarBorrow {
- self.inh.upvar_borrow_map.borrow().get_copy(&upvar_id)
+ self.inh.upvar_borrow_map.borrow()[upvar_id].clone()
}
fn capture_mode(&self, closure_expr_id: ast::NodeId)
-> ast::CaptureClause {
self.ccx.tcx.capture_mode(closure_expr_id)
}
- fn unboxed_closures<'a>(&'a self) -> &'a RefCell<DefIdMap<ty::UnboxedClosure>> {
+ fn unboxed_closures<'a>(&'a self)
+ -> &'a RefCell<DefIdMap<ty::UnboxedClosure<'tcx>>> {
&self.inh.unboxed_closures
}
}
impl<'a, 'tcx> Inherited<'a, 'tcx> {
fn new(tcx: &'a ty::ctxt<'tcx>,
- param_env: ty::ParameterEnvironment)
+ param_env: ty::ParameterEnvironment<'tcx>)
-> Inherited<'a, 'tcx> {
Inherited {
infcx: infer::new_infer_ctxt(tcx),
// Used by check_const and check_enum_variants
pub fn blank_fn_ctxt<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
inh: &'a Inherited<'a, 'tcx>,
- rty: ty::FnOutput,
+ rty: ty::FnOutput<'tcx>,
body_id: ast::NodeId)
-> FnCtxt<'a, 'tcx> {
FnCtxt {
ccx.tcx.sess.abort_if_errors();
}
-fn check_bare_fn(ccx: &CrateCtxt,
- decl: &ast::FnDecl,
- body: &ast::Block,
- id: ast::NodeId,
- fty: ty::t,
- param_env: ty::ParameterEnvironment) {
+fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
+ decl: &ast::FnDecl,
+ body: &ast::Block,
+ id: ast::NodeId,
+ fty: Ty<'tcx>,
+ param_env: ty::ParameterEnvironment<'tcx>) {
// Compute the fty from point of view of inside fn
// (replace any type-scheme with a type)
let fty = fty.subst(ccx.tcx, ¶m_env.free_substs);
- match ty::get(fty).sty {
+ match fty.sty {
ty::ty_bare_fn(ref fn_ty) => {
let inh = Inherited::new(ccx.tcx, param_env);
let fcx = check_fn(ccx, fn_ty.fn_style, id, &fn_ty.sig,
}
impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> {
- fn assign(&mut self, _span: Span, nid: ast::NodeId, ty_opt: Option<ty::t>) -> ty::t {
+ fn assign(&mut self, _span: Span, nid: ast::NodeId, ty_opt: Option<Ty<'tcx>>) -> Ty<'tcx> {
match ty_opt {
None => {
// infer the variable's type
debug!("Local variable {} is assigned type {}",
self.fcx.pat_to_string(&*local.pat),
self.fcx.infcx().ty_to_string(
- self.fcx.inh.locals.borrow().get_copy(&local.id)));
+ self.fcx.inh.locals.borrow()[local.id].clone()));
visit::walk_local(self, local);
}
debug!("Pattern binding {} is assigned to {} with type {}",
token::get_ident(path1.node),
self.fcx.infcx().ty_to_string(
- self.fcx.inh.locals.borrow().get_copy(&p.id)),
+ self.fcx.inh.locals.borrow()[p.id].clone()),
var_ty.repr(self.fcx.tcx()));
}
_ => {}
fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
fn_style: ast::FnStyle,
fn_style_id: ast::NodeId,
- fn_sig: &ty::FnSig,
+ fn_sig: &ty::FnSig<'tcx>,
decl: &ast::FnDecl,
fn_id: ast::NodeId,
body: &ast::Block,
// First, we have to replace any bound regions in the fn type with free ones.
// The free region references will be bound the node_id of the body block.
- let (_, fn_sig) = replace_late_bound_regions(tcx, fn_sig.binder_id, fn_sig, |br| {
- ty::ReFree(ty::FreeRegion {scope_id: body.id, bound_region: br})
- });
+ let fn_sig = liberate_late_bound_regions(tcx, CodeExtent::from_node_id(body.id), fn_sig);
let arg_tys = fn_sig.inputs.as_slice();
let ret_ty = fn_sig.output;
};
// Remember return type so that regionck can access it later.
- let mut fn_sig_tys: Vec<ty::t> =
+ let mut fn_sig_tys: Vec<Ty> =
arg_tys.iter()
.map(|&ty| ty)
.collect();
if let ty::FnConverging(ret_ty) = ret_ty {
- fcx.require_type_is_sized(ret_ty, decl.output.span, traits::ReturnType);
+ fcx.require_type_is_sized(ret_ty, decl.output.span(), traits::ReturnType);
fn_sig_tys.push(ret_ty);
}
}
}
-fn check_method_body(ccx: &CrateCtxt,
- item_generics: &ty::Generics,
- method: &ast::Method) {
+fn check_method_body<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
+ item_generics: &ty::Generics<'tcx>,
+ method: &ast::Method) {
/*!
* Type checks a method body.
*
let param_env = ParameterEnvironment::for_item(ccx.tcx, method.id);
let fty = ty::node_id_to_type(ccx.tcx, method.id);
+ debug!("fty (raw): {}", fty.repr(ccx.tcx));
+
+ let body_id = method.pe_body().id;
+ let fty = liberate_late_bound_regions(
+ ccx.tcx, CodeExtent::from_node_id(body_id), &ty::bind(fty)).value;
+ debug!("fty (liberated): {}", fty.repr(ccx.tcx));
check_bare_fn(ccx,
&*method.pe_fn_decl(),
param_env);
}
-fn check_impl_items_against_trait(ccx: &CrateCtxt,
- impl_span: Span,
- ast_trait_ref: &ast::TraitRef,
- impl_trait_ref: &ty::TraitRef,
- impl_items: &[ast::ImplItem]) {
+fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
+ impl_span: Span,
+ ast_trait_ref: &ast::TraitRef,
+ impl_trait_ref: &ty::TraitRef<'tcx>,
+ impl_items: &[ast::ImplItem]) {
// Locate trait methods
let tcx = ccx.tcx;
let trait_items = ty::trait_items(tcx, impl_trait_ref.def_id);
impl_method.span,
impl_method.pe_body().id,
&**trait_method_ty,
- &impl_trait_ref.substs);
+ impl_trait_ref);
}
_ => {
// This is span_bug as it should have already been
* - trait_m: the method in the trait
* - trait_to_impl_substs: the substitutions used on the type of the trait
*/
-fn compare_impl_method(tcx: &ty::ctxt,
- impl_m: &ty::Method,
- impl_m_span: Span,
- impl_m_body_id: ast::NodeId,
- trait_m: &ty::Method,
- trait_to_impl_substs: &subst::Substs) {
- debug!("compare_impl_method(trait_to_impl_substs={})",
- trait_to_impl_substs.repr(tcx));
+fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
+ impl_m: &ty::Method<'tcx>,
+ impl_m_span: Span,
+ impl_m_body_id: ast::NodeId,
+ trait_m: &ty::Method<'tcx>,
+ impl_trait_ref: &ty::TraitRef<'tcx>) {
+ debug!("compare_impl_method(impl_trait_ref={})",
+ impl_trait_ref.repr(tcx));
+
+ let impl_m_body_scope = CodeExtent::from_node_id(impl_m_body_id);
+
+ // The impl's trait ref may bind late-bound regions from the impl.
+ // Liberate them and assign them the scope of the method body.
+ //
+ // An example would be:
+ //
+ // impl<'a> Foo<&'a T> for &'a U { ... }
+ //
+ // Here, the region parameter `'a` is late-bound, so the
+ // trait reference associated with the impl will be
+ //
+ // for<'a> Foo<&'a T>
+ //
+ // liberating will convert this into:
+ //
+ // Foo<&'A T>
+ //
+ // where `'A` is the `ReFree` version of `'a`.
+ let impl_trait_ref = liberate_late_bound_regions(tcx, impl_m_body_scope, impl_trait_ref);
+
+ debug!("impl_trait_ref (liberated) = {}",
+ impl_trait_ref.repr(tcx));
+
let infcx = infer::new_infer_ctxt(tcx);
+ let trait_to_impl_substs = &impl_trait_ref.substs;
+
// Try to give more informative error messages about self typing
// mismatches. Note that any mismatch will also be detected
// below, where we construct a canonical function type that
// This code is best explained by example. Consider a trait:
//
- // trait Trait<T> {
- // fn method<'a,M>(t: T, m: &'a M) -> Self;
+ // trait Trait<'t,T> {
+ // fn method<'a,M>(t: &'t T, m: &'a M) -> Self;
// }
//
// And an impl:
//
- // impl<'i, U> Trait<&'i U> for Foo {
- // fn method<'b,N>(t: &'i U, m: &'b N) -> Foo;
+ // impl<'i, 'j, U> Trait<'j, &'i U> for Foo {
+ // fn method<'b,N>(t: &'j &'i U, m: &'b N) -> Foo;
// }
//
// We wish to decide if those two method types are compatible.
//
- // We start out with trait_to_impl_substs, that maps the trait type
- // parameters to impl type parameters:
+ // We start out with trait_to_impl_substs, that maps the trait
+ // type parameters to impl type parameters. This is taken from the
+ // impl trait reference:
//
- // trait_to_impl_substs = {T => &'i U, Self => Foo}
+ // trait_to_impl_substs = {'t => 'j, T => &'i U, Self => Foo}
//
// We create a mapping `dummy_substs` that maps from the impl type
// parameters to fresh types and regions. For type parameters,
if !check_region_bounds_on_impl_method(tcx,
impl_m_span,
impl_m,
+ impl_m_body_scope,
&trait_m.generics,
&impl_m.generics,
&trait_to_skol_substs,
return;
}
- // Check bounds.
- let it = trait_m.generics.types.get_slice(subst::FnSpace).iter()
- .zip(impl_m.generics.types.get_slice(subst::FnSpace).iter());
- for (i, (trait_param_def, impl_param_def)) in it.enumerate() {
+ // Check bounds. Note that the bounds from the impl may reference
+ // late-bound regions declared on the impl, so liberate those.
+ // This requires two artificial binding scopes -- one for the impl,
+ // and one for the method.
+ //
+ // An example would be:
+ //
+ // trait Foo<T> { fn method<U:Bound<T>>() { ... } }
+ //
+ // impl<'a> Foo<&'a T> for &'a U {
+ // fn method<U:Bound<&'a T>>() { ... }
+ // }
+ //
+ // Here, the region parameter `'a` is late-bound, so in the bound
+ // `Bound<&'a T>`, the lifetime `'a` will be late-bound with a
+ // depth of 3 (it is nested within 3 binders: the impl, method,
+ // and trait-ref itself). So when we do the liberation, we have
+ // two introduce two `ty::bind` scopes, one for the impl and one
+ // the method.
+ //
+ // The only late-bounded regions that can possibly appear here are
+ // from the impl, not the method. This is because region
+ // parameters declared on the method which appear in a type bound
+ // would be early bound. On the trait side, there can be no
+ // late-bound lifetimes because trait definitions do not introduce
+ // a late region binder.
+ let trait_bounds =
+ trait_m.generics.types.get_slice(subst::FnSpace).iter()
+ .map(|trait_param_def| &trait_param_def.bounds);
+ let impl_bounds =
+ impl_m.generics.types.get_slice(subst::FnSpace).iter()
+ .map(|impl_param_def|
+ liberate_late_bound_regions(
+ tcx,
+ impl_m_body_scope,
+ &ty::bind(ty::bind(impl_param_def.bounds.clone()))).value.value);
+ for (i, (trait_param_bounds, impl_param_bounds)) in
+ trait_bounds.zip(impl_bounds).enumerate()
+ {
// Check that the impl does not require any builtin-bounds
// that the trait does not guarantee:
let extra_bounds =
- impl_param_def.bounds.builtin_bounds -
- trait_param_def.bounds.builtin_bounds;
+ impl_param_bounds.builtin_bounds -
+ trait_param_bounds.builtin_bounds;
if !extra_bounds.is_empty() {
span_err!(tcx.sess, impl_m_span, E0051,
"in method `{}`, type parameter {} requires `{}`, \
//
// FIXME(pcwalton): We could be laxer here regarding sub- and super-
// traits, but I doubt that'll be wanted often, so meh.
- for impl_trait_bound in impl_param_def.bounds.trait_bounds.iter() {
+ for impl_trait_bound in impl_param_bounds.trait_bounds.iter() {
debug!("compare_impl_method(): impl-trait-bound subst");
let impl_trait_bound =
impl_trait_bound.subst(tcx, &impl_to_skol_substs);
- let mut ok = false;
- for trait_bound in trait_param_def.bounds.trait_bounds.iter() {
- debug!("compare_impl_method(): trait-bound subst");
- let trait_bound =
- trait_bound.subst(tcx, &trait_to_skol_substs);
- let infcx = infer::new_infer_ctxt(tcx);
- match infer::mk_sub_trait_refs(&infcx,
- true,
- infer::Misc(impl_m_span),
- trait_bound,
- impl_trait_bound.clone()) {
- Ok(_) => {
- ok = true;
- break
- }
- Err(_) => continue,
- }
- }
+ // There may be late-bound regions from the impl in the
+ // impl's bound, so "liberate" those. Note that the
+ // trait_to_skol_substs is derived from the impl's
+ // trait-ref, and the late-bound regions appearing there
+ // have already been liberated, so the result should match
+ // up.
+
+ let found_match_in_trait =
+ trait_param_bounds.trait_bounds.iter().any(|trait_bound| {
+ debug!("compare_impl_method(): trait-bound subst");
+ let trait_bound =
+ trait_bound.subst(tcx, &trait_to_skol_substs);
+ let infcx = infer::new_infer_ctxt(tcx);
+ infer::mk_sub_trait_refs(&infcx,
+ true,
+ infer::Misc(impl_m_span),
+ trait_bound,
+ impl_trait_bound.clone()).is_ok()
+ });
- if !ok {
+ if !found_match_in_trait {
span_err!(tcx.sess, impl_m_span, E0052,
"in method `{}`, type parameter {} requires bound `{}`, which is not \
required by the corresponding type parameter in the trait declaration",
}
}
- // Compute skolemized form of impl and trait method tys.
+ // Compute skolemized form of impl and trait method tys. Note
+ // that we must liberate the late-bound regions from the impl.
let impl_fty = ty::mk_bare_fn(tcx, impl_m.fty.clone());
let impl_fty = impl_fty.subst(tcx, &impl_to_skol_substs);
+ let impl_fty = liberate_late_bound_regions(
+ tcx, impl_m_body_scope, &ty::bind(impl_fty)).value;
let trait_fty = ty::mk_bare_fn(tcx, trait_m.fty.clone());
let trait_fty = trait_fty.subst(tcx, &trait_to_skol_substs);
// parameters.
infcx.resolve_regions_and_report_errors();
- fn check_region_bounds_on_impl_method(tcx: &ty::ctxt,
- span: Span,
- impl_m: &ty::Method,
- trait_generics: &ty::Generics,
- impl_generics: &ty::Generics,
- trait_to_skol_substs: &Substs,
- impl_to_skol_substs: &Substs)
- -> bool
+ fn check_region_bounds_on_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
+ span: Span,
+ impl_m: &ty::Method<'tcx>,
+ impl_m_body_scope: CodeExtent,
+ trait_generics: &ty::Generics<'tcx>,
+ impl_generics: &ty::Generics<'tcx>,
+ trait_to_skol_substs: &Substs<'tcx>,
+ impl_to_skol_substs: &Substs<'tcx>)
+ -> bool
{
/*!
debug!("check_region_bounds_on_impl_method: \
trait_generics={} \
- impl_generics={}",
+ impl_generics={} \
+ trait_to_skol_substs={} \
+ impl_to_skol_substs={}",
trait_generics.repr(tcx),
- impl_generics.repr(tcx));
+ impl_generics.repr(tcx),
+ trait_to_skol_substs.repr(tcx),
+ impl_to_skol_substs.repr(tcx));
// Must have same number of early-bound lifetime parameters.
// Unfortunately, if the user screws up the bounds, then this
let impl_bounds =
impl_param.bounds.subst(tcx, impl_to_skol_substs);
+ // The bounds may reference late-bound regions from the
+ // impl declaration. In that case, we want to replace
+ // those with the liberated variety so as to match the
+ // versions appearing in the `trait_to_skol_substs`.
+ // There are two-levels of binder to be aware of: the
+ // impl, and the method.
+ let impl_bounds =
+ ty::liberate_late_bound_regions(
+ tcx, impl_m_body_scope, &ty::bind(ty::bind(impl_bounds))).value.value;
+
debug!("check_region_bounds_on_impl_method: \
trait_param={} \
impl_param={} \
fcx.type_error_message(span, |actual| {
format!("cast to unsized type: `{}` as `{}`", actual, tstr)
}, t_e, None);
- match ty::get(t_e).sty {
+ match t_e.sty {
ty::ty_rptr(_, ty::mt { mutbl: mt, .. }) => {
let mtstr = match mt {
ast::MutMutable => "mut ",
// casts from C-like enums are allowed
} else if t_1_is_char {
let t_e = fcx.infcx().shallow_resolve(t_e);
- if ty::get(t_e).sty != ty::ty_uint(ast::TyU8) {
+ if t_e.sty != ty::ty_uint(ast::TyU8) {
fcx.type_error_message(span, |actual| {
format!("only `u8` can be cast as \
`char`, not `{}`", actual)
}, t_e, None);
}
- } else if ty::get(t_1).sty == ty::ty_bool {
+ } else if t_1.sty == ty::ty_bool {
span_err!(fcx.tcx().sess, span, E0054,
"cannot cast as `bool`, compare with zero instead");
} else if ty::type_is_region_ptr(t_e) && ty::type_is_unsafe_ptr(t_1) {
- fn types_compatible(fcx: &FnCtxt, sp: Span,
- t1: ty::t, t2: ty::t) -> bool {
- match ty::get(t1).sty {
+ fn types_compatible<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
+ t1: Ty<'tcx>, t2: Ty<'tcx>) -> bool {
+ match t1.sty {
ty::ty_vec(_, Some(_)) => {}
_ => return false
}
/* this cast is only allowed from &[T, ..n] to *T or
&T to *T. */
- match (&ty::get(t_e).sty, &ty::get(t_1).sty) {
+ match (&t_e.sty, &t_1.sty) {
(&ty::ty_rptr(_, ty::mt { ty: mt1, mutbl: ast::MutImmutable }),
&ty::ty_ptr(ty::mt { ty: mt2, mutbl: ast::MutImmutable }))
if types_compatible(fcx, e.span, mt1, mt2) => {
impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> { self.ccx.tcx }
- fn get_item_ty(&self, id: ast::DefId) -> ty::Polytype {
+ fn get_item_ty(&self, id: ast::DefId) -> ty::Polytype<'tcx> {
ty::lookup_item_type(self.tcx(), id)
}
- fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef> {
+ fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef<'tcx>> {
ty::lookup_trait_def(self.tcx(), id)
}
- fn ty_infer(&self, _span: Span) -> ty::t {
+ fn ty_infer(&self, _span: Span) -> Ty<'tcx> {
self.infcx().next_ty_var()
}
- fn associated_types_of_trait_are_valid(&self, _: ty::t, _: ast::DefId)
+ fn associated_types_of_trait_are_valid(&self, _: Ty, _: ast::DefId)
-> bool {
false
}
fn associated_type_binding(&self,
span: Span,
- _: Option<ty::t>,
+ _: Option<Ty<'tcx>>,
_: ast::DefId,
_: ast::DefId)
- -> ty::t {
+ -> Ty<'tcx> {
self.tcx().sess.span_err(span, "unsupported associated type binding");
ty::mk_err()
}
format!("{}", self as *const FnCtxt)
}
- pub fn local_ty(&self, span: Span, nid: ast::NodeId) -> ty::t {
+ pub fn local_ty(&self, span: Span, nid: ast::NodeId) -> Ty<'tcx> {
match self.inh.locals.borrow().get(&nid) {
Some(&t) => t,
None => {
pub fn default_diverging_type_variables_to_nil(&self) {
for (_, &ref ty) in self.inh.node_types.borrow_mut().iter_mut() {
if self.infcx().type_var_diverges(self.infcx().resolve_type_vars_if_possible(*ty)) {
- demand::eqtype(self, codemap::DUMMY_SP, *ty, ty::mk_nil());
+ demand::eqtype(self, codemap::DUMMY_SP, *ty, ty::mk_nil(self.tcx()));
}
}
}
#[inline]
- pub fn write_ty(&self, node_id: ast::NodeId, ty: ty::t) {
+ pub fn write_ty(&self, node_id: ast::NodeId, ty: Ty<'tcx>) {
debug!("write_ty({}, {}) in fcx {}",
node_id, ppaux::ty_to_string(self.tcx(), ty), self.tag());
self.inh.node_types.borrow_mut().insert(node_id, ty);
pub fn write_object_cast(&self,
key: ast::NodeId,
- trait_ref: Rc<ty::TraitRef>) {
+ trait_ref: Rc<ty::TraitRef<'tcx>>) {
debug!("write_object_cast key={} trait_ref={}",
key, trait_ref.repr(self.tcx()));
self.inh.object_cast_map.borrow_mut().insert(key, trait_ref);
}
- pub fn write_substs(&self, node_id: ast::NodeId, substs: ty::ItemSubsts) {
+ pub fn write_substs(&self, node_id: ast::NodeId, substs: ty::ItemSubsts<'tcx>) {
if !substs.substs.is_noop() {
debug!("write_substs({}, {}) in fcx {}",
node_id,
}
}
- pub fn write_ty_substs(&self,
- node_id: ast::NodeId,
- ty: ty::t,
- substs: ty::ItemSubsts) {
- let ty = ty.subst(self.tcx(), &substs.substs);
- self.write_ty(node_id, ty);
- self.write_substs(node_id, substs);
- }
-
pub fn write_autoderef_adjustment(&self,
node_id: ast::NodeId,
span: Span,
pub fn write_adjustment(&self,
node_id: ast::NodeId,
span: Span,
- adj: ty::AutoAdjustment) {
- debug!("write_adjustment(node_id={}, adj={})", node_id, adj);
+ adj: ty::AutoAdjustment<'tcx>) {
+ debug!("write_adjustment(node_id={}, adj={})", node_id, adj.repr(self.tcx()));
if adj.is_identity() {
return;
fn register_adjustment_obligations(&self,
span: Span,
- adj: &ty::AutoAdjustment) {
+ adj: &ty::AutoAdjustment<'tcx>) {
match *adj {
ty::AdjustAddEnv(..) => { }
ty::AdjustDerefRef(ref d_r) => {
fn register_autoref_obligations(&self,
span: Span,
- autoref: &ty::AutoRef) {
+ autoref: &ty::AutoRef<'tcx>) {
match *autoref {
ty::AutoUnsize(ref unsize) => {
self.register_unsize_obligations(span, unsize);
fn register_unsize_obligations(&self,
span: Span,
- unsize: &ty::UnsizeKind) {
+ unsize: &ty::UnsizeKind<'tcx>) {
debug!("register_unsize_obligations: unsize={}", unsize);
match *unsize {
}
ty::UnsizeVtable(ref ty_trait, self_ty) => {
vtable::check_object_safety(self.tcx(), ty_trait, span);
+
// If the type is `Foo+'a`, ensures that the type
// being cast to `Foo+'a` implements `Foo`:
vtable::register_object_cast_obligations(self,
- span,
- ty_trait,
- self_ty);
+ span,
+ ty_trait,
+ self_ty);
// If the type is `Foo+'a`, ensures that the type
// being cast to `Foo+'a` outlives `'a`:
}
}
- pub fn instantiate_item_type(&self,
- span: Span,
- def_id: ast::DefId)
- -> TypeAndSubsts
+ pub fn instantiate_type(&self,
+ span: Span,
+ def_id: ast::DefId)
+ -> TypeAndSubsts<'tcx>
{
/*!
* Returns the type of `def_id` with all generics replaced by
* by fresh type/region variables. Also returns the
* substitution from the type parameters on `def_id` to the
- * fresh variables. Registers any trait obligations specified
+ * fresh variables. Registers any trait obligations specified
* on `def_id` at the same time.
+ *
+ * Note that function is only intended to be used with types
+ * (notably, not impls). This is because it doesn't do any
+ * instantiation of late-bound regions.
*/
let polytype =
self.infcx().fresh_substs_for_generics(
span,
&polytype.generics);
+ let bounds =
+ polytype.generics.to_bounds(self.tcx(), &substs);
self.add_obligations_for_parameters(
traits::ObligationCause::new(
span,
traits::ItemObligation(def_id)),
&substs,
- &polytype.generics);
+ &bounds);
let monotype =
polytype.ty.subst(self.tcx(), &substs);
}
pub fn write_nil(&self, node_id: ast::NodeId) {
- self.write_ty(node_id, ty::mk_nil());
+ self.write_ty(node_id, ty::mk_nil(self.tcx()));
}
pub fn write_error(&self, node_id: ast::NodeId) {
self.write_ty(node_id, ty::mk_err());
}
pub fn require_type_meets(&self,
- ty: ty::t,
+ ty: Ty<'tcx>,
span: Span,
- code: traits::ObligationCauseCode,
+ code: traits::ObligationCauseCode<'tcx>,
bound: ty::BuiltinBound)
{
let obligation = traits::obligation_for_builtin_bound(
}
pub fn require_type_is_sized(&self,
- ty: ty::t,
+ ty: Ty<'tcx>,
span: Span,
- code: traits::ObligationCauseCode)
+ code: traits::ObligationCauseCode<'tcx>)
{
self.require_type_meets(ty, span, code, ty::BoundSized);
}
pub fn require_expr_have_sized_type(&self,
expr: &ast::Expr,
- code: traits::ObligationCauseCode)
+ code: traits::ObligationCauseCode<'tcx>)
{
self.require_type_is_sized(self.expr_ty(expr), expr.span, code);
}
pub fn register_obligation(&self,
- obligation: traits::Obligation)
+ obligation: traits::Obligation<'tcx>)
{
debug!("register_obligation({})",
obligation.repr(self.tcx()));
.register_obligation(self.tcx(), obligation);
}
- pub fn to_ty(&self, ast_t: &ast::Ty) -> ty::t {
+ pub fn to_ty(&self, ast_t: &ast::Ty) -> Ty<'tcx> {
let t = ast_ty_to_ty(self, self.infcx(), ast_t);
let mut bounds_checker = wf::BoundsChecker::new(self,
ast_t.span,
- self.body_id,
+ CodeExtent::from_node_id(self.body_id),
None);
bounds_checker.check_ty(t);
pat.repr(self.tcx())
}
- pub fn expr_ty(&self, ex: &ast::Expr) -> ty::t {
+ pub fn expr_ty(&self, ex: &ast::Expr) -> Ty<'tcx> {
match self.inh.node_types.borrow().get(&ex.id) {
Some(&t) => t,
None => {
}
}
- pub fn expr_ty_adjusted(&self, expr: &ast::Expr) -> ty::t {
+ pub fn expr_ty_adjusted(&self, expr: &ast::Expr) -> Ty<'tcx> {
/*!
* Fetch type of `expr` after applying adjustments that
* have been recorded in the fcx.
pub fn adjust_expr_ty(&self,
expr: &ast::Expr,
- adjustment: Option<&ty::AutoAdjustment>)
- -> ty::t
+ adjustment: Option<&ty::AutoAdjustment<'tcx>>)
+ -> Ty<'tcx>
{
/*!
* Apply `adjustment` to the type of `expr`
.map(|method| method.ty))
}
- pub fn node_ty(&self, id: ast::NodeId) -> ty::t {
+ pub fn node_ty(&self, id: ast::NodeId) -> Ty<'tcx> {
match self.inh.node_types.borrow().get(&id) {
Some(&t) => t,
None => {
}
}
- pub fn item_substs<'a>(&'a self) -> Ref<'a, NodeMap<ty::ItemSubsts>> {
+ pub fn item_substs<'a>(&'a self) -> Ref<'a, NodeMap<ty::ItemSubsts<'tcx>>> {
self.inh.item_substs.borrow()
}
pub fn opt_node_ty_substs(&self,
id: ast::NodeId,
- f: |&ty::ItemSubsts|) {
+ f: |&ty::ItemSubsts<'tcx>|) {
match self.inh.item_substs.borrow().get(&id) {
Some(s) => { f(s) }
None => { }
pub fn mk_subty(&self,
a_is_expected: bool,
origin: infer::TypeOrigin,
- sub: ty::t,
- sup: ty::t)
- -> Result<(), ty::type_err> {
+ sub: Ty<'tcx>,
+ sup: Ty<'tcx>)
+ -> Result<(), ty::type_err<'tcx>> {
infer::mk_subty(self.infcx(), a_is_expected, origin, sub, sup)
}
- pub fn can_mk_subty(&self, sub: ty::t, sup: ty::t)
- -> Result<(), ty::type_err> {
+ pub fn can_mk_subty(&self, sub: Ty<'tcx>, sup: Ty<'tcx>)
+ -> Result<(), ty::type_err<'tcx>> {
infer::can_mk_subty(self.infcx(), sub, sup)
}
- pub fn can_mk_eqty(&self, sub: ty::t, sup: ty::t)
- -> Result<(), ty::type_err> {
+ pub fn can_mk_eqty(&self, sub: Ty<'tcx>, sup: Ty<'tcx>)
+ -> Result<(), ty::type_err<'tcx>> {
infer::can_mk_eqty(self.infcx(), sub, sup)
}
pub fn mk_assignty(&self,
expr: &ast::Expr,
- sub: ty::t,
- sup: ty::t)
- -> Result<(), ty::type_err> {
+ sub: Ty<'tcx>,
+ sup: Ty<'tcx>)
+ -> Result<(), ty::type_err<'tcx>> {
match infer::mk_coercety(self.infcx(),
false,
infer::ExprAssignable(expr.span),
pub fn mk_eqty(&self,
a_is_expected: bool,
origin: infer::TypeOrigin,
- sub: ty::t,
- sup: ty::t)
- -> Result<(), ty::type_err> {
+ sub: Ty<'tcx>,
+ sup: Ty<'tcx>)
+ -> Result<(), ty::type_err<'tcx>> {
infer::mk_eqty(self.infcx(), a_is_expected, origin, sub, sup)
}
pub fn mk_subr(&self,
- origin: infer::SubregionOrigin,
+ origin: infer::SubregionOrigin<'tcx>,
sub: ty::Region,
sup: ty::Region) {
infer::mk_subr(self.infcx(), origin, sub, sup)
pub fn type_error_message(&self,
sp: Span,
mk_msg: |String| -> String,
- actual_ty: ty::t,
- err: Option<&ty::type_err>) {
+ actual_ty: Ty<'tcx>,
+ err: Option<&ty::type_err<'tcx>>) {
self.infcx().type_error_message(sp, mk_msg, actual_ty, err);
}
pub fn report_mismatched_types(&self,
sp: Span,
- e: ty::t,
- a: ty::t,
- err: &ty::type_err) {
+ e: Ty<'tcx>,
+ a: Ty<'tcx>,
+ err: &ty::type_err<'tcx>) {
self.infcx().report_mismatched_types(sp, e, a, err)
}
pub fn register_region_obligation(&self,
- origin: infer::SubregionOrigin,
- ty: ty::t,
+ origin: infer::SubregionOrigin<'tcx>,
+ ty: Ty<'tcx>,
r: ty::Region)
{
/*!
let mut region_obligations = self.inh.region_obligations.borrow_mut();
let region_obligation = RegionObligation { sub_region: r,
- sup_type: ty,
- origin: origin };
+ sup_type: ty,
+ origin: origin };
match region_obligations.entry(self.body_id) {
Vacant(entry) => { entry.set(vec![region_obligation]); },
}
}
+ pub fn add_default_region_param_bounds(&self,
+ substs: &Substs<'tcx>,
+ expr: &ast::Expr)
+ {
+ for &ty in substs.types.iter() {
+ let default_bound = ty::ReScope(CodeExtent::from_node_id(expr.id));
+ let origin = infer::RelateDefaultParamBound(expr.span, ty);
+ self.register_region_obligation(origin, ty, default_bound);
+ }
+ }
+
pub fn add_obligations_for_parameters(&self,
- cause: traits::ObligationCause,
- substs: &Substs,
- generics: &ty::Generics)
+ cause: traits::ObligationCause<'tcx>,
+ substs: &Substs<'tcx>,
+ generic_bounds: &ty::GenericBounds<'tcx>)
{
/*!
- * Given a set of generic parameter definitions (`generics`)
- * and the values provided for each of them (`substs`),
- * creates and registers suitable region obligations.
+ * Given a fully substituted set of bounds (`generic_bounds`),
+ * and the values with which each type/region parameter was
+ * instantiated (`substs`), creates and registers suitable
+ * trait/region obligations.
*
* For example, if there is a function:
*
* locally.
*/
- debug!("add_obligations_for_parameters(substs={}, generics={})",
+ assert!(!generic_bounds.has_escaping_regions());
+
+ debug!("add_obligations_for_parameters(substs={}, generic_bounds={})",
substs.repr(self.tcx()),
- generics.repr(self.tcx()));
+ generic_bounds.repr(self.tcx()));
- self.add_trait_obligations_for_generics(cause, substs, generics);
- self.add_region_obligations_for_generics(cause, substs, generics);
+ self.add_trait_obligations_for_generics(cause, substs, generic_bounds);
+ self.add_region_obligations_for_generics(cause, substs, generic_bounds);
}
fn add_trait_obligations_for_generics(&self,
- cause: traits::ObligationCause,
- substs: &Substs,
- generics: &ty::Generics) {
+ cause: traits::ObligationCause<'tcx>,
+ substs: &Substs<'tcx>,
+ generic_bounds: &ty::GenericBounds<'tcx>) {
+ assert!(!generic_bounds.has_escaping_regions());
+ assert!(!substs.has_regions_escaping_depth(0));
+
let obligations =
traits::obligations_for_generics(self.tcx(),
cause,
- generics,
- substs);
+ generic_bounds,
+ &substs.types);
obligations.map_move(|o| self.register_obligation(o));
}
fn add_region_obligations_for_generics(&self,
- cause: traits::ObligationCause,
- substs: &Substs,
- generics: &ty::Generics)
+ cause: traits::ObligationCause<'tcx>,
+ substs: &Substs<'tcx>,
+ generic_bounds: &ty::GenericBounds<'tcx>)
{
- assert_eq!(generics.types.iter().len(),
- substs.types.iter().len());
- for (type_def, &type_param) in
- generics.types.iter().zip(
+ assert!(!generic_bounds.has_escaping_regions());
+ assert_eq!(generic_bounds.types.iter().len(), substs.types.iter().len());
+
+ for (type_bounds, &type_param) in
+ generic_bounds.types.iter().zip(
substs.types.iter())
{
- let param_ty = ty::ParamTy { space: type_def.space,
- idx: type_def.index,
- def_id: type_def.def_id };
- let bounds = type_def.bounds.subst(self.tcx(), substs);
self.add_region_obligations_for_type_parameter(
- cause.span, param_ty, &bounds, type_param);
+ cause.span, type_bounds, type_param);
}
- assert_eq!(generics.regions.iter().len(),
+ assert_eq!(generic_bounds.regions.iter().len(),
substs.regions().iter().len());
- for (region_def, ®ion_param) in
- generics.regions.iter().zip(
+ for (region_bounds, ®ion_param) in
+ generic_bounds.regions.iter().zip(
substs.regions().iter())
{
- let bounds = region_def.bounds.subst(self.tcx(), substs);
self.add_region_obligations_for_region_parameter(
- cause.span, bounds.as_slice(), region_param);
+ cause.span, region_bounds.as_slice(), region_param);
}
}
fn add_region_obligations_for_type_parameter(&self,
span: Span,
- param_ty: ty::ParamTy,
- param_bound: &ty::ParamBounds,
- ty: ty::t)
+ param_bound: &ty::ParamBounds<'tcx>,
+ ty: Ty<'tcx>)
{
// For each declared region bound `T:r`, `T` must outlive `r`.
let region_bounds =
param_bound.builtin_bounds,
param_bound.trait_bounds.as_slice());
for &r in region_bounds.iter() {
- let origin = infer::RelateParamBound(span, param_ty, ty);
+ let origin = infer::RelateParamBound(span, ty);
self.register_region_obligation(origin, ty, r);
}
}
NoPreference
}
-pub fn autoderef<T>(fcx: &FnCtxt, sp: Span, base_ty: ty::t,
- expr_id: Option<ast::NodeId>,
- mut lvalue_pref: LvaluePreference,
- should_stop: |ty::t, uint| -> Option<T>)
- -> (ty::t, uint, Option<T>) {
+pub fn autoderef<'a, 'tcx, T>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
+ base_ty: Ty<'tcx>,
+ expr_id: Option<ast::NodeId>,
+ mut lvalue_pref: LvaluePreference,
+ should_stop: |Ty<'tcx>, uint| -> Option<T>)
+ -> (Ty<'tcx>, uint, Option<T>) {
/*!
* Executes an autoderef loop for the type `t`. At each step, invokes
* `should_stop` to decide whether to terminate the loop. Returns
}
/// Attempts to resolve a call expression as an overloaded call.
-fn try_overloaded_call<'a>(fcx: &FnCtxt,
- call_expression: &ast::Expr,
- callee: &ast::Expr,
- callee_type: ty::t,
- args: &[&'a P<ast::Expr>])
- -> bool {
+fn try_overloaded_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+ call_expression: &ast::Expr,
+ callee: &ast::Expr,
+ callee_type: Ty<'tcx>,
+ args: &[&P<ast::Expr>])
+ -> bool {
// Bail out if the callee is a bare function or a closure. We check those
// manually.
match *structure_of(fcx, callee.span, callee_type) {
fcx.inh.method_map.borrow_mut().insert(method_call, method_callee);
write_call(fcx, call_expression, output_type);
- if !fcx.tcx().sess.features.borrow().overloaded_calls {
+ if !fcx.tcx().sess.features.borrow().unboxed_closures {
span_err!(fcx.tcx().sess, call_expression.span, E0056,
"overloaded calls are experimental");
span_help!(fcx.tcx().sess, call_expression.span,
- "add `#![feature(overloaded_calls)]` to \
+ "add `#![feature(unboxed_closures)]` to \
the crate attributes to enable");
}
false
}
-fn try_overloaded_deref(fcx: &FnCtxt,
- span: Span,
- method_call: Option<MethodCall>,
- base_expr: Option<&ast::Expr>,
- base_ty: ty::t,
- lvalue_pref: LvaluePreference)
- -> Option<ty::mt>
+fn try_overloaded_deref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+ span: Span,
+ method_call: Option<MethodCall>,
+ base_expr: Option<&ast::Expr>,
+ base_ty: Ty<'tcx>,
+ lvalue_pref: LvaluePreference)
+ -> Option<ty::mt<'tcx>>
{
// Try DerefMut first, if preferred.
let method = match (lvalue_pref, fcx.tcx().lang_items.deref_mut_trait()) {
make_overloaded_lvalue_return_type(fcx, method_call, method)
}
-fn make_overloaded_lvalue_return_type(fcx: &FnCtxt,
- method_call: Option<MethodCall>,
- method: Option<MethodCallee>)
- -> Option<ty::mt>
+fn make_overloaded_lvalue_return_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+ method_call: Option<MethodCall>,
+ method: Option<MethodCallee<'tcx>>)
+ -> Option<ty::mt<'tcx>>
{
/*!
* For the overloaded lvalue expressions (`*x`, `x[3]`), the trait
}
}
-fn autoderef_for_index<T>(fcx: &FnCtxt,
- base_expr: &ast::Expr,
- base_ty: ty::t,
- lvalue_pref: LvaluePreference,
- step: |ty::t, ty::AutoDerefRef| -> Option<T>)
- -> Option<T>
+fn autoderef_for_index<'a, 'tcx, T>(fcx: &FnCtxt<'a, 'tcx>,
+ base_expr: &ast::Expr,
+ base_ty: Ty<'tcx>,
+ lvalue_pref: LvaluePreference,
+ step: |Ty<'tcx>, ty::AutoDerefRef<'tcx>| -> Option<T>)
+ -> Option<T>
{
+ // FIXME(#18741) -- this is almost but not quite the same as the
+ // autoderef that normal method probing does. They could likely be
+ // consolidated.
+
let (ty, autoderefs, final_mt) =
autoderef(fcx, base_expr.span, base_ty, Some(base_expr.id), lvalue_pref, |adj_ty, idx| {
let autoderefref = ty::AutoDerefRef { autoderefs: idx, autoref: None };
// After we have fully autoderef'd, if the resulting type is [T, ..n], then
// do a final unsized coercion to yield [T].
- match ty::get(ty).sty {
+ match ty.sty {
ty::ty_vec(element_ty, Some(n)) => {
let adjusted_ty = ty::mk_vec(fcx.tcx(), element_ty, None);
let autoderefref = ty::AutoDerefRef {
}
}
-fn try_overloaded_slice(fcx: &FnCtxt,
- method_call: MethodCall,
- expr: &ast::Expr,
- base_expr: &ast::Expr,
- base_ty: ty::t,
- start_expr: &Option<P<ast::Expr>>,
- end_expr: &Option<P<ast::Expr>>,
- mutbl: ast::Mutability)
- -> Option<ty::t> // return type is result of slice
+fn try_overloaded_slice<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+ method_call: MethodCall,
+ expr: &ast::Expr,
+ base_expr: &ast::Expr,
+ base_ty: Ty<'tcx>,
+ start_expr: &Option<P<ast::Expr>>,
+ end_expr: &Option<P<ast::Expr>>,
+ mutbl: ast::Mutability)
+ -> Option<Ty<'tcx>> // return type is result of slice
{
/*!
* Autoderefs `base_expr`, looking for a `Slice` impl. If it
})
}
-fn try_overloaded_slice_step(fcx: &FnCtxt,
- method_call: MethodCall,
- expr: &ast::Expr,
- base_expr: &ast::Expr,
- base_ty: ty::t, // autoderef'd type
- autoderefref: ty::AutoDerefRef,
- mutbl: ast::Mutability,
- start_expr: &Option<P<ast::Expr>>,
- end_expr: &Option<P<ast::Expr>>)
- -> Option<ty::t> // result type is type of method being called
+fn try_overloaded_slice_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+ method_call: MethodCall,
+ expr: &ast::Expr,
+ base_expr: &ast::Expr,
+ base_ty: Ty<'tcx>, // autoderef'd type
+ autoderefref: ty::AutoDerefRef<'tcx>,
+ mutbl: ast::Mutability,
+ start_expr: &Option<P<ast::Expr>>,
+ end_expr: &Option<P<ast::Expr>>)
+ // result type is type of method being called
+ -> Option<Ty<'tcx>>
{
/*!
* Checks for a `Slice` (or `SliceMut`) impl at the relevant level
})
}
-fn try_index_step(fcx: &FnCtxt,
- method_call: MethodCall,
- expr: &ast::Expr,
- base_expr: &ast::Expr,
- adjusted_ty: ty::t,
- adjustment: ty::AutoDerefRef,
- lvalue_pref: LvaluePreference)
- -> Option<(/*index type*/ ty::t, /*element type*/ ty::t)>
+fn try_index_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+ method_call: MethodCall,
+ expr: &ast::Expr,
+ base_expr: &ast::Expr,
+ adjusted_ty: Ty<'tcx>,
+ adjustment: ty::AutoDerefRef<'tcx>,
+ lvalue_pref: LvaluePreference)
+ -> Option<(/*index type*/ Ty<'tcx>, /*element type*/ Ty<'tcx>)>
{
/*!
* To type-check `base_expr[index_expr]`, we progressively autoderef (and otherwise adjust)
}
/// Given the head of a `for` expression, looks up the `next` method in the
-/// `Iterator` trait. Fails if the expression does not implement `next`.
+/// `Iterator` trait. Panics if the expression does not implement `next`.
///
/// The return type of this function represents the concrete element type
/// `A` in the type `Iterator<A>` that the method returns.
-fn lookup_method_for_for_loop(fcx: &FnCtxt,
- iterator_expr: &ast::Expr,
- loop_id: ast::NodeId)
- -> ty::t {
+fn lookup_method_for_for_loop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+ iterator_expr: &ast::Expr,
+ loop_id: ast::NodeId)
+ -> Ty<'tcx> {
let trait_did = match fcx.tcx().lang_items.require(IteratorItem) {
Ok(trait_did) => trait_did,
Err(ref err_string) => {
structurally_resolved_type(fcx, iterator_expr.span, return_type),
ty::FnDiverging => ty::mk_err()
};
- match ty::get(return_type).sty {
+ match return_type.sty {
ty::ty_enum(_, ref substs)
if !substs.types.is_empty_in(subst::TypeSpace) => {
*substs.types.get(subst::TypeSpace, 0)
}
}
-fn check_method_argument_types<'a>(fcx: &FnCtxt,
- sp: Span,
- method_fn_ty: ty::t,
- callee_expr: &ast::Expr,
- args_no_rcvr: &[&'a P<ast::Expr>],
- deref_args: DerefArgs,
- tuple_arguments: TupleArgumentsFlag)
- -> ty::FnOutput {
+fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+ sp: Span,
+ method_fn_ty: Ty<'tcx>,
+ callee_expr: &ast::Expr,
+ args_no_rcvr: &[&P<ast::Expr>],
+ deref_args: DerefArgs,
+ tuple_arguments: TupleArgumentsFlag)
+ -> ty::FnOutput<'tcx> {
if ty::type_is_error(method_fn_ty) {
let err_inputs = err_args(args_no_rcvr.len());
check_argument_types(fcx,
tuple_arguments);
ty::FnConverging(ty::mk_err())
} else {
- match ty::get(method_fn_ty).sty {
+ match method_fn_ty.sty {
ty::ty_bare_fn(ref fty) => {
// HACK(eddyb) ignore self in the definition (see above).
check_argument_types(fcx,
}
}
-fn check_argument_types<'a>(fcx: &FnCtxt,
- sp: Span,
- fn_inputs: &[ty::t],
- _callee_expr: &ast::Expr,
- args: &[&'a P<ast::Expr>],
- deref_args: DerefArgs,
- variadic: bool,
- tuple_arguments: TupleArgumentsFlag) {
+fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+ sp: Span,
+ fn_inputs: &[Ty<'tcx>],
+ _callee_expr: &ast::Expr,
+ args: &[&P<ast::Expr>],
+ deref_args: DerefArgs,
+ variadic: bool,
+ tuple_arguments: TupleArgumentsFlag) {
/*!
*
* Generic function that factors out common logic from
let expected_arg_count = fn_inputs.len();
let formal_tys = if tuple_arguments == TupleArguments {
let tuple_type = structurally_resolved_type(fcx, sp, fn_inputs[0]);
- match ty::get(tuple_type).sty {
+ match tuple_type.sty {
ty::ty_tup(ref arg_types) => {
if arg_types.len() != args.len() {
span_err!(tcx.sess, sp, E0057,
(*arg_types).clone()
}
}
- ty::ty_nil => {
- if args.len() != 0 {
- span_err!(tcx.sess, sp, E0058,
- "this function takes 0 parameters but {} parameter{} supplied",
- args.len(),
- if args.len() == 1 {" was"} else {"s were"});
- err_args(args.len())
- } else {
- vec![]
- }
- }
_ => {
span_err!(tcx.sess, sp, E0059,
"cannot use call notation; the first type parameter \
};
for (i, arg) in args.iter().take(t).enumerate() {
let is_block = match arg.node {
- ast::ExprFnBlock(..) |
- ast::ExprProc(..) |
- ast::ExprUnboxedFn(..) => true,
+ ast::ExprClosure(..) | ast::ExprProc(..) => true,
_ => false
};
match deref_args {
DoDerefArgs => {
- match ty::get(formal_ty).sty {
+ match formal_ty.sty {
ty::ty_rptr(_, mt) => formal_ty = mt.ty,
ty::ty_err => (),
_ => {
// in C but we just error out instead and require explicit casts.
let arg_ty = structurally_resolved_type(fcx, arg.span,
fcx.expr_ty(&***arg));
- match ty::get(arg_ty).sty {
+ match arg_ty.sty {
ty::ty_float(ast::TyF32) => {
fcx.type_error_message(arg.span,
|t| {
}
}
-fn err_args(len: uint) -> Vec<ty::t> {
+// FIXME(#17596) Ty<'tcx> is incorrectly invariant w.r.t 'tcx.
+fn err_args<'tcx>(len: uint) -> Vec<Ty<'tcx>> {
Vec::from_fn(len, |_| ty::mk_err())
}
-fn write_call(fcx: &FnCtxt, call_expr: &ast::Expr, output: ty::FnOutput) {
+fn write_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+ call_expr: &ast::Expr,
+ output: ty::FnOutput<'tcx>) {
fcx.write_ty(call_expr.id, match output {
ty::FnConverging(output_ty) => output_ty,
ty::FnDiverging => fcx.infcx().next_diverging_ty_var()
}
// AST fragment checking
-fn check_lit(fcx: &FnCtxt,
- lit: &ast::Lit,
- expected: Expectation)
- -> ty::t
+fn check_lit<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+ lit: &ast::Lit,
+ expected: Expectation<'tcx>)
+ -> Ty<'tcx>
{
let tcx = fcx.ccx.tcx;
opt_ty.unwrap_or_else(
|| ty::mk_float_var(tcx, fcx.infcx().next_float_var_id()))
}
- ast::LitNil => ty::mk_nil(),
ast::LitBool(_) => ty::mk_bool()
}
}
}
}
-pub fn check_expr_has_type(fcx: &FnCtxt,
- expr: &ast::Expr,
- expected: ty::t) {
+pub fn check_expr_has_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+ expr: &ast::Expr,
+ expected: Ty<'tcx>) {
check_expr_with_unifier(
fcx, expr, ExpectHasType(expected), NoPreference,
|| demand::suptype(fcx, expr.span, expected, fcx.expr_ty(expr)));
}
-fn check_expr_coercable_to_type(fcx: &FnCtxt,
- expr: &ast::Expr,
- expected: ty::t) {
+fn check_expr_coercable_to_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+ expr: &ast::Expr,
+ expected: Ty<'tcx>) {
check_expr_with_unifier(
fcx, expr, ExpectHasType(expected), NoPreference,
|| demand::coerce(fcx, expr.span, expected, expr));
}
-fn check_expr_with_hint(fcx: &FnCtxt, expr: &ast::Expr, expected: ty::t) {
+fn check_expr_with_hint<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, expr: &ast::Expr,
+ expected: Ty<'tcx>) {
check_expr_with_unifier(
fcx, expr, ExpectHasType(expected), NoPreference,
|| ())
}
-fn check_expr_with_expectation(fcx: &FnCtxt,
- expr: &ast::Expr,
- expected: Expectation) {
+fn check_expr_with_expectation<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+ expr: &ast::Expr,
+ expected: Expectation<'tcx>) {
check_expr_with_unifier(
fcx, expr, expected, NoPreference,
|| ())
}
-fn check_expr_with_expectation_and_lvalue_pref(fcx: &FnCtxt,
- expr: &ast::Expr,
- expected: Expectation,
- lvalue_pref: LvaluePreference)
+fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+ expr: &ast::Expr,
+ expected: Expectation<'tcx>,
+ lvalue_pref: LvaluePreference)
{
check_expr_with_unifier(fcx, expr, expected, lvalue_pref, || ())
}
// declared on the impl declaration e.g., `impl<A,B> for ~[(A,B)]`
// would return ($0, $1) where $0 and $1 are freshly instantiated type
// variables.
-pub fn impl_self_ty(fcx: &FnCtxt,
- span: Span, // (potential) receiver for this impl
- did: ast::DefId)
- -> TypeAndSubsts {
+pub fn impl_self_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+ span: Span, // (potential) receiver for this impl
+ did: ast::DefId)
+ -> TypeAndSubsts<'tcx> {
let tcx = fcx.tcx();
let ity = ty::lookup_item_type(tcx, did);
// Only for fields! Returns <none> for methods>
// Indifferent to privacy flags
-pub fn lookup_field_ty(tcx: &ty::ctxt,
- class_id: ast::DefId,
- items: &[ty::field_ty],
- fieldname: ast::Name,
- substs: &subst::Substs) -> Option<ty::t> {
+pub fn lookup_field_ty<'tcx>(tcx: &ty::ctxt<'tcx>,
+ class_id: ast::DefId,
+ items: &[ty::field_ty],
+ fieldname: ast::Name,
+ substs: &subst::Substs<'tcx>)
+ -> Option<Ty<'tcx>> {
let o_field = items.iter().find(|f| f.name == fieldname);
o_field.map(|f| ty::lookup_field_type(tcx, class_id, f.id, substs))
}
-pub fn lookup_tup_field_ty(tcx: &ty::ctxt,
- class_id: ast::DefId,
- items: &[ty::field_ty],
- idx: uint,
- substs: &subst::Substs) -> Option<ty::t> {
+pub fn lookup_tup_field_ty<'tcx>(tcx: &ty::ctxt<'tcx>,
+ class_id: ast::DefId,
+ items: &[ty::field_ty],
+ idx: uint,
+ substs: &subst::Substs<'tcx>)
+ -> Option<Ty<'tcx>> {
let o_field = if idx < items.len() { Some(&items[idx]) } else { None };
o_field.map(|f| ty::lookup_field_type(tcx, class_id, f.id, substs))
/// Note that inspecting a type's structure *directly* may expose the fact
/// that there are actually multiple representations for `ty_err`, so avoid
/// that when err needs to be handled differently.
-fn check_expr_with_unifier(fcx: &FnCtxt,
- expr: &ast::Expr,
- expected: Expectation,
- lvalue_pref: LvaluePreference,
- unifier: ||)
+fn check_expr_with_unifier<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+ expr: &ast::Expr,
+ expected: Expectation<'tcx>,
+ lvalue_pref: LvaluePreference,
+ unifier: ||)
{
debug!(">> typechecking: expr={} expected={}",
expr.repr(fcx.tcx()), expected.repr(fcx.tcx()));
// A generic function for doing all of the checking for call expressions
- fn check_call<'a>(fcx: &FnCtxt,
- call_expr: &ast::Expr,
- f: &ast::Expr,
- args: &[&'a P<ast::Expr>]) {
+ fn check_call(fcx: &FnCtxt,
+ call_expr: &ast::Expr,
+ f: &ast::Expr,
+ args: &[&P<ast::Expr>]) {
// Store the type of `f` as the type of the callee
let fn_ty = fcx.expr_ty(f);
// In that case, we check each argument against "error" in order to
// set up all the node type bindings.
let error_fn_sig = FnSig {
- binder_id: ast::CRATE_NODE_ID,
inputs: err_args(args.len()),
output: ty::FnConverging(ty::mk_err()),
variadic: false
// Replace any bound regions that appear in the function
// signature with region variables
- let (_, fn_sig) = replace_late_bound_regions(fcx.tcx(), fn_sig.binder_id, fn_sig, |br| {
- fcx.infcx().next_region_var(infer::LateBoundRegion(call_expr.span, br))
- });
+ let fn_sig =
+ fcx.infcx().replace_late_bound_regions_with_fresh_var(call_expr.span,
+ infer::FnCall,
+ fn_sig).0;
// Call the generic checker.
check_argument_types(fcx,
let tps = tps.iter().map(|ast_ty| fcx.to_ty(&**ast_ty)).collect::<Vec<_>>();
let fn_ty = match method::lookup(fcx,
- expr,
- &*rcvr,
+ method_name.span,
method_name.node.name,
expr_t,
- tps.as_slice(),
- DontDerefArgs,
- CheckTraitsAndInherentMethods,
- AutoderefReceiver) {
+ tps,
+ expr,
+ rcvr) {
Ok(method) => {
let method_ty = method.ty;
let method_call = MethodCall::expr(expr.id);
// A generic function for checking the then and else in an if
// or if-check
- fn check_then_else(fcx: &FnCtxt,
- cond_expr: &ast::Expr,
- then_blk: &ast::Block,
- opt_else_expr: Option<&ast::Expr>,
- id: ast::NodeId,
- sp: Span,
- expected: Expectation) {
+ fn check_then_else<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+ cond_expr: &ast::Expr,
+ then_blk: &ast::Block,
+ opt_else_expr: Option<&ast::Expr>,
+ id: ast::NodeId,
+ sp: Span,
+ expected: Expectation<'tcx>) {
check_expr_has_type(fcx, cond_expr, ty::mk_bool());
// Disregard "castable to" expectations because they
infer::IfExpressionWithNoElse(sp),
false,
then_ty,
- ty::mk_nil())
+ ty::mk_nil(fcx.tcx()))
}
};
fn lookup_op_method<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>,
op_ex: &ast::Expr,
- lhs_ty: ty::t,
+ lhs_ty: Ty<'tcx>,
opname: ast::Name,
trait_did: Option<ast::DefId>,
lhs: &'a ast::Expr,
rhs: Option<&P<ast::Expr>>,
- unbound_method: ||) -> ty::t {
+ unbound_method: ||) -> Ty<'tcx> {
let method = match trait_did {
Some(trait_did) => {
// We do eager coercions to make using operators
// could also solve this with variance or different
// traits that don't force left and right to have same
// type.
- let (adj_ty, adjustment) = match ty::get(lhs_ty).sty {
+ let (adj_ty, adjustment) = match lhs_ty.sty {
ty::ty_rptr(r_in, mt) => {
let r_adj = fcx.infcx().next_region_var(infer::Autoref(lhs.span));
fcx.mk_subr(infer::Reborrow(lhs.span), r_adj, r_in);
}
}
- fn check_user_binop(fcx: &FnCtxt,
- ex: &ast::Expr,
- lhs_expr: &ast::Expr,
- lhs_resolved_t: ty::t,
- op: ast::BinOp,
- rhs: &P<ast::Expr>) -> ty::t {
+ fn check_user_binop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+ ex: &ast::Expr,
+ lhs_expr: &ast::Expr,
+ lhs_resolved_t: Ty<'tcx>,
+ op: ast::BinOp,
+ rhs: &P<ast::Expr>) -> Ty<'tcx> {
let tcx = fcx.ccx.tcx;
let lang = &tcx.lang_items;
let (name, trait_did) = match op {
})
}
- fn check_user_unop(fcx: &FnCtxt,
- op_str: &str,
- mname: &str,
- trait_did: Option<ast::DefId>,
- ex: &ast::Expr,
- rhs_expr: &ast::Expr,
- rhs_t: ty::t) -> ty::t {
+ fn check_user_unop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+ op_str: &str,
+ mname: &str,
+ trait_did: Option<ast::DefId>,
+ ex: &ast::Expr,
+ rhs_expr: &ast::Expr,
+ rhs_t: Ty<'tcx>) -> Ty<'tcx> {
lookup_op_method(fcx, ex, rhs_t, token::intern(mname),
trait_did, rhs_expr, None, || {
fcx.type_error_message(ex.span, |actual| {
})
}
- fn check_unboxed_closure(fcx: &FnCtxt,
- expr: &ast::Expr,
- kind: ast::UnboxedClosureKind,
- decl: &ast::FnDecl,
- body: &ast::Block) {
- let mut fn_ty = astconv::ty_of_closure(
- fcx,
- expr.id,
- ast::NormalFn,
- ast::Many,
-
- // The `RegionTraitStore` and region_existential_bounds
- // are lies, but we ignore them so it doesn't matter.
- //
- // FIXME(pcwalton): Refactor this API.
- ty::region_existential_bound(ty::ReStatic),
- ty::RegionTraitStore(ty::ReStatic, ast::MutImmutable),
-
- decl,
- abi::RustCall,
- None);
-
- let region = match fcx.infcx().anon_regions(expr.span, 1) {
- Err(_) => {
- fcx.ccx.tcx.sess.span_bug(expr.span,
- "can't make anon regions here?!")
- }
- Ok(regions) => regions[0],
- };
- let closure_type = ty::mk_unboxed_closure(fcx.ccx.tcx,
- local_def(expr.id),
- region,
- fcx.inh.param_env.free_substs.clone());
- fcx.write_ty(expr.id, closure_type);
-
- check_fn(fcx.ccx,
- ast::NormalFn,
- expr.id,
- &fn_ty.sig,
- decl,
- expr.id,
- &*body,
- fcx.inh);
-
- // Tuple up the arguments and insert the resulting function type into
- // the `unboxed_closures` table.
- fn_ty.sig.inputs = vec![ty::mk_tup_or_nil(fcx.tcx(), fn_ty.sig.inputs)];
-
- let kind = match kind {
- ast::FnUnboxedClosureKind => ty::FnUnboxedClosureKind,
- ast::FnMutUnboxedClosureKind => ty::FnMutUnboxedClosureKind,
- ast::FnOnceUnboxedClosureKind => ty::FnOnceUnboxedClosureKind,
- };
-
- debug!("unboxed_closure for {} --> sig={} kind={}",
- local_def(expr.id).repr(fcx.tcx()),
- fn_ty.sig.repr(fcx.tcx()),
- kind);
-
- let unboxed_closure = ty::UnboxedClosure {
- closure_type: fn_ty,
- kind: kind,
- };
-
- fcx.inh
- .unboxed_closures
- .borrow_mut()
- .insert(local_def(expr.id), unboxed_closure);
- }
-
- fn check_expr_fn(fcx: &FnCtxt,
- expr: &ast::Expr,
- store: ty::TraitStore,
- decl: &ast::FnDecl,
- body: &ast::Block,
- expected: Expectation) {
- let tcx = fcx.ccx.tcx;
-
- // Find the expected input/output types (if any). Substitute
- // fresh bound regions for any bound regions we find in the
- // expected types so as to avoid capture.
- let expected_sty = expected.map_to_option(fcx, |x| Some((*x).clone()));
- let (expected_sig,
- expected_onceness,
- expected_bounds) = {
- match expected_sty {
- Some(ty::ty_closure(ref cenv)) => {
- let (_, sig) =
- replace_late_bound_regions(
- tcx, cenv.sig.binder_id, &cenv.sig,
- |_| fcx.inh.infcx.fresh_bound_region(expr.id));
- let onceness = match (&store, &cenv.store) {
- // As the closure type and onceness go, only three
- // combinations are legit:
- // once closure
- // many closure
- // once proc
- // If the actual and expected closure type disagree with
- // each other, set expected onceness to be always Once or
- // Many according to the actual type. Otherwise, it will
- // yield either an illegal "many proc" or a less known
- // "once closure" in the error message.
- (&ty::UniqTraitStore, &ty::UniqTraitStore) |
- (&ty::RegionTraitStore(..), &ty::RegionTraitStore(..)) =>
- cenv.onceness,
- (&ty::UniqTraitStore, _) => ast::Once,
- (&ty::RegionTraitStore(..), _) => ast::Many,
- };
- (Some(sig), onceness, cenv.bounds)
- }
- _ => {
- // Not an error! Means we're inferring the closure type
- let (bounds, onceness) = match expr.node {
- ast::ExprProc(..) => {
- let mut bounds = ty::region_existential_bound(ty::ReStatic);
- bounds.builtin_bounds.insert(ty::BoundSend); // FIXME
- (bounds, ast::Once)
- }
- _ => {
- let region = fcx.infcx().next_region_var(
- infer::AddrOfRegion(expr.span));
- (ty::region_existential_bound(region), ast::Many)
- }
- };
- (None, onceness, bounds)
- }
- }
- };
-
- // construct the function type
- let fn_ty = astconv::ty_of_closure(fcx,
- expr.id,
- ast::NormalFn,
- expected_onceness,
- expected_bounds,
- store,
- decl,
- abi::Rust,
- expected_sig);
- let fty_sig = fn_ty.sig.clone();
- let fty = ty::mk_closure(tcx, fn_ty);
- debug!("check_expr_fn fty={}", fcx.infcx().ty_to_string(fty));
-
- fcx.write_ty(expr.id, fty);
-
- // If the closure is a stack closure and hasn't had some non-standard
- // style inferred for it, then check it under its parent's style.
- // Otherwise, use its own
- let (inherited_style, inherited_style_id) = match store {
- ty::RegionTraitStore(..) => (fcx.ps.borrow().fn_style,
- fcx.ps.borrow().def),
- ty::UniqTraitStore => (ast::NormalFn, expr.id)
- };
-
- check_fn(fcx.ccx,
- inherited_style,
- inherited_style_id,
- &fty_sig,
- &*decl,
- expr.id,
- &*body,
- fcx.inh);
- }
-
-
// Check field access expressions
fn check_field(fcx: &FnCtxt,
expr: &ast::Expr,
lvalue_pref: LvaluePreference,
base: &ast::Expr,
- field: &ast::SpannedIdent,
- tys: &[P<ast::Ty>]) {
+ field: &ast::SpannedIdent) {
let tcx = fcx.ccx.tcx;
check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
let expr_t = structurally_resolved_type(fcx, expr.span,
// FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
let (_, autoderefs, field_ty) =
autoderef(fcx, expr.span, expr_t, Some(base.id), lvalue_pref, |base_t, _| {
- match ty::get(base_t).sty {
+ match base_t.sty {
ty::ty_struct(base_id, ref substs) => {
debug!("struct named {}", ppaux::ty_to_string(tcx, base_t));
let fields = ty::lookup_struct_fields(tcx, base_id);
None => {}
}
- let tps: Vec<ty::t> = tys.iter().map(|ty| fcx.to_ty(&**ty)).collect();
- match method::lookup(fcx,
- expr,
- base,
- field.node.name,
- expr_t,
- tps.as_slice(),
- DontDerefArgs,
- CheckTraitsAndInherentMethods,
- AutoderefReceiver) {
- Ok(_) => {
- fcx.type_error_message(
- field.span,
- |actual| {
- format!("attempted to take value of method `{}` on type \
- `{}`", token::get_ident(field.node), actual)
- },
- expr_t, None);
-
- tcx.sess.span_help(field.span,
- "maybe a `()` to call it is missing? \
- If not, try an anonymous function");
- }
+ if method::exists(fcx, field.span, field.node.name, expr_t, expr.id) {
+ fcx.type_error_message(
+ field.span,
+ |actual| {
+ format!("attempted to take value of method `{}` on type \
+ `{}`", token::get_ident(field.node), actual)
+ },
+ expr_t, None);
- Err(_) => {
- fcx.type_error_message(
- expr.span,
- |actual| {
- format!("attempted access of field `{}` on \
- type `{}`, but no field with that \
- name was found",
- token::get_ident(field.node),
- actual)
- },
- expr_t, None);
- }
+ tcx.sess.span_help(field.span,
+ "maybe a `()` to call it is missing? \
+ If not, try an anonymous function");
+ } else {
+ fcx.type_error_message(
+ expr.span,
+ |actual| {
+ format!("attempted access of field `{}` on \
+ type `{}`, but no field with that \
+ name was found",
+ token::get_ident(field.node),
+ actual)
+ },
+ expr_t, None);
}
fcx.write_error(expr.id);
expr: &ast::Expr,
lvalue_pref: LvaluePreference,
base: &ast::Expr,
- idx: codemap::Spanned<uint>,
- _tys: &[P<ast::Ty>]) {
+ idx: codemap::Spanned<uint>) {
let tcx = fcx.ccx.tcx;
check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
let expr_t = structurally_resolved_type(fcx, expr.span,
// FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
let (_, autoderefs, field_ty) =
autoderef(fcx, expr.span, expr_t, Some(base.id), lvalue_pref, |base_t, _| {
- match ty::get(base_t).sty {
+ match base_t.sty {
ty::ty_struct(base_id, ref substs) => {
tuple_like = ty::is_tuple_struct(tcx, base_id);
if tuple_like {
fcx.write_error(expr.id);
}
- fn check_struct_or_variant_fields(fcx: &FnCtxt,
- struct_ty: ty::t,
- span: Span,
- class_id: ast::DefId,
- node_id: ast::NodeId,
- substitutions: subst::Substs,
- field_types: &[ty::field_ty],
- ast_fields: &[ast::Field],
- check_completeness: bool) {
+ fn check_struct_or_variant_fields<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+ struct_ty: Ty<'tcx>,
+ span: Span,
+ class_id: ast::DefId,
+ node_id: ast::NodeId,
+ substitutions: subst::Substs<'tcx>,
+ field_types: &[ty::field_ty],
+ ast_fields: &[ast::Field],
+ check_completeness: bool) {
let tcx = fcx.ccx.tcx;
let mut class_field_map = FnvHashMap::new();
let TypeAndSubsts {
ty: mut struct_type,
substs: struct_substs
- } = fcx.instantiate_item_type(span, class_id);
+ } = fcx.instantiate_type(span, class_id);
// Look up and check the fields.
let class_fields = ty::lookup_struct_fields(tcx, class_id);
let TypeAndSubsts {
ty: enum_type,
substs: substitutions
- } = fcx.instantiate_item_type(span, enum_id);
+ } = fcx.instantiate_type(span, enum_id);
// Look up and check the enum variant fields.
let variant_fields = ty::lookup_struct_fields(tcx, variant_id);
}
}
- type ExprCheckerWithTy = fn(&FnCtxt, &ast::Expr, ty::t);
+ type ExprCheckerWithTy = fn(&FnCtxt, &ast::Expr, Ty);
let tcx = fcx.ccx.tcx;
let id = expr.id;
Some(&**oprnd), oprnd_t, lvalue_pref) {
Some(mt) => mt.ty,
None => {
- let is_newtype = match ty::get(oprnd_t).sty {
+ let is_newtype = match oprnd_t.sty {
ty::ty_struct(did, ref substs) => {
let fields = ty::struct_fields(fcx.tcx(), did, substs);
fields.len() == 1
oprnd_t = structurally_resolved_type(fcx, oprnd.span,
oprnd_t);
if !(ty::type_is_integral(oprnd_t) ||
- ty::get(oprnd_t).sty == ty::ty_bool) {
+ oprnd_t.sty == ty::ty_bool) {
oprnd_t = check_user_unop(fcx, "!", "not",
tcx.lang_items.not_trait(),
expr, &**oprnd, oprnd_t);
match *expr_opt {
None =>
if let Err(_) = fcx.mk_eqty(false, infer::Misc(expr.span),
- result_type, ty::mk_nil()) {
+ result_type, ty::mk_nil(fcx.tcx())) {
span_err!(tcx.sess, expr.span, E0069,
"`return;` in function returning non-nil");
},
ast::ExprMatch(ref discrim, ref arms, _) => {
_match::check_match(fcx, expr, &**discrim, arms.as_slice());
}
- ast::ExprFnBlock(_, ref decl, ref body) => {
- let region = astconv::opt_ast_region_to_region(fcx,
- fcx.infcx(),
- expr.span,
- &None);
- check_expr_fn(fcx,
- expr,
- ty::RegionTraitStore(region, ast::MutMutable),
- &**decl,
- &**body,
- expected);
- }
- ast::ExprUnboxedFn(_, kind, ref decl, ref body) => {
- check_unboxed_closure(fcx,
- expr,
- kind,
- &**decl,
- &**body);
+ ast::ExprClosure(_, opt_kind, ref decl, ref body) => {
+ closure::check_expr_closure(fcx, expr, opt_kind, &**decl, &**body, expected);
}
ast::ExprProc(ref decl, ref body) => {
- check_expr_fn(fcx,
- expr,
- ty::UniqTraitStore,
- &**decl,
- &**body,
- expected);
+ closure::check_boxed_closure(fcx,
+ expr,
+ ty::UniqTraitStore,
+ &**decl,
+ &**body,
+ expected);
}
ast::ExprBlock(ref b) => {
check_block_with_expected(fcx, &**b, expected);
ast::ExprVec(ref args) => {
let uty = match expected {
ExpectHasType(uty) => {
- match ty::get(uty).sty {
+ match uty.sty {
ty::ty_vec(ty, _) => Some(ty),
_ => None
}
uty
}
None => {
- let t: ty::t = fcx.infcx().next_ty_var();
+ let t: Ty = fcx.infcx().next_ty_var();
for e in args.iter() {
check_expr_has_type(fcx, &**e, t);
}
let uty = match expected {
ExpectHasType(uty) => {
- match ty::get(uty).sty {
+ match uty.sty {
ty::ty_vec(ty, _) => Some(ty),
_ => None
}
(uty, uty)
}
None => {
- let t: ty::t = fcx.infcx().next_ty_var();
+ let t: Ty = fcx.infcx().next_ty_var();
check_expr_has_type(fcx, &**element, t);
(fcx.expr_ty(&**element), t)
}
Some(def) => {
// Verify that this was actually a struct.
let typ = ty::lookup_item_type(fcx.ccx.tcx, def.def_id());
- match ty::get(typ.ty).sty {
+ match typ.ty.sty {
ty::ty_struct(struct_did, _) => {
check_struct_constructor(fcx,
id,
let type_and_substs = astconv::ast_path_to_ty_relaxed(fcx,
fcx.infcx(),
struct_id,
- path,
- expr.id);
+ path);
match fcx.mk_subty(false,
infer::Misc(path.span),
actual_structure_type,
fcx.require_expr_have_sized_type(expr, traits::StructInitializerSized);
}
- ast::ExprField(ref base, ref field, ref tys) => {
- check_field(fcx, expr, lvalue_pref, &**base, field, tys.as_slice());
+ ast::ExprField(ref base, ref field, _) => {
+ check_field(fcx, expr, lvalue_pref, &**base, field);
}
- ast::ExprTupField(ref base, idx, ref tys) => {
- check_tup_field(fcx, expr, lvalue_pref, &**base, idx, tys.as_slice());
+ ast::ExprTupField(ref base, idx, _) => {
+ check_tup_field(fcx, expr, lvalue_pref, &**base, idx);
}
ast::ExprIndex(ref base, ref idx) => {
check_expr_with_lvalue_pref(fcx, &**base, lvalue_pref);
expr: &ast::Expr)
{
fcx.opt_node_ty_substs(expr.id, |item_substs| {
- for &ty in item_substs.substs.types.iter() {
- let default_bound = ty::ReScope(expr.id);
- let origin = infer::RelateDefaultParamBound(expr.span, ty);
- fcx.register_region_obligation(origin, ty, default_bound);
- }
+ fcx.add_default_region_param_bounds(&item_substs.substs, expr);
});
}
-impl Expectation {
- fn only_has_type(self) -> Expectation {
+impl<'tcx> Expectation<'tcx> {
+ fn only_has_type(self) -> Expectation<'tcx> {
match self {
NoExpectation | ExpectCastableToType(..) => NoExpectation,
ExpectHasType(t) => ExpectHasType(t)
// Resolves `expected` by a single level if it is a variable. If
// there is no expected type or resolution is not possible (e.g.,
// no constraints yet present), just returns `None`.
- fn resolve(self, fcx: &FnCtxt) -> Expectation {
+ fn resolve<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Expectation<'tcx> {
match self {
NoExpectation => {
NoExpectation
}
}
- fn map(self, fcx: &FnCtxt, unpack: |&ty::sty| -> Expectation) -> Expectation {
+ fn map<'a>(self, fcx: &FnCtxt<'a, 'tcx>,
+ unpack: |&ty::sty<'tcx>| -> Expectation<'tcx>)
+ -> Expectation<'tcx> {
match self.resolve(fcx) {
NoExpectation => NoExpectation,
- ExpectCastableToType(t) | ExpectHasType(t) => unpack(&ty::get(t).sty),
+ ExpectCastableToType(t) | ExpectHasType(t) => unpack(&t.sty),
}
}
- fn map_to_option<O>(self,
- fcx: &FnCtxt,
- unpack: |&ty::sty| -> Option<O>)
- -> Option<O>
+ fn map_to_option<'a, O>(self,
+ fcx: &FnCtxt<'a, 'tcx>,
+ unpack: |&ty::sty<'tcx>| -> Option<O>)
+ -> Option<O>
{
match self.resolve(fcx) {
NoExpectation => None,
- ExpectCastableToType(t) | ExpectHasType(t) => unpack(&ty::get(t).sty),
+ ExpectCastableToType(t) | ExpectHasType(t) => unpack(&t.sty),
}
}
}
-impl Repr for Expectation {
- fn repr(&self, tcx: &ty::ctxt) -> String {
+impl<'tcx> Repr<'tcx> for Expectation<'tcx> {
+ fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
match *self {
NoExpectation => format!("NoExpectation"),
ExpectHasType(t) => format!("ExpectHasType({})",
ast::StmtExpr(ref expr, id) => {
node_id = id;
// Check with expected type of ()
- check_expr_has_type(fcx, &**expr, ty::mk_nil());
+ check_expr_has_type(fcx, &**expr, ty::mk_nil(fcx.tcx()));
let expr_ty = fcx.expr_ty(&**expr);
saw_bot = saw_bot || fcx.infcx().type_var_diverges(expr_ty);
saw_err = saw_err || ty::type_is_error(expr_ty);
}
pub fn check_block_no_value(fcx: &FnCtxt, blk: &ast::Block) {
- check_block_with_expected(fcx, blk, ExpectHasType(ty::mk_nil()));
+ check_block_with_expected(fcx, blk, ExpectHasType(ty::mk_nil(fcx.tcx())));
let blkty = fcx.node_ty(blk.id);
if ty::type_is_error(blkty) {
fcx.write_error(blk.id);
} else {
- let nilty = ty::mk_nil();
+ let nilty = ty::mk_nil(fcx.tcx());
demand::suptype(fcx, blk.span, nilty, blkty);
}
}
-fn check_block_with_expected(fcx: &FnCtxt,
- blk: &ast::Block,
- expected: Expectation) {
+fn check_block_with_expected<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+ blk: &ast::Block,
+ expected: Expectation<'tcx>) {
let prev = {
let mut fcx_ps = fcx.ps.borrow_mut();
let fn_style_state = fcx_ps.recurse(blk);
/// Checks a constant appearing in a type. At the moment this is just the
/// length expression in a fixed-length vector, but someday it might be
/// extended to type-level numeric literals.
-pub fn check_const_in_type(tcx: &ty::ctxt,
- expr: &ast::Expr,
- expected_type: ty::t) {
+pub fn check_const_in_type<'tcx>(tcx: &ty::ctxt<'tcx>,
+ expr: &ast::Expr,
+ expected_type: Ty<'tcx>) {
// Synthesize a crate context. The trait map is not needed here (though I
// imagine it will be if we have associated statics --pcwalton), so we
// leave it blank.
check_const_with_ty(&fcx, sp, e, declty);
}
-pub fn check_const_with_ty(fcx: &FnCtxt,
- _: Span,
- e: &ast::Expr,
- declty: ty::t) {
+pub fn check_const_with_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+ _: Span,
+ e: &ast::Expr,
+ declty: Ty<'tcx>) {
// Gather locals in statics (because of block expressions).
// This is technically unnecessary because locals in static items are forbidden,
// but prevents type checking from blowing up before const checking can properly
span_err!(tcx.sess, sp, E0074, "SIMD vector cannot be generic");
return;
}
- match ty::get(t).sty {
+ match t.sty {
ty::ty_struct(did, ref substs) => {
let fields = ty::lookup_struct_fields(tcx, did);
if fields.is_empty() {
}
}
- fn do_check(ccx: &CrateCtxt,
- vs: &[P<ast::Variant>],
- id: ast::NodeId,
- hint: attr::ReprAttr)
- -> Vec<Rc<ty::VariantInfo>> {
+ fn do_check<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
+ vs: &[P<ast::Variant>],
+ id: ast::NodeId,
+ hint: attr::ReprAttr)
+ -> Vec<Rc<ty::VariantInfo<'tcx>>> {
let rty = ty::node_id_to_type(ccx.tcx, id);
let mut variants: Vec<Rc<ty::VariantInfo>> = Vec::new();
}
// Returns the type parameter count and the type for the given definition.
-pub fn polytype_for_def(fcx: &FnCtxt,
- sp: Span,
- defn: def::Def)
- -> Polytype {
+pub fn polytype_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+ sp: Span,
+ defn: def::Def)
+ -> Polytype<'tcx> {
match defn {
def::DefLocal(nid) | def::DefUpvar(nid, _, _) => {
let typ = fcx.local_ty(sp, nid);
// Instantiates the given path, which must refer to an item with the given
// number of type parameters and type.
-pub fn instantiate_path(fcx: &FnCtxt,
- path: &ast::Path,
- polytype: Polytype,
- def: def::Def,
- span: Span,
- node_id: ast::NodeId) {
+pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+ path: &ast::Path,
+ polytype: Polytype<'tcx>,
+ def: def::Def,
+ span: Span,
+ node_id: ast::NodeId) {
debug!("instantiate_path(path={}, def={}, node_id={}, polytype={})",
path.repr(fcx.tcx()),
def.repr(fcx.tcx()),
assert_eq!(substs.regions().len(space), region_defs.len(space));
}
+ // The things we are substituting into the type should not contain
+ // escaping late-bound regions.
+ assert!(!substs.has_regions_escaping_depth(0));
+
+ // In the case of static items taken from impls, there may be
+ // late-bound regions associated with the impl (not declared on
+ // the fn itself). Those should be replaced with fresh variables
+ // now. These can appear either on the type being referenced, or
+ // on the associated bounds.
+ let bounds = polytype.generics.to_bounds(fcx.tcx(), &substs);
+ let (ty_late_bound, bounds) =
+ fcx.infcx().replace_late_bound_regions_with_fresh_var(
+ span,
+ infer::FnCall,
+ &ty::bind((polytype.ty, bounds))).0.value;
+
+ debug!("after late-bounds have been replaced: ty_late_bound={}", ty_late_bound.repr(fcx.tcx()));
+ debug!("after late-bounds have been replaced: bounds={}", bounds.repr(fcx.tcx()));
+
fcx.add_obligations_for_parameters(
traits::ObligationCause::new(span, traits::ItemObligation(def.def_id())),
&substs,
- &polytype.generics);
+ &bounds);
- fcx.write_ty_substs(node_id, polytype.ty, ty::ItemSubsts {
- substs: substs,
- });
+ // Substitute the values for the type parameters into the type of
+ // the referenced item.
+ let ty_substituted = ty_late_bound.subst(fcx.tcx(), &substs);
+
+ debug!("ty_substituted: ty_substituted={}", ty_substituted.repr(fcx.tcx()));
+
+ fcx.write_ty(node_id, ty_substituted);
+ fcx.write_substs(node_id, ty::ItemSubsts { substs: substs });
+ return;
fn report_error_if_segment_contains_type_parameters(
fcx: &FnCtxt,
}
}
- fn push_explicit_parameters_from_segment_to_substs(
- fcx: &FnCtxt,
+ fn push_explicit_parameters_from_segment_to_substs<'a, 'tcx>(
+ fcx: &FnCtxt<'a, 'tcx>,
space: subst::ParamSpace,
span: Span,
- type_defs: &VecPerParamSpace<ty::TypeParameterDef>,
+ type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
segment: &ast::PathSegment,
- substs: &mut Substs)
+ substs: &mut Substs<'tcx>)
{
/*!
* Finds the parameters that the user provided and adds them
}
}
- fn push_explicit_angle_bracketed_parameters_from_segment_to_substs(
- fcx: &FnCtxt,
+ fn push_explicit_angle_bracketed_parameters_from_segment_to_substs<'a, 'tcx>(
+ fcx: &FnCtxt<'a, 'tcx>,
space: subst::ParamSpace,
- type_defs: &VecPerParamSpace<ty::TypeParameterDef>,
+ type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
data: &ast::AngleBracketedParameterData,
- substs: &mut Substs)
+ substs: &mut Substs<'tcx>)
{
{
let type_count = type_defs.len(space);
}
}
- fn push_explicit_parenthesized_parameters_from_segment_to_substs(
- fcx: &FnCtxt,
+ fn push_explicit_parenthesized_parameters_from_segment_to_substs<'a, 'tcx>(
+ fcx: &FnCtxt<'a, 'tcx>,
space: subst::ParamSpace,
span: Span,
- type_defs: &VecPerParamSpace<ty::TypeParameterDef>,
+ type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
data: &ast::ParenthesizedParameterData,
- substs: &mut Substs)
+ substs: &mut Substs<'tcx>)
{
/*!
* As with
type_count);
}
- let input_tys: Vec<ty::t> =
+ let input_tys: Vec<Ty> =
data.inputs.iter().map(|ty| fcx.to_ty(&**ty)).collect();
let tuple_ty =
- ty::mk_tup_or_nil(fcx.tcx(), input_tys);
+ ty::mk_tup(fcx.tcx(), input_tys);
if type_count >= 1 {
substs.types.push(space, tuple_ty);
}
- let output_ty: Option<ty::t> =
+ let output_ty: Option<Ty> =
data.output.as_ref().map(|ty| fcx.to_ty(&**ty));
let output_ty =
- output_ty.unwrap_or(ty::mk_nil());
+ output_ty.unwrap_or(ty::mk_nil(fcx.tcx()));
if type_count >= 2 {
substs.types.push(space, output_ty);
}
}
- fn adjust_type_parameters(
- fcx: &FnCtxt,
+ fn adjust_type_parameters<'a, 'tcx>(
+ fcx: &FnCtxt<'a, 'tcx>,
span: Span,
space: ParamSpace,
- defs: &VecPerParamSpace<ty::TypeParameterDef>,
- substs: &mut Substs)
+ defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
+ substs: &mut Substs<'tcx>)
{
let provided_len = substs.types.len(space);
let desired = defs.get_slice(space);
// Resolves `typ` by a single level if `typ` is a type variable. If no
// resolution is possible, then an error is reported.
-pub fn structurally_resolved_type(fcx: &FnCtxt, sp: Span, mut ty: ty::t) -> ty::t {
+pub fn structurally_resolved_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
+ mut ty: Ty<'tcx>) -> Ty<'tcx> {
// If `ty` is a type variable, see whether we already know what it is.
ty = fcx.infcx().shallow_resolve(ty);
}
// Returns the one-level-deep structure of the given type.
-pub fn structure_of<'a>(fcx: &FnCtxt, sp: Span, typ: ty::t)
- -> &'a ty::sty {
- &ty::get(structurally_resolved_type(fcx, sp, typ)).sty
+pub fn structure_of<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span, typ: Ty<'tcx>)
+ -> &'tcx ty::sty<'tcx> {
+ &structurally_resolved_type(fcx, sp, typ).sty
}
// Returns true if b contains a break that can exit from b
}}))
}
-pub fn check_bounds_are_used(ccx: &CrateCtxt,
- span: Span,
- tps: &OwnedSlice<ast::TyParam>,
- ty: ty::t) {
+pub fn check_bounds_are_used<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
+ span: Span,
+ tps: &OwnedSlice<ast::TyParam>,
+ ty: Ty<'tcx>) {
debug!("check_bounds_are_used(n_tps={}, ty={})",
tps.len(), ppaux::ty_to_string(ccx.tcx, ty));
let mut tps_used = Vec::from_elem(tps.len(), false);
ty::walk_ty(ty, |t| {
- match ty::get(t).sty {
+ match t.sty {
ty::ty_param(ParamTy {idx, ..}) => {
debug!("Found use of ty param num {}", idx);
tps_used[idx] = true;
}
pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
- fn param(ccx: &CrateCtxt, n: uint) -> ty::t {
+ fn param<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, n: uint) -> Ty<'tcx> {
ty::mk_param(ccx.tcx, subst::FnSpace, n, local_def(0))
}
"load" => (1, vec!(ty::mk_imm_ptr(tcx, param(ccx, 0))),
param(ccx, 0)),
"store" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
- ty::mk_nil()),
+ ty::mk_nil(tcx)),
"xchg" | "xadd" | "xsub" | "and" | "nand" | "or" | "xor" | "max" |
"min" | "umax" | "umin" => {
param(ccx, 0))
}
"fence" => {
- (0, Vec::new(), ty::mk_nil())
+ (0, Vec::new(), ty::mk_nil(tcx))
}
op => {
span_err!(tcx.sess, it.span, E0092,
(0, Vec::new(), ty::FnDiverging)
} else {
let (n_tps, inputs, output) = match name.get() {
- "breakpoint" => (0, Vec::new(), ty::mk_nil()),
+ "breakpoint" => (0, Vec::new(), ty::mk_nil(tcx)),
"size_of" |
"pref_align_of" | "min_align_of" => (1u, Vec::new(), ty::mk_uint()),
"init" => (1u, Vec::new(), param(ccx, 0u)),
"uninit" => (1u, Vec::new(), param(ccx, 0u)),
- "forget" => (1u, vec!( param(ccx, 0) ), ty::mk_nil()),
+ "forget" => (1u, vec!( param(ccx, 0) ), ty::mk_nil(tcx)),
"transmute" => (2, vec!( param(ccx, 0) ), param(ccx, 1)),
"move_val_init" => {
(1u,
vec!(
- ty::mk_mut_rptr(tcx, ty::ReLateBound(it.id, ty::BrAnon(0)), param(ccx, 0)),
+ ty::mk_mut_rptr(tcx, ty::ReLateBound(ty::DebruijnIndex::new(1), ty::BrAnon(0)),
+ param(ccx, 0)),
param(ccx, 0u)
),
- ty::mk_nil())
+ ty::mk_nil(tcx))
}
"needs_drop" => (1u, Vec::new(), ty::mk_bool()),
"owns_managed" => (1u, Vec::new(), ty::mk_bool()),
}),
ty::mk_uint()
),
- ty::mk_nil())
+ ty::mk_nil(tcx))
}
"set_memory" | "volatile_set_memory" => {
(1,
ty::mk_u8(),
ty::mk_uint()
),
- ty::mk_nil())
+ ty::mk_nil(tcx))
}
"sqrtf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
"sqrtf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
"volatile_load" =>
(1, vec!( ty::mk_imm_ptr(tcx, param(ccx, 0)) ), param(ccx, 0)),
"volatile_store" =>
- (1, vec!( ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0) ), ty::mk_nil()),
+ (1, vec!( ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0) ), ty::mk_nil(tcx)),
"i8_add_with_overflow" | "i8_sub_with_overflow" | "i8_mul_with_overflow" =>
(0, vec!(ty::mk_i8(), ty::mk_i8()),
"return_address" => (0, vec![], ty::mk_imm_ptr(tcx, ty::mk_u8())),
- "assume" => (0, vec![ty::mk_bool()], ty::mk_nil()),
+ "assume" => (0, vec![ty::mk_bool()], ty::mk_nil(tcx)),
ref other => {
span_err!(tcx.sess, it.span, E0093,
fn_style: ast::UnsafeFn,
abi: abi::RustIntrinsic,
sig: FnSig {
- binder_id: it.id,
inputs: inputs,
output: output,
variadic: false,
}
}
-impl Repr for RegionObligation {
- fn repr(&self, tcx: &ty::ctxt) -> String {
+impl<'tcx> Repr<'tcx> for RegionObligation<'tcx> {
+ fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
format!("RegionObligation(sub_region={}, sup_type={}, origin={})",
self.sub_region.repr(tcx),
self.sup_type.repr(tcx),