diff options
| author | Niko Matsakis <niko@alum.mit.edu> | 2015-01-24 17:32:10 -0500 |
|---|---|---|
| committer | Niko Matsakis <niko@alum.mit.edu> | 2015-02-01 06:13:05 -0500 |
| commit | 53c1956cfbbe8a5957bfa62f57bfb0e4b999a7b0 (patch) | |
| tree | 71e0b35cb679108b2e620ec4ca01a22fc169e64e /src | |
| parent | fe4340ab18abc53af40e40a6696dfbe2375238b0 (diff) | |
| download | rust-53c1956cfbbe8a5957bfa62f57bfb0e4b999a7b0.tar.gz rust-53c1956cfbbe8a5957bfa62f57bfb0e4b999a7b0.zip | |
Introduce the notion of deferred resolutions and use it to hold off on
doing the final checking for closure calls until after trait inference is performed. This isn't important now, but it's essential if we are to delay inferring the closure kind.
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustc_typeck/check/_match.rs | 31 | ||||
| -rw-r--r-- | src/librustc_typeck/check/callee.rs | 188 | ||||
| -rw-r--r-- | src/librustc_typeck/check/closure.rs | 8 | ||||
| -rw-r--r-- | src/librustc_typeck/check/method/confirm.rs | 12 | ||||
| -rw-r--r-- | src/librustc_typeck/check/method/mod.rs | 4 | ||||
| -rw-r--r-- | src/librustc_typeck/check/mod.rs | 206 | ||||
| -rw-r--r-- | src/librustc_typeck/check/vtable.rs | 3 |
7 files changed, 308 insertions, 144 deletions
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index cb4c880717b..c4b7ffb8729 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<ast::FieldPat>], +pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &'tcx ast::Pat, + path: &ast::Path, fields: &'tcx [Spanned<ast::FieldPat>], 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<Vec<P<ast::Pat>>>, - 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<ast::Pat>]>, + 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<ast::FieldPat>], + fields: &'tcx [Spanned<ast::FieldPat>], 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 e37c1ab7f0c..dc8bde9f84d 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<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); @@ -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<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(..) => { @@ -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<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")), @@ -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<ast::Expr>], + arg_exprs: &'tcx [P<ast::Expr>], 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_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 + } + } + } +} diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index bdae34e7878..906a8a33314 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<ast::ClosureKind>, - 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<ty::FnSig<'tcx>>) { 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 56a32186c9e..c326116cbd5 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<Ty<'tcx>>) @@ -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 d92cc1dfc1e..24e9f1c8720 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<Ty<'tcx>>, - call_expr: &ast::Expr, - self_expr: &ast::Expr) + call_expr: &'tcx ast::Expr, + self_expr: &'tcx ast::Expr) -> Result<MethodCallee<'tcx>, 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 9dcde1c2a0a..565e96483b9 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<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)] @@ -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<ast::Expr>], + callee_expr: &'tcx ast::Expr, + args_no_rcvr: &'tcx [P<ast::Expr>], 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<ast::Expr>], + args: &'tcx [P<ast::Expr>], 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<ast::Expr>], + args: &'tcx [P<ast::Expr>], tps: &[P<ast::Ty>], 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<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(), @@ -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<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 { @@ -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<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 { @@ -2966,8 +2980,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, 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), @@ -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<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, @@ -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<ast::DefId>) { 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<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); @@ -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<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, @@ -4453,7 +4467,7 @@ pub fn check_enum_variants(ccx: &CrateCtxt, } 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>>> { diff --git a/src/librustc_typeck/check/vtable.rs b/src/librustc_typeck/check/vtable.rs index 41b63830279..9d8eaf98569 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(); |
