use super::check_argument_types;
use super::check_expr;
use super::check_method_argument_types;
+use super::demand;
+use super::DeferredResolution;
use super::err_args;
use super::Expectation;
use super::expected_types_for_fn_args;
use super::UnresolvedTypeAction;
use super::write_call;
+use CrateCtxt;
use middle::infer;
-use middle::ty::{self, Ty};
+use middle::ty::{self, Ty, ClosureTyper};
use syntax::ast;
use syntax::codemap::Span;
use syntax::parse::token;
use syntax::ptr::P;
-use CrateCtxt;
+use util::ppaux::Repr;
/// Check that it is legal to call methods of the trait corresponding
/// to `trait_id` (this only cares about the trait, not the specific
}
pub fn check_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
- call_expr: &ast::Expr,
- callee_expr: &ast::Expr,
- arg_exprs: &[P<ast::Expr>],
+ call_expr: &'tcx ast::Expr,
+ callee_expr: &'tcx ast::Expr,
+ arg_exprs: &'tcx [P<ast::Expr>],
expected: Expectation<'tcx>)
{
check_expr(fcx, callee_expr);
confirm_builtin_call(fcx, call_expr, callee_ty, arg_exprs, expected);
}
+ Some(CallStep::Closure(fn_sig)) => {
+ confirm_closure_call(fcx, call_expr, arg_exprs, expected, fn_sig);
+ }
+
Some(CallStep::Overloaded(method_callee)) => {
- confirm_overloaded_call(fcx, call_expr, arg_exprs, method_callee, expected);
+ confirm_overloaded_call(fcx, call_expr, callee_expr,
+ arg_exprs, expected, method_callee);
}
}
}
enum CallStep<'tcx> {
Builtin,
+ Closure(ty::FnSig<'tcx>),
Overloaded(ty::MethodCallee<'tcx>)
}
fn try_overloaded_call_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
- call_expr: &ast::Expr,
- callee_expr: &ast::Expr,
+ call_expr: &'tcx ast::Expr,
+ callee_expr: &'tcx ast::Expr,
adjusted_ty: Ty<'tcx>,
autoderefref: ty::AutoDerefRef<'tcx>)
-> Option<CallStep<'tcx>>
{
+ debug!("try_overloaded_call_step(call_expr={}, adjusted_ty={}, autoderefref={})",
+ call_expr.repr(fcx.tcx()),
+ adjusted_ty.repr(fcx.tcx()),
+ autoderefref.repr(fcx.tcx()));
+
// If the callee is a bare function or a closure, then we're all set.
match structurally_resolved_type(fcx, callee_expr.span, adjusted_ty).sty {
ty::ty_bare_fn(..) => {
return Some(CallStep::Builtin);
}
+ ty::ty_closure(def_id, _, substs) => {
+ let closure_ty =
+ fcx.closure_type(def_id, substs);
+ let fn_sig =
+ fcx.infcx().replace_late_bound_regions_with_fresh_var(call_expr.span,
+ infer::FnCall,
+ &closure_ty.sig).0;
+ fcx.record_deferred_resolution(box CallResolution {
+ call_expr: call_expr,
+ callee_expr: callee_expr,
+ adjusted_ty: adjusted_ty,
+ autoderefref: autoderefref,
+ fn_sig: fn_sig.clone(),
+ });
+ return Some(CallStep::Closure(fn_sig));
+ }
+
_ => {}
}
+ try_overloaded_call_traits(fcx, call_expr, callee_expr, adjusted_ty, autoderefref)
+ .map(|method_callee| CallStep::Overloaded(method_callee))
+}
+
+fn try_overloaded_call_traits<'a,'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+ call_expr: &ast::Expr,
+ callee_expr: &ast::Expr,
+ adjusted_ty: Ty<'tcx>,
+ autoderefref: ty::AutoDerefRef<'tcx>)
+ -> Option<ty::MethodCallee<'tcx>>
+{
// Try the options that are least restrictive on the caller first.
for &(opt_trait_def_id, method_name) in [
(fcx.tcx().lang_items.fn_trait(), token::intern("call")),
None) {
None => continue,
Some(method_callee) => {
- return Some(CallStep::Overloaded(method_callee));
+ return Some(method_callee);
}
}
}
fn confirm_builtin_call<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
call_expr: &ast::Expr,
callee_ty: Ty<'tcx>,
- arg_exprs: &[P<ast::Expr>],
+ arg_exprs: &'tcx [P<ast::Expr>],
expected: Expectation<'tcx>)
{
let error_fn_sig;
write_call(fcx, call_expr, fn_sig.output);
}
+fn confirm_closure_call<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
+ call_expr: &ast::Expr,
+ arg_exprs: &'tcx [P<ast::Expr>],
+ expected: Expectation<'tcx>,
+ fn_sig: ty::FnSig<'tcx>)
+{
+ // `fn_sig` is the *signature* of the cosure being called. We
+ // don't know the full details yet (`Fn` vs `FnMut` etc), but we
+ // do know the types expected for each argument and the return
+ // type.
+
+ let expected_arg_tys =
+ expected_types_for_fn_args(fcx,
+ call_expr.span,
+ expected,
+ fn_sig.output.clone(),
+ &*fn_sig.inputs);
+
+ check_argument_types(fcx,
+ call_expr.span,
+ &*fn_sig.inputs,
+ &*expected_arg_tys,
+ arg_exprs,
+ AutorefArgs::No,
+ fn_sig.variadic,
+ TupleArgumentsFlag::TupleArguments);
+
+ write_call(fcx, call_expr, fn_sig.output);
+}
+
fn confirm_overloaded_call<'a,'tcx>(fcx: &FnCtxt<'a, 'tcx>,
call_expr: &ast::Expr,
- arg_exprs: &[P<ast::Expr>],
- method_callee: ty::MethodCallee<'tcx>,
- expected: Expectation<'tcx>)
+ callee_expr: &'tcx ast::Expr,
+ arg_exprs: &'tcx [P<ast::Expr>],
+ expected: Expectation<'tcx>,
+ method_callee: ty::MethodCallee<'tcx>)
{
- let output_type = check_method_argument_types(fcx,
- call_expr.span,
- method_callee.ty,
- call_expr,
- arg_exprs,
- AutorefArgs::No,
- TupleArgumentsFlag::TupleArguments,
- expected);
+ let output_type =
+ check_method_argument_types(fcx,
+ call_expr.span,
+ method_callee.ty,
+ callee_expr,
+ arg_exprs,
+ AutorefArgs::No,
+ TupleArgumentsFlag::TupleArguments,
+ expected);
+ write_call(fcx, call_expr, output_type);
+
+ write_overloaded_call_method_map(fcx, call_expr, method_callee);
+}
+
+fn write_overloaded_call_method_map<'a,'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+ call_expr: &ast::Expr,
+ method_callee: ty::MethodCallee<'tcx>) {
let method_call = ty::MethodCall::expr(call_expr.id);
fcx.inh.method_map.borrow_mut().insert(method_call, method_callee);
- write_call(fcx, call_expr, output_type);
}
+struct CallResolution<'tcx> {
+ call_expr: &'tcx ast::Expr,
+ callee_expr: &'tcx ast::Expr,
+ adjusted_ty: Ty<'tcx>,
+ autoderefref: ty::AutoDerefRef<'tcx>,
+ fn_sig: ty::FnSig<'tcx>,
+}
+
+impl<'tcx> Repr<'tcx> for CallResolution<'tcx> {
+ fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
+ format!("CallResolution(call_expr={}, callee_expr={}, adjusted_ty={}, \
+ autoderefref={}, fn_sig={})",
+ self.call_expr.repr(tcx),
+ self.callee_expr.repr(tcx),
+ self.adjusted_ty.repr(tcx),
+ self.autoderefref.repr(tcx),
+ self.fn_sig.repr(tcx))
+ }
+}
+
+impl<'tcx> DeferredResolution<'tcx> for CallResolution<'tcx> {
+ fn attempt_resolution<'a>(&self, fcx: &FnCtxt<'a,'tcx>) -> bool {
+ debug!("attempt_resolution() {}",
+ self.repr(fcx.tcx()));
+
+ // We may now know enough to figure out fn vs fnmut etc.
+ match try_overloaded_call_traits(fcx, self.call_expr, self.callee_expr,
+ self.adjusted_ty, self.autoderefref.clone()) {
+ None => false,
+ Some(method_callee) => {
+ // One problem is that when we get here, we are going
+ // to have a newly instantiated function signature
+ // from the call trait. This has to be reconciled with
+ // the older function signature we had before. In
+ // principle we *should* be able to fn_sigs(), but we
+ // can't because of the annoying need for a TypeTrace.
+ // (This always bites me, should find a way to
+ // refactor it.)
+ let method_sig =
+ ty::assert_no_late_bound_regions(fcx.tcx(),
+ ty::ty_fn_sig(method_callee.ty));
+
+ debug!("attempt_resolution: method_callee={}",
+ method_callee.repr(fcx.tcx()));
+
+ for (&method_arg_ty, &self_arg_ty) in
+ method_sig.inputs[1..].iter().zip(self.fn_sig.inputs.iter())
+ {
+ demand::eqtype(fcx, self.call_expr.span, self_arg_ty, method_arg_ty);
+ }
+
+ demand::eqtype(fcx,
+ self.call_expr.span,
+ method_sig.output.unwrap(),
+ self.fn_sig.output.unwrap());
+
+ write_overloaded_call_method_map(fcx, self.call_expr, method_callee);
+
+ true
+ }
+ }
+ }
+}
// Tracks trait obligations incurred during this function body.
fulfillment_cx: RefCell<traits::FulfillmentContext<'tcx>>,
+
+ //
+ deferred_resolutions: RefCell<Vec<DeferredResolutionHandler<'tcx>>>,
+}
+
+trait DeferredResolution<'tcx> {
+ fn attempt_resolution<'a>(&self, fcx: &FnCtxt<'a,'tcx>) -> bool;
}
+type DeferredResolutionHandler<'tcx> = Box<DeferredResolution<'tcx>+'tcx>;
+
/// When type-checking an expression, we propagate downward
/// whatever type hint we are able in the form of an `Expectation`.
#[derive(Copy)]
closures: RefCell::new(DefIdMap()),
fn_sig_map: RefCell::new(NodeMap()),
fulfillment_cx: RefCell::new(traits::FulfillmentContext::new()),
+ deferred_resolutions: RefCell::new(Vec::new()),
}
}
struct CheckItemTypesVisitor<'a, 'tcx: 'a> { ccx: &'a CrateCtxt<'a, 'tcx> }
-impl<'a, 'tcx, 'v> Visitor<'v> for CheckItemTypesVisitor<'a, 'tcx> {
- fn visit_item(&mut self, i: &ast::Item) {
+impl<'a, 'tcx> Visitor<'tcx> for CheckItemTypesVisitor<'a, 'tcx> {
+ fn visit_item(&mut self, i: &'tcx ast::Item) {
check_item(self.ccx, i);
visit::walk_item(self, i);
}
- fn visit_ty(&mut self, t: &ast::Ty) {
+ fn visit_ty(&mut self, t: &'tcx ast::Ty) {
match t.node {
ast::TyFixedLengthVec(_, ref expr) => {
check_const_in_type(self.ccx, &**expr, self.ccx.tcx.types.uint);
}
fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
- decl: &ast::FnDecl,
- body: &ast::Block,
+ decl: &'tcx ast::FnDecl,
+ body: &'tcx ast::Block,
id: ast::NodeId,
raw_fty: Ty<'tcx>,
param_env: ty::ParameterEnvironment<'a, 'tcx>)
}
}
-impl<'a, 'tcx, 'v> Visitor<'v> for GatherLocalsVisitor<'a, 'tcx> {
+impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> {
// Add explicitly-declared locals.
- fn visit_local(&mut self, local: &ast::Local) {
+ fn visit_local(&mut self, local: &'tcx ast::Local) {
let o_ty = match local.ty {
Some(ref ty) => Some(self.fcx.to_ty(&**ty)),
None => None
}
// Add pattern bindings.
- fn visit_pat(&mut self, p: &ast::Pat) {
+ fn visit_pat(&mut self, p: &'tcx ast::Pat) {
if let ast::PatIdent(_, ref path1, _) = p.node {
if pat_util::pat_is_binding(&self.fcx.ccx.tcx.def_map, p) {
let var_ty = self.assign(p.span, p.id, None);
visit::walk_pat(self, p);
}
- fn visit_block(&mut self, b: &ast::Block) {
+ fn visit_block(&mut self, b: &'tcx ast::Block) {
// non-obvious: the `blk` variable maps to region lb, so
// we have to keep this up-to-date. This
// is... unfortunate. It'd be nice to not need this.
// Since an expr occurs as part of the type fixed size arrays we
// need to record the type for that node
- fn visit_ty(&mut self, t: &ast::Ty) {
+ fn visit_ty(&mut self, t: &'tcx ast::Ty) {
match t.node {
ast::TyFixedLengthVec(ref ty, ref count_expr) => {
self.visit_ty(&**ty);
}
// Don't descend into fns and items
- fn visit_fn(&mut self, _: visit::FnKind<'v>, _: &'v ast::FnDecl,
- _: &'v ast::Block, _: Span, _: ast::NodeId) { }
+ fn visit_fn(&mut self, _: visit::FnKind<'tcx>, _: &'tcx ast::FnDecl,
+ _: &'tcx ast::Block, _: Span, _: ast::NodeId) { }
fn visit_item(&mut self, _: &ast::Item) { }
}
unsafety: ast::Unsafety,
unsafety_id: ast::NodeId,
fn_sig: &ty::FnSig<'tcx>,
- decl: &ast::FnDecl,
+ decl: &'tcx ast::FnDecl,
fn_id: ast::NodeId,
- body: &ast::Block,
+ body: &'tcx ast::Block,
inherited: &'a Inherited<'a, 'tcx>)
-> FnCtxt<'a, 'tcx>
{
}
}
-pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) {
+pub fn check_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) {
debug!("check_item(it.id={}, it.ident={})",
it.id,
ty::item_path_str(ccx.tcx, local_def(it.id)));
/// * `method`: the method definition
fn check_method_body<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
item_generics: &ty::Generics<'tcx>,
- method: &ast::Method) {
+ method: &'tcx ast::Method) {
debug!("check_method_body(item_generics={}, method.id={})",
item_generics.repr(ccx.tcx),
method.id);
}
}
-fn check_cast(fcx: &FnCtxt,
- cast_expr: &ast::Expr,
- e: &ast::Expr,
- t: &ast::Ty) {
+fn check_cast<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
+ cast_expr: &ast::Expr,
+ e: &'tcx ast::Expr,
+ t: &ast::Ty) {
let id = cast_expr.id;
let span = cast_expr.span;
if ty::type_has_ty_infer(t) || ty::type_is_error(t) { Err(()) } else { Ok(t) }
}
+ fn record_deferred_resolution(&self, r: DeferredResolutionHandler<'tcx>) {
+ self.inh.deferred_resolutions.borrow_mut().push(r);
+ }
+
pub fn tag(&self) -> String {
format!("{:?}", self as *const FnCtxt)
}
fn try_index_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
method_call: MethodCall,
expr: &ast::Expr,
- base_expr: &ast::Expr,
+ base_expr: &'tcx ast::Expr,
adjusted_ty: Ty<'tcx>,
adjustment: ty::AutoDerefRef<'tcx>,
lvalue_pref: LvaluePreference,
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>],
+ callee_expr: &'tcx ast::Expr,
+ args_no_rcvr: &'tcx [P<ast::Expr>],
autoref_args: AutorefArgs,
tuple_arguments: TupleArgumentsFlag,
expected: Expectation<'tcx>)
sp: Span,
fn_inputs: &[Ty<'tcx>],
expected_arg_tys: &[Ty<'tcx>],
- args: &[P<ast::Expr>],
+ args: &'tcx [P<ast::Expr>],
autoref_args: AutorefArgs,
variadic: bool,
tuple_arguments: TupleArgumentsFlag) {
}
pub fn check_expr_has_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
- expr: &ast::Expr,
+ expr: &'tcx ast::Expr,
expected: Ty<'tcx>) {
check_expr_with_unifier(
fcx, expr, ExpectHasType(expected), NoPreference,
}
fn check_expr_coercable_to_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
- expr: &ast::Expr,
+ expr: &'tcx 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<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, expr: &ast::Expr,
+fn check_expr_with_hint<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, expr: &'tcx ast::Expr,
expected: Ty<'tcx>) {
check_expr_with_unifier(
fcx, expr, ExpectHasType(expected), NoPreference,
}
fn check_expr_with_expectation<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
- expr: &ast::Expr,
+ expr: &'tcx ast::Expr,
expected: Expectation<'tcx>) {
check_expr_with_unifier(
fcx, expr, expected, NoPreference,
}
fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
- expr: &ast::Expr,
+ expr: &'tcx ast::Expr,
expected: Expectation<'tcx>,
lvalue_pref: LvaluePreference)
{
check_expr_with_unifier(fcx, expr, expected, lvalue_pref, || ())
}
-fn check_expr(fcx: &FnCtxt, expr: &ast::Expr) {
+fn check_expr<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, expr: &'tcx ast::Expr) {
check_expr_with_unifier(fcx, expr, NoExpectation, NoPreference, || ())
}
-fn check_expr_with_lvalue_pref(fcx: &FnCtxt, expr: &ast::Expr,
- lvalue_pref: LvaluePreference) {
+fn check_expr_with_lvalue_pref<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, expr: &'tcx ast::Expr,
+ lvalue_pref: LvaluePreference) {
check_expr_with_unifier(fcx, expr, NoExpectation, lvalue_pref, || ())
}
/// that there are actually multiple representations for `ty_err`, so avoid
/// that when err needs to be handled differently.
fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
- expr: &ast::Expr,
+ expr: &'tcx ast::Expr,
expected: Expectation<'tcx>,
lvalue_pref: LvaluePreference,
unifier: F) where
// Checks a method call.
fn check_method_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
- expr: &ast::Expr,
+ expr: &'tcx ast::Expr,
method_name: ast::SpannedIdent,
- args: &[P<ast::Expr>],
+ args: &'tcx [P<ast::Expr>],
tps: &[P<ast::Ty>],
expected: Expectation<'tcx>,
lvalue_pref: LvaluePreference) {
// A generic function for checking the then and else in an if
// or if-else.
fn check_then_else<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
- cond_expr: &ast::Expr,
- then_blk: &ast::Block,
- opt_else_expr: Option<&ast::Expr>,
+ cond_expr: &'tcx ast::Expr,
+ then_blk: &'tcx ast::Block,
+ opt_else_expr: Option<&'tcx ast::Expr>,
id: ast::NodeId,
sp: Span,
expected: Expectation<'tcx>) {
}
fn lookup_op_method<'a, 'tcx, F>(fcx: &'a FnCtxt<'a, 'tcx>,
- op_ex: &ast::Expr,
+ op_ex: &'tcx ast::Expr,
lhs_ty: Ty<'tcx>,
opname: ast::Name,
trait_did: Option<ast::DefId>,
lhs: &'a ast::Expr,
- rhs: Option<&P<ast::Expr>>,
+ rhs: Option<&'tcx P<ast::Expr>>,
unbound_method: F,
autoref_args: AutorefArgs) -> Ty<'tcx> where
F: FnOnce(),
}
// could be either an expr_binop or an expr_assign_binop
- fn check_binop(fcx: &FnCtxt,
- expr: &ast::Expr,
- op: ast::BinOp,
- lhs: &ast::Expr,
- rhs: &P<ast::Expr>,
- is_binop_assignment: IsBinopAssignment) {
+ fn check_binop<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
+ expr: &'tcx ast::Expr,
+ op: ast::BinOp,
+ lhs: &'tcx ast::Expr,
+ rhs: &'tcx P<ast::Expr>,
+ is_binop_assignment: IsBinopAssignment) {
let tcx = fcx.ccx.tcx;
let lvalue_pref = match is_binop_assignment {
}
fn check_user_binop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
- ex: &ast::Expr,
- lhs_expr: &ast::Expr,
+ ex: &'tcx ast::Expr,
+ lhs_expr: &'tcx ast::Expr,
lhs_resolved_t: Ty<'tcx>,
op: ast::BinOp,
- rhs: &P<ast::Expr>) -> Ty<'tcx> {
+ rhs: &'tcx P<ast::Expr>) -> Ty<'tcx> {
let tcx = fcx.ccx.tcx;
let lang = &tcx.lang_items;
let (name, trait_did) = match op.node {
op_str: &str,
mname: &str,
trait_did: Option<ast::DefId>,
- ex: &ast::Expr,
- rhs_expr: &ast::Expr,
+ ex: &'tcx ast::Expr,
+ rhs_expr: &'tcx ast::Expr,
rhs_t: Ty<'tcx>,
op: ast::UnOp) -> Ty<'tcx> {
lookup_op_method(fcx, ex, rhs_t, token::intern(mname),
}
// Check field access expressions
- fn check_field(fcx: &FnCtxt,
- expr: &ast::Expr,
- lvalue_pref: LvaluePreference,
- base: &ast::Expr,
- field: &ast::SpannedIdent) {
+ fn check_field<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
+ expr: &'tcx ast::Expr,
+ lvalue_pref: LvaluePreference,
+ base: &'tcx ast::Expr,
+ 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,
}
// Check tuple index expressions
- fn check_tup_field(fcx: &FnCtxt,
- expr: &ast::Expr,
- lvalue_pref: LvaluePreference,
- base: &ast::Expr,
- idx: codemap::Spanned<uint>) {
+ fn check_tup_field<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
+ expr: &'tcx ast::Expr,
+ lvalue_pref: LvaluePreference,
+ base: &'tcx ast::Expr,
+ 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,
node_id: ast::NodeId,
substitutions: &'tcx subst::Substs<'tcx>,
field_types: &[ty::field_ty],
- ast_fields: &[ast::Field],
+ ast_fields: &'tcx [ast::Field],
check_completeness: bool,
enum_id_opt: Option<ast::DefId>) {
let tcx = fcx.ccx.tcx;
}
}
- fn check_struct_constructor(fcx: &FnCtxt,
- id: ast::NodeId,
- span: codemap::Span,
- class_id: ast::DefId,
- fields: &[ast::Field],
- base_expr: Option<&ast::Expr>) {
+ fn check_struct_constructor<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
+ id: ast::NodeId,
+ span: codemap::Span,
+ class_id: ast::DefId,
+ fields: &'tcx [ast::Field],
+ base_expr: Option<&'tcx ast::Expr>) {
let tcx = fcx.ccx.tcx;
// Generate the struct type.
fcx.write_ty(id, struct_type);
}
- fn check_struct_enum_variant(fcx: &FnCtxt,
- id: ast::NodeId,
- span: codemap::Span,
- enum_id: ast::DefId,
- variant_id: ast::DefId,
- fields: &[ast::Field]) {
+ fn check_struct_enum_variant<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
+ id: ast::NodeId,
+ span: codemap::Span,
+ enum_id: ast::DefId,
+ variant_id: ast::DefId,
+ fields: &'tcx [ast::Field]) {
let tcx = fcx.ccx.tcx;
// Look up the number of type parameters and the raw type, and
fcx.write_ty(id, enum_type);
}
- fn check_struct_fields_on_error(fcx: &FnCtxt,
- id: ast::NodeId,
- fields: &[ast::Field],
- base_expr: &Option<P<ast::Expr>>) {
+ fn check_struct_fields_on_error<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
+ id: ast::NodeId,
+ fields: &'tcx [ast::Field],
+ base_expr: &'tcx Option<P<ast::Expr>>) {
// Make sure to still write the types
// otherwise we might ICE
fcx.write_error(id);
}
}
-pub fn check_decl_initializer(fcx: &FnCtxt,
- nid: ast::NodeId,
- init: &ast::Expr)
+pub fn check_decl_initializer<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
+ nid: ast::NodeId,
+ init: &'tcx ast::Expr)
{
let local_ty = fcx.local_ty(init.span, nid);
check_expr_coercable_to_type(fcx, init, local_ty)
}
-pub fn check_decl_local(fcx: &FnCtxt, local: &ast::Local) {
+pub fn check_decl_local<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, local: &'tcx ast::Local) {
let tcx = fcx.ccx.tcx;
let t = fcx.local_ty(local.span, local.id);
}
}
-pub fn check_stmt(fcx: &FnCtxt, stmt: &ast::Stmt) {
+pub fn check_stmt<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, stmt: &'tcx ast::Stmt) {
let node_id;
let mut saw_bot = false;
let mut saw_err = false;
}
}
-pub fn check_block_no_value(fcx: &FnCtxt, blk: &ast::Block) {
+pub fn check_block_no_value<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, blk: &'tcx ast::Block) {
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) {
}
fn check_block_with_expected<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
- blk: &ast::Block,
+ blk: &'tcx ast::Block,
expected: Expectation<'tcx>) {
let prev = {
let mut fcx_ps = fcx.ps.borrow_mut();
/// length expression in a fixed-length vector, but someday it might be
/// extended to type-level numeric literals.
fn check_const_in_type<'a,'tcx>(ccx: &'a CrateCtxt<'a,'tcx>,
- expr: &ast::Expr,
+ expr: &'tcx ast::Expr,
expected_type: Ty<'tcx>) {
let inh = static_inherited_fields(ccx);
let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(expected_type), expr.id);
check_const_with_ty(&fcx, expr.span, expr, expected_type);
}
-fn check_const(ccx: &CrateCtxt,
- sp: Span,
- e: &ast::Expr,
- id: ast::NodeId) {
+fn check_const<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
+ sp: Span,
+ e: &'tcx ast::Expr,
+ id: ast::NodeId) {
let inh = static_inherited_fields(ccx);
let rty = ty::node_id_to_type(ccx.tcx, id);
let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), e.id);
fn check_const_with_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
_: Span,
- e: &ast::Expr,
+ e: &'tcx ast::Expr,
declty: Ty<'tcx>) {
// Gather locals in statics (because of block expressions).
// This is technically unnecessary because locals in static items are forbidden,
}
}
-pub fn check_enum_variants(ccx: &CrateCtxt,
- sp: Span,
- vs: &[P<ast::Variant>],
- id: ast::NodeId) {
+pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
+ sp: Span,
+ vs: &'tcx [P<ast::Variant>],
+ id: ast::NodeId) {
fn disr_in_range(ccx: &CrateCtxt,
ty: attr::IntType,
}
fn do_check<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
- vs: &[P<ast::Variant>],
+ vs: &'tcx [P<ast::Variant>],
id: ast::NodeId,
hint: attr::ReprAttr)
-> Vec<Rc<ty::VariantInfo<'tcx>>> {