diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index cb4c880717bc..c4b7ffb87296 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -30,7 +30,7 @@ use syntax::print::pprust; use syntax::ptr::P; pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, - pat: &ast::Pat, + pat: &'tcx ast::Pat, expected: Ty<'tcx>) { let fcx = pcx.fcx; @@ -157,9 +157,10 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, } ast::PatIdent(_, ref path, _) => { let path = ast_util::ident_to_path(path.span, path.node); - check_pat_enum(pcx, pat, &path, &Some(vec![]), expected); + check_pat_enum(pcx, pat, &path, Some(&[]), expected); } ast::PatEnum(ref path, ref subpats) => { + let subpats = subpats.as_ref().map(|v| &v[]); check_pat_enum(pcx, pat, path, subpats, expected); } ast::PatStruct(ref path, ref fields, etc) => { @@ -335,9 +336,9 @@ pub fn check_dereferencable<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, } pub fn check_match<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, - expr: &ast::Expr, - discrim: &ast::Expr, - arms: &[ast::Arm], + expr: &'tcx ast::Expr, + discrim: &'tcx ast::Expr, + arms: &'tcx [ast::Arm], expected: Expectation<'tcx>, match_src: ast::MatchSource) { let tcx = fcx.ccx.tcx; @@ -424,8 +425,8 @@ pub struct pat_ctxt<'a, 'tcx: 'a> { pub map: PatIdMap, } -pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &ast::Pat, - path: &ast::Path, fields: &[Spanned], +pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &'tcx ast::Pat, + path: &ast::Path, fields: &'tcx [Spanned], etc: bool, expected: Ty<'tcx>) { let fcx = pcx.fcx; let tcx = pcx.fcx.ccx.tcx; @@ -483,10 +484,12 @@ pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &ast::Pat, variant_def_id, etc); } -pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &ast::Pat, - path: &ast::Path, subpats: &Option>>, - expected: Ty<'tcx>) { - +pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, + pat: &ast::Pat, + path: &ast::Path, + subpats: Option<&'tcx [P]>, + expected: Ty<'tcx>) +{ // Typecheck the path. let fcx = pcx.fcx; let tcx = pcx.fcx.ccx.tcx; @@ -536,7 +539,7 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &ast::Pat, "`{}` does not name a non-struct variant or a tuple struct", name); fcx.write_error(pat.id); - if let Some(ref subpats) = *subpats { + if let Some(subpats) = subpats { for pat in subpats.iter() { check_pat(pcx, &**pat, tcx.types.err); } @@ -545,7 +548,7 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &ast::Pat, } }; - if let Some(ref subpats) = *subpats { + if let Some(subpats) = subpats { if subpats.len() == arg_tys.len() { for (subpat, arg_ty) in subpats.iter().zip(arg_tys.iter()) { check_pat(pcx, &**subpat, *arg_ty); @@ -579,7 +582,7 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &ast::Pat, /// `etc` is true if the pattern said '...' and false otherwise. pub fn check_struct_pat_fields<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, span: Span, - fields: &[Spanned], + fields: &'tcx [Spanned], struct_fields: &[ty::field<'tcx>], struct_id: ast::DefId, etc: bool) { diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index e37c1ab7f0cb..dc8bde9f84d6 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -13,6 +13,8 @@ use super::AutorefArgs; 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; @@ -24,13 +26,14 @@ use super::TupleArgumentsFlag; 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 @@ -66,9 +69,9 @@ pub fn check_legal_trait_for_method_call(ccx: &CrateCtxt, span: Span, trait_id: } pub fn check_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, - call_expr: &ast::Expr, - callee_expr: &ast::Expr, - arg_exprs: &[P], + call_expr: &'tcx ast::Expr, + callee_expr: &'tcx ast::Expr, + arg_exprs: &'tcx [P], expected: Expectation<'tcx>) { check_expr(fcx, callee_expr); @@ -96,24 +99,35 @@ pub fn check_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, 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> { + 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(..) => { @@ -123,9 +137,37 @@ fn try_overloaded_call_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, 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> +{ // 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")), @@ -147,7 +189,7 @@ fn try_overloaded_call_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, None) { None => continue, Some(method_callee) => { - return Some(CallStep::Overloaded(method_callee)); + return Some(method_callee); } } } @@ -158,7 +200,7 @@ fn try_overloaded_call_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, fn confirm_builtin_call<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, call_expr: &ast::Expr, callee_ty: Ty<'tcx>, - arg_exprs: &[P], + arg_exprs: &'tcx [P], expected: Expectation<'tcx>) { let error_fn_sig; @@ -215,22 +257,124 @@ fn confirm_builtin_call<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, 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], - method_callee: ty::MethodCallee<'tcx>, - expected: Expectation<'tcx>) +fn confirm_closure_call<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, + call_expr: &ast::Expr, + arg_exprs: &'tcx [P], + expected: Expectation<'tcx>, + fn_sig: ty::FnSig<'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 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); + // `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, + callee_expr: &'tcx ast::Expr, + arg_exprs: &'tcx [P], + expected: Expectation<'tcx>, + method_callee: ty::MethodCallee<'tcx>) +{ + 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); +} + +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 + } + } + } +} diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index bdae34e78785..906a8a33314c 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -26,8 +26,8 @@ pub fn check_expr_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, expr: &ast::Expr, _capture: ast::CaptureClause, opt_kind: Option, - decl: &ast::FnDecl, - body: &ast::Block, + decl: &'tcx ast::FnDecl, + body: &'tcx ast::Block, expected: Expectation<'tcx>) { debug!("check_expr_closure(expr={},expected={})", expr.repr(fcx.tcx()), @@ -76,8 +76,8 @@ pub fn check_expr_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, fn check_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, expr: &ast::Expr, kind: ty::ClosureKind, - decl: &ast::FnDecl, - body: &ast::Block, + decl: &'tcx ast::FnDecl, + body: &'tcx ast::Block, expected_sig: Option>) { let expr_def_id = ast_util::local_def(expr.id); diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 56a32186c9ea..c326116cbd54 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -31,8 +31,8 @@ use util::ppaux::Repr; struct ConfirmContext<'a, 'tcx:'a> { fcx: &'a FnCtxt<'a, 'tcx>, span: Span, - self_expr: &'a ast::Expr, - call_expr: &'a ast::Expr, + self_expr: &'tcx ast::Expr, + call_expr: &'tcx ast::Expr, } struct InstantiatedMethodSig<'tcx> { @@ -51,8 +51,8 @@ struct InstantiatedMethodSig<'tcx> { pub fn confirm<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, span: Span, - self_expr: &ast::Expr, - call_expr: &ast::Expr, + self_expr: &'tcx ast::Expr, + call_expr: &'tcx ast::Expr, unadjusted_self_ty: Ty<'tcx>, pick: probe::Pick<'tcx>, supplied_method_types: Vec>) @@ -70,8 +70,8 @@ pub fn confirm<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, impl<'a,'tcx> ConfirmContext<'a,'tcx> { fn new(fcx: &'a FnCtxt<'a, 'tcx>, span: Span, - self_expr: &'a ast::Expr, - call_expr: &'a ast::Expr) + self_expr: &'tcx ast::Expr, + call_expr: &'tcx ast::Expr) -> ConfirmContext<'a, 'tcx> { ConfirmContext { fcx: fcx, span: span, self_expr: self_expr, call_expr: call_expr } diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index d92cc1dfc1e9..24e9f1c8720e 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -90,8 +90,8 @@ pub fn lookup<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, method_name: ast::Name, self_ty: Ty<'tcx>, supplied_method_types: Vec>, - call_expr: &ast::Expr, - self_expr: &ast::Expr) + call_expr: &'tcx ast::Expr, + self_expr: &'tcx ast::Expr) -> Result, MethodError> { debug!("lookup(method_name={}, self_ty={}, call_expr={}, self_expr={})", diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 9dcde1c2a0a5..565e96483b9a 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -170,8 +170,17 @@ pub struct Inherited<'a, 'tcx: 'a> { // Tracks trait obligations incurred during this function body. fulfillment_cx: RefCell>, + + // + deferred_resolutions: RefCell>>, } +trait DeferredResolution<'tcx> { + fn attempt_resolution<'a>(&self, fcx: &FnCtxt<'a,'tcx>) -> bool; +} + +type DeferredResolutionHandler<'tcx> = Box+'tcx>; + /// When type-checking an expression, we propagate downward /// whatever type hint we are able in the form of an `Expectation`. #[derive(Copy)] @@ -377,6 +386,7 @@ impl<'a, 'tcx> Inherited<'a, 'tcx> { closures: RefCell::new(DefIdMap()), fn_sig_map: RefCell::new(NodeMap()), fulfillment_cx: RefCell::new(traits::FulfillmentContext::new()), + deferred_resolutions: RefCell::new(Vec::new()), } } @@ -425,13 +435,13 @@ fn static_inherited_fields<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>) 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); @@ -459,8 +469,8 @@ pub fn check_item_types(ccx: &CrateCtxt) { } 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>) @@ -512,9 +522,9 @@ impl<'a, 'tcx> GatherLocalsVisitor<'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 @@ -528,7 +538,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for GatherLocalsVisitor<'a, 'tcx> { } // 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); @@ -546,7 +556,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for GatherLocalsVisitor<'a, 'tcx> { 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. @@ -555,7 +565,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for GatherLocalsVisitor<'a, 'tcx> { // 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); @@ -566,8 +576,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for GatherLocalsVisitor<'a, 'tcx> { } // 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) { } } @@ -582,9 +592,9 @@ fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>, 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> { @@ -677,7 +687,7 @@ pub fn check_struct(ccx: &CrateCtxt, id: ast::NodeId, span: Span) { } } -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))); @@ -829,7 +839,7 @@ fn check_trait_on_unimplemented<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, /// * `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); @@ -1133,10 +1143,10 @@ fn check_cast_inner<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, } } -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; @@ -1279,6 +1289,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { 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) } @@ -2068,7 +2082,7 @@ fn autoderef_for_index<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>, 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, @@ -2138,8 +2152,8 @@ fn try_index_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, 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], + callee_expr: &'tcx ast::Expr, + args_no_rcvr: &'tcx [P], autoref_args: AutorefArgs, tuple_arguments: TupleArgumentsFlag, expected: Expectation<'tcx>) @@ -2194,7 +2208,7 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span, fn_inputs: &[Ty<'tcx>], expected_arg_tys: &[Ty<'tcx>], - args: &[P], + args: &'tcx [P], autoref_args: AutorefArgs, variadic: bool, tuple_arguments: TupleArgumentsFlag) { @@ -2462,7 +2476,7 @@ pub fn valid_range_bounds(ccx: &CrateCtxt, } 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, @@ -2470,14 +2484,14 @@ pub fn check_expr_has_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, } 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, @@ -2485,7 +2499,7 @@ fn check_expr_with_hint<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, expr: &ast::Expr, } 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, @@ -2493,19 +2507,19 @@ fn check_expr_with_expectation<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, } 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, || ()) } @@ -2613,7 +2627,7 @@ fn expected_types_for_fn_args<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, /// 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 @@ -2624,9 +2638,9 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, // 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], + args: &'tcx [P], tps: &[P], expected: Expectation<'tcx>, lvalue_pref: LvaluePreference) { @@ -2675,9 +2689,9 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, // 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>) { @@ -2717,12 +2731,12 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, '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, lhs: &'a ast::Expr, - rhs: Option<&P>, + rhs: Option<&'tcx P>, unbound_method: F, autoref_args: AutorefArgs) -> Ty<'tcx> where F: FnOnce(), @@ -2803,12 +2817,12 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, } // 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, - 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, + is_binop_assignment: IsBinopAssignment) { let tcx = fcx.ccx.tcx; let lvalue_pref = match is_binop_assignment { @@ -2923,11 +2937,11 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, } 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) -> Ty<'tcx> { + rhs: &'tcx P) -> Ty<'tcx> { let tcx = fcx.ccx.tcx; let lang = &tcx.lang_items; let (name, trait_did) = match op.node { @@ -2966,8 +2980,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, op_str: &str, mname: &str, trait_did: Option, - 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), @@ -2980,11 +2994,11 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, } // 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, @@ -3077,11 +3091,11 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, } // Check tuple index expressions - fn check_tup_field(fcx: &FnCtxt, - expr: &ast::Expr, - lvalue_pref: LvaluePreference, - base: &ast::Expr, - idx: codemap::Spanned) { + fn check_tup_field<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, + expr: &'tcx ast::Expr, + lvalue_pref: LvaluePreference, + base: &'tcx ast::Expr, + idx: codemap::Spanned) { let tcx = fcx.ccx.tcx; check_expr_with_lvalue_pref(fcx, base, lvalue_pref); let expr_t = structurally_resolved_type(fcx, expr.span, @@ -3149,7 +3163,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, 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) { let tcx = fcx.ccx.tcx; @@ -3252,12 +3266,12 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, '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. @@ -3294,12 +3308,12 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, 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 @@ -3324,10 +3338,10 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, fcx.write_ty(id, enum_type); } - fn check_struct_fields_on_error(fcx: &FnCtxt, - id: ast::NodeId, - fields: &[ast::Field], - base_expr: &Option>) { + fn check_struct_fields_on_error<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, + id: ast::NodeId, + fields: &'tcx [ast::Field], + base_expr: &'tcx Option>) { // Make sure to still write the types // otherwise we might ICE fcx.write_error(id); @@ -4126,15 +4140,15 @@ impl<'tcx> Repr<'tcx> for Expectation<'tcx> { } } -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); @@ -4159,7 +4173,7 @@ pub fn check_decl_local(fcx: &FnCtxt, local: &ast::Local) { } } -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; @@ -4204,7 +4218,7 @@ pub fn check_stmt(fcx: &FnCtxt, stmt: &ast::Stmt) { } } -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) { @@ -4216,7 +4230,7 @@ pub fn check_block_no_value(fcx: &FnCtxt, blk: &ast::Block) { } 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(); @@ -4299,17 +4313,17 @@ fn check_block_with_expected<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, /// 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); @@ -4319,7 +4333,7 @@ fn check_const(ccx: &CrateCtxt, 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, @@ -4420,10 +4434,10 @@ pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) { } } -pub fn check_enum_variants(ccx: &CrateCtxt, - sp: Span, - vs: &[P], - id: ast::NodeId) { +pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, + sp: Span, + vs: &'tcx [P], + id: ast::NodeId) { fn disr_in_range(ccx: &CrateCtxt, ty: attr::IntType, @@ -4453,7 +4467,7 @@ pub fn check_enum_variants(ccx: &CrateCtxt, } fn do_check<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, - vs: &[P], + vs: &'tcx [P], id: ast::NodeId, hint: attr::ReprAttr) -> Vec>> { diff --git a/src/librustc_typeck/check/vtable.rs b/src/librustc_typeck/check/vtable.rs index 41b63830279a..9d8eaf98569f 100644 --- a/src/librustc_typeck/check/vtable.rs +++ b/src/librustc_typeck/check/vtable.rs @@ -280,6 +280,9 @@ fn check_object_type_binds_all_associated_types<'tcx>(tcx: &ty::ctxt<'tcx>, pub fn select_all_fcx_obligations_or_error(fcx: &FnCtxt) { debug!("select_all_fcx_obligations_or_error"); + fcx.inh.deferred_resolutions.borrow_mut() + .retain(|r| !r.attempt_resolution(fcx)); + select_fcx_obligations_where_possible(fcx); fcx.default_type_parameters();