From 5592972eb94795d45728a67534a13bd0bf316ba8 Mon Sep 17 00:00:00 2001 From: Joshua Yanovski Date: Thu, 7 May 2015 05:41:46 -0700 Subject: [PATCH 01/14] Moving three fields of Inherited to be &mut instead of RefCell. --- src/librustc_typeck/check/_match.rs | 101 +++---- src/librustc_typeck/check/callee.rs | 41 ++- src/librustc_typeck/check/closure.rs | 13 +- src/librustc_typeck/check/mod.rs | 382 ++++++++++++++------------ src/librustc_typeck/check/op.rs | 24 +- src/librustc_typeck/check/regionck.rs | 257 +++++++++-------- src/librustc_typeck/check/upvar.rs | 35 ++- src/librustc_typeck/check/vtable.rs | 6 +- src/librustc_typeck/check/wf.rs | 20 +- src/librustc_typeck/lib.rs | 1 + 10 files changed, 484 insertions(+), 396 deletions(-) diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 1f4d6cc2fd471..11ffd697b4c25 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -16,9 +16,9 @@ use middle::pat_util::pat_is_resolved_const; use middle::privacy::{AllPublic, LastMod}; use middle::subst::Substs; use middle::ty::{self, Ty}; -use check::{check_expr, check_expr_has_type, check_expr_with_expectation}; -use check::{check_expr_coercable_to_type, demand, FnCtxt, Expectation}; -use check::{instantiate_path, resolve_ty_and_def_ufcs, structurally_resolved_type}; +use super::{check_expr, check_expr_has_type, check_expr_with_expectation}; +use super::{check_expr_coercable_to_type, demand, CheckEnv, FnCtxt, Expectation}; +use super::{instantiate_path, resolve_ty_and_def_ufcs, structurally_resolved_type}; use require_same_types; use util::nodemap::FnvHashMap; use util::ppaux::Repr; @@ -32,7 +32,8 @@ use syntax::parse::token; use syntax::print::pprust; use syntax::ptr::P; -pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, +pub fn check_pat<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, + pcx: &pat_ctxt<'a, 'tcx>, pat: &'tcx ast::Pat, expected: Ty<'tcx>) { @@ -48,7 +49,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, fcx.write_ty(pat.id, expected); } ast::PatLit(ref lt) => { - check_expr(fcx, &**lt); + check_expr(check_env, fcx, &**lt); let expr_ty = fcx.expr_ty(&**lt); // Byte string patterns behave the same way as array patterns @@ -83,8 +84,8 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, demand::suptype(fcx, pat.span, expected, pat_ty); } ast::PatRange(ref begin, ref end) => { - check_expr(fcx, &**begin); - check_expr(fcx, &**end); + check_expr(check_env, fcx, &**begin); + check_expr(check_env, fcx, &**end); let lhs_ty = fcx.expr_ty(&**begin); let rhs_ty = fcx.expr_ty(&**end); @@ -172,16 +173,16 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, } if let Some(ref p) = *sub { - check_pat(pcx, &**p, expected); + check_pat(check_env, pcx, &**p, expected); } } ast::PatIdent(_, ref path, _) => { let path = ast_util::ident_to_path(path.span, path.node); - check_pat_enum(pcx, pat, &path, Some(&[]), expected); + check_pat_enum(check_env, 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); + check_pat_enum(check_env, pcx, pat, path, subpats, expected); } ast::PatQPath(ref qself, ref path) => { let self_ty = fcx.to_ty(&qself.ty); @@ -215,7 +216,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, } } ast::PatStruct(ref path, ref fields, etc) => { - check_pat_struct(pcx, pat, path, fields, etc, expected); + check_pat_struct(check_env, pcx, pat, path, fields, etc, expected); } ast::PatTup(ref elements) => { let element_tys: Vec<_> = @@ -225,7 +226,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, fcx.write_ty(pat.id, pat_ty); demand::eqtype(fcx, pat.span, expected, pat_ty); for (element_pat, element_ty) in elements.iter().zip(element_tys.into_iter()) { - check_pat(pcx, &**element_pat, element_ty); + check_pat(check_env, pcx, &**element_pat, element_ty); } } ast::PatBox(ref inner) => { @@ -238,10 +239,10 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, // `demand::eqtype`. demand::eqtype(fcx, pat.span, expected, uniq_ty); fcx.write_ty(pat.id, uniq_ty); - check_pat(pcx, &**inner, inner_ty); + check_pat(check_env, pcx, &**inner, inner_ty); } else { fcx.write_error(pat.id); - check_pat(pcx, &**inner, tcx.types.err); + check_pat(check_env, pcx, &**inner, tcx.types.err); } } ast::PatRegion(ref inner, mutbl) => { @@ -257,10 +258,10 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, // below for details. demand::eqtype(fcx, pat.span, expected, rptr_ty); fcx.write_ty(pat.id, rptr_ty); - check_pat(pcx, &**inner, inner_ty); + check_pat(check_env, pcx, &**inner, inner_ty); } else { fcx.write_error(pat.id); - check_pat(pcx, &**inner, tcx.types.err); + check_pat(check_env, pcx, &**inner, tcx.types.err); } } ast::PatVec(ref before, ref slice, ref after) => { @@ -292,7 +293,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, demand::eqtype(fcx, pat.span, expected, pat_ty); for elt in before { - check_pat(pcx, &**elt, inner_ty); + check_pat(check_env, pcx, &**elt, inner_ty); } if let Some(ref slice) = *slice { let region = fcx.infcx().next_region_var(infer::PatternRegion(pat.span)); @@ -303,10 +304,10 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, ty: inner_ty, mutbl: mutbl }); - check_pat(pcx, &**slice, slice_ty); + check_pat(check_env, pcx, &**slice, slice_ty); } for elt in after { - check_pat(pcx, &**elt, inner_ty); + check_pat(check_env, pcx, &**elt, inner_ty); } } ast::PatMac(_) => tcx.sess.bug("unexpanded macro") @@ -402,7 +403,8 @@ pub fn check_dereferencable<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, } } -pub fn check_match<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, +pub fn check_match<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a, 'tcx>, expr: &'tcx ast::Expr, discrim: &'tcx ast::Expr, arms: &'tcx [ast::Arm], @@ -416,14 +418,14 @@ pub fn check_match<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, let contains_ref_bindings = arms.iter().any(|a| tcx.arm_contains_ref_binding(a)); let discrim_ty; if contains_ref_bindings { - check_expr(fcx, discrim); + check_expr(check_env, fcx, discrim); discrim_ty = fcx.expr_ty(discrim); } else { // ...but otherwise we want to use any supertype of the // discriminant. This is sort of a workaround, see note (*) in // `check_pat` for some details. discrim_ty = fcx.infcx().next_ty_var(); - check_expr_has_type(fcx, discrim, discrim_ty); + check_expr_has_type(check_env, fcx, discrim, discrim_ty); }; // Typecheck the patterns first, so that we get types for all the @@ -434,7 +436,7 @@ pub fn check_match<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, map: pat_id_map(&tcx.def_map, &*arm.pats[0]), }; for p in &arm.pats { - check_pat(&mut pcx, &**p, discrim_ty); + check_pat(check_env, &mut pcx, &**p, discrim_ty); } } @@ -456,17 +458,17 @@ pub fn check_match<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, // arm for inconsistent arms or to the whole match when a `()` type // is required). Expectation::ExpectHasType(ety) if ety != ty::mk_nil(fcx.tcx()) => { - check_expr_coercable_to_type(fcx, &*arm.body, ety); + check_expr_coercable_to_type(check_env, fcx, &*arm.body, ety); ety } _ => { - check_expr_with_expectation(fcx, &*arm.body, expected); + check_expr_with_expectation(check_env, fcx, &*arm.body, expected); fcx.node_ty(arm.body.id) } }; if let Some(ref e) = arm.guard { - check_expr_has_type(fcx, &**e, tcx.types.bool); + check_expr_has_type(check_env, fcx, &**e, tcx.types.bool); } if ty::type_is_error(result_ty) || ty::type_is_error(bty) { @@ -505,9 +507,10 @@ pub struct pat_ctxt<'a, 'tcx: 'a> { pub map: PatIdMap, } -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>) { +fn check_pat_struct<'a, 'tcx>(check_env: &mut CheckEnv<'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; @@ -520,7 +523,7 @@ pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &'tcx ast::Pat, fcx.write_error(pat.id); for field in fields { - check_pat(pcx, &*field.node.pat, tcx.types.err); + check_pat(check_env, pcx, &*field.node.pat, tcx.types.err); } return; }, @@ -539,7 +542,7 @@ pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &'tcx ast::Pat, fcx.write_error(pat.id); for field in fields { - check_pat(pcx, &*field.node.pat, tcx.types.err); + check_pat(check_env, pcx, &*field.node.pat, tcx.types.err); } return; } @@ -566,15 +569,16 @@ pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &'tcx ast::Pat, .unwrap_or_else(|| Substs::empty()); let struct_fields = ty::struct_fields(tcx, variant_def_id, &item_substs); - check_struct_pat_fields(pcx, pat.span, fields, &struct_fields, + check_struct_pat_fields(check_env, pcx, pat.span, fields, &struct_fields, variant_def_id, etc); } -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>) +fn check_pat_enum<'a, 'tcx>(check_env: &mut CheckEnv<'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; @@ -657,7 +661,7 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, if let Some(subpats) = subpats { for pat in subpats { - check_pat(pcx, &**pat, tcx.types.err); + check_pat(check_env, pcx, &**pat, tcx.types.err); } } return; @@ -667,7 +671,7 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, 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); + check_pat(check_env, pcx, &**subpat, *arg_ty); } } else if arg_tys.is_empty() { span_err!(tcx.sess, pat.span, E0024, @@ -675,7 +679,7 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, subpats.len(), if subpats.len() == 1 {""} else {"s"}, kind_name); for pat in subpats { - check_pat(pcx, &**pat, tcx.types.err); + check_pat(check_env, pcx, &**pat, tcx.types.err); } } else { span_err!(tcx.sess, pat.span, E0023, @@ -685,7 +689,7 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, arg_tys.len(), if arg_tys.len() == 1 {""} else {"s"}); for pat in subpats { - check_pat(pcx, &**pat, tcx.types.err); + check_pat(check_env, pcx, &**pat, tcx.types.err); } } } @@ -696,12 +700,13 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, /// `struct_fields` describes the type of each field of the struct. /// `struct_id` is the ID of the struct. /// `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: &'tcx [Spanned], - struct_fields: &[ty::field<'tcx>], - struct_id: ast::DefId, - etc: bool) { +fn check_struct_pat_fields<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, + pcx: &pat_ctxt<'a, 'tcx>, + span: Span, + fields: &'tcx [Spanned], + struct_fields: &[ty::field<'tcx>], + struct_id: ast::DefId, + etc: bool) { let tcx = pcx.fcx.ccx.tcx; // Index the struct fields' types. @@ -740,7 +745,7 @@ pub fn check_struct_pat_fields<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, let field_type = pcx.fcx.normalize_associated_types_in(span, &field_type); - check_pat(pcx, &*field.pat, field_type); + check_pat(check_env, pcx, &*field.pat, field_type); } // Report an error if not all the fields were specified. diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index b065eb2d2741c..7de45af7340c7 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -12,6 +12,7 @@ use super::autoderef; use super::check_argument_types; use super::check_expr; use super::check_method_argument_types; +use super::CheckEnv; use super::demand; use super::DeferredCallResolution; use super::err_args; @@ -67,13 +68,14 @@ pub fn check_legal_trait_for_method_call(ccx: &CrateCtxt, span: Span, trait_id: } } -pub fn check_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, +pub fn check_call<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a, 'tcx>, call_expr: &'tcx ast::Expr, callee_expr: &'tcx ast::Expr, arg_exprs: &'tcx [P], expected: Expectation<'tcx>) { - check_expr(fcx, callee_expr); + check_expr(check_env, fcx, callee_expr); let original_callee_ty = fcx.expr_ty(callee_expr); let (callee_ty, _, result) = autoderef(fcx, @@ -83,25 +85,27 @@ pub fn check_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, UnresolvedTypeAction::Error, LvaluePreference::NoPreference, |adj_ty, idx| { - try_overloaded_call_step(fcx, call_expr, callee_expr, adj_ty, idx) + try_overloaded_call_step(check_env, + fcx, call_expr, callee_expr, adj_ty, idx) }); match result { None => { // this will report an error since original_callee_ty is not a fn - confirm_builtin_call(fcx, call_expr, original_callee_ty, arg_exprs, expected); + confirm_builtin_call(check_env, + fcx, call_expr, original_callee_ty, arg_exprs, expected); } Some(CallStep::Builtin) => { - confirm_builtin_call(fcx, call_expr, callee_ty, arg_exprs, expected); + confirm_builtin_call(check_env, fcx, call_expr, callee_ty, arg_exprs, expected); } Some(CallStep::DeferredClosure(fn_sig)) => { - confirm_deferred_closure_call(fcx, call_expr, arg_exprs, expected, fn_sig); + confirm_deferred_closure_call(check_env, fcx, call_expr, arg_exprs, expected, fn_sig); } Some(CallStep::Overloaded(method_callee)) => { - confirm_overloaded_call(fcx, call_expr, callee_expr, + confirm_overloaded_call(check_env, fcx, call_expr, callee_expr, arg_exprs, expected, method_callee); } } @@ -113,7 +117,8 @@ enum CallStep<'tcx> { Overloaded(ty::MethodCallee<'tcx>) } -fn try_overloaded_call_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, +fn try_overloaded_call_step<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a, 'tcx>, call_expr: &'tcx ast::Expr, callee_expr: &'tcx ast::Expr, adjusted_ty: Ty<'tcx>, @@ -145,7 +150,7 @@ fn try_overloaded_call_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, fcx.infcx().replace_late_bound_regions_with_fresh_var(call_expr.span, infer::FnCall, &closure_ty.sig).0; - fcx.record_deferred_call_resolution(def_id, Box::new(CallResolution { + check_env.record_deferred_call_resolution(def_id, Box::new(CallResolution { call_expr: call_expr, callee_expr: callee_expr, adjusted_ty: adjusted_ty, @@ -213,7 +218,8 @@ fn try_overloaded_call_traits<'a,'tcx>(fcx: &FnCtxt<'a, 'tcx>, None } -fn confirm_builtin_call<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, +fn confirm_builtin_call<'a,'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a,'tcx>, call_expr: &ast::Expr, callee_ty: Ty<'tcx>, arg_exprs: &'tcx [P], @@ -261,7 +267,8 @@ fn confirm_builtin_call<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, expected, fn_sig.output, &fn_sig.inputs); - check_argument_types(fcx, + check_argument_types(check_env, + fcx, call_expr.span, &fn_sig.inputs, &expected_arg_tys[..], @@ -272,7 +279,8 @@ fn confirm_builtin_call<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, write_call(fcx, call_expr, fn_sig.output); } -fn confirm_deferred_closure_call<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, +fn confirm_deferred_closure_call<'a,'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a,'tcx>, call_expr: &ast::Expr, arg_exprs: &'tcx [P], expected: Expectation<'tcx>, @@ -290,7 +298,8 @@ fn confirm_deferred_closure_call<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, fn_sig.output.clone(), &*fn_sig.inputs); - check_argument_types(fcx, + check_argument_types(check_env, + fcx, call_expr.span, &*fn_sig.inputs, &*expected_arg_tys, @@ -301,7 +310,8 @@ fn confirm_deferred_closure_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>, +fn confirm_overloaded_call<'a,'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a, 'tcx>, call_expr: &ast::Expr, callee_expr: &'tcx ast::Expr, arg_exprs: &'tcx [P], @@ -309,7 +319,8 @@ fn confirm_overloaded_call<'a,'tcx>(fcx: &FnCtxt<'a, 'tcx>, method_callee: ty::MethodCallee<'tcx>) { let output_type = - check_method_argument_types(fcx, + check_method_argument_types(check_env, + fcx, call_expr.span, method_callee.ty, callee_expr, diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index d2a06fcf99091..1f0382c4dfdb4 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -10,7 +10,7 @@ //! Code for type-checking closure expressions. -use super::{check_fn, Expectation, FnCtxt}; +use super::{check_fn, CheckEnv, Expectation, FnCtxt}; use astconv; use middle::region; @@ -22,7 +22,8 @@ use syntax::ast; use syntax::ast_util; use util::ppaux::Repr; -pub fn check_expr_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, +pub fn check_expr_closure<'a,'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a,'tcx>, expr: &ast::Expr, _capture: ast::CaptureClause, decl: &'tcx ast::FnDecl, @@ -39,10 +40,11 @@ pub fn check_expr_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, Some(ty) => deduce_expectations_from_expected_type(fcx, ty), None => (None, None) }; - check_closure(fcx, expr, expected_kind, decl, body, expected_sig) + check_closure(check_env, fcx, expr, expected_kind, decl, body, expected_sig) } -fn check_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, +fn check_closure<'a,'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a,'tcx>, expr: &ast::Expr, opt_kind: Option, decl: &'tcx ast::FnDecl, @@ -73,7 +75,8 @@ fn check_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, region::DestructionScopeData::new(body.id), &fn_ty.sig); - check_fn(fcx.ccx, + check_fn(check_env, + fcx.ccx, ast::Unsafety::Normal, expr.id, &fn_sig, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index c05c1c6b08523..f4c593c5f5e97 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -80,9 +80,9 @@ pub use self::LvaluePreference::*; pub use self::Expectation::*; pub use self::compare_method::{compare_impl_method, compare_const_impl}; use self::TupleArgumentsFlag::*; +use self::_match::pat_ctxt; use astconv::{self, ast_region_to_region, ast_ty_to_ty, AstConv, PathParamMode}; -use check::_match::pat_ctxt; use fmt_macros::{Parser, Piece, Position}; use middle::astconv_util::{check_path_args, NO_TPS, NO_REGIONS}; use middle::def; @@ -128,15 +128,15 @@ use syntax::visit::{self, Visitor}; mod assoc; pub mod dropck; -pub mod _match; -pub mod vtable; +mod _match; +mod vtable; pub mod writeback; -pub mod regionck; -pub mod coercion; +mod regionck; +mod coercion; pub mod demand; pub mod method; mod upvar; -pub mod wf; +mod wf; mod cast; mod closure; mod callee; @@ -167,13 +167,15 @@ pub struct Inherited<'a, 'tcx: 'a> { closure_kinds: RefCell>, object_cast_map: ObjectCastMap<'tcx>, + // Tracks trait obligations incurred during this function body. + fulfillment_cx: RefCell>, +} + +pub struct CheckEnv<'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>>>, - - // Tracks trait obligations incurred during this function body. - fulfillment_cx: RefCell>, + fn_sig_map: NodeMap>>, // When we process a call like `c()` where `c` is a closure type, // we may not have decided yet whether `c` is a `Fn`, `FnMut`, or @@ -182,9 +184,9 @@ pub struct Inherited<'a, 'tcx: 'a> { // decision. We keep these deferred resolutions grouped by the // def-id of the closure, so that once we decide, we can easily go // back and process them. - deferred_call_resolutions: RefCell>>>, + deferred_call_resolutions: DefIdMap>>, - deferred_cast_checks: RefCell>>, + deferred_cast_checks: Vec>, } trait DeferredCallResolution<'tcx> { @@ -388,10 +390,7 @@ impl<'a, 'tcx> Inherited<'a, 'tcx> { upvar_capture_map: RefCell::new(FnvHashMap()), closure_tys: RefCell::new(DefIdMap()), closure_kinds: RefCell::new(DefIdMap()), - fn_sig_map: RefCell::new(NodeMap()), fulfillment_cx: RefCell::new(traits::FulfillmentContext::new()), - deferred_call_resolutions: RefCell::new(DefIdMap()), - deferred_cast_checks: RefCell::new(Vec::new()), } } @@ -413,6 +412,35 @@ impl<'a, 'tcx> Inherited<'a, 'tcx> { } +impl<'tcx> CheckEnv<'tcx> { + fn new() -> Self { + CheckEnv { + fn_sig_map: NodeMap(), + deferred_call_resolutions: DefIdMap(), + deferred_cast_checks: Vec::new(), + } + } + + fn record_deferred_call_resolution(&mut self, + closure_def_id: ast::DefId, + r: DeferredCallResolutionHandler<'tcx>) { + self.deferred_call_resolutions.entry(closure_def_id).or_insert(vec![]).push(r); + } + + fn remove_deferred_call_resolutions(&mut self, + closure_def_id: ast::DefId) + -> Vec> + { + self.deferred_call_resolutions.remove(&closure_def_id).unwrap_or(Vec::new()) + } + + fn check_casts<'a>(&mut self, fcx: &'a FnCtxt<'a, 'tcx>) { + for check in self.deferred_cast_checks.drain(..) { + cast::check_cast(fcx, &check); + } + } +} + // 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>, @@ -430,12 +458,12 @@ pub fn blank_fn_ctxt<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>, } } -fn static_inherited_fields<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>) - -> Inherited<'a, 'tcx> { +fn static_fields<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>) + -> (CheckEnv<'tcx>, Inherited<'a, 'tcx>) { // It's kind of a kludge to manufacture a fake function context // and statement context, but we might as well do write the code only once let param_env = ty::empty_parameter_environment(ccx.tcx); - Inherited::new(ccx.tcx, param_env) + (CheckEnv::new(), Inherited::new(ccx.tcx, param_env)) } struct CheckItemTypesVisitor<'a, 'tcx: 'a> { ccx: &'a CrateCtxt<'a, 'tcx> } @@ -511,6 +539,7 @@ fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, match raw_fty.sty { ty::ty_bare_fn(_, ref fn_ty) => { let inh = Inherited::new(ccx.tcx, param_env); + let mut check_env = CheckEnv::new(); // Compute the fty from point of view of inside fn. let fn_sig = @@ -522,14 +551,14 @@ fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let fn_sig = inh.normalize_associated_types_in(&inh.param_env, body.span, body.id, &fn_sig); - let fcx = check_fn(ccx, fn_ty.unsafety, fn_id, &fn_sig, + let fcx = check_fn(&mut check_env, ccx, fn_ty.unsafety, fn_id, &fn_sig, decl, fn_id, body, &inh); vtable::select_all_fcx_obligations_and_apply_defaults(&fcx); - upvar::closure_analyze_fn(&fcx, fn_id, decl, body); - vtable::select_all_fcx_obligations_or_error(&fcx); - fcx.check_casts(); - regionck::regionck_fn(&fcx, fn_id, fn_span, decl, body); + upvar::closure_analyze_fn(&mut check_env, &fcx, fn_id, decl, body); + vtable::select_all_fcx_obligations_or_error(&mut check_env, &fcx); + check_env.check_casts(&fcx); + regionck::regionck_fn(&mut check_env, &fcx, fn_id, fn_span, decl, body); writeback::resolve_type_vars_in_fn(&fcx, decl, body); } _ => ccx.tcx.sess.impossible_case(body.span, @@ -538,6 +567,7 @@ fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, } struct GatherLocalsVisitor<'a, 'tcx: 'a> { + check_env: &'a mut CheckEnv<'tcx>, fcx: &'a FnCtxt<'a, 'tcx> } @@ -606,7 +636,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> { match t.node { ast::TyFixedLengthVec(ref ty, ref count_expr) => { self.visit_ty(&**ty); - check_expr_with_hint(self.fcx, &**count_expr, self.fcx.tcx().types.usize); + check_expr_with_hint(self.check_env, self.fcx, &**count_expr, self.fcx.tcx().types.usize); } _ => visit::walk_ty(self, t) } @@ -625,7 +655,8 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> { /// /// * ... /// * inherited: other fields inherited from the enclosing fn (if any) -fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>, +fn check_fn<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, + ccx: &'a CrateCtxt<'a, 'tcx>, unsafety: ast::Unsafety, unsafety_id: ast::NodeId, fn_sig: &ty::FnSig<'tcx>, @@ -673,10 +704,10 @@ fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>, fn_id, fn_sig_tys.repr(tcx)); - inherited.fn_sig_map.borrow_mut().insert(fn_id, fn_sig_tys); + check_env.fn_sig_map.insert(fn_id, fn_sig_tys); { - let mut visit = GatherLocalsVisitor { fcx: &fcx, }; + let mut visit = GatherLocalsVisitor { check_env: check_env, fcx: &fcx, }; // Add formal parameters. for (arg_ty, input) in arg_tys.iter().zip(decl.inputs.iter()) { @@ -695,13 +726,13 @@ fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>, fcx: &fcx, map: pat_id_map(&tcx.def_map, &*input.pat), }; - _match::check_pat(&pcx, &*input.pat, *arg_ty); + _match::check_pat(visit.check_env, &pcx, &*input.pat, *arg_ty); } visit.visit_block(body); } - check_block_with_expected(&fcx, body, match ret_ty { + check_block_with_expected(check_env, &fcx, body, match ret_ty { ty::FnConverging(result_type) => ExpectHasType(result_type), ty::FnDiverging => NoExpectation }); @@ -1318,21 +1349,6 @@ 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_call_resolution(&self, - closure_def_id: ast::DefId, - r: DeferredCallResolutionHandler<'tcx>) { - let mut deferred_call_resolutions = self.inh.deferred_call_resolutions.borrow_mut(); - deferred_call_resolutions.entry(closure_def_id).or_insert(vec![]).push(r); - } - - fn remove_deferred_call_resolutions(&self, - closure_def_id: ast::DefId) - -> Vec> - { - let mut deferred_call_resolutions = self.inh.deferred_call_resolutions.borrow_mut(); - deferred_call_resolutions.remove(&closure_def_id).unwrap_or(Vec::new()) - } - pub fn tag(&self) -> String { let self_ptr: *const FnCtxt = self; format!("{:?}", self_ptr) @@ -1808,15 +1824,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { o_field.map(|f| ty::lookup_field_type(self.tcx(), class_id, f.id, substs)) .map(|t| self.normalize_associated_types_in(span, &t)) } - - fn check_casts(&self) { - let mut deferred_cast_checks = self.inh.deferred_cast_checks.borrow_mut(); - for check in deferred_cast_checks.iter() { - cast::check_cast(self, check); - } - - deferred_cast_checks.clear(); - } } impl<'a, 'tcx> RegionScope for FnCtxt<'a, 'tcx> { @@ -2115,7 +2122,8 @@ fn try_index_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, }) } -fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, +fn check_method_argument_types<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a, 'tcx>, sp: Span, method_fn_ty: Ty<'tcx>, callee_expr: &'tcx ast::Expr, @@ -2131,7 +2139,8 @@ fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, TupleArguments => vec![ty::mk_tup(fcx.tcx(), err_inputs)], }; - check_argument_types(fcx, + check_argument_types(check_env, + fcx, sp, &err_inputs[..], &[], @@ -2148,7 +2157,8 @@ fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, expected, fty.sig.0.output, &fty.sig.0.inputs[1..]); - check_argument_types(fcx, + check_argument_types(check_env, + fcx, sp, &fty.sig.0.inputs[1..], &expected_arg_tys[..], @@ -2167,7 +2177,8 @@ fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, /// Generic function that factors out common logic from function calls, method calls and overloaded /// operators. -fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, +fn check_argument_types<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a, 'tcx>, sp: Span, fn_inputs: &[Ty<'tcx>], expected_arg_tys: &[Ty<'tcx>], @@ -2292,7 +2303,7 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, Expectation::rvalue_hint(ty) }); - check_expr_with_unifier(fcx, &**arg, + check_expr_with_unifier(check_env, fcx, &**arg, expected.unwrap_or(ExpectHasType(formal_ty)), NoPreference, || { // 2. Coerce to the most detailed type that could be coerced @@ -2313,7 +2324,7 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, // arguments which we skipped above. if variadic { for arg in args.iter().skip(expected_arg_count) { - check_expr(fcx, &**arg); + check_expr(check_env, fcx, &**arg); // There are a few types which get autopromoted when passed via varargs // in C but we just error out instead and require explicit casts. @@ -2409,52 +2420,59 @@ fn check_lit<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, } } -pub fn check_expr_has_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, - expr: &'tcx ast::Expr, - expected: Ty<'tcx>) { +fn check_expr_has_type<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a, 'tcx>, + expr: &'tcx ast::Expr, + expected: Ty<'tcx>) { check_expr_with_unifier( - fcx, expr, ExpectHasType(expected), NoPreference, + check_env, fcx, expr, ExpectHasType(expected), NoPreference, || demand::suptype(fcx, expr.span, expected, fcx.expr_ty(expr))); } -fn check_expr_coercable_to_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, +fn check_expr_coercable_to_type<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a, 'tcx>, expr: &'tcx ast::Expr, expected: Ty<'tcx>) { check_expr_with_unifier( - fcx, expr, ExpectHasType(expected), NoPreference, + check_env, fcx, expr, ExpectHasType(expected), NoPreference, || demand::coerce(fcx, expr.span, expected, expr)); } -fn check_expr_with_hint<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, expr: &'tcx ast::Expr, +fn check_expr_with_hint<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a, 'tcx>, expr: &'tcx ast::Expr, expected: Ty<'tcx>) { check_expr_with_unifier( - fcx, expr, ExpectHasType(expected), NoPreference, + check_env, fcx, expr, ExpectHasType(expected), NoPreference, || ()) } -fn check_expr_with_expectation<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, +fn check_expr_with_expectation<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a, 'tcx>, expr: &'tcx ast::Expr, expected: Expectation<'tcx>) { check_expr_with_unifier( - fcx, expr, expected, NoPreference, + check_env, fcx, expr, expected, NoPreference, || ()) } -fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, +fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a, 'tcx>, expr: &'tcx ast::Expr, expected: Expectation<'tcx>, lvalue_pref: LvaluePreference) { - check_expr_with_unifier(fcx, expr, expected, lvalue_pref, || ()) + check_expr_with_unifier(check_env, fcx, expr, expected, lvalue_pref, || ()) } -fn check_expr<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, expr: &'tcx ast::Expr) { - check_expr_with_unifier(fcx, expr, NoExpectation, NoPreference, || ()) +fn check_expr<'a,'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a,'tcx>, expr: &'tcx ast::Expr) { + check_expr_with_unifier(check_env, fcx, expr, NoExpectation, NoPreference, || ()) } -fn check_expr_with_lvalue_pref<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, expr: &'tcx ast::Expr, +fn check_expr_with_lvalue_pref<'a,'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a,'tcx>, expr: &'tcx ast::Expr, lvalue_pref: LvaluePreference) { - check_expr_with_unifier(fcx, expr, NoExpectation, lvalue_pref, || ()) + check_expr_with_unifier(check_env, fcx, expr, NoExpectation, lvalue_pref, || ()) } // determine the `self` type, using fresh variables for all variables @@ -2552,7 +2570,8 @@ fn expected_types_for_fn_args<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, /// 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<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, +fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a, 'tcx>, expr: &'tcx ast::Expr, expected: Expectation<'tcx>, lvalue_pref: LvaluePreference, @@ -2563,7 +2582,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, expr.repr(fcx.tcx()), expected.repr(fcx.tcx())); // Checks a method call. - fn check_method_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, + fn check_method_call<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a, 'tcx>, expr: &'tcx ast::Expr, method_name: ast::SpannedIdent, args: &'tcx [P], @@ -2571,7 +2591,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, expected: Expectation<'tcx>, lvalue_pref: LvaluePreference) { let rcvr = &*args[0]; - check_expr_with_lvalue_pref(fcx, &*rcvr, lvalue_pref); + check_expr_with_lvalue_pref(check_env, fcx, &*rcvr, lvalue_pref); // no need to check for bot/err -- callee does that let expr_t = structurally_resolved_type(fcx, @@ -2601,7 +2621,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, }; // Call the generic checker. - let ret_ty = check_method_argument_types(fcx, + let ret_ty = check_method_argument_types(check_env, + fcx, method_name.span, fn_ty, expr, @@ -2614,22 +2635,23 @@ 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>, + fn check_then_else<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a, 'tcx>, 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>) { - check_expr_has_type(fcx, cond_expr, fcx.tcx().types.bool); + check_expr_has_type(check_env, fcx, cond_expr, fcx.tcx().types.bool); let expected = expected.adjust_for_branches(fcx); - check_block_with_expected(fcx, then_blk, expected); + check_block_with_expected(check_env, fcx, then_blk, expected); let then_ty = fcx.node_ty(then_blk.id); let branches_ty = match opt_else_expr { Some(ref else_expr) => { - check_expr_with_expectation(fcx, &**else_expr, expected); + check_expr_with_expectation(check_env, fcx, &**else_expr, expected); let else_ty = fcx.expr_ty(&**else_expr); infer::common_supertype(fcx.infcx(), infer::IfExpression(sp), @@ -2657,13 +2679,14 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, } // Check field access expressions - fn check_field<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, + fn check_field<'a,'tcx>(check_env: &mut CheckEnv<'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); + check_expr_with_lvalue_pref(check_env, fcx, base, lvalue_pref); let expr_t = structurally_resolved_type(fcx, expr.span, fcx.expr_ty(base)); // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop. @@ -2758,13 +2781,14 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, } // Check tuple index expressions - fn check_tup_field<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, + fn check_tup_field<'a,'tcx>(check_env: &mut CheckEnv<'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); + check_expr_with_lvalue_pref(check_env, fcx, base, lvalue_pref); let expr_t = structurally_resolved_type(fcx, expr.span, fcx.expr_ty(base)); let mut tuple_like = false; @@ -2823,7 +2847,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, fcx.write_error(expr.id); } - fn check_struct_or_variant_fields<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, + fn check_struct_or_variant_fields<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a, 'tcx>, struct_ty: Ty<'tcx>, span: Span, class_id: ast::DefId, @@ -2899,7 +2924,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, // Make sure to give a type to the field even if there's // an error, so we can continue typechecking - check_expr_coercable_to_type(fcx, &*field.expr, expected_field_type); + check_expr_coercable_to_type(check_env, fcx, &*field.expr, expected_field_type); } if error_happened { @@ -2933,7 +2958,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, } } - fn check_struct_constructor<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, + fn check_struct_constructor<'a,'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a,'tcx>, id: ast::NodeId, span: codemap::Span, class_id: ast::DefId, @@ -2949,7 +2975,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, // Look up and check the fields. let class_fields = ty::lookup_struct_fields(tcx, class_id); - check_struct_or_variant_fields(fcx, + check_struct_or_variant_fields(check_env, + fcx, struct_type, span, class_id, @@ -2967,7 +2994,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, match base_expr { None => {} Some(base_expr) => { - check_expr_has_type(fcx, &*base_expr, struct_type); + check_expr_has_type(check_env, fcx, &*base_expr, struct_type); } } @@ -2975,7 +3002,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, fcx.write_ty(id, struct_type); } - fn check_struct_enum_variant<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, + fn check_struct_enum_variant<'a,'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a,'tcx>, id: ast::NodeId, span: codemap::Span, enum_id: ast::DefId, @@ -2992,7 +3020,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, // Look up and check the enum variant fields. let variant_fields = ty::lookup_struct_fields(tcx, variant_id); - check_struct_or_variant_fields(fcx, + check_struct_or_variant_fields(check_env, + fcx, enum_type, span, variant_id, @@ -3005,7 +3034,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, fcx.write_ty(id, enum_type); } - fn check_struct_fields_on_error<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, + fn check_struct_fields_on_error<'a,'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a,'tcx>, id: ast::NodeId, fields: &'tcx [ast::Field], base_expr: &'tcx Option>) { @@ -3013,10 +3043,10 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, // otherwise we might ICE fcx.write_error(id); for field in fields { - check_expr(fcx, &*field.expr); + check_expr(check_env, fcx, &*field.expr); } match *base_expr { - Some(ref base) => check_expr(fcx, &**base), + Some(ref base) => check_expr(check_env, fcx, &**base), None => {} } } @@ -3027,8 +3057,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, let id = expr.id; match expr.node { ast::ExprBox(ref opt_place, ref subexpr) => { - opt_place.as_ref().map(|place|check_expr(fcx, &**place)); - check_expr(fcx, &**subexpr); + opt_place.as_ref().map(|place|check_expr(check_env, fcx, &**place)); + check_expr(check_env, fcx, &**subexpr); let mut checked = false; opt_place.as_ref().map(|place| match place.node { @@ -3058,10 +3088,10 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, fcx.write_ty(id, typ); } ast::ExprBinary(op, ref lhs, ref rhs) => { - op::check_binop(fcx, expr, op, lhs, rhs); + op::check_binop(check_env, fcx, expr, op, lhs, rhs); } ast::ExprAssignOp(op, ref lhs, ref rhs) => { - op::check_binop_assign(fcx, expr, op, lhs, rhs); + op::check_binop_assign(check_env, fcx, expr, op, lhs, rhs); } ast::ExprUnary(unop, ref oprnd) => { let expected_inner = expected.to_option(fcx).map_or(NoExpectation, |ty| { @@ -3087,7 +3117,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, _ => NoPreference }; check_expr_with_expectation_and_lvalue_pref( - fcx, &**oprnd, expected_inner, lvalue_pref); + check_env, fcx, &**oprnd, expected_inner, lvalue_pref); let mut oprnd_t = fcx.expr_ty(&**oprnd); if !ty::type_is_error(oprnd_t) { @@ -3182,7 +3212,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, ast::MutMutable => PreferMutLvalue, ast::MutImmutable => NoPreference }; - check_expr_with_expectation_and_lvalue_pref(fcx, + check_expr_with_expectation_and_lvalue_pref(check_env, + fcx, &**oprnd, hint, lvalue_pref); @@ -3250,10 +3281,10 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, } ast::ExprInlineAsm(ref ia) => { for &(_, ref input) in &ia.inputs { - check_expr(fcx, &**input); + check_expr(check_env, fcx, &**input); } for &(_, ref out, _) in &ia.outputs { - check_expr(fcx, &**out); + check_expr(check_env, fcx, &**out); } fcx.write_nil(id); } @@ -3271,13 +3302,13 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, "`return;` in function returning non-nil"); }, Some(ref e) => { - check_expr_coercable_to_type(fcx, &**e, result_type); + check_expr_coercable_to_type(check_env, fcx, &**e, result_type); } } } ty::FnDiverging => { if let Some(ref e) = *expr_opt { - check_expr(fcx, &**e); + check_expr(check_env, fcx, &**e); } span_err!(tcx.sess, expr.span, E0166, "`return` in a function declared as diverging"); @@ -3286,14 +3317,15 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, fcx.write_ty(id, fcx.infcx().next_diverging_ty_var()); } ast::ExprParen(ref a) => { - check_expr_with_expectation_and_lvalue_pref(fcx, + check_expr_with_expectation_and_lvalue_pref(check_env, + fcx, &**a, expected, lvalue_pref); fcx.write_ty(id, fcx.expr_ty(&**a)); } ast::ExprAssign(ref lhs, ref rhs) => { - check_expr_with_lvalue_pref(fcx, &**lhs, PreferMutLvalue); + check_expr_with_lvalue_pref(check_env, fcx, &**lhs, PreferMutLvalue); let tcx = fcx.tcx(); if !ty::expr_is_lval(tcx, &**lhs) { @@ -3302,7 +3334,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, } let lhs_ty = fcx.expr_ty(&**lhs); - check_expr_coercable_to_type(fcx, &**rhs, lhs_ty); + check_expr_coercable_to_type(check_env, fcx, &**rhs, lhs_ty); let rhs_ty = fcx.expr_ty(&**rhs); fcx.require_expr_have_sized_type(&**lhs, traits::AssignmentLhsSized); @@ -3314,15 +3346,15 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, } } ast::ExprIf(ref cond, ref then_blk, ref opt_else_expr) => { - check_then_else(fcx, &**cond, &**then_blk, opt_else_expr.as_ref().map(|e| &**e), + check_then_else(check_env, fcx, &**cond, &**then_blk, opt_else_expr.as_ref().map(|e| &**e), id, expr.span, expected); } ast::ExprIfLet(..) => { tcx.sess.span_bug(expr.span, "non-desugared ExprIfLet"); } ast::ExprWhile(ref cond, ref body, _) => { - check_expr_has_type(fcx, &**cond, tcx.types.bool); - check_block_no_value(fcx, &**body); + check_expr_has_type(check_env, fcx, &**cond, tcx.types.bool); + check_block_no_value(check_env, fcx, &**body); let cond_ty = fcx.expr_ty(&**cond); let body_ty = fcx.node_ty(body.id); if ty::type_is_error(cond_ty) || ty::type_is_error(body_ty) { @@ -3339,7 +3371,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, tcx.sess.span_bug(expr.span, "non-desugared ExprForLoop"); } ast::ExprLoop(ref body, _) => { - check_block_no_value(fcx, &**body); + check_block_no_value(check_env, fcx, &**body); if !may_break(tcx, expr.id, &**body) { fcx.write_ty(id, fcx.infcx().next_diverging_ty_var()); } else { @@ -3347,20 +3379,20 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, } } ast::ExprMatch(ref discrim, ref arms, match_src) => { - _match::check_match(fcx, expr, &**discrim, arms, expected, match_src); + _match::check_match(check_env, fcx, expr, &**discrim, arms, expected, match_src); } ast::ExprClosure(capture, ref decl, ref body) => { - closure::check_expr_closure(fcx, expr, capture, &**decl, &**body, expected); + closure::check_expr_closure(check_env, fcx, expr, capture, &**decl, &**body, expected); } ast::ExprBlock(ref b) => { - check_block_with_expected(fcx, &**b, expected); + check_block_with_expected(check_env, fcx, &**b, expected); fcx.write_ty(id, fcx.node_ty(b.id)); } ast::ExprCall(ref callee, ref args) => { - callee::check_call(fcx, expr, &**callee, &args[..], expected); + callee::check_call(check_env, fcx, expr, &**callee, &args[..], expected); } ast::ExprMethodCall(ident, ref tps, ref args) => { - check_method_call(fcx, expr, ident, &args[..], &tps[..], expected, lvalue_pref); + check_method_call(check_env, fcx, expr, ident, &args[..], &tps[..], expected, lvalue_pref); let arg_tys = args.iter().map(|a| fcx.expr_ty(&**a)); let args_err = arg_tys.fold(false, |rest_err, a| { @@ -3371,14 +3403,14 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, } ast::ExprCast(ref e, ref t) => { if let ast::TyFixedLengthVec(_, ref count_expr) = t.node { - check_expr_with_hint(fcx, &**count_expr, tcx.types.usize); + check_expr_with_hint(check_env, fcx, &**count_expr, tcx.types.usize); } // Find the type of `e`. Supply hints based on the type we are casting to, // if appropriate. let t_1 = fcx.to_ty(t); let t_1 = structurally_resolved_type(fcx, expr.span, t_1); - check_expr_with_expectation(fcx, e, ExpectCastableToType(t_1)); + check_expr_with_expectation(check_env, fcx, e, ExpectCastableToType(t_1)); let t_e = fcx.expr_ty(e); // Eagerly check for some obvious errors. @@ -3392,9 +3424,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, fcx.write_ty(id, t_1); // Defer other checks until we're done type checking. - let mut deferred_cast_checks = fcx.inh.deferred_cast_checks.borrow_mut(); let cast_check = cast::CastCheck::new((**e).clone(), t_e, t_1, expr.span); - deferred_cast_checks.push(cast_check); + check_env.deferred_cast_checks.push(cast_check); } } ast::ExprVec(ref args) => { @@ -3408,14 +3439,14 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, let typ = match uty { Some(uty) => { for e in args { - check_expr_coercable_to_type(fcx, &**e, uty); + check_expr_coercable_to_type(check_env, fcx, &**e, uty); } uty } None => { let t: Ty = fcx.infcx().next_ty_var(); for e in args { - check_expr_has_type(fcx, &**e, t); + check_expr_has_type(check_env, fcx, &**e, t); } t } @@ -3424,7 +3455,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, fcx.write_ty(id, typ); } ast::ExprRepeat(ref element, ref count_expr) => { - check_expr_has_type(fcx, &**count_expr, tcx.types.usize); + check_expr_has_type(check_env, fcx, &**count_expr, tcx.types.usize); let count = ty::eval_repeat_count(fcx.tcx(), &**count_expr); let uty = match expected { @@ -3439,12 +3470,12 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, let (element_ty, t) = match uty { Some(uty) => { - check_expr_coercable_to_type(fcx, &**element, uty); + check_expr_coercable_to_type(check_env, fcx, &**element, uty); (uty, uty) } None => { let t: Ty = fcx.infcx().next_ty_var(); - check_expr_has_type(fcx, &**element, t); + check_expr_has_type(check_env, fcx, &**element, t); (fcx.expr_ty(&**element), t) } }; @@ -3479,11 +3510,11 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, let t = match flds { Some(ref fs) if i < fs.len() => { let ety = fs[i]; - check_expr_coercable_to_type(fcx, &**e, ety); + check_expr_coercable_to_type(check_env, fcx, &**e, ety); ety } _ => { - check_expr_with_expectation(fcx, &**e, NoExpectation); + check_expr_with_expectation(check_env, fcx, &**e, NoExpectation); fcx.expr_ty(&**e) } }; @@ -3502,7 +3533,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, let def = lookup_full_def(tcx, path.span, id); let struct_id = match def { def::DefVariant(enum_id, variant_id, true) => { - check_struct_enum_variant(fcx, id, expr.span, enum_id, + check_struct_enum_variant(check_env, fcx, id, expr.span, enum_id, variant_id, &fields[..]); enum_id } @@ -3510,7 +3541,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, span_err!(tcx.sess, path.span, E0159, "use of trait `{}` as a struct constructor", pprust::path_to_string(path)); - check_struct_fields_on_error(fcx, + check_struct_fields_on_error(check_env, + fcx, id, &fields[..], base_expr); @@ -3521,7 +3553,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, let typ = ty::lookup_item_type(fcx.ccx.tcx, def.def_id()); match typ.ty.sty { ty::ty_struct(struct_did, _) => { - check_struct_constructor(fcx, + check_struct_constructor(check_env, + fcx, id, expr.span, struct_did, @@ -3532,7 +3565,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, span_err!(tcx.sess, path.span, E0071, "`{}` does not name a structure", pprust::path_to_string(path)); - check_struct_fields_on_error(fcx, + check_struct_fields_on_error(check_env, + fcx, id, &fields[..], base_expr); @@ -3575,14 +3609,14 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, fcx.require_expr_have_sized_type(expr, traits::StructInitializerSized); } ast::ExprField(ref base, ref field) => { - check_field(fcx, expr, lvalue_pref, &**base, field); + check_field(check_env, fcx, expr, lvalue_pref, &**base, field); } ast::ExprTupField(ref base, idx) => { - check_tup_field(fcx, expr, lvalue_pref, &**base, idx); + check_tup_field(check_env, fcx, expr, lvalue_pref, &**base, idx); } ast::ExprIndex(ref base, ref idx) => { - check_expr_with_lvalue_pref(fcx, &**base, lvalue_pref); - check_expr(fcx, &**idx); + check_expr_with_lvalue_pref(check_env, fcx, &**base, lvalue_pref); + check_expr(check_env, fcx, &**idx); let base_t = fcx.expr_ty(&**base); let idx_t = fcx.expr_ty(&**idx); @@ -3600,7 +3634,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, fcx.write_ty(id, element_ty); } None => { - check_expr_has_type(fcx, &**idx, fcx.tcx().types.err); + check_expr_has_type(check_env, fcx, &**idx, fcx.tcx().types.err); fcx.type_error_message( expr.span, |actual| { @@ -3616,11 +3650,11 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, } ast::ExprRange(ref start, ref end) => { let t_start = start.as_ref().map(|e| { - check_expr(fcx, &**e); + check_expr(check_env, fcx, &**e); fcx.expr_ty(&**e) }); let t_end = end.as_ref().map(|e| { - check_expr(fcx, &**e); + check_expr(check_env, fcx, &**e); fcx.expr_ty(&**e) }); @@ -3840,15 +3874,16 @@ impl<'tcx> Repr<'tcx> for Expectation<'tcx> { } } -pub fn check_decl_initializer<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, - local: &'tcx ast::Local, - init: &'tcx ast::Expr) +fn check_decl_initializer<'a,'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a,'tcx>, + local: &'tcx ast::Local, + init: &'tcx ast::Expr) { let ref_bindings = fcx.tcx().pat_contains_ref_binding(&local.pat); let local_ty = fcx.local_ty(init.span, local.id); if !ref_bindings { - check_expr_coercable_to_type(fcx, init, local_ty) + check_expr_coercable_to_type(check_env, fcx, init, local_ty) } else { // Somewhat subtle: if we have a `ref` binding in the pattern, // we want to avoid introducing coercions for the RHS. This is @@ -3858,20 +3893,21 @@ pub fn check_decl_initializer<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, // referent for the reference that results is *equal to* the // type of the lvalue it is referencing, and not some // supertype thereof. - check_expr(fcx, init); + check_expr(check_env, fcx, init); let init_ty = fcx.expr_ty(init); demand::eqtype(fcx, init.span, init_ty, local_ty); }; } -pub fn check_decl_local<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, local: &'tcx ast::Local) { +fn check_decl_local<'a,'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a,'tcx>, local: &'tcx ast::Local) { let tcx = fcx.ccx.tcx; let t = fcx.local_ty(local.span, local.id); fcx.write_ty(local.id, t); if let Some(ref init) = local.init { - check_decl_initializer(fcx, local, &**init); + check_decl_initializer(check_env, fcx, local, &**init); let init_ty = fcx.expr_ty(&**init); if ty::type_is_error(init_ty) { fcx.write_ty(local.id, init_ty); @@ -3882,14 +3918,15 @@ pub fn check_decl_local<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, local: &'tcx ast::Local) fcx: fcx, map: pat_id_map(&tcx.def_map, &*local.pat), }; - _match::check_pat(&pcx, &*local.pat, t); + _match::check_pat(check_env, &pcx, &*local.pat, t); let pat_ty = fcx.node_ty(local.pat.id); if ty::type_is_error(pat_ty) { fcx.write_ty(local.id, pat_ty); } } -pub fn check_stmt<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, stmt: &'tcx ast::Stmt) { +fn check_stmt<'a,'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a,'tcx>, stmt: &'tcx ast::Stmt) { let node_id; let mut saw_bot = false; let mut saw_err = false; @@ -3898,7 +3935,7 @@ pub fn check_stmt<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, stmt: &'tcx ast::Stmt) { node_id = id; match decl.node { ast::DeclLocal(ref l) => { - check_decl_local(fcx, &**l); + check_decl_local(check_env, fcx, &**l); let l_t = fcx.node_ty(l.id); saw_bot = saw_bot || fcx.infcx().type_var_diverges(l_t); saw_err = saw_err || ty::type_is_error(l_t); @@ -3909,14 +3946,14 @@ pub fn check_stmt<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, stmt: &'tcx ast::Stmt) { ast::StmtExpr(ref expr, id) => { node_id = id; // Check with expected type of () - check_expr_has_type(fcx, &**expr, ty::mk_nil(fcx.tcx())); + check_expr_has_type(check_env, 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); } ast::StmtSemi(ref expr, id) => { node_id = id; - check_expr(fcx, &**expr); + check_expr(check_env, fcx, &**expr); let expr_ty = fcx.expr_ty(&**expr); saw_bot |= fcx.infcx().type_var_diverges(expr_ty); saw_err |= ty::type_is_error(expr_ty); @@ -3934,8 +3971,9 @@ pub fn check_stmt<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, stmt: &'tcx ast::Stmt) { } } -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()))); +fn check_block_no_value<'a,'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a,'tcx>, blk: &'tcx ast::Block) { + check_block_with_expected(check_env, 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); @@ -3945,7 +3983,8 @@ pub fn check_block_no_value<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, blk: &'tcx ast::Bloc } } -fn check_block_with_expected<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, +fn check_block_with_expected<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a, 'tcx>, blk: &'tcx ast::Block, expected: Expectation<'tcx>) { let prev = { @@ -3958,7 +3997,7 @@ fn check_block_with_expected<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, let mut any_diverges = false; let mut any_err = false; for s in &blk.stmts { - check_stmt(fcx, &**s); + check_stmt(check_env, fcx, &**s); let s_id = ast_util::stmt_id(&**s); let s_ty = fcx.node_ty(s_id); if any_diverges && !warned && match s.node { @@ -4003,11 +4042,11 @@ fn check_block_with_expected<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, } let ety = match expected { ExpectHasType(ety) => { - check_expr_coercable_to_type(fcx, &**e, ety); + check_expr_coercable_to_type(check_env, fcx, &**e, ety); ety } _ => { - check_expr_with_expectation(fcx, &**e, expected); + check_expr_with_expectation(check_env, fcx, &**e, expected); fcx.expr_ty(&**e) } }; @@ -4031,23 +4070,24 @@ fn check_block_with_expected<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, fn check_const_in_type<'a,'tcx>(ccx: &'a CrateCtxt<'a,'tcx>, expr: &'tcx ast::Expr, expected_type: Ty<'tcx>) { - let inh = static_inherited_fields(ccx); + let (mut check_env, inh) = static_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); + check_const_with_ty(&mut check_env, &fcx, expr.span, expr, expected_type); } 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 (mut check_env, inh) = static_fields(ccx); let rty = ty::node_id_to_type(ccx.tcx, id); let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), e.id); let declty = fcx.ccx.tcx.tcache.borrow().get(&local_def(id)).unwrap().ty; - check_const_with_ty(&fcx, sp, e, declty); + check_const_with_ty(&mut check_env, &fcx, sp, e, declty); } -fn check_const_with_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, +fn check_const_with_ty<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a, 'tcx>, _: Span, e: &'tcx ast::Expr, declty: Ty<'tcx>) { @@ -4055,13 +4095,13 @@ fn check_const_with_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, // This is technically unnecessary because locals in static items are forbidden, // but prevents type checking from blowing up before const checking can properly // emit a error. - GatherLocalsVisitor { fcx: fcx }.visit_expr(e); + GatherLocalsVisitor { check_env: check_env, fcx: fcx }.visit_expr(e); - check_expr_with_hint(fcx, e, declty); + check_expr_with_hint(check_env, fcx, e, declty); demand::coerce(fcx, e.span, declty, e); - vtable::select_all_fcx_obligations_or_error(fcx); - fcx.check_casts(); - regionck::regionck_expr(fcx, e); + vtable::select_all_fcx_obligations_or_error(check_env, fcx); + check_env.check_casts(fcx); + regionck::regionck_expr(check_env, fcx, e); writeback::resolve_type_vars_in_expr(fcx, e); } @@ -4192,13 +4232,13 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, let rty = ty::node_id_to_type(ccx.tcx, id); let mut disr_vals: Vec = Vec::new(); - let inh = static_inherited_fields(ccx); + let (mut check_env, inh) = static_fields(ccx); let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), id); let (_, repr_type_ty) = ty::enum_repr_type(ccx.tcx, Some(&hint)); for v in vs { if let Some(ref e) = v.node.disr_expr { - check_const_with_ty(&fcx, e.span, e, repr_type_ty); + check_const_with_ty(&mut check_env, &fcx, e.span, e, repr_type_ty); } } diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index b4000788d1998..d8f78d0588f78 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -14,6 +14,7 @@ use super::{ check_expr, check_expr_coercable_to_type, check_expr_with_lvalue_pref, + CheckEnv, demand, method, FnCtxt, @@ -28,7 +29,8 @@ use syntax::parse::token; use util::ppaux::{Repr, UserString}; /// Check a `a = b` -pub fn check_binop_assign<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, +pub fn check_binop_assign<'a,'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a,'tcx>, expr: &'tcx ast::Expr, op: ast::BinOp, lhs_expr: &'tcx ast::Expr, @@ -36,8 +38,8 @@ pub fn check_binop_assign<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, { let tcx = fcx.ccx.tcx; - check_expr_with_lvalue_pref(fcx, lhs_expr, PreferMutLvalue); - check_expr(fcx, rhs_expr); + check_expr_with_lvalue_pref(check_env, fcx, lhs_expr, PreferMutLvalue); + check_expr(check_env, fcx, rhs_expr); let lhs_ty = structurally_resolved_type(fcx, lhs_expr.span, fcx.expr_ty(lhs_expr)); let rhs_ty = structurally_resolved_type(fcx, rhs_expr.span, fcx.expr_ty(rhs_expr)); @@ -65,7 +67,8 @@ pub fn check_binop_assign<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, } /// Check a potentially overloaded binary operator. -pub fn check_binop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, +pub fn check_binop<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a, 'tcx>, expr: &'tcx ast::Expr, op: ast::BinOp, lhs_expr: &'tcx ast::Expr, @@ -80,7 +83,7 @@ pub fn check_binop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, lhs_expr.repr(tcx), rhs_expr.repr(tcx)); - check_expr(fcx, lhs_expr); + check_expr(check_env, fcx, lhs_expr); let lhs_ty = fcx.resolve_type_vars_if_possible(fcx.expr_ty(lhs_expr)); // Annoyingly, SIMD ops don't fit into the PartialEq/PartialOrd @@ -88,7 +91,7 @@ pub fn check_binop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, // should change, but for now if LHS is SIMD we go down a // different path that bypassess all traits. if ty::type_is_simd(fcx.tcx(), lhs_ty) { - check_expr_coercable_to_type(fcx, rhs_expr, lhs_ty); + check_expr_coercable_to_type(check_env, fcx, rhs_expr, lhs_ty); let rhs_ty = fcx.resolve_type_vars_if_possible(fcx.expr_ty(lhs_expr)); let return_ty = enforce_builtin_binop_types(fcx, lhs_expr, lhs_ty, rhs_expr, rhs_ty, op); fcx.write_ty(expr.id, return_ty); @@ -99,7 +102,7 @@ pub fn check_binop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, BinOpCategory::Shortcircuit => { // && and || are a simple case. demand::suptype(fcx, lhs_expr.span, ty::mk_bool(tcx), lhs_ty); - check_expr_coercable_to_type(fcx, rhs_expr, ty::mk_bool(tcx)); + check_expr_coercable_to_type(check_env, fcx, rhs_expr, ty::mk_bool(tcx)); fcx.write_ty(expr.id, ty::mk_bool(tcx)); } _ => { @@ -107,7 +110,7 @@ pub fn check_binop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, // overloaded. This is the way to be most flexible w/r/t // types that get inferred. let (rhs_ty, return_ty) = - check_overloaded_binop(fcx, expr, lhs_expr, lhs_ty, rhs_expr, op); + check_overloaded_binop(check_env, fcx, expr, lhs_expr, lhs_ty, rhs_expr, op); // Supply type inference hints if relevant. Probably these // hints should be enforced during select as part of the @@ -201,7 +204,8 @@ fn enforce_builtin_binop_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, } } -fn check_overloaded_binop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, +fn check_overloaded_binop<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a, 'tcx>, expr: &'tcx ast::Expr, lhs_expr: &'tcx ast::Expr, lhs_ty: Ty<'tcx>, @@ -240,7 +244,7 @@ fn check_overloaded_binop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, }; // see `NB` above - check_expr_coercable_to_type(fcx, rhs_expr, rhs_ty_var); + check_expr_coercable_to_type(check_env, fcx, rhs_expr, rhs_ty_var); (rhs_ty_var, return_ty) } diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 19cb570c82d13..1750828b4934c 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -83,9 +83,10 @@ //! contents. use astconv::AstConv; -use check::dropck; -use check::FnCtxt; -use check::vtable; +use super::dropck; +use super::CheckEnv; +use super::FnCtxt; +use super::vtable; use middle::free_region::FreeRegionMap; use middle::implicator; use middle::mem_categorization as mc; @@ -113,8 +114,8 @@ macro_rules! ignore_err { /////////////////////////////////////////////////////////////////////////// // PUBLIC ENTRY POINTS -pub fn regionck_expr(fcx: &FnCtxt, e: &ast::Expr) { - let mut rcx = Rcx::new(fcx, RepeatingScope(e.id), e.id, Subject(e.id)); +pub fn regionck_expr<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, fcx: &FnCtxt<'a, 'tcx>, e: &ast::Expr) { + let mut rcx = Rcx::new(check_env, fcx, RepeatingScope(e.id), e.id, Subject(e.id)); if fcx.err_count_since_creation() == 0 { // regionck assumes typeck succeeded rcx.visit_expr(e); @@ -123,21 +124,22 @@ pub fn regionck_expr(fcx: &FnCtxt, e: &ast::Expr) { rcx.resolve_regions_and_report_errors(); } -pub fn regionck_item(fcx: &FnCtxt, item: &ast::Item) { - let mut rcx = Rcx::new(fcx, RepeatingScope(item.id), item.id, Subject(item.id)); +pub fn regionck_item<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, fcx: &FnCtxt<'a, 'tcx>, item: &ast::Item) { + let mut rcx = Rcx::new(check_env, fcx, RepeatingScope(item.id), item.id, Subject(item.id)); let tcx = fcx.tcx(); rcx.free_region_map.relate_free_regions_from_predicates(tcx, &fcx.inh.param_env.caller_bounds); rcx.visit_region_obligations(item.id); rcx.resolve_regions_and_report_errors(); } -pub fn regionck_fn(fcx: &FnCtxt, - fn_id: ast::NodeId, - fn_span: Span, - decl: &ast::FnDecl, - blk: &ast::Block) { +pub fn regionck_fn<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a, 'tcx>, + fn_id: ast::NodeId, + fn_span: Span, + decl: &ast::FnDecl, + blk: &ast::Block) { debug!("regionck_fn(id={})", fn_id); - let mut rcx = Rcx::new(fcx, RepeatingScope(blk.id), blk.id, Subject(fn_id)); + let mut rcx = Rcx::new(check_env, fcx, RepeatingScope(blk.id), blk.id, Subject(fn_id)); if fcx.err_count_since_creation() == 0 { // regionck assumes typeck succeeded @@ -157,10 +159,11 @@ pub fn regionck_fn(fcx: &FnCtxt, /// Checks that the types in `component_tys` are well-formed. This will add constraints into the /// region graph. Does *not* run `resolve_regions_and_report_errors` and so forth. -pub fn regionck_ensure_component_tys_wf<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, +pub fn regionck_ensure_component_tys_wf<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a, 'tcx>, span: Span, component_tys: &[Ty<'tcx>]) { - let mut rcx = Rcx::new(fcx, RepeatingScope(0), 0, SubjectNode::None); + let mut rcx = Rcx::new(check_env, fcx, RepeatingScope(0), 0, SubjectNode::None); for &component_ty in component_tys { // Check that each type outlives the empty region. Since the // empty region is a subregion of all others, this can't fail @@ -175,6 +178,8 @@ pub fn regionck_ensure_component_tys_wf<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, // INTERNALS pub struct Rcx<'a, 'tcx: 'a> { + check_env: &'a mut CheckEnv<'tcx>, + fcx: &'a FnCtxt<'a, 'tcx>, region_bound_pairs: Vec<(ty::Region, GenericKind<'tcx>)>, @@ -195,13 +200,109 @@ pub struct Rcx<'a, 'tcx: 'a> { pub struct RepeatingScope(ast::NodeId); pub enum SubjectNode { Subject(ast::NodeId), None } +/// Try to resolve the type for the given node, returning t_err if an error results. Note that +/// we never care about the details of the error, the same error will be detected and reported +/// in the writeback phase. +/// +/// Note one important point: we do not attempt to resolve *region variables* here. This is +/// because regionck is essentially adding constraints to those region variables and so may yet +/// influence how they are resolved. +/// +/// Consider this silly example: +/// +/// ``` +/// fn borrow(x: &int) -> &int {x} +/// fn foo(x: @int) -> int { // block: B +/// let b = borrow(x); // region: +/// *b +/// } +/// ``` +/// +/// Here, the region of `b` will be ``. `` is constrained to be some subregion of the +/// block B and some superregion of the call. If we forced it now, we'd choose the smaller +/// region (the call). But that would make the *b illegal. Since we don't resolve, the type +/// of b will be `&.int` and then `*b` will require that `` be bigger than the let and +/// the `*b` expression, so we will effectively resolve `` to be the block B. +fn resolve_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, unresolved_ty: Ty<'tcx>) -> Ty<'tcx> { + fcx.infcx().resolve_type_vars_if_possible(&unresolved_ty) +} + +/// This method populates the region map's `free_region_map`. It walks over the transformed +/// argument and return types for each function just before we check the body of that function, +/// looking for types where you have a borrowed pointer to other borrowed data (e.g., `&'a &'b +/// [usize]`. We do not allow references to outlive the things they point at, so we can assume +/// that `'a <= 'b`. This holds for both the argument and return types, basically because, on +/// the caller side, the caller is responsible for checking that the type of every expression +/// (including the actual values for the arguments, as well as the return type of the fn call) +/// is well-formed. +/// +/// Tests: `src/test/compile-fail/regions-free-region-ordering-*.rs` +fn relate_free_regions<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, + tcx: &ty::ctxt<'tcx>, + free_region_map: &mut FreeRegionMap, + region_bound_pairs: &mut Vec<(ty::Region, GenericKind<'tcx>)>, + fn_sig_tys: &[Ty<'tcx>], + body_id: ast::NodeId, + span: Span) { + debug!("relate_free_regions >>"); + + for &ty in fn_sig_tys { + let ty = resolve_type(fcx, ty); + debug!("relate_free_regions(t={})", ty.repr(tcx)); + let body_scope = CodeExtent::from_node_id(body_id); + let body_scope = ty::ReScope(body_scope); + let implications = implicator::implications(fcx.infcx(), fcx, body_id, + ty, body_scope, span); + + // Record any relations between free regions that we observe into the free-region-map. + free_region_map.relate_free_regions_from_implications(tcx, &implications); + + // But also record other relationships, such as `T:'x`, + // that don't go into the free-region-map but which we use + // here. + for implication in implications { + debug!("implication: {}", implication.repr(tcx)); + match implication { + implicator::Implication::RegionSubRegion(_, + ty::ReFree(free_a), + ty::ReInfer(ty::ReVar(vid_b))) => { + fcx.inh.infcx.add_given(free_a, vid_b); + } + implicator::Implication::RegionSubGeneric(_, r_a, ref generic_b) => { + debug!("RegionSubGeneric: {} <= {}", + r_a.repr(tcx), generic_b.repr(tcx)); + + region_bound_pairs.push((r_a, generic_b.clone())); + } + implicator::Implication::RegionSubRegion(..) | + implicator::Implication::RegionSubClosure(..) | + implicator::Implication::Predicate(..) => { + // In principle, we could record (and take + // advantage of) every relationship here, but + // we are also free not to -- it simply means + // strictly less that we can successfully type + // check. (It may also be that we should + // revise our inference system to be more + // general and to make use of *every* + // relationship that arises here, but + // presently we do not.) + } + } + } + } + + debug!("<< relate_free_regions"); +} + impl<'a, 'tcx> Rcx<'a, 'tcx> { - pub fn new(fcx: &'a FnCtxt<'a, 'tcx>, + fn new(check_env: &'a mut CheckEnv<'tcx>, + fcx: &'a FnCtxt<'a, 'tcx>, initial_repeating_scope: RepeatingScope, initial_body_id: ast::NodeId, subject: SubjectNode) -> Rcx<'a, 'tcx> { let RepeatingScope(initial_repeating_scope) = initial_repeating_scope; - Rcx { fcx: fcx, + Rcx { check_env: check_env, + fcx: fcx, repeating_scope: initial_repeating_scope, body_id: initial_body_id, subject: subject, @@ -222,47 +323,20 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> { mem::replace(&mut self.repeating_scope, scope) } - /// Try to resolve the type for the given node, returning t_err if an error results. Note that - /// we never care about the details of the error, the same error will be detected and reported - /// in the writeback phase. - /// - /// Note one important point: we do not attempt to resolve *region variables* here. This is - /// because regionck is essentially adding constraints to those region variables and so may yet - /// influence how they are resolved. - /// - /// Consider this silly example: - /// - /// ``` - /// fn borrow(x: &int) -> &int {x} - /// fn foo(x: @int) -> int { // block: B - /// let b = borrow(x); // region: - /// *b - /// } - /// ``` - /// - /// Here, the region of `b` will be ``. `` is constrained to be some subregion of the - /// block B and some superregion of the call. If we forced it now, we'd choose the smaller - /// region (the call). But that would make the *b illegal. Since we don't resolve, the type - /// of b will be `&.int` and then `*b` will require that `` be bigger than the let and - /// the `*b` expression, so we will effectively resolve `` to be the block B. - pub fn resolve_type(&self, unresolved_ty: Ty<'tcx>) -> Ty<'tcx> { - self.fcx.infcx().resolve_type_vars_if_possible(&unresolved_ty) - } - /// Try to resolve the type for the given node. fn resolve_node_type(&self, id: ast::NodeId) -> Ty<'tcx> { let t = self.fcx.node_ty(id); - self.resolve_type(t) + resolve_type(self.fcx, t) } fn resolve_method_type(&self, method_call: MethodCall) -> Option> { let method_ty = self.fcx.inh.method_map.borrow() .get(&method_call).map(|method| method.ty); - method_ty.map(|method_ty| self.resolve_type(method_ty)) + method_ty.map(|method_ty| resolve_type(self.fcx, method_ty)) } /// Try to resolve the type for the given node. - pub fn resolve_expr_type_adjusted(&mut self, expr: &ast::Expr) -> Ty<'tcx> { + fn resolve_expr_type_adjusted(&mut self, expr: &ast::Expr) -> Ty<'tcx> { let ty_unadjusted = self.resolve_node_type(expr.id); if ty::type_is_error(ty_unadjusted) { ty_unadjusted @@ -280,22 +354,26 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> { body: &ast::Block, span: Span) { + // When we enter a function, we can derive debug!("visit_fn_body(id={})", id); - let fn_sig_map = self.fcx.inh.fn_sig_map.borrow(); - let fn_sig = match fn_sig_map.get(&id) { - Some(f) => f, + let old_region_bounds_pairs_len = self.region_bound_pairs.len(); + + let old_body_id = self.set_body_id(body.id); + + match self.check_env.fn_sig_map.get(&id) { + Some(fn_sig) => { + relate_free_regions(self.fcx, self.tcx(), + &mut self.free_region_map, &mut self.region_bound_pairs, + &fn_sig[..], body.id, span); + }, None => { self.tcx().sess.bug( &format!("No fn-sig entry for id={}", id)); } }; - let old_region_bounds_pairs_len = self.region_bound_pairs.len(); - - let old_body_id = self.set_body_id(body.id); - self.relate_free_regions(&fn_sig[..], body.id, span); link_fn_args(self, CodeExtent::from_node_id(body.id), &fn_decl.inputs[..]); self.visit_block(body); self.visit_region_obligations(body.id); @@ -312,7 +390,7 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> { // region checking can introduce new pending obligations // which, when processed, might generate new region // obligations. So make sure we process those. - vtable::select_all_fcx_obligations_or_error(self.fcx); + vtable::select_all_fcx_obligations_or_error(self.check_env, self.fcx); // Make a copy of the region obligations vec because we'll need // to be able to borrow the fulfillment-cx below when projecting. @@ -324,7 +402,7 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> { for r_o in ®ion_obligations { debug!("visit_region_obligations: r_o={}", r_o.repr(self.tcx())); - let sup_type = self.resolve_type(r_o.sup_type); + let sup_type = resolve_type(self.fcx, r_o.sup_type); let origin = infer::RelateParamBound(r_o.cause.span, sup_type); type_must_outlive(self, origin, sup_type, r_o.sub_region); } @@ -334,71 +412,6 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> { self.fcx.inh.fulfillment_cx.borrow().region_obligations(node_id).len()); } - /// This method populates the region map's `free_region_map`. It walks over the transformed - /// argument and return types for each function just before we check the body of that function, - /// looking for types where you have a borrowed pointer to other borrowed data (e.g., `&'a &'b - /// [usize]`. We do not allow references to outlive the things they point at, so we can assume - /// that `'a <= 'b`. This holds for both the argument and return types, basically because, on - /// the caller side, the caller is responsible for checking that the type of every expression - /// (including the actual values for the arguments, as well as the return type of the fn call) - /// is well-formed. - /// - /// Tests: `src/test/compile-fail/regions-free-region-ordering-*.rs` - fn relate_free_regions(&mut self, - fn_sig_tys: &[Ty<'tcx>], - body_id: ast::NodeId, - span: Span) { - debug!("relate_free_regions >>"); - let tcx = self.tcx(); - - for &ty in fn_sig_tys { - let ty = self.resolve_type(ty); - debug!("relate_free_regions(t={})", ty.repr(tcx)); - let body_scope = CodeExtent::from_node_id(body_id); - let body_scope = ty::ReScope(body_scope); - let implications = implicator::implications(self.fcx.infcx(), self.fcx, body_id, - ty, body_scope, span); - - // Record any relations between free regions that we observe into the free-region-map. - self.free_region_map.relate_free_regions_from_implications(tcx, &implications); - - // But also record other relationships, such as `T:'x`, - // that don't go into the free-region-map but which we use - // here. - for implication in implications { - debug!("implication: {}", implication.repr(tcx)); - match implication { - implicator::Implication::RegionSubRegion(_, - ty::ReFree(free_a), - ty::ReInfer(ty::ReVar(vid_b))) => { - self.fcx.inh.infcx.add_given(free_a, vid_b); - } - implicator::Implication::RegionSubGeneric(_, r_a, ref generic_b) => { - debug!("RegionSubGeneric: {} <= {}", - r_a.repr(tcx), generic_b.repr(tcx)); - - self.region_bound_pairs.push((r_a, generic_b.clone())); - } - implicator::Implication::RegionSubRegion(..) | - implicator::Implication::RegionSubClosure(..) | - implicator::Implication::Predicate(..) => { - // In principle, we could record (and take - // advantage of) every relationship here, but - // we are also free not to -- it simply means - // strictly less that we can successfully type - // check. (It may also be that we should - // revise our inference system to be more - // general and to make use of *every* - // relationship that arises here, but - // presently we do not.) - } - } - } - } - - debug!("<< relate_free_regions"); - } - fn resolve_regions_and_report_errors(&self) { let subject_node_id = match self.subject { Subject(s) => s, @@ -965,7 +978,7 @@ fn check_safety_of_rvalue_destructor_if_necessary<'a, 'tcx>(rcx: &mut Rcx<'a, 't mc::cat_rvalue(region) => { match region { ty::ReScope(rvalue_scope) => { - let typ = rcx.resolve_type(cmt.ty); + let typ = resolve_type(rcx.fcx, cmt.ty); dropck::check_safety_of_destructor_if_necessary(rcx, typ, span, diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs index 340cca7d47e7a..1c47419e9838a 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -40,7 +40,7 @@ //! then mean that all later passes would have to check for these figments //! and report an error, and it just seems like more mess in the end.) -use super::FnCtxt; +use super::{CheckEnv, FnCtxt}; use middle::expr_use_visitor as euv; use middle::mem_categorization as mc; @@ -56,20 +56,21 @@ use util::ppaux::Repr; /////////////////////////////////////////////////////////////////////////// // PUBLIC ENTRY POINTS -pub fn closure_analyze_fn(fcx: &FnCtxt, - _id: ast::NodeId, - _decl: &ast::FnDecl, - body: &ast::Block) +pub fn closure_analyze_fn<'a,'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a,'tcx>, + _id: ast::NodeId, + _decl: &ast::FnDecl, + body: &ast::Block) { let mut seed = SeedBorrowKind::new(fcx); seed.visit_block(body); let closures_with_inferred_kinds = seed.closures_with_inferred_kinds; - let mut adjust = AdjustBorrowKind::new(fcx, &closures_with_inferred_kinds); + let mut adjust = AdjustBorrowKind::new(check_env, fcx, &closures_with_inferred_kinds); adjust.visit_block(body); // it's our job to process these. - assert!(fcx.inh.deferred_call_resolutions.borrow().is_empty()); + assert!(adjust.check_env.deferred_call_resolutions.is_empty()); } /////////////////////////////////////////////////////////////////////////// @@ -167,15 +168,21 @@ impl<'a,'tcx> SeedBorrowKind<'a,'tcx> { // ADJUST BORROW KIND struct AdjustBorrowKind<'a,'tcx:'a> { + check_env: &'a mut CheckEnv<'tcx>, fcx: &'a FnCtxt<'a,'tcx>, closures_with_inferred_kinds: &'a HashSet, } impl<'a,'tcx> AdjustBorrowKind<'a,'tcx> { - fn new(fcx: &'a FnCtxt<'a,'tcx>, + fn new(check_env: &'a mut CheckEnv<'tcx>, + fcx: &'a FnCtxt<'a,'tcx>, closures_with_inferred_kinds: &'a HashSet) -> AdjustBorrowKind<'a,'tcx> { - AdjustBorrowKind { fcx: fcx, closures_with_inferred_kinds: closures_with_inferred_kinds } + AdjustBorrowKind { + check_env: check_env, + fcx: fcx, + closures_with_inferred_kinds: closures_with_inferred_kinds, + } } fn tcx(&self) -> &'a ty::ctxt<'tcx> { @@ -191,8 +198,10 @@ impl<'a,'tcx> AdjustBorrowKind<'a,'tcx> { debug!("analyzing closure `{}` with fn body id `{}`", id, body.id); - let mut euv = euv::ExprUseVisitor::new(self, self.fcx); - euv.walk_fn(decl, body); + { + let mut euv = euv::ExprUseVisitor::new(self, self.fcx); + euv.walk_fn(decl, body); + } // If we had not yet settled on a closure kind for this closure, // then we should have by now. Process and remove any deferred resolutions. @@ -234,8 +243,8 @@ impl<'a,'tcx> AdjustBorrowKind<'a,'tcx> { let closure_def_id = ast_util::local_def(id); if self.closures_with_inferred_kinds.contains(&id) { let mut deferred_call_resolutions = - self.fcx.remove_deferred_call_resolutions(closure_def_id); - for deferred_call_resolution in deferred_call_resolutions.iter_mut() { + self.check_env.remove_deferred_call_resolutions(closure_def_id); + for deferred_call_resolution in &mut deferred_call_resolutions { deferred_call_resolution.resolve(self.fcx); } } diff --git a/src/librustc_typeck/check/vtable.rs b/src/librustc_typeck/check/vtable.rs index a9094fce57c61..7ecaf294a6d02 100644 --- a/src/librustc_typeck/check/vtable.rs +++ b/src/librustc_typeck/check/vtable.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use check::FnCtxt; +use super::{CheckEnv, FnCtxt}; use middle::traits::{self, ObjectSafetyViolation, MethodViolationCode}; use middle::traits::{Obligation, ObligationCause}; use middle::traits::report_fulfillment_errors; @@ -142,12 +142,12 @@ pub fn select_all_fcx_obligations_and_apply_defaults(fcx: &FnCtxt) { select_fcx_obligations_where_possible(fcx); } -pub fn select_all_fcx_obligations_or_error(fcx: &FnCtxt) { +pub fn select_all_fcx_obligations_or_error(check_env: &mut CheckEnv, fcx: &FnCtxt) { debug!("select_all_fcx_obligations_or_error"); // upvar inference should have ensured that all deferred call // resolutions are handled by now. - assert!(fcx.inh.deferred_call_resolutions.borrow().is_empty()); + assert!(check_env.deferred_call_resolutions.is_empty()); select_all_fcx_obligations_and_apply_defaults(fcx); let mut fulfillment_cx = fcx.inh.fulfillment_cx.borrow_mut(); diff --git a/src/librustc_typeck/check/wf.rs b/src/librustc_typeck/check/wf.rs index c2209ba2dc647..e0eba4c38cd1c 100644 --- a/src/librustc_typeck/check/wf.rs +++ b/src/librustc_typeck/check/wf.rs @@ -9,7 +9,7 @@ // except according to those terms. use astconv::AstConv; -use check::{FnCtxt, Inherited, blank_fn_ctxt, vtable, regionck}; +use super::{CheckEnv, FnCtxt, Inherited, blank_fn_ctxt, vtable, regionck}; use constrained_type_params::{identify_constrained_type_params, Parameter}; use CrateCtxt; use middle::region; @@ -135,7 +135,8 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { } fn with_fcx(&mut self, item: &ast::Item, mut f: F) where - F: for<'fcx> FnMut(&mut CheckTypeWellFormedVisitor<'ccx, 'tcx>, &FnCtxt<'fcx, 'tcx>), + F: for<'fcx> FnMut(&mut CheckTypeWellFormedVisitor<'ccx, 'tcx>, + &mut CheckEnv<'tcx>, &FnCtxt<'fcx, 'tcx>), { let ccx = self.ccx; let item_def_id = local_def(item.id); @@ -148,18 +149,19 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { &type_scheme.generics, &type_predicates, item.id); + let mut check_env = CheckEnv::new(); let inh = Inherited::new(ccx.tcx, param_env); let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(type_scheme.ty), item.id); - f(self, &fcx); - vtable::select_all_fcx_obligations_or_error(&fcx); - regionck::regionck_item(&fcx, item); + f(self, &mut check_env, &fcx); + vtable::select_all_fcx_obligations_or_error(&mut check_env, &fcx); + regionck::regionck_item(&mut check_env, &fcx, item); } /// In a type definition, we check that to ensure that the types of the fields are well-formed. fn check_type_defn(&mut self, item: &ast::Item, mut lookup_fields: F) where F: for<'fcx> FnMut(&FnCtxt<'fcx, 'tcx>) -> Vec>, { - self.with_fcx(item, |this, fcx| { + self.with_fcx(item, |this, check_env, fcx| { let variants = lookup_fields(fcx); let mut bounds_checker = BoundsChecker::new(fcx, item.span, @@ -190,14 +192,14 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { variants.iter().flat_map(|v| v.fields.iter().map(|f| f.ty)).collect(); regionck::regionck_ensure_component_tys_wf( - fcx, item.span, &field_tys); + check_env, fcx, item.span, &field_tys); }); } fn check_item_type(&mut self, item: &ast::Item) { - self.with_fcx(item, |this, fcx| { + self.with_fcx(item, |this, _, fcx| { let mut bounds_checker = BoundsChecker::new(fcx, item.span, item.id, @@ -216,7 +218,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { fn check_impl(&mut self, item: &ast::Item) { - self.with_fcx(item, |this, fcx| { + self.with_fcx(item, |this, _, fcx| { let mut bounds_checker = BoundsChecker::new(fcx, item.span, item.id, diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index e50693ea804b6..9389cab6c577c 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -78,6 +78,7 @@ This API is completely unstable and subject to change. #![feature(box_patterns)] #![feature(box_syntax)] #![feature(collections)] +#![feature(collections_drain)] #![feature(core)] #![feature(quote)] #![feature(rustc_diagnostic_macros)] From 312a77be993c4d1b437b4ef7e728ebe21c758aca Mon Sep 17 00:00:00 2001 From: Joshua Yanovski Date: Thu, 7 May 2015 16:54:45 -0700 Subject: [PATCH 02/14] Move node_types from Inherited to CheckEnv. --- src/librustc_typeck/check/_match.rs | 97 +- src/librustc_typeck/check/callee.rs | 72 +- src/librustc_typeck/check/cast.rs | 14 +- src/librustc_typeck/check/closure.rs | 19 +- src/librustc_typeck/check/coercion.rs | 16 +- src/librustc_typeck/check/demand.rs | 13 +- src/librustc_typeck/check/method/confirm.rs | 66 +- src/librustc_typeck/check/method/mod.rs | 49 +- src/librustc_typeck/check/method/probe.rs | 132 +-- src/librustc_typeck/check/method/suggest.rs | 35 +- src/librustc_typeck/check/mod.rs | 958 +++++++++++--------- src/librustc_typeck/check/op.rs | 39 +- src/librustc_typeck/check/regionck.rs | 61 +- src/librustc_typeck/check/upvar.rs | 162 ++-- src/librustc_typeck/check/vtable.rs | 32 +- src/librustc_typeck/check/wf.rs | 130 +-- src/librustc_typeck/check/writeback.rs | 29 +- 17 files changed, 1094 insertions(+), 830 deletions(-) diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 11ffd697b4c25..2234993c37e99 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -17,7 +17,7 @@ use middle::privacy::{AllPublic, LastMod}; use middle::subst::Substs; use middle::ty::{self, Ty}; use super::{check_expr, check_expr_has_type, check_expr_with_expectation}; -use super::{check_expr_coercable_to_type, demand, CheckEnv, FnCtxt, Expectation}; +use super::{check_expr_coercable_to_type, demand, CheckEnv, FnCtxt, FnCtxtTyper, Expectation}; use super::{instantiate_path, resolve_ty_and_def_ufcs, structurally_resolved_type}; use require_same_types; use util::nodemap::FnvHashMap; @@ -46,18 +46,19 @@ pub fn check_pat<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, match pat.node { ast::PatWild(_) => { - fcx.write_ty(pat.id, expected); + fcx.write_ty(check_env, pat.id, expected); } ast::PatLit(ref lt) => { check_expr(check_env, fcx, &**lt); - let expr_ty = fcx.expr_ty(&**lt); + let expr_ty = fcx.expr_ty(check_env, &**lt); // Byte string patterns behave the same way as array patterns // They can denote both statically and dynamically sized byte arrays let mut pat_ty = expr_ty; if let ast::ExprLit(ref lt) = lt.node { if let ast::LitBinary(_) = lt.node { - let expected_ty = structurally_resolved_type(fcx, pat.span, expected); + let expected_ty = structurally_resolved_type(check_env, fcx, + pat.span, expected); if let ty::ty_rptr(_, mt) = expected_ty.sty { if let ty::ty_vec(_, None) = mt.ty.sty { pat_ty = ty::mk_slice(tcx, tcx.mk_region(ty::ReStatic), @@ -67,7 +68,7 @@ pub fn check_pat<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, } } - fcx.write_ty(pat.id, pat_ty); + fcx.write_ty(check_env, pat.id, pat_ty); // somewhat surprising: in this case, the subtyping // relation goes the opposite way as the other @@ -87,8 +88,8 @@ pub fn check_pat<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, check_expr(check_env, fcx, &**begin); check_expr(check_env, fcx, &**end); - let lhs_ty = fcx.expr_ty(&**begin); - let rhs_ty = fcx.expr_ty(&**end); + let lhs_ty = fcx.expr_ty(check_env, &**begin); + let rhs_ty = fcx.expr_ty(check_env, &**end); let lhs_eq_rhs = require_same_types( @@ -116,7 +117,7 @@ pub fn check_pat<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, "only char and numeric types are allowed in range"); } - fcx.write_ty(pat.id, lhs_ty); + fcx.write_ty(check_env, pat.id, lhs_ty); // subtyping doesn't matter here, as the value is some kind of scalar demand::eqtype(fcx, pat.span, expected, lhs_ty); @@ -125,10 +126,13 @@ pub fn check_pat<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, let const_did = tcx.def_map.borrow().get(&pat.id).unwrap().def_id(); let const_scheme = ty::lookup_item_type(tcx, const_did); assert!(const_scheme.generics.is_empty()); - let const_ty = pcx.fcx.instantiate_type_scheme(pat.span, - &Substs::empty(), - &const_scheme.ty); - fcx.write_ty(pat.id, const_ty); + let const_ty = { + let typer = FnCtxtTyper::new(check_env, fcx); + typer.instantiate_type_scheme(pat.span, + &Substs::empty(), + &const_scheme.ty) + }; + fcx.write_ty(check_env, pat.id, const_ty); // FIXME(#20489) -- we should limit the types here to scalars or something! @@ -162,7 +166,7 @@ pub fn check_pat<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, } } - fcx.write_ty(pat.id, typ); + fcx.write_ty(check_env, pat.id, typ); // if there are multiple arms, make sure they all agree on // what the type of the binding `x` ought to be @@ -185,7 +189,10 @@ pub fn check_pat<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, check_pat_enum(check_env, pcx, pat, path, subpats, expected); } ast::PatQPath(ref qself, ref path) => { - let self_ty = fcx.to_ty(&qself.ty); + let self_ty = { + let typer = FnCtxtTyper::new(check_env, fcx); + typer.to_ty(&qself.ty) + }; let path_res = if let Some(&d) = tcx.def_map.borrow().get(&pat.id) { d } else if qself.position == 0 { @@ -200,18 +207,18 @@ pub fn check_pat<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, &format!("unbound path {}", pat.repr(tcx))) }; if let Some((opt_ty, segments, def)) = - resolve_ty_and_def_ufcs(fcx, path_res, Some(self_ty), + resolve_ty_and_def_ufcs(check_env, fcx, path_res, Some(self_ty), path, pat.span, pat.id) { if check_assoc_item_is_const(pcx, def, pat.span) { let scheme = ty::lookup_item_type(tcx, def.def_id()); let predicates = ty::lookup_predicates(tcx, def.def_id()); - instantiate_path(fcx, segments, + instantiate_path(check_env, fcx, segments, scheme, &predicates, opt_ty, def, pat.span, pat.id); - let const_ty = fcx.node_ty(pat.id); + let const_ty = fcx.node_ty(check_env, pat.id); demand::suptype(fcx, pat.span, expected, const_ty); } else { - fcx.write_error(pat.id) + fcx.write_error(check_env, pat.id) } } } @@ -223,7 +230,7 @@ pub fn check_pat<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, (0..elements.len()).map(|_| fcx.infcx().next_ty_var()) .collect(); let pat_ty = ty::mk_tup(tcx, element_tys.clone()); - fcx.write_ty(pat.id, pat_ty); + fcx.write_ty(check_env, pat.id, pat_ty); demand::eqtype(fcx, pat.span, expected, pat_ty); for (element_pat, element_ty) in elements.iter().zip(element_tys.into_iter()) { check_pat(check_env, pcx, &**element_pat, element_ty); @@ -238,10 +245,10 @@ pub fn check_pat<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, // think any errors can be introduced by using // `demand::eqtype`. demand::eqtype(fcx, pat.span, expected, uniq_ty); - fcx.write_ty(pat.id, uniq_ty); + fcx.write_ty(check_env, pat.id, uniq_ty); check_pat(check_env, pcx, &**inner, inner_ty); } else { - fcx.write_error(pat.id); + fcx.write_error(check_env, pat.id); check_pat(check_env, pcx, &**inner, tcx.types.err); } } @@ -257,15 +264,15 @@ pub fn check_pat<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, // `eqtype` turns out to be equally general. See (*) // below for details. demand::eqtype(fcx, pat.span, expected, rptr_ty); - fcx.write_ty(pat.id, rptr_ty); + fcx.write_ty(check_env, pat.id, rptr_ty); check_pat(check_env, pcx, &**inner, inner_ty); } else { - fcx.write_error(pat.id); + fcx.write_error(check_env, pat.id); check_pat(check_env, pcx, &**inner, tcx.types.err); } } ast::PatVec(ref before, ref slice, ref after) => { - let expected_ty = structurally_resolved_type(fcx, pat.span, expected); + let expected_ty = structurally_resolved_type(check_env, fcx, pat.span, expected); let inner_ty = fcx.infcx().next_ty_var(); let pat_ty = match expected_ty.sty { ty::ty_vec(_, Some(size)) => ty::mk_vec(tcx, inner_ty, Some({ @@ -285,7 +292,7 @@ pub fn check_pat<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, } }; - fcx.write_ty(pat.id, pat_ty); + fcx.write_ty(check_env, pat.id, pat_ty); // `demand::subtype` would be good enough, but using // `eqtype` turns out to be equally general. See (*) @@ -419,7 +426,7 @@ pub fn check_match<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, let discrim_ty; if contains_ref_bindings { check_expr(check_env, fcx, discrim); - discrim_ty = fcx.expr_ty(discrim); + discrim_ty = fcx.expr_ty(check_env, discrim); } else { // ...but otherwise we want to use any supertype of the // discriminant. This is sort of a workaround, see note (*) in @@ -463,7 +470,7 @@ pub fn check_match<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, } _ => { check_expr_with_expectation(check_env, fcx, &*arm.body, expected); - fcx.node_ty(arm.body.id) + fcx.node_ty(check_env, arm.body.id) } }; @@ -499,7 +506,7 @@ pub fn check_match<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, } }); - fcx.write_ty(expr.id, result_ty); + fcx.write_ty(check_env, expr.id, result_ty); } pub struct pat_ctxt<'a, 'tcx: 'a> { @@ -520,7 +527,7 @@ fn check_pat_struct<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, let name = pprust::path_to_string(path); span_err!(tcx.sess, pat.span, E0168, "use of trait `{}` in a struct pattern", name); - fcx.write_error(pat.id); + fcx.write_error(check_env, pat.id); for field in fields { check_pat(check_env, pcx, &*field.node.pat, tcx.types.err); @@ -539,7 +546,7 @@ fn check_pat_struct<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, let name = pprust::path_to_string(path); span_err!(tcx.sess, pat.span, E0163, "`{}` does not name a struct or a struct variant", name); - fcx.write_error(pat.id); + fcx.write_error(check_env, pat.id); for field in fields { check_pat(check_env, pcx, &*field.node.pat, tcx.types.err); @@ -550,7 +557,8 @@ fn check_pat_struct<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, } }; - instantiate_path(pcx.fcx, + instantiate_path(check_env, + pcx.fcx, &path.segments, ty::lookup_item_type(tcx, enum_def_id), &ty::lookup_predicates(tcx, enum_def_id), @@ -559,7 +567,7 @@ fn check_pat_struct<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, pat.span, pat.id); - let pat_ty = fcx.node_ty(pat.id); + let pat_ty = fcx.node_ty(check_env, pat.id); demand::eqtype(fcx, pat.span, expected, pat_ty); let item_substs = fcx @@ -586,7 +594,7 @@ fn check_pat_enum<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, let path_res = *tcx.def_map.borrow().get(&pat.id).unwrap(); - let (opt_ty, segments, def) = match resolve_ty_and_def_ufcs(fcx, path_res, + let (opt_ty, segments, def) = match resolve_ty_and_def_ufcs(check_env, fcx, path_res, None, path, pat.span, pat.id) { Some(resolution) => resolution, @@ -598,7 +606,7 @@ fn check_pat_enum<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, // Items that were partially resolved before should have been resolved to // associated constants (i.e. not methods). if path_res.depth != 0 && !check_assoc_item_is_const(pcx, def, pat.span) { - fcx.write_error(pat.id); + fcx.write_error(check_env, pat.id); return; } @@ -616,7 +624,7 @@ fn check_pat_enum<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, } else { ctor_scheme }; - instantiate_path(pcx.fcx, segments, + instantiate_path(check_env, pcx.fcx, segments, path_scheme, &ctor_predicates, opt_ty, def, pat.span, pat.id); @@ -624,30 +632,32 @@ fn check_pat_enum<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, // associated const, and we should quit now, since the rest of this // function uses checks specific to structs and enums. if path_res.depth != 0 { - let pat_ty = fcx.node_ty(pat.id); + let pat_ty = fcx.node_ty(check_env, pat.id); demand::suptype(fcx, pat.span, expected, pat_ty); return; } - let pat_ty = fcx.node_ty(pat.id); + let pat_ty = fcx.node_ty(check_env, pat.id); demand::eqtype(fcx, pat.span, expected, pat_ty); - let real_path_ty = fcx.node_ty(pat.id); + let real_path_ty = fcx.node_ty(check_env, pat.id); let (arg_tys, kind_name): (Vec<_>, &'static str) = match real_path_ty.sty { ty::ty_enum(enum_def_id, expected_substs) if def == def::DefVariant(enum_def_id, def.def_id(), false) => { let variant = ty::enum_variant_with_id(tcx, enum_def_id, def.def_id()); + let typer = FnCtxtTyper::new(check_env, fcx); (variant.args.iter() - .map(|t| fcx.instantiate_type_scheme(pat.span, expected_substs, t)) + .map(|t| typer.instantiate_type_scheme(pat.span, expected_substs, t)) .collect(), "variant") } ty::ty_struct(struct_def_id, expected_substs) => { let struct_fields = ty::struct_fields(tcx, struct_def_id, expected_substs); + let typer = FnCtxtTyper::new(check_env, fcx); (struct_fields.iter() - .map(|field| fcx.instantiate_type_scheme(pat.span, + .map(|field| typer.instantiate_type_scheme(pat.span, expected_substs, &field.mt.ty)) .collect(), @@ -657,7 +667,7 @@ fn check_pat_enum<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, let name = pprust::path_to_string(path); span_err!(tcx.sess, pat.span, E0164, "`{}` does not name a non-struct variant or a tuple struct", name); - fcx.write_error(pat.id); + fcx.write_error(check_env, pat.id); if let Some(subpats) = subpats { for pat in subpats { @@ -743,7 +753,10 @@ fn check_struct_pat_fields<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, } }; - let field_type = pcx.fcx.normalize_associated_types_in(span, &field_type); + let field_type = { + let typer = FnCtxtTyper::new(check_env, pcx.fcx); + typer.normalize_associated_types_in(span, &field_type) + }; check_pat(check_env, pcx, &*field.pat, field_type); } diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index 7de45af7340c7..59740b5a2dc9d 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -19,6 +19,7 @@ use super::err_args; use super::Expectation; use super::expected_types_for_fn_args; use super::FnCtxt; +use super::FnCtxtTyper; use super::LvaluePreference; use super::method; use super::structurally_resolved_type; @@ -76,18 +77,19 @@ pub fn check_call<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, expected: Expectation<'tcx>) { check_expr(check_env, fcx, callee_expr); - let original_callee_ty = fcx.expr_ty(callee_expr); + let original_callee_ty = fcx.expr_ty(check_env, callee_expr); let (callee_ty, _, result) = - autoderef(fcx, + autoderef(check_env, + fcx, callee_expr.span, original_callee_ty, Some(callee_expr), UnresolvedTypeAction::Error, LvaluePreference::NoPreference, - |adj_ty, idx| { - try_overloaded_call_step(check_env, - fcx, call_expr, callee_expr, adj_ty, idx) - }); + |adj_ty, idx| Some((adj_ty, idx))); + let result = result.and_then( |(adj_ty, idx)| { + try_overloaded_call_step(check_env, fcx, call_expr, callee_expr, adj_ty, idx) + }); match result { None => { @@ -131,7 +133,7 @@ fn try_overloaded_call_step<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, autoderefs); // 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 { + match structurally_resolved_type(check_env, fcx, callee_expr.span, adjusted_ty).sty { ty::ty_bare_fn(..) => { fcx.write_autoderef_adjustment(callee_expr.id, autoderefs); return Some(CallStep::Builtin); @@ -143,13 +145,20 @@ fn try_overloaded_call_step<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, // Check whether this is a call to a closure where we // haven't yet decided on whether the closure is fn vs // fnmut vs fnonce. If so, we have to defer further processing. - if fcx.closure_kind(def_id).is_none() { - 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; + let fn_sig = { + let typer = FnCtxtTyper::new(check_env, fcx); + match typer.closure_kind(def_id) { + Some(_) => None, + None => Some({ + let closure_ty = + typer.closure_type(def_id, substs); + fcx.infcx().replace_late_bound_regions_with_fresh_var(call_expr.span, + infer::FnCall, + &closure_ty.sig).0 + }) + } + }; + if let Some(fn_sig) = fn_sig { check_env.record_deferred_call_resolution(def_id, Box::new(CallResolution { call_expr: call_expr, callee_expr: callee_expr, @@ -177,11 +186,12 @@ fn try_overloaded_call_step<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, _ => {} } - try_overloaded_call_traits(fcx, call_expr, callee_expr, adjusted_ty, autoderefs) + try_overloaded_call_traits(check_env, fcx, call_expr, callee_expr, adjusted_ty, autoderefs) .map(|method_callee| CallStep::Overloaded(method_callee)) } -fn try_overloaded_call_traits<'a,'tcx>(fcx: &FnCtxt<'a, 'tcx>, +fn try_overloaded_call_traits<'a,'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a, 'tcx>, call_expr: &ast::Expr, callee_expr: &ast::Expr, adjusted_ty: Ty<'tcx>, @@ -199,7 +209,8 @@ fn try_overloaded_call_traits<'a,'tcx>(fcx: &FnCtxt<'a, 'tcx>, None => continue, }; - match method::lookup_in_trait_adjusted(fcx, + match method::lookup_in_trait_adjusted(check_env, + fcx, call_expr.span, Some(&*callee_expr), method_name, @@ -258,11 +269,14 @@ fn confirm_builtin_call<'a,'tcx>(check_env: &mut CheckEnv<'tcx>, fcx.infcx().replace_late_bound_regions_with_fresh_var(call_expr.span, infer::FnCall, fn_sig).0; - let fn_sig = - fcx.normalize_associated_types_in(call_expr.span, &fn_sig); + let fn_sig = { + let typer = FnCtxtTyper::new(check_env, fcx); + typer.normalize_associated_types_in(call_expr.span, &fn_sig) + }; // Call the generic checker. - let expected_arg_tys = expected_types_for_fn_args(fcx, + let expected_arg_tys = expected_types_for_fn_args(check_env, + fcx, call_expr.span, expected, fn_sig.output, @@ -276,7 +290,7 @@ fn confirm_builtin_call<'a,'tcx>(check_env: &mut CheckEnv<'tcx>, fn_sig.variadic, TupleArgumentsFlag::DontTupleArguments); - write_call(fcx, call_expr, fn_sig.output); + write_call(check_env, fcx, call_expr, fn_sig.output); } fn confirm_deferred_closure_call<'a,'tcx>(check_env: &mut CheckEnv<'tcx>, @@ -292,7 +306,8 @@ fn confirm_deferred_closure_call<'a,'tcx>(check_env: &mut CheckEnv<'tcx>, // type. let expected_arg_tys = - expected_types_for_fn_args(fcx, + expected_types_for_fn_args(check_env, + fcx, call_expr.span, expected, fn_sig.output.clone(), @@ -307,7 +322,7 @@ fn confirm_deferred_closure_call<'a,'tcx>(check_env: &mut CheckEnv<'tcx>, fn_sig.variadic, TupleArgumentsFlag::TupleArguments); - write_call(fcx, call_expr, fn_sig.output); + write_call(check_env, fcx, call_expr, fn_sig.output); } fn confirm_overloaded_call<'a,'tcx>(check_env: &mut CheckEnv<'tcx>, @@ -327,7 +342,7 @@ fn confirm_overloaded_call<'a,'tcx>(check_env: &mut CheckEnv<'tcx>, arg_exprs, TupleArgumentsFlag::TupleArguments, expected); - write_call(fcx, call_expr, output_type); + write_call(check_env, fcx, call_expr, output_type); write_overloaded_call_method_map(fcx, call_expr, method_callee); } @@ -362,16 +377,19 @@ impl<'tcx> Repr<'tcx> for CallResolution<'tcx> { } impl<'tcx> DeferredCallResolution<'tcx> for CallResolution<'tcx> { - fn resolve<'a>(&mut self, fcx: &FnCtxt<'a,'tcx>) { + fn resolve<'a>(&mut self, check_env: &mut CheckEnv<'tcx>, fcx: &FnCtxt<'a,'tcx>) { debug!("DeferredCallResolution::resolve() {}", self.repr(fcx.tcx())); // we should not be invoked until the closure kind has been // determined by upvar inference - assert!(fcx.closure_kind(self.closure_def_id).is_some()); + { + let typer = FnCtxtTyper::new(check_env, fcx); + assert!(typer.closure_kind(self.closure_def_id).is_some()); + } // We may now know enough to figure out fn vs fnmut etc. - match try_overloaded_call_traits(fcx, self.call_expr, self.callee_expr, + match try_overloaded_call_traits(check_env, fcx, self.call_expr, self.callee_expr, self.adjusted_ty, self.autoderefs) { Some(method_callee) => { // One problem is that when we get here, we are going diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index f0495436bc1b2..1aad68f45abb4 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -11,6 +11,7 @@ //! Code for type-checking cast expressions. use super::coercion; +use super::CheckEnv; use super::demand; use super::FnCtxt; use super::structurally_resolved_type; @@ -43,7 +44,8 @@ impl<'tcx> CastCheck<'tcx> { } } -pub fn check_cast<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, cast: &CastCheck<'tcx>) { +pub fn check_cast<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a, 'tcx>, cast: &CastCheck<'tcx>) { fn cast_through_integer_err<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, span: Span, t_1: Ty<'tcx>, @@ -58,12 +60,12 @@ pub fn check_cast<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, cast: &CastCheck<'tcx>) { let span = cast.span; let e = &cast.expr; - let t_e = structurally_resolved_type(fcx, span, cast.expr_ty); - let t_1 = structurally_resolved_type(fcx, span, cast.cast_ty); + let t_e = structurally_resolved_type(check_env, fcx, span, cast.expr_ty); + let t_1 = structurally_resolved_type(check_env, fcx, span, cast.cast_ty); // Check for trivial casts. if !ty::type_has_ty_infer(t_1) { - if let Ok(()) = coercion::mk_assignty(fcx, e, t_e, t_1) { + if let Ok(()) = coercion::mk_assignty(check_env, fcx, e, t_e, t_1) { if ty::type_is_numeric(t_1) && ty::type_is_numeric(t_e) { fcx.tcx().sess.add_lint(lint::builtin::TRIVIAL_NUMERIC_CASTS, e.id, @@ -104,7 +106,7 @@ pub fn check_cast<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, cast: &CastCheck<'tcx>) { let t_1_is_trivial = t_1_is_scalar && !t_1_is_char && !t_1_is_bare_fn; if t_e_is_bare_fn_item && t_1_is_bare_fn { - demand::coerce(fcx, e.span, t_1, &e); + demand::coerce(check_env, fcx, e.span, t_1, &e); } else if t_1_is_char { let t_e = fcx.infcx().shallow_resolve(t_e); if t_e.sty != ty::ty_uint(ast::TyU8) { @@ -167,7 +169,7 @@ pub fn check_cast<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, cast: &CastCheck<'tcx>) { /* this case is allowed */ } _ => { - demand::coerce(fcx, e.span, t_1, &e); + demand::coerce(check_env, fcx, e.span, t_1, &e); } } } else if fcx.type_is_fat_ptr(t_e, span) != fcx.type_is_fat_ptr(t_1, span) { diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 1f0382c4dfdb4..0d642eebf3580 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -10,7 +10,7 @@ //! Code for type-checking closure expressions. -use super::{check_fn, CheckEnv, Expectation, FnCtxt}; +use super::{check_fn, CheckEnv, Expectation, FnCtxt, FnCtxtTyper}; use astconv; use middle::region; @@ -56,19 +56,22 @@ fn check_closure<'a,'tcx>(check_env: &mut CheckEnv<'tcx>, opt_kind, expected_sig.repr(fcx.tcx())); - let mut fn_ty = astconv::ty_of_closure( - fcx, - ast::Unsafety::Normal, - decl, - abi::RustCall, - expected_sig); + let mut fn_ty = { + let typer = FnCtxtTyper::new(check_env, fcx); + astconv::ty_of_closure( + &typer, + ast::Unsafety::Normal, + decl, + abi::RustCall, + expected_sig) + }; let closure_type = ty::mk_closure(fcx.ccx.tcx, expr_def_id, fcx.ccx.tcx.mk_substs( fcx.inh.param_env.free_substs.clone())); - fcx.write_ty(expr.id, closure_type); + fcx.write_ty(check_env, expr.id, closure_type); let fn_sig = ty::liberate_late_bound_regions(fcx.tcx(), diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index 28df1c2159577..0f9db79bd59ad 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -60,8 +60,8 @@ //! sort of a minor point so I've opted to leave it for later---after all //! we may want to adjust precisely when coercions occur. -use check::{autoderef, FnCtxt, NoPreference, PreferMutLvalue, UnresolvedTypeAction}; -use check::vtable; +use super::{autoderef, CheckEnv, FnCtxt, NoPreference, PreferMutLvalue, UnresolvedTypeAction}; +use super::vtable; use middle::infer::{self, Coercion}; use middle::subst; @@ -110,6 +110,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { } fn coerce(&self, + check_env: &mut CheckEnv<'tcx>, expr_a: &ast::Expr, a: Ty<'tcx>, b: Ty<'tcx>) @@ -139,7 +140,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { ty::ty_rptr(_, mt_b) => { return self.unpack_actual_value(a, |a| { - self.coerce_borrowed_pointer(expr_a, a, b, mt_b.mutbl) + self.coerce_borrowed_pointer(check_env, expr_a, a, b, mt_b.mutbl) }); } @@ -171,6 +172,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { /// To match `A` with `B`, autoderef will be performed, /// calling `deref`/`deref_mut` where necessary. fn coerce_borrowed_pointer(&self, + check_env: &mut CheckEnv<'tcx>, expr_a: &ast::Expr, a: Ty<'tcx>, b: Ty<'tcx>, @@ -203,7 +205,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { ast::MutImmutable => NoPreference }; let mut first_error = None; - let (_, autoderefs, success) = autoderef(self.fcx, + let (_, autoderefs, success) = autoderef(check_env, + self.fcx, expr_a.span, a, Some(expr_a), @@ -490,7 +493,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { } } -pub fn mk_assignty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, +pub fn mk_assignty<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a, 'tcx>, expr: &ast::Expr, a: Ty<'tcx>, b: Ty<'tcx>) @@ -503,7 +507,7 @@ pub fn mk_assignty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, origin: infer::ExprAssignable(expr.span), unsizing_obligation: Cell::new(None) }; - Ok((try!(coerce.coerce(expr, a, b)), + Ok((try!(coerce.coerce(check_env, expr, a, b)), coerce.unsizing_obligation.get())) }) })); diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index cd6a1226e00c9..fd9c4859affb2 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -9,7 +9,7 @@ // except according to those terms. -use check::{coercion, FnCtxt}; +use super::{coercion, CheckEnv, FnCtxt}; use middle::ty::{self, Ty}; use middle::infer; @@ -54,17 +54,18 @@ pub fn eqtype<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span, } // Checks that the type of `expr` can be coerced to `expected`. -pub fn coerce<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, +pub fn coerce<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a, 'tcx>, sp: Span, expected: Ty<'tcx>, expr: &ast::Expr) { - let expr_ty = fcx.expr_ty(expr); + let expr_ty = fcx.expr_ty(check_env, expr); debug!("demand::coerce(expected = {}, expr_ty = {})", expected.repr(fcx.ccx.tcx), expr_ty.repr(fcx.ccx.tcx)); - let expr_ty = fcx.resolve_type_vars_if_possible(expr_ty); - let expected = fcx.resolve_type_vars_if_possible(expected); - match coercion::mk_assignty(fcx, expr, expr_ty, expected) { + let expr_ty = fcx.resolve_type_vars_if_possible(check_env, expr_ty); + let expected = fcx.resolve_type_vars_if_possible(check_env, expected); + match coercion::mk_assignty(check_env, fcx, expr, expr_ty, expected) { Ok(()) => { /* ok */ } Err(ref err) => { fcx.report_mismatched_types(sp, expected, expr_ty, err); diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index c068bfaa82eb7..46800dff4f47d 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -10,7 +10,7 @@ use super::probe; -use check::{self, FnCtxt, NoPreference, PreferMutLvalue, callee, demand}; +use check::{self, CheckEnv, FnCtxt, FnCtxtTyper, NoPreference, PreferMutLvalue, callee, demand}; use check::UnresolvedTypeAction; use middle::mem_categorization::Typer; use middle::subst::{self}; @@ -27,6 +27,7 @@ use std::iter::repeat; use util::ppaux::Repr; struct ConfirmContext<'a, 'tcx:'a> { + check_env: &'a mut CheckEnv<'tcx>, fcx: &'a FnCtxt<'a, 'tcx>, span: Span, self_expr: &'tcx ast::Expr, @@ -47,7 +48,8 @@ struct InstantiatedMethodSig<'tcx> { method_predicates: ty::InstantiatedPredicates<'tcx>, } -pub fn confirm<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, +pub fn confirm<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a, 'tcx>, span: Span, self_expr: &'tcx ast::Expr, call_expr: &'tcx ast::Expr, @@ -61,18 +63,25 @@ pub fn confirm<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, pick.repr(fcx.tcx()), supplied_method_types.repr(fcx.tcx())); - let mut confirm_cx = ConfirmContext::new(fcx, span, self_expr, call_expr); + let mut confirm_cx = ConfirmContext::new(check_env, fcx, span, self_expr, call_expr); confirm_cx.confirm(unadjusted_self_ty, pick, supplied_method_types) } impl<'a,'tcx> ConfirmContext<'a,'tcx> { - fn new(fcx: &'a FnCtxt<'a, 'tcx>, + fn new(check_env: &'a mut CheckEnv<'tcx>, + fcx: &'a FnCtxt<'a, 'tcx>, span: Span, 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 } + ConfirmContext { + check_env: check_env, + fcx: fcx, + span: span, + self_expr: self_expr, + call_expr: call_expr, + } } fn confirm(&mut self, @@ -153,7 +162,8 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { // Commit the autoderefs by calling `autoderef again, but this // time writing the results into the various tables. - let (autoderefd_ty, n, result) = check::autoderef(self.fcx, + let (autoderefd_ty, n, result) = check::autoderef(self.check_env, + self.fcx, self.span, unadjusted_self_ty, Some(self.self_expr), @@ -202,7 +212,8 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { probe::InherentImplPick(impl_def_id) => { assert!(ty::impl_trait_ref(self.tcx(), impl_def_id).is_none(), "impl {:?} is not an inherent impl", impl_def_id); - let impl_polytype = check::impl_self_ty(self.fcx, self.span, impl_def_id); + let impl_polytype = + check::impl_self_ty(self.check_env, self.fcx, self.span, impl_def_id); (impl_polytype.substs, MethodStatic(pick.item.def_id())) } @@ -250,9 +261,11 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { // respectively, then we want to return the type // parameters from the trait ([$A,$B]), not those from // the impl ([$A,$B,$C]) not the receiver type ([$C]). - let impl_polytype = check::impl_self_ty(self.fcx, self.span, impl_def_id); + let impl_polytype = + check::impl_self_ty(self.check_env, self.fcx, self.span, impl_def_id); + let typer = FnCtxtTyper::new(self.check_env, self.fcx); let impl_trait_ref = - self.fcx.instantiate_type_scheme( + typer.instantiate_type_scheme( self.span, &impl_polytype.substs, &ty::impl_trait_ref(self.tcx(), impl_def_id).unwrap()); @@ -303,7 +316,8 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { // yield an object-type (e.g., `&Object` or `Box` // etc). - let (_, _, result) = check::autoderef(self.fcx, + let (_, _, result) = check::autoderef(self.check_env, + self.fcx, self.span, self_ty, None, @@ -311,13 +325,12 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { NoPreference, |ty, _| { match ty.sty { - ty::ty_trait(ref data) => Some(closure(self, ty, &**data)), + ty::ty_trait(ref data) => Some((ty, data)), _ => None, } }); - match result { - Some(r) => r, + Some((ty, data)) => closure(self, ty, &**data), None => { self.tcx().sess.span_bug( self.span, @@ -401,8 +414,9 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { // be no late-bound regions appearing here. let method_predicates = pick.item.as_opt_method().unwrap() .predicates.instantiate(self.tcx(), &all_substs); - let method_predicates = self.fcx.normalize_associated_types_in(self.span, - &method_predicates); + let typer = FnCtxtTyper::new(self.check_env, self.fcx); + let method_predicates = typer.normalize_associated_types_in(self.span, + &method_predicates); debug!("method_predicates after subst = {}", method_predicates.repr(self.tcx())); @@ -418,7 +432,8 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { debug!("late-bound lifetimes from method instantiated, method_sig={}", method_sig.repr(self.tcx())); - let method_sig = self.fcx.instantiate_type_scheme(self.span, &all_substs, &method_sig); + let typer = FnCtxtTyper::new(self.check_env, self.fcx); + let method_sig = typer.instantiate_type_scheme(self.span, &all_substs, &method_sig); debug!("type scheme substituted, method_sig={}", method_sig.repr(self.tcx())); @@ -453,7 +468,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { /// When we select a method with an `&mut self` receiver, we have to go convert any /// auto-derefs, indices, etc from `Deref` and `Index` into `DerefMut` and `IndexMut` /// respectively. - fn fixup_derefs_on_method_receiver_if_necessary(&self, + fn fixup_derefs_on_method_receiver_if_necessary(&mut self, method_callee: &MethodCallee) { let sig = match method_callee.ty.sty { ty::ty_bare_fn(_, ref f) => f.sig.clone(), @@ -502,9 +517,11 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { i, expr.repr(self.tcx()), autoderef_count); if autoderef_count > 0 { - check::autoderef(self.fcx, + let expr_ty = self.fcx.expr_ty(self.check_env, expr); + check::autoderef(self.check_env, + self.fcx, expr.span, - self.fcx.expr_ty(expr), + expr_ty, Some(expr), UnresolvedTypeAction::Error, PreferMutLvalue, @@ -560,16 +577,17 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { let (adjusted_base_ty, unsize) = if let Some(target) = unsize { (target, true) } else { - (self.fcx.adjust_expr_ty(base_expr, + (self.fcx.adjust_expr_ty(self.check_env, base_expr, Some(&ty::AdjustDerefRef(ty::AutoDerefRef { autoderefs: autoderefs, autoref: None, unsize: None }))), false) }; - let index_expr_ty = self.fcx.expr_ty(&**index_expr); + let index_expr_ty = self.fcx.expr_ty(self.check_env, &**index_expr); let result = check::try_index_step( + self.check_env, self.fcx, MethodCall::expr(expr.id), expr, @@ -583,7 +601,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { if let Some((input_ty, return_ty)) = result { demand::suptype(self.fcx, index_expr.span, input_ty, index_expr_ty); - let expr_ty = self.fcx.expr_ty(&*expr); + let expr_ty = self.fcx.expr_ty(self.check_env, &*expr); demand::suptype(self.fcx, expr.span, expr_ty, return_ty); } } @@ -591,13 +609,15 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { // if this is an overloaded deref, then re-evaluate with // a preference for mut let method_call = MethodCall::expr(expr.id); + let expr_ty = self.fcx.expr_ty(self.check_env, &**base_expr); if self.fcx.inh.method_map.borrow().contains_key(&method_call) { check::try_overloaded_deref( + self.check_env, self.fcx, expr.span, Some(method_call), Some(&**base_expr), - self.fcx.expr_ty(&**base_expr), + expr_ty, PreferMutLvalue); } } diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index c070df6b5939d..2572ee7005f5a 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -11,9 +11,11 @@ //! Method lookup: the secret sauce of Rust. See `README.md`. use astconv::AstConv; -use check::FnCtxt; -use check::vtable; -use check::vtable::select_new_fcx_obligations; +use super::CheckEnv; +use super::FnCtxt; +use super::FnCtxtTyper; +use super::vtable; +use super::vtable::select_new_fcx_obligations; use middle::def; use middle::privacy::{AllPublic, DependsOn, LastPrivate, LastMod}; use middle::subst; @@ -61,7 +63,8 @@ pub enum CandidateSource { type ItemIndex = usize; // just for doc purposes /// Determines whether the type `self_ty` supports a method name `method_name` or not. -pub fn exists<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, +pub fn exists<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a, 'tcx>, span: Span, method_name: ast::Name, self_ty: Ty<'tcx>, @@ -69,7 +72,7 @@ pub fn exists<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, -> bool { let mode = probe::Mode::MethodCall; - match probe::probe(fcx, span, mode, method_name, self_ty, call_expr_id) { + match probe::probe(check_env, fcx, span, mode, method_name, self_ty, call_expr_id) { Ok(..) => true, Err(NoMatch(..)) => false, Err(Ambiguity(..)) => true, @@ -91,7 +94,8 @@ pub fn exists<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, /// * `self_ty`: the (unadjusted) type of the self expression (`foo`) /// * `supplied_method_types`: the explicit method type parameters, if any (`T1..Tn`) /// * `self_expr`: the self expression (`foo`) -pub fn lookup<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, +pub fn lookup<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a, 'tcx>, span: Span, method_name: ast::Name, self_ty: Ty<'tcx>, @@ -108,11 +112,19 @@ pub fn lookup<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, let mode = probe::Mode::MethodCall; let self_ty = fcx.infcx().resolve_type_vars_if_possible(&self_ty); - let pick = try!(probe::probe(fcx, span, mode, method_name, self_ty, call_expr.id)); - Ok(confirm::confirm(fcx, span, self_expr, call_expr, self_ty, pick, supplied_method_types)) + let pick = try!(probe::probe(check_env, fcx, span, mode, method_name, self_ty, call_expr.id)); + Ok(confirm::confirm(check_env, + fcx, + span, + self_expr, + call_expr, + self_ty, + pick, + supplied_method_types)) } -pub fn lookup_in_trait<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, +pub fn lookup_in_trait<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a, 'tcx>, span: Span, self_expr: Option<&ast::Expr>, m_name: ast::Name, @@ -121,7 +133,7 @@ pub fn lookup_in_trait<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, opt_input_types: Option>>) -> Option> { - lookup_in_trait_adjusted(fcx, span, self_expr, m_name, trait_def_id, + lookup_in_trait_adjusted(check_env, fcx, span, self_expr, m_name, trait_def_id, 0, false, self_ty, opt_input_types) } @@ -134,7 +146,8 @@ pub fn lookup_in_trait<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, /// method-lookup code. In particular, autoderef on index is basically identical to autoderef with /// normal probes, except that the test also looks for built-in indexing. Also, the second half of /// this method is basically the same as confirmation. -pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, +pub fn lookup_in_trait_adjusted<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a, 'tcx>, span: Span, self_expr: Option<&ast::Expr>, m_name: ast::Name, @@ -179,7 +192,8 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, poly_trait_ref.as_predicate()); // Now we want to know if this can be matched - let mut selcx = traits::SelectionContext::new(fcx.infcx(), fcx); + let typer = FnCtxtTyper::new(check_env, fcx); + let mut selcx = traits::SelectionContext::new(fcx.infcx(), &typer); if !selcx.evaluate_obligation(&obligation) { debug!("--> Cannot match obligation"); return None; // Cannot be matched, no such method resolution is possible. @@ -204,7 +218,7 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, let fn_sig = fcx.infcx().replace_late_bound_regions_with_fresh_var(span, infer::FnCall, &method_ty.fty.sig).0; - let fn_sig = fcx.instantiate_type_scheme(span, trait_ref.substs, &fn_sig); + let fn_sig = typer.instantiate_type_scheme(span, trait_ref.substs, &fn_sig); let transformed_self_ty = fn_sig.inputs[0]; let fty = ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(ty::BareFnTy { sig: ty::Binder(fn_sig), @@ -224,7 +238,7 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, // // Note that as the method comes from a trait, it should not have // any late-bound regions appearing in its bounds. - let method_bounds = fcx.instantiate_bounds(span, trait_ref.substs, &method_ty.predicates); + let method_bounds = typer.instantiate_bounds(span, trait_ref.substs, &method_ty.predicates); assert!(!method_bounds.has_escaping_regions()); fcx.add_obligations_for_parameters( traits::ObligationCause::misc(span, fcx.body_id), @@ -233,7 +247,7 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, // FIXME(#18653) -- Try to resolve obligations, giving us more // typing information, which can sometimes be needed to avoid // pathological region inference failures. - vtable::select_new_fcx_obligations(fcx); + vtable::select_new_fcx_obligations(check_env, fcx); // Insert any adjustments needed (always an autoref of some mutability). match self_expr { @@ -303,7 +317,8 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, Some(callee) } -pub fn resolve_ufcs<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, +pub fn resolve_ufcs<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a, 'tcx>, span: Span, method_name: ast::Name, self_ty: Ty<'tcx>, @@ -311,7 +326,7 @@ pub fn resolve_ufcs<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, -> Result<(def::Def, LastPrivate), MethodError> { let mode = probe::Mode::Path; - let pick = try!(probe::probe(fcx, span, mode, method_name, self_ty, expr_id)); + let pick = try!(probe::probe(check_env, fcx, span, mode, method_name, self_ty, expr_id)); let def_id = pick.item.def_id(); let mut lp = LastMod(AllPublic); let provenance = match pick.kind { diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index c94fa03702681..1512c1f58bebd 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -14,7 +14,7 @@ use super::{CandidateSource,ImplSource,TraitSource}; use super::suggest; use check; -use check::{FnCtxt, NoPreference, UnresolvedTypeAction}; +use check::{CheckEnv, FnCtxt, FnCtxtTyper, NoPreference, UnresolvedTypeAction}; use middle::fast_reject; use middle::subst; use middle::subst::Subst; @@ -113,7 +113,8 @@ pub enum Mode { Path } -pub fn probe<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, +pub fn probe<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a, 'tcx>, span: Span, mode: Mode, item_name: ast::Name, @@ -134,7 +135,7 @@ pub fn probe<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, // think cause spurious errors. Really though this part should // take place in the `fcx.infcx().probe` below. let steps = if mode == Mode::MethodCall { - match create_steps(fcx, span, self_ty) { + match create_steps(check_env, fcx, span, self_ty) { Some(steps) => steps, None => return Err(MethodError::NoMatch(Vec::new(), Vec::new())), } @@ -174,19 +175,21 @@ pub fn probe<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, item_name, steps, opt_simplified_steps); - probe_cx.assemble_inherent_candidates(); + probe_cx.assemble_inherent_candidates(check_env); try!(probe_cx.assemble_extension_candidates_for_traits_in_scope(scope_expr_id)); - probe_cx.pick() + probe_cx.pick(check_env) }) } -fn create_steps<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, +fn create_steps<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a, 'tcx>, span: Span, self_ty: Ty<'tcx>) -> Option>> { let mut steps = Vec::new(); - let (final_ty, dereferences, _) = check::autoderef(fcx, + let (final_ty, dereferences, _) = check::autoderef(check_env, + fcx, span, self_ty, None, @@ -258,30 +261,31 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { /////////////////////////////////////////////////////////////////////////// // CANDIDATE ASSEMBLY - fn assemble_inherent_candidates(&mut self) { + fn assemble_inherent_candidates(&mut self, check_env: &mut CheckEnv<'tcx>) { let steps = self.steps.clone(); for step in &*steps { - self.assemble_probe(step.self_ty); + self.assemble_probe(check_env, step.self_ty); } } - fn assemble_probe(&mut self, self_ty: Ty<'tcx>) { + fn assemble_probe(&mut self, check_env: &mut CheckEnv<'tcx>, self_ty: Ty<'tcx>) { debug!("assemble_probe: self_ty={}", self_ty.repr(self.tcx())); match self_ty.sty { ty::ty_trait(box ref data) => { self.assemble_inherent_candidates_from_object(self_ty, data); - self.assemble_inherent_impl_candidates_for_type(data.principal_def_id()); + self.assemble_inherent_impl_candidates_for_type(check_env, + data.principal_def_id()); } ty::ty_enum(did, _) | ty::ty_struct(did, _) | ty::ty_closure(did, _) => { - self.assemble_inherent_impl_candidates_for_type(did); + self.assemble_inherent_impl_candidates_for_type(check_env, did); } ty::ty_uniq(_) => { if let Some(box_did) = self.tcx().lang_items.owned_box() { - self.assemble_inherent_impl_candidates_for_type(box_did); + self.assemble_inherent_impl_candidates_for_type(check_env, box_did); } } ty::ty_param(p) => { @@ -289,98 +293,107 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { } ty::ty_char => { let lang_def_id = self.tcx().lang_items.char_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); + self.assemble_inherent_impl_for_primitive(check_env, lang_def_id); } ty::ty_str => { let lang_def_id = self.tcx().lang_items.str_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); + self.assemble_inherent_impl_for_primitive(check_env, lang_def_id); } ty::ty_vec(_, None) => { let lang_def_id = self.tcx().lang_items.slice_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); + self.assemble_inherent_impl_for_primitive(check_env, lang_def_id); } ty::ty_ptr(ty::mt { ty: _, mutbl: ast::MutImmutable }) => { let lang_def_id = self.tcx().lang_items.const_ptr_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); + self.assemble_inherent_impl_for_primitive(check_env, lang_def_id); } ty::ty_ptr(ty::mt { ty: _, mutbl: ast::MutMutable }) => { let lang_def_id = self.tcx().lang_items.mut_ptr_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); + self.assemble_inherent_impl_for_primitive(check_env, lang_def_id); } ty::ty_int(ast::TyI8) => { let lang_def_id = self.tcx().lang_items.i8_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); + self.assemble_inherent_impl_for_primitive(check_env, lang_def_id); } ty::ty_int(ast::TyI16) => { let lang_def_id = self.tcx().lang_items.i16_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); + self.assemble_inherent_impl_for_primitive(check_env, lang_def_id); } ty::ty_int(ast::TyI32) => { let lang_def_id = self.tcx().lang_items.i32_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); + self.assemble_inherent_impl_for_primitive(check_env, lang_def_id); } ty::ty_int(ast::TyI64) => { let lang_def_id = self.tcx().lang_items.i64_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); + self.assemble_inherent_impl_for_primitive(check_env, lang_def_id); } ty::ty_int(ast::TyIs) => { let lang_def_id = self.tcx().lang_items.isize_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); + self.assemble_inherent_impl_for_primitive(check_env, lang_def_id); } ty::ty_uint(ast::TyU8) => { let lang_def_id = self.tcx().lang_items.u8_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); + self.assemble_inherent_impl_for_primitive(check_env, lang_def_id); } ty::ty_uint(ast::TyU16) => { let lang_def_id = self.tcx().lang_items.u16_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); + self.assemble_inherent_impl_for_primitive(check_env, lang_def_id); } ty::ty_uint(ast::TyU32) => { let lang_def_id = self.tcx().lang_items.u32_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); + self.assemble_inherent_impl_for_primitive(check_env, lang_def_id); } ty::ty_uint(ast::TyU64) => { let lang_def_id = self.tcx().lang_items.u64_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); + self.assemble_inherent_impl_for_primitive(check_env, lang_def_id); } ty::ty_uint(ast::TyUs) => { let lang_def_id = self.tcx().lang_items.usize_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); + self.assemble_inherent_impl_for_primitive(check_env, lang_def_id); } ty::ty_float(ast::TyF32) => { let lang_def_id = self.tcx().lang_items.f32_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); + self.assemble_inherent_impl_for_primitive(check_env, lang_def_id); } ty::ty_float(ast::TyF64) => { let lang_def_id = self.tcx().lang_items.f64_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); + self.assemble_inherent_impl_for_primitive(check_env, lang_def_id); } _ => { } } } - fn assemble_inherent_impl_for_primitive(&mut self, lang_def_id: Option) { + fn assemble_inherent_impl_for_primitive(&mut self, + check_env: &mut CheckEnv<'tcx>, + lang_def_id: Option) + { if let Some(impl_def_id) = lang_def_id { ty::populate_implementations_for_primitive_if_necessary(self.tcx(), impl_def_id); - self.assemble_inherent_impl_probe(impl_def_id); + self.assemble_inherent_impl_probe(check_env, impl_def_id); } } - fn assemble_inherent_impl_candidates_for_type(&mut self, def_id: ast::DefId) { + fn assemble_inherent_impl_candidates_for_type(&mut self, + check_env: &mut CheckEnv<'tcx>, + def_id: ast::DefId) + { // Read the inherent implementation candidates for this type from the // metadata if necessary. ty::populate_implementations_for_type_if_necessary(self.tcx(), def_id); if let Some(impl_infos) = self.tcx().inherent_impls.borrow().get(&def_id) { for &impl_def_id in &***impl_infos { - self.assemble_inherent_impl_probe(impl_def_id); + self.assemble_inherent_impl_probe(check_env, impl_def_id); } } } - fn assemble_inherent_impl_probe(&mut self, impl_def_id: ast::DefId) { + fn assemble_inherent_impl_probe(&mut self, + check_env: &mut CheckEnv<'tcx>, + impl_def_id: ast::DefId) + { if !self.impl_dups.insert(impl_def_id) { return; // already visited } @@ -398,7 +411,8 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { } let (impl_ty, impl_substs) = self.impl_ty_and_substs(impl_def_id); - let impl_ty = self.fcx.instantiate_type_scheme(self.span, &impl_substs, &impl_ty); + let typer = FnCtxtTyper::new(check_env, self.fcx); + let impl_ty = typer.instantiate_type_scheme(self.span, &impl_substs, &impl_ty); // Determine the receiver type that the method itself expects. let xform_self_ty = @@ -835,8 +849,8 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { /////////////////////////////////////////////////////////////////////////// // THE ACTUAL SEARCH - fn pick(mut self) -> PickResult<'tcx> { - match self.pick_core() { + fn pick(mut self, check_env: &mut CheckEnv<'tcx>) -> PickResult<'tcx> { + match self.pick_core(check_env) { Some(r) => return r, None => {} } @@ -851,7 +865,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { try!(self.assemble_extension_candidates_for_all_traits()); - let out_of_scope_traits = match self.pick_core() { + let out_of_scope_traits = match self.pick_core(check_env) { Some(Ok(p)) => vec![p.item.container().id()], Some(Err(MethodError::Ambiguity(v))) => v.into_iter().map(|source| { match source { @@ -880,29 +894,33 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { Err(MethodError::NoMatch(static_candidates, out_of_scope_traits)) } - fn pick_core(&mut self) -> Option> { + fn pick_core(&mut self, check_env: &mut CheckEnv<'tcx>) -> Option> { let steps = self.steps.clone(); // find the first step that works - steps.iter().filter_map(|step| self.pick_step(step)).next() + steps.iter().filter_map(|step| self.pick_step(check_env, step)).next() } - fn pick_step(&mut self, step: &CandidateStep<'tcx>) -> Option> { + fn pick_step(&mut self, + check_env: &mut CheckEnv<'tcx>, + step: &CandidateStep<'tcx>) -> Option> + { debug!("pick_step: step={}", step.repr(self.tcx())); if ty::type_is_error(step.self_ty) { return None; } - match self.pick_by_value_method(step) { + match self.pick_by_value_method(check_env, step) { Some(result) => return Some(result), None => {} } - self.pick_autorefd_method(step) + self.pick_autorefd_method(check_env, step) } fn pick_by_value_method(&mut self, + check_env: &mut CheckEnv<'tcx>, step: &CandidateStep<'tcx>) -> Option> { @@ -920,7 +938,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { return None; } - self.pick_method(step.self_ty).map(|r| r.map(|mut pick| { + self.pick_method(check_env, step.self_ty).map(|r| r.map(|mut pick| { pick.autoderefs = step.autoderefs; // Insert a `&*` or `&mut *` if this is a reference type: @@ -934,6 +952,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { } fn pick_autorefd_method(&mut self, + check_env: &mut CheckEnv<'tcx>, step: &CandidateStep<'tcx>) -> Option> { @@ -949,7 +968,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { ty: step.self_ty, mutbl: m }); - self.pick_method(autoref_ty).map(|r| r.map(|mut pick| { + self.pick_method(check_env, autoref_ty).map(|r| r.map(|mut pick| { pick.autoderefs = step.autoderefs; pick.autoref = Some(m); pick.unsize = if step.unsize { @@ -962,11 +981,14 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { }).nth(0) } - fn pick_method(&mut self, self_ty: Ty<'tcx>) -> Option> { + fn pick_method(&mut self, + check_env: &mut CheckEnv<'tcx>, + self_ty: Ty<'tcx>) -> Option> + { debug!("pick_method(self_ty={})", self.infcx().ty_to_string(self_ty)); debug!("searching inherent candidates"); - match self.consider_candidates(self_ty, &self.inherent_candidates) { + match self.consider_candidates(check_env, self_ty, &self.inherent_candidates) { None => {} Some(pick) => { return Some(pick); @@ -974,16 +996,17 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { } debug!("searching extension candidates"); - self.consider_candidates(self_ty, &self.extension_candidates) + self.consider_candidates(check_env, self_ty, &self.extension_candidates) } fn consider_candidates(&self, + check_env: &mut CheckEnv<'tcx>, self_ty: Ty<'tcx>, probes: &[Candidate<'tcx>]) -> Option> { let mut applicable_candidates: Vec<_> = probes.iter() - .filter(|&probe| self.consider_probe(self_ty, probe)) + .filter(|&probe| self.consider_probe(check_env, self_ty, probe)) .collect(); debug!("applicable_candidates: {}", applicable_candidates.repr(self.tcx())); @@ -1006,7 +1029,11 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { }) } - fn consider_probe(&self, self_ty: Ty<'tcx>, probe: &Candidate<'tcx>) -> bool { + fn consider_probe(&self, + check_env: &mut CheckEnv<'tcx>, + self_ty: Ty<'tcx>, + probe: &Candidate<'tcx>) -> bool + { debug!("consider_probe: self_ty={} probe={}", self_ty.repr(self.tcx()), probe.repr(self.tcx())); @@ -1028,7 +1055,8 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { match probe.kind { InherentImplCandidate(impl_def_id, ref substs) | ExtensionImplCandidate(impl_def_id, _, ref substs, _) => { - let selcx = &mut traits::SelectionContext::new(self.infcx(), self.fcx); + let typer = FnCtxtTyper::new(check_env, self.fcx); + let selcx = &mut traits::SelectionContext::new(self.infcx(), &typer); let cause = traits::ObligationCause::misc(self.span, self.fcx.body_id); // Check whether the impl imposes obligations we have to worry about. diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 17658675ee280..28cd29111b723 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -14,7 +14,7 @@ use CrateCtxt; use astconv::AstConv; -use check::{self, FnCtxt}; +use check::{self, CheckEnv, FnCtxt}; use middle::ty::{self, Ty}; use middle::def; use metadata::{csearch, cstore, decoder}; @@ -29,7 +29,8 @@ use std::cmp::Ordering; use super::{MethodError, CandidateSource, impl_method, trait_method}; -pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, +pub fn report_error<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a, 'tcx>, span: Span, rcvr_ty: Ty<'tcx>, method_name: ast::Name, @@ -72,10 +73,10 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, span, "found defined static methods, maybe a `self` is missing?"); - report_candidates(fcx, span, method_name, static_sources); + report_candidates(check_env, fcx, span, method_name, static_sources); } - suggest_traits_to_import(fcx, span, rcvr_ty, method_name, + suggest_traits_to_import(check_env, fcx, span, rcvr_ty, method_name, rcvr_expr, out_of_scope_traits) } @@ -83,7 +84,7 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, span_err!(fcx.sess(), span, E0034, "multiple applicable methods in scope"); - report_candidates(fcx, span, method_name, sources); + report_candidates(check_env, fcx, span, method_name, sources); } MethodError::ClosureAmbiguity(trait_def_id) => { @@ -102,10 +103,12 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, } } - fn report_candidates(fcx: &FnCtxt, - span: Span, - method_name: ast::Name, - mut sources: Vec) { + fn report_candidates<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a, 'tcx>, + span: Span, + method_name: ast::Name, + mut sources: Vec) + { sources.sort(); sources.dedup(); @@ -118,7 +121,7 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, let impl_span = fcx.tcx().map.def_id_span(impl_did, span); let method_span = fcx.tcx().map.def_id_span(method.def_id, impl_span); - let impl_ty = check::impl_self_ty(fcx, span, impl_did).ty; + let impl_ty = check::impl_self_ty(check_env, fcx, span, impl_did).ty; let insertion = match ty::impl_trait_ref(fcx.tcx(), impl_did) { None => format!(""), @@ -149,7 +152,8 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, pub type AllTraitsVec = Vec; -fn suggest_traits_to_import<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, +fn suggest_traits_to_import<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a, 'tcx>, span: Span, rcvr_ty: Ty<'tcx>, method_name: ast::Name, @@ -182,7 +186,7 @@ fn suggest_traits_to_import<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, return } - let type_is_local = type_derefs_to_local(fcx, span, rcvr_ty, rcvr_expr); + let type_is_local = type_derefs_to_local(check_env, fcx, span, rcvr_ty, rcvr_expr); // there's no implemented traits, so lets suggest some traits to // implement, by finding ones that have the method name, and are @@ -229,7 +233,8 @@ fn suggest_traits_to_import<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, /// Checks whether there is a local type somewhere in the chain of /// autoderefs of `rcvr_ty`. -fn type_derefs_to_local<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, +fn type_derefs_to_local<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a, 'tcx>, span: Span, rcvr_ty: Ty<'tcx>, rcvr_expr: Option<&ast::Expr>) -> bool { @@ -252,10 +257,10 @@ fn type_derefs_to_local<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, // This occurs for UFCS desugaring of `T::method`, where there is no // receiver expression for the method call, and thus no autoderef. if rcvr_expr.is_none() { - return is_local(fcx.resolve_type_vars_if_possible(rcvr_ty)); + return is_local(fcx.resolve_type_vars_if_possible(check_env, rcvr_ty)); } - check::autoderef(fcx, span, rcvr_ty, None, + check::autoderef(check_env, fcx, span, rcvr_ty, None, check::UnresolvedTypeAction::Ignore, check::NoPreference, |ty, _| { if is_local(ty) { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index f4c593c5f5e97..dee26b14df804 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -158,7 +158,6 @@ pub struct Inherited<'a, 'tcx: 'a> { param_env: ty::ParameterEnvironment<'a, 'tcx>, // Temporary tables: - node_types: RefCell>>, item_substs: RefCell>>, adjustments: RefCell>>, method_map: MethodMap<'tcx>, @@ -172,6 +171,9 @@ pub struct Inherited<'a, 'tcx: 'a> { } pub struct CheckEnv<'tcx> { + // Temporary tables: + node_types: NodeMap>, + // 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. @@ -190,7 +192,7 @@ pub struct CheckEnv<'tcx> { } trait DeferredCallResolution<'tcx> { - fn resolve<'a>(&mut self, fcx: &FnCtxt<'a,'tcx>); + fn resolve<'a>(&mut self, check_env: &mut CheckEnv<'tcx>, fcx: &FnCtxt<'a,'tcx>); } type DeferredCallResolutionHandler<'tcx> = Box+'tcx>; @@ -304,57 +306,209 @@ pub struct FnCtxt<'a, 'tcx: 'a> { ccx: &'a CrateCtxt<'a, 'tcx>, } -impl<'a, 'tcx> mc::Typer<'tcx> for FnCtxt<'a, 'tcx> { +// FIXME: Determine whether we actually need these. +#[derive(Clone, Copy)] +pub struct FnCtxtTyper<'a, 'tcx: 'a> { + fcx: &'a FnCtxt<'a, 'tcx>, + + check_env: &'a CheckEnv<'tcx> +} + +impl<'a, 'tcx> FnCtxtTyper<'a, 'tcx> { + fn new(check_env: &'a CheckEnv<'tcx>, fcx: &'a FnCtxt<'a, 'tcx>) -> Self { + FnCtxtTyper { check_env: check_env, fcx: fcx } + } + + fn normalize_associated_types_in(&self, span: Span, value: &T) -> T + where T : TypeFoldable<'tcx> + Clone + HasProjectionTypes + Repr<'tcx> + { + self.fcx.inh.normalize_associated_types_in(self, span, self.fcx.body_id, value) + } + + fn normalize_associated_type(&self, + span: Span, + trait_ref: ty::TraitRef<'tcx>, + item_name: ast::Name) + -> Ty<'tcx> + { + let cause = traits::ObligationCause::new(span, + self.fcx.body_id, + traits::ObligationCauseCode::MiscObligation); + self.fcx.inh.fulfillment_cx + .borrow_mut() + .normalize_projection_type(self.fcx.infcx(), + self, + ty::ProjectionTy { + trait_ref: trait_ref, + item_name: item_name, + }, + cause) + } + + /// Basically whenever we are converting from a type scheme into + /// the fn body space, we always want to normalize associated + /// types as well. This function combines the two. + fn instantiate_type_scheme(&self, + span: Span, + substs: &Substs<'tcx>, + value: &T) + -> T + where T : TypeFoldable<'tcx> + Clone + HasProjectionTypes + Repr<'tcx> + { + let value = value.subst(self.tcx(), substs); + let typer = FnCtxtTyper::new(self.check_env, self.fcx); + let result = typer.normalize_associated_types_in(span, &value); + debug!("instantiate_type_scheme(value={}, substs={}) = {}", + value.repr(self.tcx()), + substs.repr(self.tcx()), + result.repr(self.tcx())); + result + } + + /// As `instantiate_type_scheme`, but for the bounds found in a + /// generic type scheme. + fn instantiate_bounds(&self, + span: Span, + substs: &Substs<'tcx>, + bounds: &ty::GenericPredicates<'tcx>) + -> ty::InstantiatedPredicates<'tcx> + { + ty::InstantiatedPredicates { + predicates: self.instantiate_type_scheme(span, substs, &bounds.predicates) + } + } + + + /// 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 on `def_id` at the same time. + /// + /// Note that function is only intended to be used with types (notably, not fns). This is + /// because it doesn't do any instantiation of late-bound regions. + pub fn instantiate_type(&self, + span: Span, + def_id: ast::DefId) + -> TypeAndSubsts<'tcx> + { + let type_scheme = + ty::lookup_item_type(self.tcx(), def_id); + let type_predicates = + ty::lookup_predicates(self.tcx(), def_id); + let substs = + self.fcx.infcx().fresh_substs_for_generics( + span, + &type_scheme.generics); + let bounds = + self.instantiate_bounds(span, &substs, &type_predicates); + self.fcx.add_obligations_for_parameters( + traits::ObligationCause::new( + span, + self.fcx.body_id, + traits::ItemObligation(def_id)), + &bounds); + let monotype = + self.instantiate_type_scheme(span, &substs, &type_scheme.ty); + + TypeAndSubsts { + ty: monotype, + substs: substs + } + } + + /// Returns the type that this AST path refers to. If the path has no type + /// parameters and the corresponding type has type parameters, fresh type + /// and/or region variables are substituted. + /// + /// This is used when checking the constructor in struct literals. + fn instantiate_struct_literal_ty(&self, + did: ast::DefId, + path: &ast::Path) + -> TypeAndSubsts<'tcx> + { + let tcx = self.tcx(); + + let ty::TypeScheme { generics, ty: decl_ty } = + ty::lookup_item_type(tcx, did); + + let substs = astconv::ast_path_substs_for_ty(self, self.fcx, + path.span, + PathParamMode::Optional, + &generics, + path.segments.last().unwrap()); + + let ty = self.instantiate_type_scheme(path.span, &substs, &decl_ty); + + TypeAndSubsts { substs: substs, ty: ty } + } + + pub fn to_ty(&self, ast_t: &ast::Ty) -> Ty<'tcx> { + let t = ast_ty_to_ty(self, self.fcx, ast_t); + + let mut bounds_checker = wf::BoundsChecker::new(self.check_env, + self.fcx, + ast_t.span, + self.fcx.body_id, + None); + bounds_checker.check_ty(t); + + t + } +} + +impl<'a, 'tcx> mc::Typer<'tcx> for FnCtxtTyper<'a, 'tcx> { fn node_ty(&self, id: ast::NodeId) -> McResult> { - let ty = self.node_ty(id); - self.resolve_type_vars_or_error(&ty) + let ty = self.fcx.node_ty(&self.check_env, id); + self.fcx.resolve_type_vars_or_error(&ty) } fn expr_ty_adjusted(&self, expr: &ast::Expr) -> McResult> { - let ty = self.adjust_expr_ty(expr, self.inh.adjustments.borrow().get(&expr.id)); - self.resolve_type_vars_or_error(&ty) + let ty = self.fcx.adjust_expr_ty(&self.check_env, expr, + self.fcx.inh.adjustments.borrow().get(&expr.id)); + self.fcx.resolve_type_vars_or_error(&ty) } fn type_moves_by_default(&self, span: Span, ty: Ty<'tcx>) -> bool { - let ty = self.infcx().resolve_type_vars_if_possible(&ty); - !traits::type_known_to_meet_builtin_bound(self.infcx(), self, ty, ty::BoundCopy, span) + let ty = self.fcx.infcx().resolve_type_vars_if_possible(&ty); + !traits::type_known_to_meet_builtin_bound(self.fcx.infcx(), self, ty, ty::BoundCopy, span) } fn node_method_ty(&self, method_call: ty::MethodCall) -> Option> { - self.inh.method_map.borrow() - .get(&method_call) - .map(|method| method.ty) - .map(|ty| self.infcx().resolve_type_vars_if_possible(&ty)) + self.fcx.inh.method_map.borrow() + .get(&method_call) + .map(|method| method.ty) + .map(|ty| self.fcx + .infcx() + .resolve_type_vars_if_possible(&ty)) } fn node_method_origin(&self, method_call: ty::MethodCall) -> Option> { - self.inh.method_map.borrow() - .get(&method_call) - .map(|method| method.origin.clone()) + self.fcx.inh.method_map.borrow() + .get(&method_call) + .map(|method| method.origin.clone()) } fn adjustments(&self) -> &RefCell>> { - &self.inh.adjustments + &self.fcx.inh.adjustments } fn is_method_call(&self, id: ast::NodeId) -> bool { - self.inh.method_map.borrow().contains_key(&ty::MethodCall::expr(id)) + self.fcx.inh.method_map.borrow().contains_key(&ty::MethodCall::expr(id)) } fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option { - self.param_env().temporary_scope(rvalue_id) + self.fcx.param_env().temporary_scope(rvalue_id) } fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option { - self.inh.upvar_capture_map.borrow().get(&upvar_id).cloned() + self.fcx.inh.upvar_capture_map.borrow().get(&upvar_id).cloned() } } -impl<'a, 'tcx> ty::ClosureTyper<'tcx> for FnCtxt<'a, 'tcx> { +impl<'a, 'tcx> ty::ClosureTyper<'tcx> for FnCtxtTyper<'a, 'tcx> { fn param_env<'b>(&'b self) -> &'b ty::ParameterEnvironment<'b,'tcx> { - &self.inh.param_env + &self.fcx.inh.param_env } fn closure_kind(&self, def_id: ast::DefId) -> Option { - self.inh.closure_kinds.borrow().get(&def_id).cloned() + self.fcx.inh.closure_kinds.borrow().get(&def_id).cloned() } fn closure_type(&self, @@ -362,7 +516,7 @@ impl<'a, 'tcx> ty::ClosureTyper<'tcx> for FnCtxt<'a, 'tcx> { substs: &subst::Substs<'tcx>) -> ty::ClosureTy<'tcx> { - self.inh.closure_tys.borrow().get(&def_id).unwrap().subst(self.tcx(), substs) + self.fcx.inh.closure_tys.borrow().get(&def_id).unwrap().subst(self.fcx.tcx(), substs) } fn closure_upvars(&self, @@ -382,7 +536,6 @@ impl<'a, 'tcx> Inherited<'a, 'tcx> { infcx: infer::new_infer_ctxt(tcx), locals: RefCell::new(NodeMap()), param_env: param_env, - node_types: RefCell::new(NodeMap()), item_substs: RefCell::new(NodeMap()), adjustments: RefCell::new(NodeMap()), method_map: RefCell::new(FnvHashMap()), @@ -409,12 +562,12 @@ impl<'a, 'tcx> Inherited<'a, 'tcx> { body_id, value) } - } impl<'tcx> CheckEnv<'tcx> { fn new() -> Self { CheckEnv { + node_types: NodeMap(), fn_sig_map: NodeMap(), deferred_call_resolutions: DefIdMap(), deferred_cast_checks: Vec::new(), @@ -435,9 +588,11 @@ impl<'tcx> CheckEnv<'tcx> { } fn check_casts<'a>(&mut self, fcx: &'a FnCtxt<'a, 'tcx>) { - for check in self.deferred_cast_checks.drain(..) { - cast::check_cast(fcx, &check); + let mut deferred_cast_checks = replace(&mut self.deferred_cast_checks, Vec::new()); + for check in deferred_cast_checks.drain(..) { + cast::check_cast(self, fcx, &check); } + replace(&mut self.deferred_cast_checks, deferred_cast_checks); } } @@ -554,12 +709,12 @@ fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let fcx = check_fn(&mut check_env, ccx, fn_ty.unsafety, fn_id, &fn_sig, decl, fn_id, body, &inh); - vtable::select_all_fcx_obligations_and_apply_defaults(&fcx); + vtable::select_all_fcx_obligations_and_apply_defaults(&mut check_env, &fcx); upvar::closure_analyze_fn(&mut check_env, &fcx, fn_id, decl, body); vtable::select_all_fcx_obligations_or_error(&mut check_env, &fcx); check_env.check_casts(&fcx); regionck::regionck_fn(&mut check_env, &fcx, fn_id, fn_span, decl, body); - writeback::resolve_type_vars_in_fn(&fcx, decl, body); + writeback::resolve_type_vars_in_fn(&mut check_env, &fcx, decl, body); } _ => ccx.tcx.sess.impossible_case(body.span, "check_bare_fn: function type expected") @@ -592,10 +747,10 @@ impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> { // Add explicitly-declared locals. 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 - }; + let o_ty = local.ty.as_ref().map( |ty| { + let typer = FnCtxtTyper::new(self.check_env, self.fcx); + typer.to_ty(&**ty) + } ); self.assign(local.span, local.id, o_ty); debug!("Local variable {} is assigned type {}", self.fcx.pat_to_string(&*local.pat), @@ -738,7 +893,7 @@ fn check_fn<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, }); for (input, arg) in decl.inputs.iter().zip(arg_tys.iter()) { - fcx.write_ty(input.id, *arg); + fcx.write_ty(check_env, input.id, *arg); } fcx @@ -1140,7 +1295,8 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, } } -fn report_cast_to_unsized_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, +fn report_cast_to_unsized_type<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a, 'tcx>, span: Span, t_span: Span, e_span: Span, @@ -1190,12 +1346,12 @@ fn report_cast_to_unsized_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, "consider using a box or reference as appropriate"); } } - fcx.write_error(id); + fcx.write_error(check_env, id); } -impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> { - fn tcx(&self) -> &ty::ctxt<'tcx> { self.ccx.tcx } +impl<'a, 'tcx> AstConv<'tcx> for FnCtxtTyper<'a, 'tcx> { + fn tcx(&self) -> &ty::ctxt<'tcx> { self.fcx.ccx.tcx } fn get_item_type_scheme(&self, _: Span, id: ast::DefId) -> Result, ErrorReported> @@ -1215,7 +1371,7 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> { } fn get_free_substs(&self) -> Option<&Substs<'tcx>> { - Some(&self.inh.param_env.free_substs) + Some(&self.fcx.inh.param_env.free_substs) } fn get_type_parameter_bounds(&self, @@ -1224,23 +1380,24 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> { -> Result>, ErrorReported> { let def = self.tcx().type_parameter_def(node_id); - let r = self.inh.param_env.caller_bounds - .iter() - .filter_map(|predicate| { - match *predicate { - ty::Predicate::Trait(ref data) => { - if data.0.self_ty().is_param(def.space, def.index) { - Some(data.to_poly_trait_ref()) - } else { - None - } - } - _ => { - None - } - } - }) - .collect(); + let r = self.fcx.inh.param_env + .caller_bounds + .iter() + .filter_map(|predicate| { + match *predicate { + ty::Predicate::Trait(ref data) => { + if data.0.self_ty().is_param(def.space, def.index) { + Some(data.to_poly_trait_ref()) + } else { + None + } + } + _ => { + None + } + } + }) + .collect(); Ok(r) } @@ -1249,12 +1406,12 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> { assoc_name: ast::Name) -> bool { - let trait_def = ty::lookup_trait_def(self.ccx.tcx, trait_def_id); + let trait_def = ty::lookup_trait_def(self.tcx(), trait_def_id); trait_def.associated_type_names.contains(&assoc_name) } fn ty_infer(&self, _span: Span) -> Ty<'tcx> { - self.infcx().next_ty_var() + self.fcx.infcx().next_ty_var() } fn projected_ty_from_poly_trait_ref(&self, @@ -1264,7 +1421,7 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> { -> Ty<'tcx> { let (trait_ref, _) = - self.infcx().replace_late_bound_regions_with_fresh_var( + self.fcx.infcx().replace_late_bound_regions_with_fresh_var( span, infer::LateBoundRegionConversionTime::AssocTypeProjection(item_name), &poly_trait_ref); @@ -1304,7 +1461,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Resolves type variables in `ty` if possible. Unlike the infcx /// version, this version will also select obligations if it seems /// useful, in an effort to get more type information. - fn resolve_type_vars_if_possible(&self, mut ty: Ty<'tcx>) -> Ty<'tcx> { + fn resolve_type_vars_if_possible(&self, check_env: &CheckEnv<'tcx>, + mut ty: Ty<'tcx>) -> Ty<'tcx> { debug!("resolve_type_vars_if_possible(ty={})", ty.repr(self.tcx())); // No ty::infer()? Nothing needs doing. @@ -1321,7 +1479,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } // If not, try resolving any new fcx obligations that have cropped up. - vtable::select_new_fcx_obligations(self); + vtable::select_new_fcx_obligations(check_env, self); ty = self.infcx().resolve_type_vars_if_possible(&ty); if !ty::type_has_ty_infer(ty) { debug!("resolve_type_vars_if_possible: ty={}", ty.repr(self.tcx())); @@ -1332,7 +1490,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // possible. This can help substantially when there are // indirect dependencies that don't seem worth tracking // precisely. - vtable::select_fcx_obligations_where_possible(self); + vtable::select_fcx_obligations_where_possible(check_env, self); ty = self.infcx().resolve_type_vars_if_possible(&ty); debug!("resolve_type_vars_if_possible: ty={}", ty.repr(self.tcx())); @@ -1368,9 +1526,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Apply "fallbacks" to some types /// ! gets replaced with (), unconstrained ints with i32, and unconstrained floats with f64. - pub fn default_type_parameters(&self) { + pub fn default_type_parameters(&self, check_env: &mut CheckEnv<'tcx>) { use middle::ty::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat, Neither}; - for (_, &mut ref ty) in &mut *self.inh.node_types.borrow_mut() { + for (_, &mut ref ty) in &mut check_env.node_types { let resolved = self.infcx().resolve_type_vars_if_possible(ty); if self.infcx().type_var_diverges(resolved) { demand::eqtype(self, codemap::DUMMY_SP, *ty, ty::mk_nil(self.tcx())); @@ -1389,10 +1547,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } #[inline] - pub fn write_ty(&self, node_id: ast::NodeId, ty: Ty<'tcx>) { + pub fn write_ty(&self, check_env: &mut CheckEnv<'tcx>, 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); + check_env.node_types.insert(node_id, ty); } pub fn write_substs(&self, node_id: ast::NodeId, substs: ty::ItemSubsts<'tcx>) { @@ -1431,132 +1589,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.inh.adjustments.borrow_mut().insert(node_id, adj); } - /// Basically whenever we are converting from a type scheme into - /// the fn body space, we always want to normalize associated - /// types as well. This function combines the two. - fn instantiate_type_scheme(&self, - span: Span, - substs: &Substs<'tcx>, - value: &T) - -> T - where T : TypeFoldable<'tcx> + Clone + HasProjectionTypes + Repr<'tcx> - { - let value = value.subst(self.tcx(), substs); - let result = self.normalize_associated_types_in(span, &value); - debug!("instantiate_type_scheme(value={}, substs={}) = {}", - value.repr(self.tcx()), - substs.repr(self.tcx()), - result.repr(self.tcx())); - result - } - - /// As `instantiate_type_scheme`, but for the bounds found in a - /// generic type scheme. - fn instantiate_bounds(&self, - span: Span, - substs: &Substs<'tcx>, - bounds: &ty::GenericPredicates<'tcx>) - -> ty::InstantiatedPredicates<'tcx> - { - ty::InstantiatedPredicates { - predicates: self.instantiate_type_scheme(span, substs, &bounds.predicates) - } - } - - - fn normalize_associated_types_in(&self, span: Span, value: &T) -> T - where T : TypeFoldable<'tcx> + Clone + HasProjectionTypes + Repr<'tcx> - { - self.inh.normalize_associated_types_in(self, span, self.body_id, value) - } - - fn normalize_associated_type(&self, - span: Span, - trait_ref: ty::TraitRef<'tcx>, - item_name: ast::Name) - -> Ty<'tcx> - { - let cause = traits::ObligationCause::new(span, - self.body_id, - traits::ObligationCauseCode::MiscObligation); - self.inh.fulfillment_cx - .borrow_mut() - .normalize_projection_type(self.infcx(), - self, - ty::ProjectionTy { - trait_ref: trait_ref, - item_name: item_name, - }, - cause) - } - - /// 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 on `def_id` at the same time. - /// - /// Note that function is only intended to be used with types (notably, not fns). This is - /// because it doesn't do any instantiation of late-bound regions. - pub fn instantiate_type(&self, - span: Span, - def_id: ast::DefId) - -> TypeAndSubsts<'tcx> - { - let type_scheme = - ty::lookup_item_type(self.tcx(), def_id); - let type_predicates = - ty::lookup_predicates(self.tcx(), def_id); - let substs = - self.infcx().fresh_substs_for_generics( - span, - &type_scheme.generics); - let bounds = - self.instantiate_bounds(span, &substs, &type_predicates); - self.add_obligations_for_parameters( - traits::ObligationCause::new( - span, - self.body_id, - traits::ItemObligation(def_id)), - &bounds); - let monotype = - self.instantiate_type_scheme(span, &substs, &type_scheme.ty); - - TypeAndSubsts { - ty: monotype, - substs: substs - } + pub fn write_nil(&self, check_env: &mut CheckEnv<'tcx>, node_id: ast::NodeId) { + self.write_ty(check_env, node_id, ty::mk_nil(self.tcx())); } - - /// Returns the type that this AST path refers to. If the path has no type - /// parameters and the corresponding type has type parameters, fresh type - /// and/or region variables are substituted. - /// - /// This is used when checking the constructor in struct literals. - fn instantiate_struct_literal_ty(&self, - did: ast::DefId, - path: &ast::Path) - -> TypeAndSubsts<'tcx> - { - let tcx = self.tcx(); - - let ty::TypeScheme { generics, ty: decl_ty } = - ty::lookup_item_type(tcx, did); - - let substs = astconv::ast_path_substs_for_ty(self, self, - path.span, - PathParamMode::Optional, - &generics, - path.segments.last().unwrap()); - - let ty = self.instantiate_type_scheme(path.span, &substs, &decl_ty); - - TypeAndSubsts { substs: substs, ty: ty } - } - - pub fn write_nil(&self, node_id: ast::NodeId) { - self.write_ty(node_id, ty::mk_nil(self.tcx())); - } - pub fn write_error(&self, node_id: ast::NodeId) { - self.write_ty(node_id, self.tcx().types.err); + pub fn write_error(&self, check_env: &mut CheckEnv<'tcx>, node_id: ast::NodeId) { + self.write_ty(check_env, node_id, self.tcx().types.err); } pub fn require_type_meets(&self, @@ -1580,10 +1617,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } pub fn require_expr_have_sized_type(&self, + check_env: &mut CheckEnv<'tcx>, expr: &ast::Expr, code: traits::ObligationCauseCode<'tcx>) { - self.require_type_is_sized(self.expr_ty(expr), expr.span, code); + self.require_type_is_sized(self.expr_ty(check_env, expr), expr.span, code); } pub fn type_is_known_to_be_sized(&self, @@ -1624,24 +1662,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .register_predicate_obligation(self.infcx(), obligation); } - pub fn to_ty(&self, ast_t: &ast::Ty) -> Ty<'tcx> { - let t = ast_ty_to_ty(self, self, ast_t); - - let mut bounds_checker = wf::BoundsChecker::new(self, - ast_t.span, - self.body_id, - None); - bounds_checker.check_ty(t); - - t - } - pub fn pat_to_string(&self, pat: &ast::Pat) -> String { pat.repr(self.tcx()) } - pub fn expr_ty(&self, ex: &ast::Expr) -> Ty<'tcx> { - match self.inh.node_types.borrow().get(&ex.id) { + pub fn expr_ty(&self, check_env: &CheckEnv<'tcx>, ex: &ast::Expr) -> Ty<'tcx> { + match check_env.node_types.get(&ex.id) { Some(&t) => t, None => { self.tcx().sess.bug(&format!("no type for expr in fcx {}", @@ -1652,11 +1678,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Apply `adjustment` to the type of `expr` pub fn adjust_expr_ty(&self, + check_env: &CheckEnv<'tcx>, expr: &ast::Expr, adjustment: Option<&ty::AutoAdjustment<'tcx>>) -> Ty<'tcx> { - let raw_ty = self.expr_ty(expr); + let raw_ty = self.expr_ty(check_env, expr); let raw_ty = self.infcx().shallow_resolve(raw_ty); let resolve_ty = |ty: Ty<'tcx>| self.infcx().resolve_type_vars_if_possible(&ty); ty::adjust_ty(self.tcx(), @@ -1669,8 +1696,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .map(|method| resolve_ty(method.ty))) } - pub fn node_ty(&self, id: ast::NodeId) -> Ty<'tcx> { - match self.inh.node_types.borrow().get(&id) { + pub fn node_ty(&self, check_env: &CheckEnv<'tcx>, id: ast::NodeId) -> Ty<'tcx> { + match check_env.node_types.get(&id) { Some(&t) => t, None if self.err_count_since_creation() != 0 => self.tcx().types.err, None => { @@ -1800,6 +1827,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Only for fields! Returns for methods> // Indifferent to privacy flags pub fn lookup_field_ty(&self, + check_env: &mut CheckEnv<'tcx>, span: Span, class_id: ast::DefId, items: &[ty::field_ty], @@ -1809,10 +1837,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { let o_field = items.iter().find(|f| f.name == fieldname); o_field.map(|f| ty::lookup_field_type(self.tcx(), class_id, f.id, substs)) - .map(|t| self.normalize_associated_types_in(span, &t)) + .map(|t| { + let typer = FnCtxtTyper::new(check_env, self); + typer.normalize_associated_types_in(span, &t) + }) } pub fn lookup_tup_field_ty(&self, + check_env: &mut CheckEnv<'tcx>, span: Span, class_id: ast::DefId, items: &[ty::field_ty], @@ -1822,7 +1854,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { let o_field = if idx < items.len() { Some(&items[idx]) } else { None }; o_field.map(|f| ty::lookup_field_type(self.tcx(), class_id, f.id, substs)) - .map(|t| self.normalize_associated_types_in(span, &t)) + .map(|t| { + let typer = FnCtxtTyper::new(check_env, self); + typer.normalize_associated_types_in(span, &t) + }) } } @@ -1868,7 +1903,8 @@ pub enum UnresolvedTypeAction { /// /// Note: this method does not modify the adjustments table. The caller is responsible for /// inserting an AutoAdjustment record into the `fcx` using one of the suitable methods. -pub fn autoderef<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>, +pub fn autoderef<'a, 'tcx, T, F>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a, 'tcx>, sp: Span, base_ty: Ty<'tcx>, opt_expr: Option<&ast::Expr>, @@ -1887,7 +1923,7 @@ pub fn autoderef<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>, for autoderefs in 0..fcx.tcx().sess.recursion_limit.get() { let resolved_t = match unresolved_type_action { UnresolvedTypeAction::Error => { - let resolved_t = structurally_resolved_type(fcx, sp, t); + let resolved_t = structurally_resolved_type(check_env, fcx, sp, t); if ty::type_is_error(resolved_t) { return (resolved_t, autoderefs, None); } @@ -1898,7 +1934,7 @@ pub fn autoderef<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>, // (i.e. it is an inference variable) because `ty::deref` // and `try_overloaded_deref` both simply return `None` // in such a case without producing spurious errors. - fcx.resolve_type_vars_if_possible(t) + fcx.resolve_type_vars_if_possible(check_env, t) } }; @@ -1925,7 +1961,7 @@ pub fn autoderef<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>, // when they encounter an overloaded autoderef, have // to do some reconstructive surgery. This is a pretty // complex mess that is begging for a proper MIR. - try_overloaded_deref(fcx, sp, method_call, None, resolved_t, lvalue_pref) + try_overloaded_deref(check_env, fcx, sp, method_call, None, resolved_t, lvalue_pref) } }; match mt { @@ -1946,7 +1982,8 @@ pub fn autoderef<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>, (fcx.tcx().types.err, 0, None) } -fn try_overloaded_deref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, +fn try_overloaded_deref<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a, 'tcx>, span: Span, method_call: Option, base_expr: Option<&ast::Expr>, @@ -1957,7 +1994,7 @@ fn try_overloaded_deref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, // Try DerefMut first, if preferred. let method = match (lvalue_pref, fcx.tcx().lang_items.deref_mut_trait()) { (PreferMutLvalue, Some(trait_did)) => { - method::lookup_in_trait(fcx, span, base_expr, + method::lookup_in_trait(check_env, fcx, span, base_expr, token::intern("deref_mut"), trait_did, base_ty, None) } @@ -1967,7 +2004,7 @@ fn try_overloaded_deref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, // Otherwise, fall back to Deref. let method = match (method, fcx.tcx().lang_items.deref_trait()) { (None, Some(trait_did)) => { - method::lookup_in_trait(fcx, span, base_expr, + method::lookup_in_trait(check_env, fcx, span, base_expr, token::intern("deref"), trait_did, base_ty, None) } @@ -2003,7 +2040,8 @@ fn make_overloaded_lvalue_return_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, } } -fn lookup_indexing<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, +fn lookup_indexing<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a, 'tcx>, expr: &ast::Expr, base_expr: &'tcx ast::Expr, base_ty: Ty<'tcx>, @@ -2015,15 +2053,17 @@ fn lookup_indexing<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, // autoderef that normal method probing does. They could likely be // consolidated. - let (ty, autoderefs, final_mt) = autoderef(fcx, + let (ty, autoderefs, final_mt) = autoderef(check_env, + fcx, base_expr.span, base_ty, Some(base_expr), UnresolvedTypeAction::Error, lvalue_pref, - |adj_ty, idx| { - try_index_step(fcx, MethodCall::expr(expr.id), expr, base_expr, - adj_ty, idx, false, lvalue_pref, idx_ty) + |adj_ty, idx| Some((adj_ty, idx))); + let final_mt = final_mt.and_then( |(adj_ty, idx)| { + try_index_step(check_env, fcx, MethodCall::expr(expr.id), expr, base_expr, + adj_ty, idx, false, lvalue_pref, idx_ty) }); if final_mt.is_some() { @@ -2034,7 +2074,7 @@ fn lookup_indexing<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, // do a final unsized coercion to yield [T]. if let ty::ty_vec(element_ty, Some(_)) = ty.sty { let adjusted_ty = ty::mk_vec(fcx.tcx(), element_ty, None); - try_index_step(fcx, MethodCall::expr(expr.id), expr, base_expr, + try_index_step(check_env, fcx, MethodCall::expr(expr.id), expr, base_expr, adjusted_ty, autoderefs, true, lvalue_pref, idx_ty) } else { None @@ -2045,7 +2085,8 @@ fn lookup_indexing<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, /// `base_expr`, looking for a type which either supports builtin indexing or overloaded indexing. /// This loop implements one step in that search; the autoderef loop is implemented by /// `lookup_indexing`. -fn try_index_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, +fn try_index_step<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a, 'tcx>, method_call: MethodCall, expr: &ast::Expr, base_expr: &'tcx ast::Expr, @@ -2083,7 +2124,8 @@ fn try_index_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, // Try `IndexMut` first, if preferred. let method = match (lvalue_pref, tcx.lang_items.index_mut_trait()) { (PreferMutLvalue, Some(trait_did)) => { - method::lookup_in_trait_adjusted(fcx, + method::lookup_in_trait_adjusted(check_env, + fcx, expr.span, Some(&*base_expr), token::intern("index_mut"), @@ -2099,7 +2141,8 @@ fn try_index_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, // Otherwise, fall back to `Index`. let method = match (method, tcx.lang_items.index_trait()) { (None, Some(trait_did)) => { - method::lookup_in_trait_adjusted(fcx, + method::lookup_in_trait_adjusted(check_env, + fcx, expr.span, Some(&*base_expr), token::intern("index"), @@ -2152,7 +2195,8 @@ fn check_method_argument_types<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, match method_fn_ty.sty { ty::ty_bare_fn(_, ref fty) => { // HACK(eddyb) ignore self in the definition (see above). - let expected_arg_tys = expected_types_for_fn_args(fcx, + let expected_arg_tys = expected_types_for_fn_args(check_env, + fcx, sp, expected, fty.sig.0.output, @@ -2198,7 +2242,7 @@ fn check_argument_types<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, let mut expected_arg_tys = expected_arg_tys; 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]); + let tuple_type = structurally_resolved_type(check_env, fcx, sp, fn_inputs[0]); match tuple_type.sty { ty::ty_tup(ref arg_types) => { if arg_types.len() != args.len() { @@ -2274,7 +2318,7 @@ fn check_argument_types<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, // an "opportunistic" vtable resolution of any trait bounds on // the call. This helps coercions. if check_blocks { - vtable::select_new_fcx_obligations(fcx); + vtable::select_new_fcx_obligations(check_env, fcx); } // For variadic functions, we don't have a declared type for all of @@ -2305,12 +2349,13 @@ fn check_argument_types<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, check_expr_with_unifier(check_env, fcx, &**arg, expected.unwrap_or(ExpectHasType(formal_ty)), - NoPreference, || { + NoPreference, |check_env| { // 2. Coerce to the most detailed type that could be coerced // to, which is `expected_ty` if `rvalue_hint` returns an // `ExprHasType(expected_ty)`, or the `formal_ty` otherwise. let coerce_ty = expected.and_then(|e| e.only_has_type(fcx)); - demand::coerce(fcx, arg.span, coerce_ty.unwrap_or(formal_ty), &**arg); + demand::coerce(check_env, fcx, + arg.span, coerce_ty.unwrap_or(formal_ty), &**arg); // 3. Relate the expected type and the formal one, // if the expected type was used for the coercion. @@ -2328,8 +2373,8 @@ fn check_argument_types<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, // There are a few types which get autopromoted when passed via varargs // 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)); + let expr_ty = fcx.expr_ty(check_env, &**arg); + let arg_ty = structurally_resolved_type(check_env, fcx, arg.span, expr_ty); match arg_ty.sty { ty::ty_float(ast::TyF32) => { fcx.type_error_message(arg.span, @@ -2363,10 +2408,11 @@ fn err_args<'tcx>(tcx: &ty::ctxt<'tcx>, len: usize) -> Vec> { (0..len).map(|_| tcx.types.err).collect() } -fn write_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, +fn write_call<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a, 'tcx>, call_expr: &ast::Expr, output: ty::FnOutput<'tcx>) { - fcx.write_ty(call_expr.id, match output { + fcx.write_ty(check_env, call_expr.id, match output { ty::FnConverging(output_ty) => output_ty, ty::FnDiverging => fcx.infcx().next_diverging_ty_var() }); @@ -2426,7 +2472,7 @@ fn check_expr_has_type<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, expected: Ty<'tcx>) { check_expr_with_unifier( check_env, fcx, expr, ExpectHasType(expected), NoPreference, - || demand::suptype(fcx, expr.span, expected, fcx.expr_ty(expr))); + |check_env| demand::suptype(fcx, expr.span, expected, fcx.expr_ty(check_env, expr))); } fn check_expr_coercable_to_type<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, @@ -2435,7 +2481,7 @@ fn check_expr_coercable_to_type<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, expected: Ty<'tcx>) { check_expr_with_unifier( check_env, fcx, expr, ExpectHasType(expected), NoPreference, - || demand::coerce(fcx, expr.span, expected, expr)); + |check_env| demand::coerce(check_env, fcx, expr.span, expected, expr)); } fn check_expr_with_hint<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, @@ -2443,7 +2489,7 @@ fn check_expr_with_hint<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, expected: Ty<'tcx>) { check_expr_with_unifier( check_env, fcx, expr, ExpectHasType(expected), NoPreference, - || ()) + |_| ()) } fn check_expr_with_expectation<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, @@ -2452,7 +2498,7 @@ fn check_expr_with_expectation<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, expected: Expectation<'tcx>) { check_expr_with_unifier( check_env, fcx, expr, expected, NoPreference, - || ()) + |_| ()) } fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, @@ -2461,28 +2507,29 @@ fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(check_env: &mut CheckEn expected: Expectation<'tcx>, lvalue_pref: LvaluePreference) { - check_expr_with_unifier(check_env, fcx, expr, expected, lvalue_pref, || ()) + check_expr_with_unifier(check_env, fcx, expr, expected, lvalue_pref, |_| ()) } fn check_expr<'a,'tcx>(check_env: &mut CheckEnv<'tcx>, fcx: &FnCtxt<'a,'tcx>, expr: &'tcx ast::Expr) { - check_expr_with_unifier(check_env, fcx, expr, NoExpectation, NoPreference, || ()) + check_expr_with_unifier(check_env, fcx, expr, NoExpectation, NoPreference, |_| ()) } fn check_expr_with_lvalue_pref<'a,'tcx>(check_env: &mut CheckEnv<'tcx>, fcx: &FnCtxt<'a,'tcx>, expr: &'tcx ast::Expr, lvalue_pref: LvaluePreference) { - check_expr_with_unifier(check_env, fcx, expr, NoExpectation, lvalue_pref, || ()) + check_expr_with_unifier(check_env, fcx, expr, NoExpectation, lvalue_pref, |_| ()) } // determine the `self` type, using fresh variables for all variables // declared on the impl declaration e.g., `impl for ~[(A,B)]` // would return ($0, $1) where $0 and $1 are freshly instantiated type // variables. -pub fn impl_self_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, - span: Span, // (potential) receiver for this impl - did: ast::DefId) - -> TypeAndSubsts<'tcx> { +fn impl_self_ty<'a, 'tcx>(check_env: &mut CheckEnv<'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); @@ -2494,7 +2541,8 @@ pub fn impl_self_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, let rps = fcx.inh.infcx.region_vars_for_defs(span, rps); let tps = fcx.inh.infcx.next_ty_vars(n_tps); let substs = subst::Substs::new_type(tps, rps); - let substd_ty = fcx.instantiate_type_scheme(span, &substs, &raw_ty); + let typer = FnCtxtTyper::new(check_env, fcx); + let substd_ty = typer.instantiate_type_scheme(span, &substs, &raw_ty); TypeAndSubsts { substs: substs, ty: substd_ty } } @@ -2523,7 +2571,9 @@ enum TupleArgumentsFlag { /// Unifies the return type with the expected type early, for more coercions /// and forward type information on the argument expressions. -fn expected_types_for_fn_args<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, +// FIXME: Figure out whether we actually need CheckEnv here. +fn expected_types_for_fn_args<'a, 'tcx>(_: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a, 'tcx>, call_span: Span, expected_ret: Expectation<'tcx>, formal_ret: ty::FnOutput<'tcx>, @@ -2576,7 +2626,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, expected: Expectation<'tcx>, lvalue_pref: LvaluePreference, unifier: F) where - F: FnOnce(), + F: FnOnce(&mut CheckEnv<'tcx>), { debug!(">> typechecking: expr={} expected={}", expr.repr(fcx.tcx()), expected.repr(fcx.tcx())); @@ -2594,12 +2644,15 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, check_expr_with_lvalue_pref(check_env, fcx, &*rcvr, lvalue_pref); // no need to check for bot/err -- callee does that - let expr_t = structurally_resolved_type(fcx, - expr.span, - fcx.expr_ty(&*rcvr)); + let expr_ty = fcx.expr_ty(check_env, &*rcvr); + let expr_t = structurally_resolved_type(check_env, fcx, expr.span, expr_ty); - let tps = tps.iter().map(|ast_ty| fcx.to_ty(&**ast_ty)).collect::>(); - let fn_ty = match method::lookup(fcx, + let tps = { + let typer = FnCtxtTyper::new(check_env, fcx); + tps.iter().map(|ast_ty| typer.to_ty(&**ast_ty)).collect::>() + }; + let fn_ty = match method::lookup(check_env, + fcx, method_name.span, method_name.node.name, expr_t, @@ -2613,9 +2666,9 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, method_ty } Err(error) => { - method::report_error(fcx, method_name.span, expr_t, + method::report_error(check_env, fcx, method_name.span, expr_t, method_name.node.name, Some(rcvr), error); - fcx.write_error(expr.id); + fcx.write_error(check_env, expr.id); fcx.tcx().types.err } }; @@ -2630,7 +2683,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, DontTupleArguments, expected); - write_call(fcx, expr, ret_ty); + write_call(check_env, fcx, expr, ret_ty); } // A generic function for checking the then and else in an if @@ -2647,12 +2700,12 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, let expected = expected.adjust_for_branches(fcx); check_block_with_expected(check_env, fcx, then_blk, expected); - let then_ty = fcx.node_ty(then_blk.id); + let then_ty = fcx.node_ty(check_env, then_blk.id); let branches_ty = match opt_else_expr { Some(ref else_expr) => { check_expr_with_expectation(check_env, fcx, &**else_expr, expected); - let else_ty = fcx.expr_ty(&**else_expr); + let else_ty = fcx.expr_ty(check_env, &**else_expr); infer::common_supertype(fcx.infcx(), infer::IfExpression(sp), true, @@ -2668,14 +2721,14 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, } }; - let cond_ty = fcx.expr_ty(cond_expr); + let cond_ty = fcx.expr_ty(check_env, cond_expr); let if_ty = if ty::type_is_error(cond_ty) { fcx.tcx().types.err } else { branches_ty }; - fcx.write_ty(id, if_ty); + fcx.write_ty(check_env, id, if_ty); } // Check field access expressions @@ -2687,36 +2740,38 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, field: &ast::SpannedIdent) { let tcx = fcx.ccx.tcx; check_expr_with_lvalue_pref(check_env, fcx, base, lvalue_pref); - let expr_t = structurally_resolved_type(fcx, expr.span, - fcx.expr_ty(base)); + let expr_ty = fcx.expr_ty(check_env, base); + let expr_t = structurally_resolved_type(check_env, fcx, expr.span, expr_ty); // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop. - let (_, autoderefs, field_ty) = autoderef(fcx, - expr.span, - expr_t, - Some(base), - UnresolvedTypeAction::Error, - lvalue_pref, - |base_t, _| { + let (_, autoderefs, result) = autoderef(check_env, fcx, + expr.span, + expr_t, + Some(base), + UnresolvedTypeAction::Error, + lvalue_pref, + |base_t, _| { match base_t.sty { ty::ty_struct(base_id, substs) => { debug!("struct named {}", ppaux::ty_to_string(tcx, base_t)); - let fields = ty::lookup_struct_fields(tcx, base_id); - fcx.lookup_field_ty(expr.span, base_id, &fields[..], - field.node.name, &(*substs)) + Some((base_id, substs, ty::lookup_struct_fields(tcx, base_id))) } _ => None } }); + let field_ty = result.and_then( |(base_id, substs, fields)| + fcx.lookup_field_ty(check_env, + expr.span, base_id, &fields[..], + field.node.name, &(*substs))); match field_ty { Some(field_ty) => { - fcx.write_ty(expr.id, field_ty); + fcx.write_ty(check_env, expr.id, field_ty); fcx.write_autoderef_adjustment(base.id, autoderefs); return; } None => {} } - if method::exists(fcx, field.span, field.node.name, expr_t, expr.id) { + if method::exists(check_env, fcx, field.span, field.node.name, expr_t, expr.id) { fcx.type_error_message( field.span, |actual| { @@ -2744,7 +2799,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, } } - fcx.write_error(expr.id); + fcx.write_error(check_env, expr.id); } // displays hints about the closest matches in field names @@ -2789,39 +2844,39 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, idx: codemap::Spanned) { let tcx = fcx.ccx.tcx; check_expr_with_lvalue_pref(check_env, fcx, base, lvalue_pref); - let expr_t = structurally_resolved_type(fcx, expr.span, - fcx.expr_ty(base)); + let expr_ty = fcx.expr_ty(check_env, base); + let expr_t = structurally_resolved_type(check_env, fcx, expr.span, expr_ty); let mut tuple_like = false; // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop. - let (_, autoderefs, field_ty) = autoderef(fcx, - expr.span, + let (_, autoderefs, base_t) = autoderef(check_env, fcx, + expr.span, expr_t, Some(base), UnresolvedTypeAction::Error, lvalue_pref, - |base_t, _| { - match base_t.sty { - ty::ty_struct(base_id, substs) => { - tuple_like = ty::is_tuple_struct(tcx, base_id); - if tuple_like { - debug!("tuple struct named {}", ppaux::ty_to_string(tcx, base_t)); - let fields = ty::lookup_struct_fields(tcx, base_id); - fcx.lookup_tup_field_ty(expr.span, base_id, &fields[..], - idx.node, &(*substs)) - } else { - None - } - } - ty::ty_tup(ref v) => { - tuple_like = true; - if idx.node < v.len() { Some(v[idx.node]) } else { None } - } - _ => None + |base_t, _| Some(base_t)); + let field_ty = base_t.and_then( |base_t| match base_t.sty { + ty::ty_struct(base_id, substs ) => { + tuple_like = ty::is_tuple_struct(tcx, base_id); + if tuple_like { + debug!("tuple struct named {}", ppaux::ty_to_string(tcx, base_t)); + let fields = ty::lookup_struct_fields(tcx, base_id); + fcx.lookup_tup_field_ty(check_env, + expr.span, base_id, &fields[..], + idx.node, &(*substs)) + } else { + None } - }); + } + ty::ty_tup(ref v) => { + tuple_like = true; + if idx.node < v.len() { Some(v[idx.node]) } else { None } + } + _ => None + } ); match field_ty { Some(field_ty) => { - fcx.write_ty(expr.id, field_ty); + fcx.write_ty(check_env, expr.id, field_ty); fcx.write_autoderef_adjustment(base.id, autoderefs); return; } @@ -2844,7 +2899,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, }, expr_t, None); - fcx.write_error(expr.id); + fcx.write_error(check_env, expr.id); } fn check_struct_or_variant_fields<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, @@ -2913,8 +2968,9 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, expected_field_type = ty::lookup_field_type( tcx, class_id, field_id, substitutions); + let typer = FnCtxtTyper::new(check_env, fcx); expected_field_type = - fcx.normalize_associated_types_in( + typer.normalize_associated_types_in( field.span, &expected_field_type); class_field_map.insert( field.ident.node.name, (field_id, true)); @@ -2928,7 +2984,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, } if error_happened { - fcx.write_error(node_id); + fcx.write_error(check_env, node_id); } if check_completeness && !error_happened { @@ -2953,8 +3009,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, } if !error_happened { - fcx.write_ty(node_id, ty::mk_struct(fcx.ccx.tcx, - class_id, substitutions)); + fcx.write_ty(check_env, node_id, + ty::mk_struct(fcx.ccx.tcx, class_id, substitutions)); } } @@ -2971,7 +3027,10 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, let TypeAndSubsts { ty: mut struct_type, substs: struct_substs - } = fcx.instantiate_type(span, class_id); + } = { + let typer = FnCtxtTyper::new(check_env, fcx); + typer.instantiate_type(span, class_id) + }; // Look up and check the fields. let class_fields = ty::lookup_struct_fields(tcx, class_id); @@ -2986,7 +3045,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, fields, base_expr.is_none(), None); - if ty::type_is_error(fcx.node_ty(id)) { + if ty::type_is_error(fcx.node_ty(check_env, id)) { struct_type = tcx.types.err; } @@ -2999,7 +3058,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, } // Write in the resulting type. - fcx.write_ty(id, struct_type); + fcx.write_ty(check_env, id, struct_type); } fn check_struct_enum_variant<'a,'tcx>(check_env: &mut CheckEnv<'tcx>, @@ -3016,7 +3075,10 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, let TypeAndSubsts { ty: enum_type, substs: substitutions - } = fcx.instantiate_type(span, enum_id); + } = { + let typer = FnCtxtTyper::new(check_env, fcx); + typer.instantiate_type(span, enum_id) + }; // Look up and check the enum variant fields. let variant_fields = ty::lookup_struct_fields(tcx, variant_id); @@ -3031,7 +3093,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, fields, true, Some(enum_id)); - fcx.write_ty(id, enum_type); + fcx.write_ty(check_env, id, enum_type); } fn check_struct_fields_on_error<'a,'tcx>(check_env: &mut CheckEnv<'tcx>, @@ -3041,7 +3103,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, base_expr: &'tcx Option>) { // Make sure to still write the types // otherwise we might ICE - fcx.write_error(id); + fcx.write_error(check_env, id); for field in fields { check_expr(check_env, fcx, &*field.expr); } @@ -3067,9 +3129,9 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, // places: the exchange heap and the managed heap. let definition = lookup_full_def(tcx, path.span, place.id); let def_id = definition.def_id(); - let referent_ty = fcx.expr_ty(&**subexpr); + let referent_ty = fcx.expr_ty(check_env, &**subexpr); if tcx.lang_items.exchange_heap() == Some(def_id) { - fcx.write_ty(id, ty::mk_uniq(tcx, referent_ty)); + fcx.write_ty(check_env, id, ty::mk_uniq(tcx, referent_ty)); checked = true } } @@ -3079,13 +3141,13 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, if !checked { span_err!(tcx.sess, expr.span, E0066, "only the managed heap and exchange heap are currently supported"); - fcx.write_ty(id, tcx.types.err); + fcx.write_ty(check_env, id, tcx.types.err); } } ast::ExprLit(ref lit) => { let typ = check_lit(fcx, &**lit, expected); - fcx.write_ty(id, typ); + fcx.write_ty(check_env, id, typ); } ast::ExprBinary(op, ref lhs, ref rhs) => { op::check_binop(check_env, fcx, expr, op, lhs, rhs); @@ -3118,7 +3180,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, }; check_expr_with_expectation_and_lvalue_pref( check_env, fcx, &**oprnd, expected_inner, lvalue_pref); - let mut oprnd_t = fcx.expr_ty(&**oprnd); + let mut oprnd_t = fcx.expr_ty(check_env, &**oprnd); if !ty::type_is_error(oprnd_t) { match unop { @@ -3126,10 +3188,10 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, oprnd_t = ty::mk_uniq(tcx, oprnd_t); } ast::UnDeref => { - oprnd_t = structurally_resolved_type(fcx, expr.span, oprnd_t); + oprnd_t = structurally_resolved_type(check_env, fcx, expr.span, oprnd_t); oprnd_t = match ty::deref(oprnd_t, true) { Some(mt) => mt.ty, - None => match try_overloaded_deref(fcx, expr.span, + None => match try_overloaded_deref(check_env, fcx, expr.span, Some(MethodCall::expr(expr.id)), Some(&**oprnd), oprnd_t, lvalue_pref) { Some(mt) => mt.ty, @@ -3160,21 +3222,21 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, }; } ast::UnNot => { - oprnd_t = structurally_resolved_type(fcx, oprnd.span, + oprnd_t = structurally_resolved_type(check_env, fcx, oprnd.span, oprnd_t); if !(ty::type_is_integral(oprnd_t) || oprnd_t.sty == ty::ty_bool) { - oprnd_t = op::check_user_unop(fcx, "!", "not", + oprnd_t = op::check_user_unop(check_env, fcx, "!", "not", tcx.lang_items.not_trait(), expr, &**oprnd, oprnd_t, unop); } } ast::UnNeg => { - oprnd_t = structurally_resolved_type(fcx, oprnd.span, + oprnd_t = structurally_resolved_type(check_env, fcx, oprnd.span, oprnd_t); if !(ty::type_is_integral(oprnd_t) || ty::type_is_fp(oprnd_t)) { - oprnd_t = op::check_user_unop(fcx, "-", "neg", + oprnd_t = op::check_user_unop(check_env, fcx, "-", "neg", tcx.lang_items.neg_trait(), expr, &**oprnd, oprnd_t, unop); } @@ -3190,7 +3252,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, } } } - fcx.write_ty(id, oprnd_t); + fcx.write_ty(check_env, id, oprnd_t); } ast::ExprAddrOf(mutbl, ref oprnd) => { let hint = expected.only_has_type(fcx).map_or(NoExpectation, |ty| { @@ -3218,7 +3280,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, hint, lvalue_pref); - let tm = ty::mt { ty: fcx.expr_ty(&**oprnd), mutbl: mutbl }; + let tm = ty::mt { ty: fcx.expr_ty(check_env, &**oprnd), mutbl: mutbl }; let oprnd_t = if ty::type_is_error(tm.ty) { tcx.types.err } else { @@ -3238,11 +3300,12 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, let region = fcx.infcx().next_region_var(infer::AddrOfRegion(expr.span)); ty::mk_rptr(tcx, tcx.mk_region(region), tm) }; - fcx.write_ty(id, oprnd_t); + fcx.write_ty(check_env, id, oprnd_t); } ast::ExprPath(ref maybe_qself, ref path) => { let opt_self_ty = maybe_qself.as_ref().map(|qself| { - fcx.to_ty(&qself.ty) + let typer = FnCtxtTyper::new(check_env, fcx); + typer.to_ty(&qself.ty) }); let path_res = if let Some(&d) = tcx.def_map.borrow().get(&id) { @@ -3260,12 +3323,13 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, }; if let Some((opt_ty, segments, def)) = - resolve_ty_and_def_ufcs(fcx, path_res, opt_self_ty, path, + resolve_ty_and_def_ufcs(check_env, fcx, path_res, opt_self_ty, path, expr.span, expr.id) { let (scheme, predicates) = type_scheme_and_predicates_for_def(fcx, expr.span, def); - instantiate_path(fcx, + instantiate_path(check_env, + fcx, segments, scheme, &predicates, @@ -3286,11 +3350,11 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, for &(_, ref out, _) in &ia.outputs { check_expr(check_env, fcx, &**out); } - fcx.write_nil(id); + fcx.write_nil(check_env, id); } ast::ExprMac(_) => tcx.sess.bug("unexpanded macro"), - ast::ExprBreak(_) => { fcx.write_ty(id, fcx.infcx().next_diverging_ty_var()); } - ast::ExprAgain(_) => { fcx.write_ty(id, fcx.infcx().next_diverging_ty_var()); } + ast::ExprBreak(_) => { fcx.write_ty(check_env, id, fcx.infcx().next_diverging_ty_var()); } + ast::ExprAgain(_) => { fcx.write_ty(check_env, id, fcx.infcx().next_diverging_ty_var()); } ast::ExprRet(ref expr_opt) => { match fcx.ret_ty { ty::FnConverging(result_type) => { @@ -3314,7 +3378,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, "`return` in a function declared as diverging"); } } - fcx.write_ty(id, fcx.infcx().next_diverging_ty_var()); + fcx.write_ty(check_env, id, fcx.infcx().next_diverging_ty_var()); } ast::ExprParen(ref a) => { check_expr_with_expectation_and_lvalue_pref(check_env, @@ -3322,7 +3386,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, &**a, expected, lvalue_pref); - fcx.write_ty(id, fcx.expr_ty(&**a)); + let expr_ty = fcx.expr_ty(check_env, &**a); + fcx.write_ty(check_env, id, expr_ty); } ast::ExprAssign(ref lhs, ref rhs) => { check_expr_with_lvalue_pref(check_env, fcx, &**lhs, PreferMutLvalue); @@ -3333,16 +3398,16 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, "illegal left-hand side expression"); } - let lhs_ty = fcx.expr_ty(&**lhs); + let lhs_ty = fcx.expr_ty(check_env, &**lhs); check_expr_coercable_to_type(check_env, fcx, &**rhs, lhs_ty); - let rhs_ty = fcx.expr_ty(&**rhs); + let rhs_ty = fcx.expr_ty(check_env, &**rhs); - fcx.require_expr_have_sized_type(&**lhs, traits::AssignmentLhsSized); + fcx.require_expr_have_sized_type(check_env, &**lhs, traits::AssignmentLhsSized); if ty::type_is_error(lhs_ty) || ty::type_is_error(rhs_ty) { - fcx.write_error(id); + fcx.write_error(check_env, id); } else { - fcx.write_nil(id); + fcx.write_nil(check_env, id); } } ast::ExprIf(ref cond, ref then_blk, ref opt_else_expr) => { @@ -3355,13 +3420,13 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, ast::ExprWhile(ref cond, ref body, _) => { check_expr_has_type(check_env, fcx, &**cond, tcx.types.bool); check_block_no_value(check_env, fcx, &**body); - let cond_ty = fcx.expr_ty(&**cond); - let body_ty = fcx.node_ty(body.id); + let cond_ty = fcx.expr_ty(check_env, &**cond); + let body_ty = fcx.node_ty(check_env, body.id); if ty::type_is_error(cond_ty) || ty::type_is_error(body_ty) { - fcx.write_error(id); + fcx.write_error(check_env, id); } else { - fcx.write_nil(id); + fcx.write_nil(check_env, id); } } ast::ExprWhileLet(..) => { @@ -3373,9 +3438,9 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, ast::ExprLoop(ref body, _) => { check_block_no_value(check_env, fcx, &**body); if !may_break(tcx, expr.id, &**body) { - fcx.write_ty(id, fcx.infcx().next_diverging_ty_var()); + fcx.write_ty(check_env, id, fcx.infcx().next_diverging_ty_var()); } else { - fcx.write_nil(id); + fcx.write_nil(check_env, id); } } ast::ExprMatch(ref discrim, ref arms, match_src) => { @@ -3386,19 +3451,20 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, } ast::ExprBlock(ref b) => { check_block_with_expected(check_env, fcx, &**b, expected); - fcx.write_ty(id, fcx.node_ty(b.id)); + let node_ty = fcx.node_ty(check_env, b.id); + fcx.write_ty(check_env, id, node_ty); } ast::ExprCall(ref callee, ref args) => { callee::check_call(check_env, fcx, expr, &**callee, &args[..], expected); } ast::ExprMethodCall(ident, ref tps, ref args) => { check_method_call(check_env, fcx, expr, ident, &args[..], &tps[..], expected, lvalue_pref); - let arg_tys = args.iter().map(|a| fcx.expr_ty(&**a)); - let args_err = arg_tys.fold(false, - |rest_err, a| { - rest_err || ty::type_is_error(a)}); + let args_err = { + let arg_tys = args.iter().map(|a| fcx.expr_ty(check_env, &**a)); + arg_tys.fold(false, |rest_err, a| rest_err || ty::type_is_error(a)) + }; if args_err { - fcx.write_error(id); + fcx.write_error(check_env, id); } } ast::ExprCast(ref e, ref t) => { @@ -3408,20 +3474,23 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, // Find the type of `e`. Supply hints based on the type we are casting to, // if appropriate. - let t_1 = fcx.to_ty(t); - let t_1 = structurally_resolved_type(fcx, expr.span, t_1); + let t_1 = { + let typer = FnCtxtTyper::new(check_env, fcx); + typer.to_ty(t) + }; + let t_1 = structurally_resolved_type(check_env, fcx, expr.span, t_1); check_expr_with_expectation(check_env, fcx, e, ExpectCastableToType(t_1)); - let t_e = fcx.expr_ty(e); + let t_e = fcx.expr_ty(check_env, e); // Eagerly check for some obvious errors. if ty::type_is_error(t_e) { - fcx.write_error(id); + fcx.write_error(check_env, id); } else if !fcx.type_is_known_to_be_sized(t_1, expr.span) { - report_cast_to_unsized_type(fcx, expr.span, t.span, e.span, t_1, t_e, id); + report_cast_to_unsized_type(check_env, fcx, expr.span, t.span, e.span, t_1, t_e, id); } else { // Write a type for the whole expression, assuming everything is going // to work out Ok. - fcx.write_ty(id, t_1); + fcx.write_ty(check_env, id, t_1); // Defer other checks until we're done type checking. let cast_check = cast::CastCheck::new((**e).clone(), t_e, t_1, expr.span); @@ -3452,7 +3521,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, } }; let typ = ty::mk_vec(tcx, typ, Some(args.len())); - fcx.write_ty(id, typ); + fcx.write_ty(check_env, id, typ); } ast::ExprRepeat(ref element, ref count_expr) => { check_expr_has_type(check_env, fcx, &**count_expr, tcx.types.usize); @@ -3476,7 +3545,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, None => { let t: Ty = fcx.infcx().next_ty_var(); check_expr_has_type(check_env, fcx, &**element, t); - (fcx.expr_ty(&**element), t) + (fcx.expr_ty(check_env, &**element), t) } }; @@ -3491,10 +3560,10 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, } if ty::type_is_error(element_ty) { - fcx.write_error(id); + fcx.write_error(check_env, id); } else { let t = ty::mk_vec(tcx, t, Some(count)); - fcx.write_ty(id, t); + fcx.write_ty(check_env, id, t); } } ast::ExprTup(ref elts) => { @@ -3515,17 +3584,17 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, } _ => { check_expr_with_expectation(check_env, fcx, &**e, NoExpectation); - fcx.expr_ty(&**e) + fcx.expr_ty(check_env, &**e) } }; err_field = err_field || ty::type_is_error(t); t }).collect(); if err_field { - fcx.write_error(id); + fcx.write_error(check_env, id); } else { let typ = ty::mk_tup(tcx, elt_ts); - fcx.write_ty(id, typ); + fcx.write_ty(check_env, id, typ); } } ast::ExprStruct(ref path, ref fields, ref base_expr) => { @@ -3580,9 +3649,10 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, // Turn the path into a type and verify that that type unifies with // the resulting structure type. This is needed to handle type // parameters correctly. - let actual_structure_type = fcx.expr_ty(&*expr); + let actual_structure_type = fcx.expr_ty(check_env, &*expr); if !ty::type_is_error(actual_structure_type) { - let type_and_substs = fcx.instantiate_struct_literal_ty(struct_id, path); + let typer = FnCtxtTyper::new(check_env, fcx); + let type_and_substs = typer.instantiate_struct_literal_ty(struct_id, path); match fcx.mk_subty(false, infer::Misc(path.span), actual_structure_type, @@ -3606,7 +3676,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, } } - fcx.require_expr_have_sized_type(expr, traits::StructInitializerSized); + fcx.require_expr_have_sized_type(check_env, expr, traits::StructInitializerSized); } ast::ExprField(ref base, ref field) => { check_field(check_env, fcx, expr, lvalue_pref, &**base, field); @@ -3618,20 +3688,20 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, check_expr_with_lvalue_pref(check_env, fcx, &**base, lvalue_pref); check_expr(check_env, fcx, &**idx); - let base_t = fcx.expr_ty(&**base); - let idx_t = fcx.expr_ty(&**idx); + let base_t = fcx.expr_ty(check_env, &**base); + let idx_t = fcx.expr_ty(check_env, &**idx); if ty::type_is_error(base_t) { - fcx.write_ty(id, base_t); + fcx.write_ty(check_env, id, base_t); } else if ty::type_is_error(idx_t) { - fcx.write_ty(id, idx_t); + fcx.write_ty(check_env, id, idx_t); } else { - let base_t = structurally_resolved_type(fcx, expr.span, base_t); - match lookup_indexing(fcx, expr, base, base_t, idx_t, lvalue_pref) { + let base_t = structurally_resolved_type(check_env, fcx, expr.span, base_t); + match lookup_indexing(check_env, fcx, expr, base, base_t, idx_t, lvalue_pref) { Some((index_ty, element_ty)) => { - let idx_expr_ty = fcx.expr_ty(idx); + let idx_expr_ty = fcx.expr_ty(check_env, idx); demand::eqtype(fcx, expr.span, index_ty, idx_expr_ty); - fcx.write_ty(id, element_ty); + fcx.write_ty(check_env, id, element_ty); } None => { check_expr_has_type(check_env, fcx, &**idx, fcx.tcx().types.err); @@ -3643,7 +3713,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, }, base_t, None); - fcx.write_ty(id, fcx.tcx().types.err); + fcx.write_ty(check_env, id, fcx.tcx().types.err); } } } @@ -3651,11 +3721,11 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, ast::ExprRange(ref start, ref end) => { let t_start = start.as_ref().map(|e| { check_expr(check_env, fcx, &**e); - fcx.expr_ty(&**e) + fcx.expr_ty(check_env, &**e) }); let t_end = end.as_ref().map(|e| { check_expr(check_env, fcx, &**e); - fcx.expr_ty(&**e) + fcx.expr_ty(check_env, &**e) }); let idx_type = match (t_start, t_end) { @@ -3698,7 +3768,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, if let Some(did) = did { let predicates = ty::lookup_predicates(tcx, did); let substs = Substs::new_type(vec![idx_type], vec![]); - let bounds = fcx.instantiate_bounds(expr.span, &substs, &predicates); + let typer = FnCtxtTyper::new(check_env, fcx); + let bounds = typer.instantiate_bounds(expr.span, &substs, &predicates); fcx.add_obligations_for_parameters( traits::ObligationCause::new(expr.span, fcx.body_id, @@ -3723,7 +3794,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, } }; - fcx.write_ty(id, range_type); + fcx.write_ty(check_env, id, range_type); } } @@ -3731,13 +3802,14 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, debug!("type of expr({}) {} is...", expr.id, syntax::print::pprust::expr_to_string(expr)); debug!("... {}, expected is {}", - ppaux::ty_to_string(tcx, fcx.expr_ty(expr)), + ppaux::ty_to_string(tcx, fcx.expr_ty(check_env, expr)), expected.repr(tcx)); - unifier(); + unifier(check_env); } -pub fn resolve_ty_and_def_ufcs<'a, 'b, 'tcx>(fcx: &FnCtxt<'b, 'tcx>, +pub fn resolve_ty_and_def_ufcs<'a, 'b, 'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'b, 'tcx>, path_res: def::PathResolution, opt_self_ty: Option>, path: &'a ast::Path, @@ -3754,15 +3826,18 @@ pub fn resolve_ty_and_def_ufcs<'a, 'b, 'tcx>(fcx: &FnCtxt<'b, 'tcx>, let mut def = path_res.base_def; let ty_segments = path.segments.init(); let base_ty_end = path.segments.len() - path_res.depth; - let ty = astconv::finish_resolving_def_to_ty(fcx, fcx, span, - PathParamMode::Optional, - &mut def, - opt_self_ty, - &ty_segments[..base_ty_end], - &ty_segments[base_ty_end..]); + let ty = { + let typer = FnCtxtTyper::new(check_env, fcx); + astconv::finish_resolving_def_to_ty(&typer, fcx, span, + PathParamMode::Optional, + &mut def, + opt_self_ty, + &ty_segments[..base_ty_end], + &ty_segments[base_ty_end..]) + }; let item_segment = path.segments.last().unwrap(); let item_name = item_segment.identifier.name; - match method::resolve_ufcs(fcx, span, item_name, ty, node_id) { + match method::resolve_ufcs(check_env, fcx, span, item_name, ty, node_id) { Ok((def, lp)) => { // Write back the new resolution. fcx.ccx.tcx.def_map.borrow_mut() @@ -3774,9 +3849,9 @@ pub fn resolve_ty_and_def_ufcs<'a, 'b, 'tcx>(fcx: &FnCtxt<'b, 'tcx>, Some((Some(ty), slice::ref_slice(item_segment), def)) } Err(error) => { - method::report_error(fcx, span, ty, + method::report_error(check_env, fcx, span, ty, item_name, None, error); - fcx.write_error(node_id); + fcx.write_error(check_env, node_id); None } } @@ -3823,7 +3898,8 @@ impl<'tcx> Expectation<'tcx> { // 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<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Expectation<'tcx> { + fn resolve<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Expectation<'tcx> + { match self { NoExpectation => { NoExpectation @@ -3894,7 +3970,7 @@ fn check_decl_initializer<'a,'tcx>(check_env: &mut CheckEnv<'tcx>, // type of the lvalue it is referencing, and not some // supertype thereof. check_expr(check_env, fcx, init); - let init_ty = fcx.expr_ty(init); + let init_ty = fcx.expr_ty(check_env, init); demand::eqtype(fcx, init.span, init_ty, local_ty); }; } @@ -3904,13 +3980,13 @@ fn check_decl_local<'a,'tcx>(check_env: &mut CheckEnv<'tcx>, let tcx = fcx.ccx.tcx; let t = fcx.local_ty(local.span, local.id); - fcx.write_ty(local.id, t); + fcx.write_ty(check_env, local.id, t); if let Some(ref init) = local.init { check_decl_initializer(check_env, fcx, local, &**init); - let init_ty = fcx.expr_ty(&**init); + let init_ty = fcx.expr_ty(check_env, &**init); if ty::type_is_error(init_ty) { - fcx.write_ty(local.id, init_ty); + fcx.write_ty(check_env, local.id, init_ty); } } @@ -3919,9 +3995,9 @@ fn check_decl_local<'a,'tcx>(check_env: &mut CheckEnv<'tcx>, map: pat_id_map(&tcx.def_map, &*local.pat), }; _match::check_pat(check_env, &pcx, &*local.pat, t); - let pat_ty = fcx.node_ty(local.pat.id); + let pat_ty = fcx.node_ty(check_env, local.pat.id); if ty::type_is_error(pat_ty) { - fcx.write_ty(local.id, pat_ty); + fcx.write_ty(check_env, local.id, pat_ty); } } @@ -3936,7 +4012,7 @@ fn check_stmt<'a,'tcx>(check_env: &mut CheckEnv<'tcx>, match decl.node { ast::DeclLocal(ref l) => { check_decl_local(check_env, fcx, &**l); - let l_t = fcx.node_ty(l.id); + let l_t = fcx.node_ty(check_env, l.id); saw_bot = saw_bot || fcx.infcx().type_var_diverges(l_t); saw_err = saw_err || ty::type_is_error(l_t); } @@ -3947,36 +4023,36 @@ fn check_stmt<'a,'tcx>(check_env: &mut CheckEnv<'tcx>, node_id = id; // Check with expected type of () check_expr_has_type(check_env, fcx, &**expr, ty::mk_nil(fcx.tcx())); - let expr_ty = fcx.expr_ty(&**expr); + let expr_ty = fcx.expr_ty(check_env, &**expr); saw_bot = saw_bot || fcx.infcx().type_var_diverges(expr_ty); saw_err = saw_err || ty::type_is_error(expr_ty); } ast::StmtSemi(ref expr, id) => { node_id = id; check_expr(check_env, fcx, &**expr); - let expr_ty = fcx.expr_ty(&**expr); + let expr_ty = fcx.expr_ty(check_env, &**expr); saw_bot |= fcx.infcx().type_var_diverges(expr_ty); saw_err |= ty::type_is_error(expr_ty); } ast::StmtMac(..) => fcx.ccx.tcx.sess.bug("unexpanded macro") } if saw_bot { - fcx.write_ty(node_id, fcx.infcx().next_diverging_ty_var()); + fcx.write_ty(check_env, node_id, fcx.infcx().next_diverging_ty_var()); } else if saw_err { - fcx.write_error(node_id); + fcx.write_error(check_env, node_id); } else { - fcx.write_nil(node_id) + fcx.write_nil(check_env, node_id) } } fn check_block_no_value<'a,'tcx>(check_env: &mut CheckEnv<'tcx>, fcx: &FnCtxt<'a,'tcx>, blk: &'tcx ast::Block) { check_block_with_expected(check_env, fcx, blk, ExpectHasType(ty::mk_nil(fcx.tcx()))); - let blkty = fcx.node_ty(blk.id); + let blkty = fcx.node_ty(check_env, blk.id); if ty::type_is_error(blkty) { - fcx.write_error(blk.id); + fcx.write_error(check_env, blk.id); } else { let nilty = ty::mk_nil(fcx.tcx()); demand::suptype(fcx, blk.span, nilty, blkty); @@ -3999,7 +4075,7 @@ fn check_block_with_expected<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, for s in &blk.stmts { check_stmt(check_env, fcx, &**s); let s_id = ast_util::stmt_id(&**s); - let s_ty = fcx.node_ty(s_id); + let s_ty = fcx.node_ty(check_env, s_id); if any_diverges && !warned && match s.node { ast::StmtDecl(ref decl, _) => { match decl.node { @@ -4024,11 +4100,11 @@ fn check_block_with_expected<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, } match blk.expr { None => if any_err { - fcx.write_error(blk.id); + fcx.write_error(check_env, blk.id); } else if any_diverges { - fcx.write_ty(blk.id, fcx.infcx().next_diverging_ty_var()); + fcx.write_ty(check_env, blk.id, fcx.infcx().next_diverging_ty_var()); } else { - fcx.write_nil(blk.id); + fcx.write_nil(check_env, blk.id); }, Some(ref e) => { if any_diverges && !warned { @@ -4047,16 +4123,16 @@ fn check_block_with_expected<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, } _ => { check_expr_with_expectation(check_env, fcx, &**e, expected); - fcx.expr_ty(&**e) + fcx.expr_ty(check_env, &**e) } }; if any_err { - fcx.write_error(blk.id); + fcx.write_error(check_env, blk.id); } else if any_diverges { - fcx.write_ty(blk.id, fcx.infcx().next_diverging_ty_var()); + fcx.write_ty(check_env, blk.id, fcx.infcx().next_diverging_ty_var()); } else { - fcx.write_ty(blk.id, ety); + fcx.write_ty(check_env, blk.id, ety); } } }; @@ -4098,11 +4174,11 @@ fn check_const_with_ty<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, GatherLocalsVisitor { check_env: check_env, fcx: fcx }.visit_expr(e); check_expr_with_hint(check_env, fcx, e, declty); - demand::coerce(fcx, e.span, declty, e); + demand::coerce(check_env, fcx, e.span, declty, e); vtable::select_all_fcx_obligations_or_error(check_env, fcx); check_env.check_casts(fcx); regionck::regionck_expr(check_env, fcx, e); - writeback::resolve_type_vars_in_expr(fcx, e); + writeback::resolve_type_vars_in_expr(check_env, fcx, e); } /// Checks whether a type can be represented in memory. In particular, it @@ -4338,7 +4414,8 @@ fn type_scheme_and_predicates_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, // Instantiates the given path, which must refer to an item with the given // number of type parameters and type. -pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, +pub fn instantiate_path<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a, 'tcx>, segments: &[ast::PathSegment], type_scheme: TypeScheme<'tcx>, type_predicates: &ty::GenericPredicates<'tcx>, @@ -4527,7 +4604,8 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, } Some(space) => { - push_explicit_parameters_from_segment_to_substs(fcx, + push_explicit_parameters_from_segment_to_substs(check_env, + fcx, space, span, type_defs, @@ -4565,15 +4643,17 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, // Add all the obligations that are required, substituting and // normalized appropriately. - let bounds = fcx.instantiate_bounds(span, &substs, &type_predicates); - fcx.add_obligations_for_parameters( + let ty_substituted = { + let typer = FnCtxtTyper::new(check_env, fcx); + let bounds = typer.instantiate_bounds(span, &substs, &type_predicates); + fcx.add_obligations_for_parameters( traits::ObligationCause::new(span, fcx.body_id, traits::ItemObligation(def.def_id())), &bounds); // Substitute the values for the type parameters into the type of // the referenced item. - let ty_substituted = fcx.instantiate_type_scheme(span, &substs, &type_scheme.ty); - + typer.instantiate_type_scheme(span, &substs, &type_scheme.ty) + }; if let Some((def::FromImpl(impl_def_id), self_ty)) = ufcs_method { // In the case of `Foo::method` and `>::method`, if `method` @@ -4586,7 +4666,8 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, assert_eq!(substs.regions().len(subst::TypeSpace), impl_scheme.generics.regions.len(subst::TypeSpace)); - let impl_ty = fcx.instantiate_type_scheme(span, &substs, &impl_scheme.ty); + let typer = FnCtxtTyper::new(check_env, fcx); + let impl_ty = typer.instantiate_type_scheme(span, &substs, &impl_scheme.ty); if fcx.mk_subty(false, infer::Misc(span), self_ty, impl_ty).is_err() { fcx.tcx().sess.span_bug(span, &format!( @@ -4596,7 +4677,7 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, } } - fcx.write_ty(node_id, ty_substituted); + fcx.write_ty(check_env, node_id, ty_substituted); fcx.write_substs(node_id, ty::ItemSubsts { substs: substs }); return; @@ -4610,6 +4691,7 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, /// etc that is more complicated. I wanted however to do the reporting of *too many* parameters /// here because we can easily use the precise span of the N+1'th parameter. fn push_explicit_parameters_from_segment_to_substs<'a, 'tcx>( + check_env: &mut CheckEnv<'tcx>, fcx: &FnCtxt<'a, 'tcx>, space: subst::ParamSpace, span: Span, @@ -4621,19 +4703,20 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, match segment.parameters { ast::AngleBracketedParameters(ref data) => { push_explicit_angle_bracketed_parameters_from_segment_to_substs( - fcx, space, type_defs, region_defs, data, substs); + check_env, fcx, space, type_defs, region_defs, data, substs); } ast::ParenthesizedParameters(ref data) => { span_err!(fcx.tcx().sess, span, E0238, "parenthesized parameters may only be used with a trait"); push_explicit_parenthesized_parameters_from_segment_to_substs( - fcx, space, span, type_defs, data, substs); + check_env, fcx, space, span, type_defs, data, substs); } } } fn push_explicit_angle_bracketed_parameters_from_segment_to_substs<'a, 'tcx>( + check_env: &mut CheckEnv<'tcx>, fcx: &FnCtxt<'a, 'tcx>, space: subst::ParamSpace, type_defs: &VecPerParamSpace>, @@ -4645,7 +4728,8 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, let type_count = type_defs.len(space); assert_eq!(substs.types.len(space), 0); for (i, typ) in data.types.iter().enumerate() { - let t = fcx.to_ty(&**typ); + let typer = FnCtxtTyper::new(check_env, fcx); + let t = typer.to_ty(&**typ); if i < type_count { substs.types.push(space, t); } else if i == type_count { @@ -4693,6 +4777,7 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, /// difference has to do with the treatment of anonymous /// regions, which are translated into bound regions (NYI). fn push_explicit_parenthesized_parameters_from_segment_to_substs<'a, 'tcx>( + check_env: &mut CheckEnv<'tcx>, fcx: &FnCtxt<'a, 'tcx>, space: subst::ParamSpace, span: Span, @@ -4708,8 +4793,9 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, type_count); } + let typer = FnCtxtTyper::new(check_env, fcx); let input_tys: Vec = - data.inputs.iter().map(|ty| fcx.to_ty(&**ty)).collect(); + data.inputs.iter().map(|ty| typer.to_ty(&**ty)).collect(); let tuple_ty = ty::mk_tup(fcx.tcx(), input_tys); @@ -4719,7 +4805,7 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, } let output_ty: Option = - data.output.as_ref().map(|ty| fcx.to_ty(&**ty)); + data.output.as_ref().map(|ty| typer.to_ty(&**ty)); let output_ty = output_ty.unwrap_or(ty::mk_nil(fcx.tcx())); @@ -4831,13 +4917,14 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, } } -fn structurally_resolve_type_or_else<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, +fn structurally_resolve_type_or_else<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a, 'tcx>, sp: Span, ty: Ty<'tcx>, f: F) -> Ty<'tcx> where F: Fn() -> Ty<'tcx> { - let mut ty = fcx.resolve_type_vars_if_possible(ty); + let mut ty = fcx.resolve_type_vars_if_possible(check_env, ty); if ty::type_is_ty_var(ty) { let alternative = f(); @@ -4860,12 +4947,13 @@ fn structurally_resolve_type_or_else<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, // 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<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, +pub fn structurally_resolved_type<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a, 'tcx>, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> { - structurally_resolve_type_or_else(fcx, sp, ty, || { + structurally_resolve_type_or_else(check_env, fcx, sp, ty, || { fcx.tcx().types.err }) } diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index d8f78d0588f78..e7be6afb6ffa6 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -41,12 +41,14 @@ pub fn check_binop_assign<'a,'tcx>(check_env: &mut CheckEnv<'tcx>, check_expr_with_lvalue_pref(check_env, fcx, lhs_expr, PreferMutLvalue); check_expr(check_env, fcx, rhs_expr); - let lhs_ty = structurally_resolved_type(fcx, lhs_expr.span, fcx.expr_ty(lhs_expr)); - let rhs_ty = structurally_resolved_type(fcx, rhs_expr.span, fcx.expr_ty(rhs_expr)); + let expr_ty = fcx.expr_ty(check_env, lhs_expr); + let lhs_ty = structurally_resolved_type(check_env, fcx, lhs_expr.span, expr_ty); + let expr_ty = fcx.expr_ty(check_env, rhs_expr); + let rhs_ty = structurally_resolved_type(check_env, fcx, rhs_expr.span, expr_ty); if is_builtin_binop(fcx.tcx(), lhs_ty, rhs_ty, op) { enforce_builtin_binop_types(fcx, lhs_expr, lhs_ty, rhs_expr, rhs_ty, op); - fcx.write_nil(expr.id); + fcx.write_nil(check_env, expr.id); } else { // error types are considered "builtin" assert!(!ty::type_is_error(lhs_ty) || !ty::type_is_error(rhs_ty)); @@ -55,7 +57,7 @@ pub fn check_binop_assign<'a,'tcx>(check_env: &mut CheckEnv<'tcx>, ast_util::binop_to_string(op.node), lhs_ty.user_string(fcx.tcx()), rhs_ty.user_string(fcx.tcx())); - fcx.write_error(expr.id); + fcx.write_error(check_env, expr.id); } let tcx = fcx.tcx(); @@ -63,7 +65,7 @@ pub fn check_binop_assign<'a,'tcx>(check_env: &mut CheckEnv<'tcx>, span_err!(tcx.sess, lhs_expr.span, E0067, "illegal left-hand side expression"); } - fcx.require_expr_have_sized_type(lhs_expr, traits::AssignmentLhsSized); + fcx.require_expr_have_sized_type(check_env, lhs_expr, traits::AssignmentLhsSized); } /// Check a potentially overloaded binary operator. @@ -84,7 +86,7 @@ pub fn check_binop<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, rhs_expr.repr(tcx)); check_expr(check_env, fcx, lhs_expr); - let lhs_ty = fcx.resolve_type_vars_if_possible(fcx.expr_ty(lhs_expr)); + let lhs_ty = fcx.resolve_type_vars_if_possible(check_env, fcx.expr_ty(check_env, lhs_expr)); // Annoyingly, SIMD ops don't fit into the PartialEq/PartialOrd // traits, because their return type is not bool. Perhaps this @@ -92,9 +94,9 @@ pub fn check_binop<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, // different path that bypassess all traits. if ty::type_is_simd(fcx.tcx(), lhs_ty) { check_expr_coercable_to_type(check_env, fcx, rhs_expr, lhs_ty); - let rhs_ty = fcx.resolve_type_vars_if_possible(fcx.expr_ty(lhs_expr)); + let rhs_ty = fcx.resolve_type_vars_if_possible(check_env, fcx.expr_ty(check_env, lhs_expr)); let return_ty = enforce_builtin_binop_types(fcx, lhs_expr, lhs_ty, rhs_expr, rhs_ty, op); - fcx.write_ty(expr.id, return_ty); + fcx.write_ty(check_env, expr.id, return_ty); return; } @@ -103,7 +105,7 @@ pub fn check_binop<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, // && and || are a simple case. demand::suptype(fcx, lhs_expr.span, ty::mk_bool(tcx), lhs_ty); check_expr_coercable_to_type(check_env, fcx, rhs_expr, ty::mk_bool(tcx)); - fcx.write_ty(expr.id, ty::mk_bool(tcx)); + fcx.write_ty(check_env, expr.id, ty::mk_bool(tcx)); } _ => { // Otherwise, we always treat operators as if they are @@ -124,7 +126,7 @@ pub fn check_binop<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, // deduce that the result type should be `u32`, even // though we don't know yet what type 2 has and hence // can't pin this down to a specific impl. - let rhs_ty = fcx.resolve_type_vars_if_possible(rhs_ty); + let rhs_ty = fcx.resolve_type_vars_if_possible(check_env, rhs_ty); if !ty::type_is_ty_var(lhs_ty) && !ty::type_is_ty_var(rhs_ty) && @@ -135,7 +137,7 @@ pub fn check_binop<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, demand::suptype(fcx, expr.span, builtin_return_ty, return_ty); } - fcx.write_ty(expr.id, return_ty); + fcx.write_ty(check_env, expr.id, return_ty); } } } @@ -227,7 +229,8 @@ fn check_overloaded_binop<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, // particularly for things like `String + &String`. let rhs_ty_var = fcx.infcx().next_ty_var(); - let return_ty = match lookup_op_method(fcx, expr, lhs_ty, vec![rhs_ty_var], + let return_ty = match lookup_op_method(check_env, fcx, + expr, lhs_ty, vec![rhs_ty_var], token::intern(name), trait_def_id, lhs_expr) { Ok(return_ty) => return_ty, @@ -249,7 +252,8 @@ fn check_overloaded_binop<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, (rhs_ty_var, return_ty) } -pub fn check_user_unop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, +pub fn check_user_unop<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a, 'tcx>, op_str: &str, mname: &str, trait_did: Option, @@ -260,7 +264,8 @@ pub fn check_user_unop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, -> Ty<'tcx> { assert!(ast_util::is_by_value_unop(op)); - match lookup_op_method(fcx, ex, operand_ty, vec![], + match lookup_op_method(check_env, fcx, + ex, operand_ty, vec![], token::intern(mname), trait_did, operand_expr) { Ok(t) => t, @@ -299,7 +304,8 @@ fn name_and_trait_def_id(fcx: &FnCtxt, op: ast::BinOp) -> (&'static str, Option< } } -fn lookup_op_method<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>, +fn lookup_op_method<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &'a FnCtxt<'a, 'tcx>, expr: &'tcx ast::Expr, lhs_ty: Ty<'tcx>, other_tys: Vec>, @@ -317,7 +323,8 @@ fn lookup_op_method<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>, let method = match trait_did { Some(trait_did) => { - method::lookup_in_trait_adjusted(fcx, + method::lookup_in_trait_adjusted(check_env, + fcx, expr.span, Some(lhs_expr), opname, diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 1750828b4934c..f30abb5e95070 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -86,6 +86,7 @@ use astconv::AstConv; use super::dropck; use super::CheckEnv; use super::FnCtxt; +use super::FnCtxtTyper; use super::vtable; use middle::free_region::FreeRegionMap; use middle::implicator; @@ -237,7 +238,8 @@ fn resolve_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, unresolved_ty: Ty<'tcx>) -> Ty /// is well-formed. /// /// Tests: `src/test/compile-fail/regions-free-region-ordering-*.rs` -fn relate_free_regions<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, +fn relate_free_regions<'a, 'tcx>(check_env: &CheckEnv<'tcx>, + fcx: &FnCtxt<'a, 'tcx>, tcx: &ty::ctxt<'tcx>, free_region_map: &mut FreeRegionMap, region_bound_pairs: &mut Vec<(ty::Region, GenericKind<'tcx>)>, @@ -251,7 +253,8 @@ fn relate_free_regions<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, debug!("relate_free_regions(t={})", ty.repr(tcx)); let body_scope = CodeExtent::from_node_id(body_id); let body_scope = ty::ReScope(body_scope); - let implications = implicator::implications(fcx.infcx(), fcx, body_id, + let typer = FnCtxtTyper::new(check_env, fcx); + let implications = implicator::implications(fcx.infcx(), &typer, body_id, ty, body_scope, span); // Record any relations between free regions that we observe into the free-region-map. @@ -325,7 +328,7 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> { /// Try to resolve the type for the given node. fn resolve_node_type(&self, id: ast::NodeId) -> Ty<'tcx> { - let t = self.fcx.node_ty(id); + let t = self.fcx.node_ty(self.check_env, id); resolve_type(self.fcx, t) } @@ -364,7 +367,7 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> { match self.check_env.fn_sig_map.get(&id) { Some(fn_sig) => { - relate_free_regions(self.fcx, self.tcx(), + relate_free_regions(self.check_env, self.fcx, self.tcx(), &mut self.free_region_map, &mut self.region_bound_pairs, &fn_sig[..], body.id, span); }, @@ -564,7 +567,8 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) { // If necessary, constrain destructors in the unadjusted form of this // expression. let cmt_result = { - let mc = mc::MemCategorizationContext::new(rcx.fcx); + let typer = FnCtxtTyper::new(rcx.check_env, rcx.fcx); + let mc = mc::MemCategorizationContext::new(&typer); mc.cat_expr_unadjusted(expr) }; match cmt_result { @@ -583,7 +587,8 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) { // If necessary, constrain destructors in this expression. This will be // the adjusted form if there is an adjustment. let cmt_result = { - let mc = mc::MemCategorizationContext::new(rcx.fcx); + let typer = FnCtxtTyper::new(rcx.check_env, rcx.fcx); + let mc = mc::MemCategorizationContext::new(&typer); mc.cat_expr(expr) }; match cmt_result { @@ -926,7 +931,8 @@ fn constrain_autoderefs<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>, r.repr(rcx.tcx()), m); { - let mc = mc::MemCategorizationContext::new(rcx.fcx); + let typer = FnCtxtTyper::new(rcx.check_env, rcx.fcx); + let mc = mc::MemCategorizationContext::new(&typer); let self_cmt = ignore_err!(mc.cat_expr_autoderefd(deref_expr, i)); debug!("constrain_autoderefs: self_cmt={:?}", self_cmt.repr(rcx.tcx())); @@ -1051,7 +1057,8 @@ fn link_addr_of(rcx: &mut Rcx, expr: &ast::Expr, debug!("link_addr_of(expr={}, base={})", expr.repr(rcx.tcx()), base.repr(rcx.tcx())); let cmt = { - let mc = mc::MemCategorizationContext::new(rcx.fcx); + let typer = FnCtxtTyper::new(rcx.check_env, rcx.fcx); + let mc = mc::MemCategorizationContext::new(&typer); ignore_err!(mc.cat_expr(base)) }; @@ -1069,7 +1076,8 @@ fn link_local(rcx: &Rcx, local: &ast::Local) { None => { return; } Some(ref expr) => &**expr, }; - let mc = mc::MemCategorizationContext::new(rcx.fcx); + let typer = FnCtxtTyper::new(rcx.check_env, rcx.fcx); + let mc = mc::MemCategorizationContext::new(&typer); let discr_cmt = ignore_err!(mc.cat_expr(init_expr)); link_pattern(rcx, mc, discr_cmt, &*local.pat); } @@ -1079,7 +1087,8 @@ fn link_local(rcx: &Rcx, local: &ast::Local) { /// linked to the lifetime of its guarantor (if any). fn link_match(rcx: &Rcx, discr: &ast::Expr, arms: &[ast::Arm]) { debug!("regionck::for_match()"); - let mc = mc::MemCategorizationContext::new(rcx.fcx); + let typer = FnCtxtTyper::new(rcx.check_env, rcx.fcx); + let mc = mc::MemCategorizationContext::new(&typer); let discr_cmt = ignore_err!(mc.cat_expr(discr)); debug!("discr_cmt={}", discr_cmt.repr(rcx.tcx())); for arm in arms { @@ -1094,9 +1103,10 @@ fn link_match(rcx: &Rcx, discr: &ast::Expr, arms: &[ast::Arm]) { /// linked to the lifetime of its guarantor (if any). fn link_fn_args(rcx: &Rcx, body_scope: CodeExtent, args: &[ast::Arg]) { debug!("regionck::link_fn_args(body_scope={:?})", body_scope); - let mc = mc::MemCategorizationContext::new(rcx.fcx); + let typer = FnCtxtTyper::new(rcx.check_env, rcx.fcx); + let mc = mc::MemCategorizationContext::new(&typer); for arg in args { - let arg_ty = rcx.fcx.node_ty(arg.id); + let arg_ty = rcx.fcx.node_ty(rcx.check_env, arg.id); let re_scope = ty::ReScope(body_scope); let arg_cmt = mc.cat_rvalue(arg.id, arg.ty.span, re_scope, arg_ty); debug!("arg_ty={} arg_cmt={}", @@ -1109,7 +1119,7 @@ fn link_fn_args(rcx: &Rcx, body_scope: CodeExtent, args: &[ast::Arg]) { /// Link lifetimes of any ref bindings in `root_pat` to the pointers found in the discriminant, if /// needed. fn link_pattern<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>, - mc: mc::MemCategorizationContext>, + mc: mc::MemCategorizationContext>, discr_cmt: mc::cmt<'tcx>, root_pat: &ast::Pat) { debug!("link_pattern(discr_cmt={}, root_pat={})", @@ -1148,7 +1158,8 @@ fn link_autoref(rcx: &Rcx, autoref: &ty::AutoRef) { debug!("link_autoref(autoref={:?})", autoref); - let mc = mc::MemCategorizationContext::new(rcx.fcx); + let typer = FnCtxtTyper::new(rcx.check_env, rcx.fcx); + let mc = mc::MemCategorizationContext::new(&typer); let expr_cmt = ignore_err!(mc.cat_expr_autoderefd(expr, autoderefs)); debug!("expr_cmt={}", expr_cmt.repr(rcx.tcx())); @@ -1173,7 +1184,8 @@ fn link_by_ref(rcx: &Rcx, let tcx = rcx.tcx(); debug!("link_by_ref(expr={}, callee_scope={:?})", expr.repr(tcx), callee_scope); - let mc = mc::MemCategorizationContext::new(rcx.fcx); + let typer = FnCtxtTyper::new(rcx.check_env, rcx.fcx); + let mc = mc::MemCategorizationContext::new(&typer); let expr_cmt = ignore_err!(mc.cat_expr(expr)); let borrow_region = ty::ReScope(callee_scope); link_region(rcx, expr.span, &borrow_region, ty::ImmBorrow, expr_cmt); @@ -1419,8 +1431,11 @@ pub fn type_must_outlive<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>, ty.repr(rcx.tcx()), region.repr(rcx.tcx())); - let implications = implicator::implications(rcx.fcx.infcx(), rcx.fcx, rcx.body_id, - ty, region, origin.span()); + let implications = { + let typer = FnCtxtTyper::new(rcx.check_env, rcx.fcx); + implicator::implications(rcx.fcx.infcx(), &typer, rcx.body_id, + ty, region, origin.span()) + }; for implication in implications { debug!("implication: {}", implication.repr(rcx.tcx())); match implication { @@ -1460,7 +1475,10 @@ fn closure_must_outlive<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>, debug!("closure_must_outlive(region={}, def_id={}, substs={})", region.repr(rcx.tcx()), def_id.repr(rcx.tcx()), substs.repr(rcx.tcx())); - let upvars = rcx.fcx.closure_upvars(def_id, substs).unwrap(); + let upvars = { + let typer = FnCtxtTyper::new(rcx.check_env, rcx.fcx); + typer.closure_upvars(def_id, substs).unwrap() + }; for upvar in upvars { let var_id = upvar.def.def_id().local_id(); type_must_outlive( @@ -1564,9 +1582,10 @@ fn projection_bounds<'a,'tcx>(rcx: &Rcx<'a, 'tcx>, outlives.repr(tcx)); // apply the substitutions (and normalize any projected types) - let outlives = fcx.instantiate_type_scheme(span, - projection_ty.trait_ref.substs, - &outlives); + let typer = FnCtxtTyper::new(rcx.check_env, fcx); + let outlives = typer.instantiate_type_scheme(span, + projection_ty.trait_ref.substs, + &outlives); debug!("projection_bounds: outlives={} (2)", outlives.repr(tcx)); diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs index 1c47419e9838a..d873a09072b18 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -40,7 +40,7 @@ //! then mean that all later passes would have to check for these figments //! and report an error, and it just seems like more mess in the end.) -use super::{CheckEnv, FnCtxt}; +use super::{CheckEnv, FnCtxt, FnCtxtTyper}; use middle::expr_use_visitor as euv; use middle::mem_categorization as mc; @@ -173,83 +173,15 @@ struct AdjustBorrowKind<'a,'tcx:'a> { closures_with_inferred_kinds: &'a HashSet, } -impl<'a,'tcx> AdjustBorrowKind<'a,'tcx> { - fn new(check_env: &'a mut CheckEnv<'tcx>, - fcx: &'a FnCtxt<'a,'tcx>, - closures_with_inferred_kinds: &'a HashSet) - -> AdjustBorrowKind<'a,'tcx> { - AdjustBorrowKind { - check_env: check_env, - fcx: fcx, - closures_with_inferred_kinds: closures_with_inferred_kinds, - } - } +struct AdjustBorrowDelegate<'a,'tcx:'a> { + fcx: &'a FnCtxt<'a,'tcx>, + closures_with_inferred_kinds: &'a HashSet, +} +impl<'a,'tcx> AdjustBorrowDelegate<'a,'tcx> { fn tcx(&self) -> &'a ty::ctxt<'tcx> { self.fcx.tcx() } - - fn analyze_closure(&mut self, id: ast::NodeId, decl: &ast::FnDecl, body: &ast::Block) { - /*! - * Analysis starting point. - */ - - self.visit_block(body); - - debug!("analyzing closure `{}` with fn body id `{}`", id, body.id); - - { - let mut euv = euv::ExprUseVisitor::new(self, self.fcx); - euv.walk_fn(decl, body); - } - - // If we had not yet settled on a closure kind for this closure, - // then we should have by now. Process and remove any deferred resolutions. - // - // Interesting fact: all calls to this closure must come - // *after* its definition. Initially, I thought that some - // kind of fixed-point iteration would be required, due to the - // possibility of twisted examples like this one: - // - // ```rust - // let mut closure0 = None; - // let vec = vec!(1, 2, 3); - // - // loop { - // { - // let closure1 = || { - // match closure0.take() { - // Some(c) => { - // return c(); // (*) call to `closure0` before it is defined - // } - // None => { } - // } - // }; - // closure1(); - // } - // - // closure0 = || vec; - // } - // ``` - // - // However, this turns out to be wrong. Examples like this - // fail to compile because the type of the variable `c` above - // is an inference variable. And in fact since closure types - // cannot be written, there is no way to make this example - // work without a boxed closure. This implies that we can't - // have two closures that recursively call one another without - // some form of boxing (and hence explicit writing of a - // closure kind) involved. Huzzah. -nmatsakis - let closure_def_id = ast_util::local_def(id); - if self.closures_with_inferred_kinds.contains(&id) { - let mut deferred_call_resolutions = - self.check_env.remove_deferred_call_resolutions(closure_def_id); - for deferred_call_resolution in &mut deferred_call_resolutions { - deferred_call_resolution.resolve(self.fcx); - } - } - } - fn adjust_upvar_borrow_kind_for_consume(&self, cmt: mc::cmt<'tcx>, mode: euv::ConsumeMode) @@ -411,6 +343,7 @@ impl<'a,'tcx> AdjustBorrowKind<'a,'tcx> { } } + /// We infer the borrow_kind with which to borrow upvars in a stack closure. The borrow_kind /// basically follows a lattice of `imm < unique-imm < mut`, moving from left to right as needed /// (but never right to left). Here the argument `mutbl` is the borrow_kind that is required by @@ -480,6 +413,85 @@ impl<'a,'tcx> AdjustBorrowKind<'a,'tcx> { } } +impl<'a,'tcx> AdjustBorrowKind<'a,'tcx> { + fn new(check_env: &'a mut CheckEnv<'tcx>, + fcx: &'a FnCtxt<'a,'tcx>, + closures_with_inferred_kinds: &'a HashSet) + -> AdjustBorrowKind<'a,'tcx> { + AdjustBorrowKind { + check_env: check_env, + fcx: fcx, + closures_with_inferred_kinds: closures_with_inferred_kinds, + } + } + + fn analyze_closure(&mut self, id: ast::NodeId, decl: &ast::FnDecl, body: &ast::Block) { + /*! + * Analysis starting point. + */ + + self.visit_block(body); + + debug!("analyzing closure `{}` with fn body id `{}`", id, body.id); + + { + let mut delegate = AdjustBorrowDelegate { + fcx: self.fcx, + closures_with_inferred_kinds: self.closures_with_inferred_kinds, + }; + let typer = FnCtxtTyper::new(self.check_env, self.fcx); + let mut euv = euv::ExprUseVisitor::new(&mut delegate, &typer); + euv.walk_fn(decl, body); + } + + // If we had not yet settled on a closure kind for this closure, + // then we should have by now. Process and remove any deferred resolutions. + // + // Interesting fact: all calls to this closure must come + // *after* its definition. Initially, I thought that some + // kind of fixed-point iteration would be required, due to the + // possibility of twisted examples like this one: + // + // ```rust + // let mut closure0 = None; + // let vec = vec!(1, 2, 3); + // + // loop { + // { + // let closure1 = || { + // match closure0.take() { + // Some(c) => { + // return c(); // (*) call to `closure0` before it is defined + // } + // None => { } + // } + // }; + // closure1(); + // } + // + // closure0 = || vec; + // } + // ``` + // + // However, this turns out to be wrong. Examples like this + // fail to compile because the type of the variable `c` above + // is an inference variable. And in fact since closure types + // cannot be written, there is no way to make this example + // work without a boxed closure. This implies that we can't + // have two closures that recursively call one another without + // some form of boxing (and hence explicit writing of a + // closure kind) involved. Huzzah. -nmatsakis + let closure_def_id = ast_util::local_def(id); + if self.closures_with_inferred_kinds.contains(&id) { + let mut deferred_call_resolutions = + self.check_env.remove_deferred_call_resolutions(closure_def_id); + for deferred_call_resolution in &mut deferred_call_resolutions { + deferred_call_resolution.resolve(self.check_env, self.fcx); + } + } + } +} + impl<'a, 'tcx, 'v> Visitor<'v> for AdjustBorrowKind<'a, 'tcx> { fn visit_fn(&mut self, fn_kind: visit::FnKind<'v>, @@ -500,7 +512,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for AdjustBorrowKind<'a, 'tcx> { } } -impl<'a,'tcx> euv::Delegate<'tcx> for AdjustBorrowKind<'a,'tcx> { +impl<'a,'tcx> euv::Delegate<'tcx> for AdjustBorrowDelegate<'a,'tcx> { fn consume(&mut self, _consume_id: ast::NodeId, _consume_span: Span, diff --git a/src/librustc_typeck/check/vtable.rs b/src/librustc_typeck/check/vtable.rs index 7ecaf294a6d02..5e3dcbfdc0e5c 100644 --- a/src/librustc_typeck/check/vtable.rs +++ b/src/librustc_typeck/check/vtable.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use super::{CheckEnv, FnCtxt}; +use super::{CheckEnv, FnCtxt, FnCtxtTyper}; use middle::traits::{self, ObjectSafetyViolation, MethodViolationCode}; use middle::traits::{Obligation, ObligationCause}; use middle::traits::report_fulfillment_errors; @@ -134,24 +134,27 @@ pub fn register_object_cast_obligations<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, object_trait_ref } -pub fn select_all_fcx_obligations_and_apply_defaults(fcx: &FnCtxt) { +pub fn select_all_fcx_obligations_and_apply_defaults<'a, 'ctx>(check_env: &mut CheckEnv<'ctx>, + fcx: &FnCtxt<'a, 'ctx>) { debug!("select_all_fcx_obligations_and_apply_defaults"); - select_fcx_obligations_where_possible(fcx); - fcx.default_type_parameters(); - select_fcx_obligations_where_possible(fcx); + select_fcx_obligations_where_possible(check_env, fcx); + fcx.default_type_parameters(check_env); + select_fcx_obligations_where_possible(check_env, fcx); } -pub fn select_all_fcx_obligations_or_error(check_env: &mut CheckEnv, fcx: &FnCtxt) { +pub fn select_all_fcx_obligations_or_error<'a, 'ctx>(check_env: &mut CheckEnv<'ctx>, + fcx: &FnCtxt<'a, 'ctx>) { debug!("select_all_fcx_obligations_or_error"); // upvar inference should have ensured that all deferred call // resolutions are handled by now. assert!(check_env.deferred_call_resolutions.is_empty()); - select_all_fcx_obligations_and_apply_defaults(fcx); + select_all_fcx_obligations_and_apply_defaults(check_env, fcx); let mut fulfillment_cx = fcx.inh.fulfillment_cx.borrow_mut(); - let r = fulfillment_cx.select_all_or_error(fcx.infcx(), fcx); + let typer = FnCtxtTyper::new(check_env, fcx); + let r = fulfillment_cx.select_all_or_error(fcx.infcx(), &typer); match r { Ok(()) => { } Err(errors) => { report_fulfillment_errors(fcx.infcx(), &errors); } @@ -159,12 +162,14 @@ pub fn select_all_fcx_obligations_or_error(check_env: &mut CheckEnv, fcx: &FnCtx } /// Select as many obligations as we can at present. -pub fn select_fcx_obligations_where_possible(fcx: &FnCtxt) +pub fn select_fcx_obligations_where_possible<'a, 'ctx>(check_env: &CheckEnv<'ctx>, + fcx: &FnCtxt<'a, 'ctx>) { + let typer = FnCtxtTyper::new(check_env, fcx); match fcx.inh.fulfillment_cx .borrow_mut() - .select_where_possible(fcx.infcx(), fcx) + .select_where_possible(fcx.infcx(), &typer) { Ok(()) => { } Err(errors) => { report_fulfillment_errors(fcx.infcx(), &errors); } @@ -174,11 +179,14 @@ pub fn select_fcx_obligations_where_possible(fcx: &FnCtxt) /// Try to select any fcx obligation that we haven't tried yet, in an effort to improve inference. /// You could just call `select_fcx_obligations_where_possible` except that it leads to repeated /// work. -pub fn select_new_fcx_obligations(fcx: &FnCtxt) { +pub fn select_new_fcx_obligations<'a, 'ctx>(check_env: &CheckEnv<'ctx>, + fcx: &FnCtxt<'a, 'ctx>) +{ + let typer = FnCtxtTyper::new(check_env, fcx); match fcx.inh.fulfillment_cx .borrow_mut() - .select_new_obligations(fcx.infcx(), fcx) + .select_new_obligations(fcx.infcx(), &typer) { Ok(()) => { } Err(errors) => { report_fulfillment_errors(fcx.infcx(), &errors); } diff --git a/src/librustc_typeck/check/wf.rs b/src/librustc_typeck/check/wf.rs index e0eba4c38cd1c..fb27858bd5199 100644 --- a/src/librustc_typeck/check/wf.rs +++ b/src/librustc_typeck/check/wf.rs @@ -9,7 +9,7 @@ // except according to those terms. use astconv::AstConv; -use super::{CheckEnv, FnCtxt, Inherited, blank_fn_ctxt, vtable, regionck}; +use super::{CheckEnv, FnCtxt, FnCtxtTyper, Inherited, blank_fn_ctxt, vtable, regionck}; use constrained_type_params::{identify_constrained_type_params, Parameter}; use CrateCtxt; use middle::region; @@ -104,15 +104,15 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { self.check_item_type(item); } ast::ItemStruct(ref struct_def, ref ast_generics) => { - self.check_type_defn(item, |fcx| { - vec![struct_variant(fcx, &**struct_def)] + self.check_type_defn(item, |check_env, fcx| { + vec![struct_variant(check_env, fcx, &**struct_def)] }); self.check_variances_for_type_defn(item, ast_generics); } ast::ItemEnum(ref enum_def, ref ast_generics) => { - self.check_type_defn(item, |fcx| { - enum_variants(fcx, enum_def) + self.check_type_defn(item, |check_env, fcx| { + enum_variants(check_env, fcx, enum_def) }); self.check_variances_for_type_defn(item, ast_generics); @@ -159,31 +159,34 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { /// In a type definition, we check that to ensure that the types of the fields are well-formed. fn check_type_defn(&mut self, item: &ast::Item, mut lookup_fields: F) where - F: for<'fcx> FnMut(&FnCtxt<'fcx, 'tcx>) -> Vec>, + F: for<'fcx> FnMut(&mut CheckEnv<'tcx>, &FnCtxt<'fcx, 'tcx>) -> Vec>, { self.with_fcx(item, |this, check_env, fcx| { - let variants = lookup_fields(fcx); - let mut bounds_checker = BoundsChecker::new(fcx, - item.span, - item.id, - Some(&mut this.cache)); - debug!("check_type_defn at bounds_checker.scope: {:?}", bounds_checker.scope); - - for variant in &variants { - for field in &variant.fields { - // Regions are checked below. - bounds_checker.check_traits_in_ty(field.ty); - } + let variants = lookup_fields(check_env, fcx); + { + let mut bounds_checker = BoundsChecker::new(check_env, + fcx, + item.span, + item.id, + Some(&mut this.cache)); + debug!("check_type_defn at bounds_checker.scope: {:?}", bounds_checker.scope); + + for variant in &variants { + for field in &variant.fields { + // Regions are checked below. + bounds_checker.check_traits_in_ty(field.ty); + } - // For DST, all intermediate types must be sized. - if !variant.fields.is_empty() { - for field in variant.fields.init() { - fcx.register_builtin_bound( - field.ty, - ty::BoundSized, - traits::ObligationCause::new(field.span, - fcx.body_id, - traits::FieldSized)); + // For DST, all intermediate types must be sized. + if !variant.fields.is_empty() { + for field in variant.fields.init() { + fcx.register_builtin_bound( + field.ty, + ty::BoundSized, + traits::ObligationCause::new(field.span, + fcx.body_id, + traits::FieldSized)); + } } } } @@ -199,17 +202,19 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { fn check_item_type(&mut self, item: &ast::Item) { - self.with_fcx(item, |this, _, fcx| { - let mut bounds_checker = BoundsChecker::new(fcx, + self.with_fcx(item, |this, check_env, fcx| { + let mut bounds_checker = BoundsChecker::new(check_env, + fcx, item.span, item.id, Some(&mut this.cache)); debug!("check_item_type at bounds_checker.scope: {:?}", bounds_checker.scope); let type_scheme = ty::lookup_item_type(fcx.tcx(), local_def(item.id)); - let item_ty = fcx.instantiate_type_scheme(item.span, - &fcx.inh.param_env.free_substs, - &type_scheme.ty); + let typer = FnCtxtTyper::new(check_env, fcx); + let item_ty = typer.instantiate_type_scheme(item.span, + &fcx.inh.param_env.free_substs, + &type_scheme.ty); bounds_checker.check_traits_in_ty(item_ty); }); @@ -218,8 +223,9 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { fn check_impl(&mut self, item: &ast::Item) { - self.with_fcx(item, |this, _, fcx| { - let mut bounds_checker = BoundsChecker::new(fcx, + self.with_fcx(item, |this, check_env, fcx| { + let mut bounds_checker = BoundsChecker::new(check_env, + fcx, item.span, item.id, Some(&mut this.cache)); @@ -229,9 +235,10 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { // that is, with all type parameters converted from bound // to free. let self_ty = ty::node_id_to_type(fcx.tcx(), item.id); - let self_ty = fcx.instantiate_type_scheme(item.span, - &fcx.inh.param_env.free_substs, - &self_ty); + let typer = FnCtxtTyper::new(check_env, fcx); + let self_ty = typer.instantiate_type_scheme(item.span, + &fcx.inh.param_env.free_substs, + &self_ty); bounds_checker.check_traits_in_ty(self_ty); @@ -242,9 +249,9 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { Some(t) => { t } }; - let trait_ref = fcx.instantiate_type_scheme(item.span, - &fcx.inh.param_env.free_substs, - &trait_ref); + let trait_ref = typer.instantiate_type_scheme(item.span, + &fcx.inh.param_env.free_substs, + &trait_ref); // We are stricter on the trait-ref in an impl than the // self-type. In particular, we enforce region @@ -267,7 +274,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { let predicates = ty::lookup_super_predicates(fcx.tcx(), poly_trait_ref.def_id()); let predicates = predicates.instantiate_supertrait(fcx.tcx(), &poly_trait_ref); let predicates = { - let selcx = &mut traits::SelectionContext::new(fcx.infcx(), fcx); + let selcx = &mut traits::SelectionContext::new(fcx.infcx(), &typer); traits::normalize(selcx, cause.clone(), &predicates) }; for predicate in predicates.value.predicates { @@ -473,6 +480,7 @@ impl<'ccx, 'tcx, 'v> Visitor<'v> for CheckTypeWellFormedVisitor<'ccx, 'tcx> { } pub struct BoundsChecker<'cx,'tcx:'cx> { + check_env: &'cx CheckEnv<'tcx>, fcx: &'cx FnCtxt<'cx,'tcx>, span: Span, @@ -486,12 +494,14 @@ pub struct BoundsChecker<'cx,'tcx:'cx> { } impl<'cx,'tcx> BoundsChecker<'cx,'tcx> { - pub fn new(fcx: &'cx FnCtxt<'cx,'tcx>, + pub fn new(check_env: &'cx CheckEnv<'tcx>, + fcx: &'cx FnCtxt<'cx,'tcx>, span: Span, scope: ast::NodeId, cache: Option<&'cx mut HashSet>>) -> BoundsChecker<'cx,'tcx> { - BoundsChecker { fcx: fcx, span: span, scope: scope, + BoundsChecker { check_env: check_env, + fcx: fcx, span: span, scope: scope, cache: cache, binding_count: 0 } } @@ -507,9 +517,10 @@ impl<'cx,'tcx> BoundsChecker<'cx,'tcx> { pub fn check_trait_ref(&mut self, trait_ref: &ty::TraitRef<'tcx>) { let trait_predicates = ty::lookup_predicates(self.fcx.tcx(), trait_ref.def_id); - let bounds = self.fcx.instantiate_bounds(self.span, - trait_ref.substs, - &trait_predicates); + let typer = FnCtxtTyper::new(self.check_env, self.fcx); + let bounds = typer.instantiate_bounds(self.span, + trait_ref.substs, + &trait_predicates); self.fcx.add_obligations_for_parameters( traits::ObligationCause::new( @@ -575,8 +586,9 @@ impl<'cx,'tcx> TypeFolder<'tcx> for BoundsChecker<'cx,'tcx> { ty::ty_struct(type_id, substs) | ty::ty_enum(type_id, substs) => { let type_predicates = ty::lookup_predicates(self.fcx.tcx(), type_id); - let bounds = self.fcx.instantiate_bounds(self.span, substs, - &type_predicates); + let typer = FnCtxtTyper::new(self.check_env, self.fcx); + let bounds = typer.instantiate_bounds(self.span, substs, + &type_predicates); if self.binding_count == 0 { self.fcx.add_obligations_for_parameters( @@ -638,7 +650,8 @@ struct AdtField<'tcx> { span: Span, } -fn struct_variant<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, +fn struct_variant<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a, 'tcx>, struct_def: &ast::StructDef) -> AdtVariant<'tcx> { let fields = @@ -646,16 +659,18 @@ fn struct_variant<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, .iter() .map(|field| { let field_ty = ty::node_id_to_type(fcx.tcx(), field.node.id); - let field_ty = fcx.instantiate_type_scheme(field.span, - &fcx.inh.param_env.free_substs, - &field_ty); + let typer = FnCtxtTyper::new(check_env, fcx); + let field_ty = typer.instantiate_type_scheme(field.span, + &fcx.inh.param_env.free_substs, + &field_ty); AdtField { ty: field_ty, span: field.span } }) .collect(); AdtVariant { fields: fields } } -fn enum_variants<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, +fn enum_variants<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a, 'tcx>, enum_def: &ast::EnumDef) -> Vec> { enum_def.variants.iter() @@ -672,10 +687,11 @@ fn enum_variants<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, AdtVariant { fields: args.iter().enumerate().map(|(index, arg)| { let arg_ty = arg_tys[index]; + let typer = FnCtxtTyper::new(check_env, fcx); let arg_ty = - fcx.instantiate_type_scheme(variant.span, - &fcx.inh.param_env.free_substs, - &arg_ty); + typer.instantiate_type_scheme(variant.span, + &fcx.inh.param_env.free_substs, + &arg_ty); AdtField { ty: arg_ty, span: arg.ty.span @@ -689,7 +705,7 @@ fn enum_variants<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, } } ast::StructVariantKind(ref struct_def) => { - struct_variant(fcx, &**struct_def) + struct_variant(check_env, fcx, &**struct_def) } } }) diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 889975f0eb2f9..16ac5e8d9f3b1 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -14,7 +14,7 @@ use self::ResolveReason::*; use astconv::AstConv; -use check::FnCtxt; +use super::{CheckEnv, FnCtxt}; use middle::pat_util; use middle::ty::{self, Ty, MethodCall, MethodCallee}; use middle::ty_fold::{TypeFolder,TypeFoldable}; @@ -35,20 +35,22 @@ use syntax::visit::Visitor; /////////////////////////////////////////////////////////////////////////// // Entry point functions -pub fn resolve_type_vars_in_expr(fcx: &FnCtxt, e: &ast::Expr) { +pub fn resolve_type_vars_in_expr<'a, 'ctx>(check_env: &mut CheckEnv<'ctx>, + fcx: &FnCtxt<'a, 'ctx>, e: &ast::Expr) { assert_eq!(fcx.writeback_errors.get(), false); - let mut wbcx = WritebackCx::new(fcx); + let mut wbcx = WritebackCx::new(check_env, fcx); wbcx.visit_expr(e); wbcx.visit_upvar_borrow_map(); wbcx.visit_closures(); wbcx.visit_object_cast_map(); } -pub fn resolve_type_vars_in_fn(fcx: &FnCtxt, - decl: &ast::FnDecl, - blk: &ast::Block) { +pub fn resolve_type_vars_in_fn<'a, 'ctx>(check_env: &mut CheckEnv<'ctx>, + fcx: &FnCtxt<'a, 'ctx>, + decl: &ast::FnDecl, + blk: &ast::Block) { assert_eq!(fcx.writeback_errors.get(), false); - let mut wbcx = WritebackCx::new(fcx); + let mut wbcx = WritebackCx::new(check_env, fcx); wbcx.visit_block(blk); for arg in &decl.inputs { wbcx.visit_node_id(ResolvingPattern(arg.pat.span), arg.id); @@ -74,12 +76,15 @@ pub fn resolve_type_vars_in_fn(fcx: &FnCtxt, // do elsewhere. struct WritebackCx<'cx, 'tcx: 'cx> { + check_env: &'cx mut CheckEnv<'tcx>, fcx: &'cx FnCtxt<'cx, 'tcx>, } impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { - fn new(fcx: &'cx FnCtxt<'cx, 'tcx>) -> WritebackCx<'cx, 'tcx> { - WritebackCx { fcx: fcx } + fn new(check_env: &'cx mut CheckEnv<'tcx>, + fcx: &'cx FnCtxt<'cx, 'tcx>) -> WritebackCx<'cx, 'tcx> + { + WritebackCx { check_env: check_env, fcx: fcx } } fn tcx(&self) -> &'cx ty::ctxt<'tcx> { @@ -92,10 +97,10 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { // operating on scalars, we clear the overload. fn fix_scalar_binary_expr(&mut self, e: &ast::Expr) { if let ast::ExprBinary(ref op, ref lhs, ref rhs) = e.node { - let lhs_ty = self.fcx.node_ty(lhs.id); + let lhs_ty = self.fcx.node_ty(self.check_env, lhs.id); let lhs_ty = self.fcx.infcx().resolve_type_vars_if_possible(&lhs_ty); - let rhs_ty = self.fcx.node_ty(rhs.id); + let rhs_ty = self.fcx.node_ty(self.check_env, rhs.id); let rhs_ty = self.fcx.infcx().resolve_type_vars_if_possible(&rhs_ty); if ty::type_is_scalar(lhs_ty) && ty::type_is_scalar(rhs_ty) { @@ -265,7 +270,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { self.visit_adjustments(reason, id); // Resolve the type of the node with id `id` - let n_ty = self.fcx.node_ty(id); + let n_ty = self.fcx.node_ty(self.check_env, id); let n_ty = self.resolve(&n_ty, reason); write_ty_to_tcx(self.tcx(), id, n_ty); debug!("Node {} has type {}", id, n_ty.repr(self.tcx())); From 319988f0d72b4d8a5070cf9c57c8adc2b2505158 Mon Sep 17 00:00:00 2001 From: Joshua Yanovski Date: Fri, 8 May 2015 09:14:23 -0700 Subject: [PATCH 03/14] Fix incorrect behavior introduced into autoderef calls. --- src/librustc_typeck/check/callee.rs | 7 +- src/librustc_typeck/check/coercion.rs | 2 +- src/librustc_typeck/check/method/confirm.rs | 71 ++++++++++--------- src/librustc_typeck/check/method/probe.rs | 2 +- src/librustc_typeck/check/method/suggest.rs | 2 +- src/librustc_typeck/check/mod.rs | 75 ++++++++++----------- 6 files changed, 82 insertions(+), 77 deletions(-) diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index 59740b5a2dc9d..577b7eb7d1c67 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -86,10 +86,9 @@ pub fn check_call<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, Some(callee_expr), UnresolvedTypeAction::Error, LvaluePreference::NoPreference, - |adj_ty, idx| Some((adj_ty, idx))); - let result = result.and_then( |(adj_ty, idx)| { - try_overloaded_call_step(check_env, fcx, call_expr, callee_expr, adj_ty, idx) - }); + |check_env, adj_ty, idx| { + try_overloaded_call_step(check_env, fcx, call_expr, callee_expr, adj_ty, idx) + }); match result { None => { diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index 0f9db79bd59ad..9994a32620d27 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -212,7 +212,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { Some(expr_a), UnresolvedTypeAction::Ignore, lvalue_pref, - |inner_ty, autoderef| { + |_, inner_ty, autoderef| { if autoderef == 0 { // Don't let this pass, otherwise it would cause // &T to autoref to &&T. diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 46800dff4f47d..402111a942734 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -27,7 +27,6 @@ use std::iter::repeat; use util::ppaux::Repr; struct ConfirmContext<'a, 'tcx:'a> { - check_env: &'a mut CheckEnv<'tcx>, fcx: &'a FnCtxt<'a, 'tcx>, span: Span, self_expr: &'tcx ast::Expr, @@ -63,20 +62,18 @@ pub fn confirm<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, pick.repr(fcx.tcx()), supplied_method_types.repr(fcx.tcx())); - let mut confirm_cx = ConfirmContext::new(check_env, fcx, span, self_expr, call_expr); - confirm_cx.confirm(unadjusted_self_ty, pick, supplied_method_types) + let mut confirm_cx = ConfirmContext::new(fcx, span, self_expr, call_expr); + confirm_cx.confirm(check_env, unadjusted_self_ty, pick, supplied_method_types) } impl<'a,'tcx> ConfirmContext<'a,'tcx> { - fn new(check_env: &'a mut CheckEnv<'tcx>, - fcx: &'a FnCtxt<'a, 'tcx>, + fn new(fcx: &'a FnCtxt<'a, 'tcx>, span: Span, self_expr: &'tcx ast::Expr, call_expr: &'tcx ast::Expr) -> ConfirmContext<'a, 'tcx> { ConfirmContext { - check_env: check_env, fcx: fcx, span: span, self_expr: self_expr, @@ -85,20 +82,21 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { } fn confirm(&mut self, + check_env: &mut CheckEnv<'tcx>, unadjusted_self_ty: Ty<'tcx>, pick: probe::Pick<'tcx>, supplied_method_types: Vec>) -> MethodCallee<'tcx> { // Adjust the self expression the user provided and obtain the adjusted type. - let self_ty = self.adjust_self_ty(unadjusted_self_ty, &pick); + let self_ty = self.adjust_self_ty(check_env, unadjusted_self_ty, &pick); // Make sure nobody calls `drop()` explicitly. self.enforce_illegal_method_limitations(&pick); // Create substitutions for the method's type parameters. let (rcvr_substs, method_origin) = - self.fresh_receiver_substs(self_ty, &pick); + self.fresh_receiver_substs(check_env, self_ty, &pick); let (method_types, method_regions) = self.instantiate_method_substs(&pick, supplied_method_types); let all_substs = rcvr_substs.with_method(method_types, method_regions); @@ -107,7 +105,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { // Create the final signature for the method, replacing late-bound regions. let InstantiatedMethodSig { method_sig, all_substs, method_predicates - } = self.instantiate_method_sig(&pick, all_substs); + } = self.instantiate_method_sig(check_env, &pick, all_substs); let method_self_ty = method_sig.inputs[0]; // Unify the (adjusted) self type with what the method expects. @@ -132,7 +130,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { // If this is an `&mut self` method, bias the receiver // expression towards mutability (this will switch // e.g. `Deref` to `DerefMut` in overloaded derefs and so on). - self.fixup_derefs_on_method_receiver_if_necessary(&callee); + self.fixup_derefs_on_method_receiver_if_necessary(check_env, &callee); callee } @@ -141,6 +139,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { // ADJUSTMENTS fn adjust_self_ty(&mut self, + check_env: &mut CheckEnv<'tcx>, unadjusted_self_ty: Ty<'tcx>, pick: &probe::Pick<'tcx>) -> Ty<'tcx> @@ -162,14 +161,14 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { // Commit the autoderefs by calling `autoderef again, but this // time writing the results into the various tables. - let (autoderefd_ty, n, result) = check::autoderef(self.check_env, + let (autoderefd_ty, n, result) = check::autoderef(check_env, self.fcx, self.span, unadjusted_self_ty, Some(self.self_expr), UnresolvedTypeAction::Error, NoPreference, - |_, n| { + |_, _, n| { if n == pick.autoderefs { Some(()) } else { @@ -204,6 +203,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { /// Note that this substitution may include late-bound regions from the impl level. If so, /// these are instantiated later in the `instantiate_method_sig` routine. fn fresh_receiver_substs(&mut self, + check_env: &mut CheckEnv<'tcx>, self_ty: Ty<'tcx>, pick: &probe::Pick<'tcx>) -> (subst::Substs<'tcx>, MethodOrigin<'tcx>) @@ -213,13 +213,13 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { assert!(ty::impl_trait_ref(self.tcx(), impl_def_id).is_none(), "impl {:?} is not an inherent impl", impl_def_id); let impl_polytype = - check::impl_self_ty(self.check_env, self.fcx, self.span, impl_def_id); + check::impl_self_ty(check_env, self.fcx, self.span, impl_def_id); (impl_polytype.substs, MethodStatic(pick.item.def_id())) } probe::ObjectPick(trait_def_id, method_num, vtable_index) => { - self.extract_trait_ref(self_ty, |this, object_ty, data| { + self.extract_trait_ref(check_env, self_ty, |this, object_ty, data| { // The object data has no entry for the Self // Type. For the purposes of this method call, we // substitute the object type itself. This @@ -262,8 +262,8 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { // parameters from the trait ([$A,$B]), not those from // the impl ([$A,$B,$C]) not the receiver type ([$C]). let impl_polytype = - check::impl_self_ty(self.check_env, self.fcx, self.span, impl_def_id); - let typer = FnCtxtTyper::new(self.check_env, self.fcx); + check::impl_self_ty(check_env, self.fcx, self.span, impl_def_id); + let typer = FnCtxtTyper::new(check_env, self.fcx); let impl_trait_ref = typer.instantiate_type_scheme( self.span, @@ -308,7 +308,11 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { } } - fn extract_trait_ref(&mut self, self_ty: Ty<'tcx>, mut closure: F) -> R where + fn extract_trait_ref(&mut self, + check_env: &mut CheckEnv<'tcx>, + self_ty: Ty<'tcx>, + mut closure: F + ) -> R where F: FnMut(&mut ConfirmContext<'a, 'tcx>, Ty<'tcx>, &ty::TyTrait<'tcx>) -> R, { // If we specified that this is an object method, then the @@ -316,21 +320,22 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { // yield an object-type (e.g., `&Object` or `Box` // etc). - let (_, _, result) = check::autoderef(self.check_env, + let (_, _, result) = check::autoderef(check_env, self.fcx, self.span, self_ty, None, UnresolvedTypeAction::Error, NoPreference, - |ty, _| { + |_, ty, _| { match ty.sty { - ty::ty_trait(ref data) => Some((ty, data)), + ty::ty_trait(ref data) => Some(closure(self, ty, &**data)), _ => None, } }); + match result { - Some((ty, data)) => closure(self, ty, &**data), + Some(r) => r, None => { self.tcx().sess.span_bug( self.span, @@ -401,6 +406,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { // fn instantiate_method_sig(&mut self, + check_env: &mut CheckEnv<'tcx>, pick: &probe::Pick<'tcx>, all_substs: subst::Substs<'tcx>) -> InstantiatedMethodSig<'tcx> @@ -414,7 +420,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { // be no late-bound regions appearing here. let method_predicates = pick.item.as_opt_method().unwrap() .predicates.instantiate(self.tcx(), &all_substs); - let typer = FnCtxtTyper::new(self.check_env, self.fcx); + let typer = FnCtxtTyper::new(check_env, self.fcx); let method_predicates = typer.normalize_associated_types_in(self.span, &method_predicates); @@ -432,7 +438,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { debug!("late-bound lifetimes from method instantiated, method_sig={}", method_sig.repr(self.tcx())); - let typer = FnCtxtTyper::new(self.check_env, self.fcx); + let typer = FnCtxtTyper::new(check_env, self.fcx); let method_sig = typer.instantiate_type_scheme(self.span, &all_substs, &method_sig); debug!("type scheme substituted, method_sig={}", method_sig.repr(self.tcx())); @@ -469,6 +475,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { /// auto-derefs, indices, etc from `Deref` and `Index` into `DerefMut` and `IndexMut` /// respectively. fn fixup_derefs_on_method_receiver_if_necessary(&mut self, + check_env: &mut CheckEnv<'tcx>, method_callee: &MethodCallee) { let sig = match method_callee.ty.sty { ty::ty_bare_fn(_, ref f) => f.sig.clone(), @@ -517,15 +524,15 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { i, expr.repr(self.tcx()), autoderef_count); if autoderef_count > 0 { - let expr_ty = self.fcx.expr_ty(self.check_env, expr); - check::autoderef(self.check_env, + let expr_ty = self.fcx.expr_ty(check_env, expr); + check::autoderef(check_env, self.fcx, expr.span, expr_ty, Some(expr), UnresolvedTypeAction::Error, PreferMutLvalue, - |_, autoderefs| { + |_, _, autoderefs| { if autoderefs == autoderef_count + 1 { Some(()) } else { @@ -577,17 +584,17 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { let (adjusted_base_ty, unsize) = if let Some(target) = unsize { (target, true) } else { - (self.fcx.adjust_expr_ty(self.check_env, base_expr, + (self.fcx.adjust_expr_ty(check_env, base_expr, Some(&ty::AdjustDerefRef(ty::AutoDerefRef { autoderefs: autoderefs, autoref: None, unsize: None }))), false) }; - let index_expr_ty = self.fcx.expr_ty(self.check_env, &**index_expr); + let index_expr_ty = self.fcx.expr_ty(check_env, &**index_expr); let result = check::try_index_step( - self.check_env, + check_env, self.fcx, MethodCall::expr(expr.id), expr, @@ -601,7 +608,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { if let Some((input_ty, return_ty)) = result { demand::suptype(self.fcx, index_expr.span, input_ty, index_expr_ty); - let expr_ty = self.fcx.expr_ty(self.check_env, &*expr); + let expr_ty = self.fcx.expr_ty(check_env, &*expr); demand::suptype(self.fcx, expr.span, expr_ty, return_ty); } } @@ -609,10 +616,10 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { // if this is an overloaded deref, then re-evaluate with // a preference for mut let method_call = MethodCall::expr(expr.id); - let expr_ty = self.fcx.expr_ty(self.check_env, &**base_expr); + let expr_ty = self.fcx.expr_ty(check_env, &**base_expr); if self.fcx.inh.method_map.borrow().contains_key(&method_call) { check::try_overloaded_deref( - self.check_env, + check_env, self.fcx, expr.span, Some(method_call), diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 1512c1f58bebd..94842512936ee 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -195,7 +195,7 @@ fn create_steps<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, None, UnresolvedTypeAction::Error, NoPreference, - |t, d| { + |_, t, d| { steps.push(CandidateStep { self_ty: t, autoderefs: d, diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 28cd29111b723..a9be6d5815110 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -262,7 +262,7 @@ fn type_derefs_to_local<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, check::autoderef(check_env, fcx, span, rcvr_ty, None, check::UnresolvedTypeAction::Ignore, check::NoPreference, - |ty, _| { + |_, ty, _| { if is_local(ty) { Some(()) } else { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index dee26b14df804..ec80323b16d32 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1912,7 +1912,7 @@ pub fn autoderef<'a, 'tcx, T, F>(check_env: &mut CheckEnv<'tcx>, mut lvalue_pref: LvaluePreference, mut should_stop: F) -> (Ty<'tcx>, usize, Option) - where F: FnMut(Ty<'tcx>, usize) -> Option, + where F: FnMut(&mut CheckEnv<'tcx>, Ty<'tcx>, usize) -> Option, { debug!("autoderef(base_ty={}, opt_expr={}, lvalue_pref={:?})", base_ty.repr(fcx.tcx()), @@ -1938,7 +1938,7 @@ pub fn autoderef<'a, 'tcx, T, F>(check_env: &mut CheckEnv<'tcx>, } }; - match should_stop(resolved_t, autoderefs) { + match should_stop(check_env, resolved_t, autoderefs) { Some(x) => return (resolved_t, autoderefs, Some(x)), None => {} } @@ -2060,10 +2060,9 @@ fn lookup_indexing<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, Some(base_expr), UnresolvedTypeAction::Error, lvalue_pref, - |adj_ty, idx| Some((adj_ty, idx))); - let final_mt = final_mt.and_then( |(adj_ty, idx)| { + |check_env, adj_ty, idx| { try_index_step(check_env, fcx, MethodCall::expr(expr.id), expr, base_expr, - adj_ty, idx, false, lvalue_pref, idx_ty) + adj_ty, idx, false, lvalue_pref, idx_ty) }); if final_mt.is_some() { @@ -2743,25 +2742,24 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, let expr_ty = fcx.expr_ty(check_env, base); let expr_t = structurally_resolved_type(check_env, fcx, expr.span, expr_ty); // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop. - let (_, autoderefs, result) = autoderef(check_env, fcx, - expr.span, - expr_t, - Some(base), - UnresolvedTypeAction::Error, - lvalue_pref, - |base_t, _| { + let (_, autoderefs, field_ty) = autoderef(check_env, fcx, + expr.span, + expr_t, + Some(base), + UnresolvedTypeAction::Error, + lvalue_pref, + |check_env, base_t, _| { match base_t.sty { ty::ty_struct(base_id, substs) => { debug!("struct named {}", ppaux::ty_to_string(tcx, base_t)); - Some((base_id, substs, ty::lookup_struct_fields(tcx, base_id))) + let fields = ty::lookup_struct_fields(tcx, base_id); + fcx.lookup_field_ty(check_env, + expr.span, base_id, &fields[..], + field.node.name, &(*substs)) } _ => None } }); - let field_ty = result.and_then( |(base_id, substs, fields)| - fcx.lookup_field_ty(check_env, - expr.span, base_id, &fields[..], - field.node.name, &(*substs))); match field_ty { Some(field_ty) => { fcx.write_ty(check_env, expr.id, field_ty); @@ -2848,32 +2846,33 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, let expr_t = structurally_resolved_type(check_env, fcx, expr.span, expr_ty); let mut tuple_like = false; // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop. - let (_, autoderefs, base_t) = autoderef(check_env, fcx, - expr.span, + let (_, autoderefs, field_ty) = autoderef(check_env, fcx, + expr.span, expr_t, Some(base), UnresolvedTypeAction::Error, lvalue_pref, - |base_t, _| Some(base_t)); - let field_ty = base_t.and_then( |base_t| match base_t.sty { - ty::ty_struct(base_id, substs ) => { - tuple_like = ty::is_tuple_struct(tcx, base_id); - if tuple_like { - debug!("tuple struct named {}", ppaux::ty_to_string(tcx, base_t)); - let fields = ty::lookup_struct_fields(tcx, base_id); - fcx.lookup_tup_field_ty(check_env, - expr.span, base_id, &fields[..], - idx.node, &(*substs)) - } else { - None + |check_env, base_t, _| { + match base_t.sty { + ty::ty_struct(base_id, substs) => { + tuple_like = ty::is_tuple_struct(tcx, base_id); + if tuple_like { + debug!("tuple struct named {}", ppaux::ty_to_string(tcx, base_t)); + let fields = ty::lookup_struct_fields(tcx, base_id); + fcx.lookup_tup_field_ty(check_env, + expr.span, base_id, &fields[..], + idx.node, &(*substs)) + } else { + None + } + } + ty::ty_tup(ref v) => { + tuple_like = true; + if idx.node < v.len() { Some(v[idx.node]) } else { None } + } + _ => None } - } - ty::ty_tup(ref v) => { - tuple_like = true; - if idx.node < v.len() { Some(v[idx.node]) } else { None } - } - _ => None - } ); + }); match field_ty { Some(field_ty) => { fcx.write_ty(check_env, expr.id, field_ty); From 71d1803a673f3ccc84464dabfb32ba26ad9fd84e Mon Sep 17 00:00:00 2001 From: Joshua Yanovski Date: Fri, 8 May 2015 09:34:51 -0700 Subject: [PATCH 04/14] Whitespace nits. --- src/librustc_typeck/check/_match.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 2234993c37e99..4ba0edb4c0f7d 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -129,8 +129,8 @@ pub fn check_pat<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, let const_ty = { let typer = FnCtxtTyper::new(check_env, fcx); typer.instantiate_type_scheme(pat.span, - &Substs::empty(), - &const_scheme.ty) + &Substs::empty(), + &const_scheme.ty) }; fcx.write_ty(check_env, pat.id, const_ty); From ff198f76d385b80b9e9a68e5ec42aa057c99bff6 Mon Sep 17 00:00:00 2001 From: Joshua Yanovski Date: Fri, 8 May 2015 09:45:36 -0700 Subject: [PATCH 05/14] Move locals to not use RefCell. --- src/librustc_typeck/check/_match.rs | 4 ++-- src/librustc_typeck/check/mod.rs | 32 +++++++++++++++----------- src/librustc_typeck/check/writeback.rs | 2 +- 3 files changed, 22 insertions(+), 16 deletions(-) diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 4ba0edb4c0f7d..bb85fb3debeec 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -142,7 +142,7 @@ pub fn check_pat<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, demand::suptype(fcx, pat.span, expected, const_ty); } ast::PatIdent(bm, ref path, ref sub) if pat_is_binding(&tcx.def_map, pat) => { - let typ = fcx.local_ty(pat.span, pat.id); + let typ = fcx.local_ty(check_env, pat.span, pat.id); match bm { ast::BindByRef(mutbl) => { // if the binding is like @@ -172,7 +172,7 @@ pub fn check_pat<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, // what the type of the binding `x` ought to be let canon_id = *pcx.map.get(&path.node).unwrap(); if canon_id != pat.id { - let ct = fcx.local_ty(pat.span, canon_id); + let ct = fcx.local_ty(check_env, pat.span, canon_id); demand::eqtype(fcx, pat.span, ct, typ); } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index ec80323b16d32..6b0af5811912d 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -154,7 +154,6 @@ mod op; /// share the inherited fields. pub struct Inherited<'a, 'tcx: 'a> { infcx: infer::InferCtxt<'a, 'tcx>, - locals: RefCell>>, param_env: ty::ParameterEnvironment<'a, 'tcx>, // Temporary tables: @@ -171,6 +170,8 @@ pub struct Inherited<'a, 'tcx: 'a> { } pub struct CheckEnv<'tcx> { + locals: NodeMap>, + // Temporary tables: node_types: NodeMap>, @@ -534,7 +535,6 @@ impl<'a, 'tcx> Inherited<'a, 'tcx> { -> Inherited<'a, 'tcx> { Inherited { infcx: infer::new_infer_ctxt(tcx), - locals: RefCell::new(NodeMap()), param_env: param_env, item_substs: RefCell::new(NodeMap()), adjustments: RefCell::new(NodeMap()), @@ -567,6 +567,7 @@ impl<'a, 'tcx> Inherited<'a, 'tcx> { impl<'tcx> CheckEnv<'tcx> { fn new() -> Self { CheckEnv { + locals: NodeMap(), node_types: NodeMap(), fn_sig_map: NodeMap(), deferred_call_resolutions: DefIdMap(), @@ -732,12 +733,12 @@ impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> { None => { // infer the variable's type let var_ty = self.fcx.infcx().next_ty_var(); - self.fcx.inh.locals.borrow_mut().insert(nid, var_ty); + self.check_env.locals.insert(nid, var_ty); var_ty } Some(typ) => { // take type that the user specified - self.fcx.inh.locals.borrow_mut().insert(nid, typ); + self.check_env.locals.insert(nid, typ); typ } } @@ -755,7 +756,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> { 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(&local.id).unwrap().clone())); + self.check_env.locals.get(&local.id).unwrap().clone())); visit::walk_local(self, local); } @@ -771,7 +772,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> { 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(&p.id).unwrap().clone()), + self.check_env.locals.get(&p.id).unwrap().clone()), var_ty.repr(self.fcx.tcx())); } } @@ -1512,8 +1513,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { format!("{:?}", self_ptr) } - pub fn local_ty(&self, span: Span, nid: ast::NodeId) -> Ty<'tcx> { - match self.inh.locals.borrow().get(&nid) { + pub fn local_ty(&self, + check_env: &mut CheckEnv<'tcx>, + span: Span, + nid: ast::NodeId) -> Ty<'tcx> { + match check_env.locals.get(&nid) { Some(&t) => t, None => { self.tcx().sess.span_err( @@ -3324,7 +3328,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, if let Some((opt_ty, segments, def)) = resolve_ty_and_def_ufcs(check_env, fcx, path_res, opt_self_ty, path, expr.span, expr.id) { - let (scheme, predicates) = type_scheme_and_predicates_for_def(fcx, + let (scheme, predicates) = type_scheme_and_predicates_for_def(check_env, + fcx, expr.span, def); instantiate_path(check_env, @@ -3956,7 +3961,7 @@ fn check_decl_initializer<'a,'tcx>(check_env: &mut CheckEnv<'tcx>, { let ref_bindings = fcx.tcx().pat_contains_ref_binding(&local.pat); - let local_ty = fcx.local_ty(init.span, local.id); + let local_ty = fcx.local_ty(check_env, init.span, local.id); if !ref_bindings { check_expr_coercable_to_type(check_env, fcx, init, local_ty) } else { @@ -3978,7 +3983,7 @@ fn check_decl_local<'a,'tcx>(check_env: &mut CheckEnv<'tcx>, fcx: &FnCtxt<'a,'tcx>, local: &'tcx ast::Local) { let tcx = fcx.ccx.tcx; - let t = fcx.local_ty(local.span, local.id); + let t = fcx.local_ty(check_env, local.span, local.id); fcx.write_ty(check_env, local.id, t); if let Some(ref init) = local.init { @@ -4380,13 +4385,14 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, } // Returns the type parameter count and the type for the given definition. -fn type_scheme_and_predicates_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, +fn type_scheme_and_predicates_for_def<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a, 'tcx>, sp: Span, defn: def::Def) -> (TypeScheme<'tcx>, GenericPredicates<'tcx>) { match defn { def::DefLocal(nid) | def::DefUpvar(nid, _) => { - let typ = fcx.local_ty(sp, nid); + let typ = fcx.local_ty(check_env, sp, nid); (ty::TypeScheme { generics: ty::Generics::empty(), ty: typ }, ty::GenericPredicates::empty()) } diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 16ac5e8d9f3b1..9b72ccbf0cb0d 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -189,7 +189,7 @@ impl<'cx, 'tcx, 'v> Visitor<'v> for WritebackCx<'cx, 'tcx> { return; } - let var_ty = self.fcx.local_ty(l.span, l.id); + let var_ty = self.fcx.local_ty(self.check_env, l.span, l.id); let var_ty = self.resolve(&var_ty, ResolvingLocal(l.span)); write_ty_to_tcx(self.tcx(), l.id, var_ty); visit::walk_local(self, l); From 05c8c7cff9d5cb9be91dc02a7bbf795f72ace8ee Mon Sep 17 00:00:00 2001 From: Joshua Yanovski Date: Fri, 8 May 2015 10:37:17 -0700 Subject: [PATCH 06/14] Move method_map to not need RefCell. --- src/librustc_typeck/check/callee.rs | 10 ++-- src/librustc_typeck/check/method/confirm.rs | 2 +- src/librustc_typeck/check/mod.rs | 40 ++++++------- src/librustc_typeck/check/op.rs | 2 +- src/librustc_typeck/check/regionck.rs | 65 +++++++++++---------- src/librustc_typeck/check/writeback.rs | 10 ++-- 6 files changed, 65 insertions(+), 64 deletions(-) diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index 577b7eb7d1c67..03fcd3bbe9342 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -343,14 +343,16 @@ fn confirm_overloaded_call<'a,'tcx>(check_env: &mut CheckEnv<'tcx>, expected); write_call(check_env, fcx, call_expr, output_type); - write_overloaded_call_method_map(fcx, call_expr, method_callee); + write_overloaded_call_method_map(check_env, fcx, call_expr, method_callee); } -fn write_overloaded_call_method_map<'a,'tcx>(fcx: &FnCtxt<'a, 'tcx>, +// FIXME: Figure out if we still need `FnCtxt` here. +fn write_overloaded_call_method_map<'a,'tcx>(check_env: &mut CheckEnv<'tcx>, + _: &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); + check_env.method_map.insert(method_call, method_callee); } struct CallResolution<'tcx> { @@ -418,7 +420,7 @@ impl<'tcx> DeferredCallResolution<'tcx> for CallResolution<'tcx> { method_sig.output.unwrap_or(nilty), self.fn_sig.output.unwrap_or(nilty)); - write_overloaded_call_method_map(fcx, self.call_expr, method_callee); + write_overloaded_call_method_map(check_env, fcx, self.call_expr, method_callee); } None => { fcx.tcx().sess.span_bug( diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 402111a942734..57362e2800bbb 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -617,7 +617,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { // a preference for mut let method_call = MethodCall::expr(expr.id); let expr_ty = self.fcx.expr_ty(check_env, &**base_expr); - if self.fcx.inh.method_map.borrow().contains_key(&method_call) { + if check_env.method_map.contains_key(&method_call) { check::try_overloaded_deref( check_env, self.fcx, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 6b0af5811912d..5b0928ddef008 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -98,7 +98,7 @@ use middle::ty::{FnSig, GenericPredicates, TypeScheme}; use middle::ty::{Disr, ParamTy, ParameterEnvironment}; use middle::ty::{self, HasProjectionTypes, RegionEscape, ToPolyTraitRef, Ty}; use middle::ty::liberate_late_bound_regions; -use middle::ty::{MethodCall, MethodCallee, MethodMap, ObjectCastMap}; +use middle::ty::{MethodCall, MethodCallee, ObjectCastMap}; use middle::ty_fold::{TypeFolder, TypeFoldable}; use rscope::RegionScope; use session::Session; @@ -159,7 +159,6 @@ pub struct Inherited<'a, 'tcx: 'a> { // Temporary tables: item_substs: RefCell>>, adjustments: RefCell>>, - method_map: MethodMap<'tcx>, upvar_capture_map: RefCell, closure_tys: RefCell>>, closure_kinds: RefCell>, @@ -174,6 +173,7 @@ pub struct CheckEnv<'tcx> { // Temporary tables: node_types: NodeMap>, + method_map: FnvHashMap>, // A mapping from each fn's id to its signature, with all bound // regions replaced with free ones. Unlike the other tables, this @@ -472,25 +472,23 @@ impl<'a, 'tcx> mc::Typer<'tcx> for FnCtxtTyper<'a, 'tcx> { } fn node_method_ty(&self, method_call: ty::MethodCall) -> Option> { - self.fcx.inh.method_map.borrow() - .get(&method_call) - .map(|method| method.ty) - .map(|ty| self.fcx - .infcx() - .resolve_type_vars_if_possible(&ty)) + self.check_env.method_map.get(&method_call) + .map(|method| method.ty) + .map(|ty| self.fcx + .infcx() + .resolve_type_vars_if_possible(&ty)) } fn node_method_origin(&self, method_call: ty::MethodCall) -> Option> { - self.fcx.inh.method_map.borrow() - .get(&method_call) - .map(|method| method.origin.clone()) + self.check_env.method_map.get(&method_call) + .map(|method| method.origin.clone()) } fn adjustments(&self) -> &RefCell>> { &self.fcx.inh.adjustments } fn is_method_call(&self, id: ast::NodeId) -> bool { - self.fcx.inh.method_map.borrow().contains_key(&ty::MethodCall::expr(id)) + self.check_env.method_map.contains_key(&ty::MethodCall::expr(id)) } fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option { self.fcx.param_env().temporary_scope(rvalue_id) @@ -538,7 +536,6 @@ impl<'a, 'tcx> Inherited<'a, 'tcx> { param_env: param_env, item_substs: RefCell::new(NodeMap()), adjustments: RefCell::new(NodeMap()), - method_map: RefCell::new(FnvHashMap()), object_cast_map: RefCell::new(NodeMap()), upvar_capture_map: RefCell::new(FnvHashMap()), closure_tys: RefCell::new(DefIdMap()), @@ -569,6 +566,7 @@ impl<'tcx> CheckEnv<'tcx> { CheckEnv { locals: NodeMap(), node_types: NodeMap(), + method_map: FnvHashMap(), fn_sig_map: NodeMap(), deferred_call_resolutions: DefIdMap(), deferred_cast_checks: Vec::new(), @@ -1695,9 +1693,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr.id, raw_ty, adjustment, - |method_call| self.inh.method_map.borrow() - .get(&method_call) - .map(|method| resolve_ty(method.ty))) + |method_call| check_env.method_map.get(&method_call) + .map(|method| resolve_ty(method.ty))) } pub fn node_ty(&self, check_env: &CheckEnv<'tcx>, id: ast::NodeId) -> Ty<'tcx> { @@ -2015,13 +2012,14 @@ fn try_overloaded_deref<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, (method, _) => method }; - make_overloaded_lvalue_return_type(fcx, method_call, method) + make_overloaded_lvalue_return_type(check_env, fcx, method_call, method) } /// For the overloaded lvalue expressions (`*x`, `x[3]`), the trait returns a type of `&T`, but the /// actual type we assign to the *expression* is `T`. So this function just peels off the return /// type by one layer to yield `T`. It also inserts the `method-callee` into the method map. -fn make_overloaded_lvalue_return_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, +fn make_overloaded_lvalue_return_type<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a, 'tcx>, method_call: Option, method: Option>) -> Option> @@ -2034,7 +2032,7 @@ fn make_overloaded_lvalue_return_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, let ret_ty = ty::no_late_bound_regions(fcx.tcx(), &ret_ty).unwrap().unwrap(); if let Some(method_call) = method_call { - fcx.inh.method_map.borrow_mut().insert(method_call, method); + check_env.method_map.insert(method_call, method); } // method returns &T, but the type as visible to user is T, so deref @@ -2163,7 +2161,7 @@ fn try_index_step<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, // If some lookup succeeded, install method in table method.and_then(|method| { debug!("try_index_step: success, using overloaded indexing"); - make_overloaded_lvalue_return_type(fcx, Some(method_call), Some(method)). + make_overloaded_lvalue_return_type(check_env, fcx, Some(method_call), Some(method)). map(|ret| (input_ty, ret.ty)) }) } @@ -2665,7 +2663,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, Ok(method) => { let method_ty = method.ty; let method_call = MethodCall::expr(expr.id); - fcx.inh.method_map.borrow_mut().insert(method_call, method); + check_env.method_map.insert(method_call, method); method_ty } Err(error) => { diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index e7be6afb6ffa6..441431ec6d3f6 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -343,7 +343,7 @@ fn lookup_op_method<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, // HACK(eddyb) Fully qualified path to work around a resolve bug. let method_call = ::middle::ty::MethodCall::expr(expr.id); - fcx.inh.method_map.borrow_mut().insert(method_call, method); + check_env.method_map.insert(method_call, method); // extract return type for method; all late bound regions // should have been instantiated by now diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index f30abb5e95070..01b094bf64cbf 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -299,10 +299,10 @@ fn relate_free_regions<'a, 'tcx>(check_env: &CheckEnv<'tcx>, impl<'a, 'tcx> Rcx<'a, 'tcx> { fn new(check_env: &'a mut CheckEnv<'tcx>, - fcx: &'a FnCtxt<'a, 'tcx>, - initial_repeating_scope: RepeatingScope, - initial_body_id: ast::NodeId, - subject: SubjectNode) -> Rcx<'a, 'tcx> { + fcx: &'a FnCtxt<'a, 'tcx>, + initial_repeating_scope: RepeatingScope, + initial_body_id: ast::NodeId, + subject: SubjectNode) -> Rcx<'a, 'tcx>{ let RepeatingScope(initial_repeating_scope) = initial_repeating_scope; Rcx { check_env: check_env, fcx: fcx, @@ -333,7 +333,7 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> { } fn resolve_method_type(&self, method_call: MethodCall) -> Option> { - let method_ty = self.fcx.inh.method_map.borrow() + let method_ty = self.check_env.method_map .get(&method_call).map(|method| method.ty); method_ty.map(|method_ty| resolve_type(self.fcx, method_ty)) } @@ -530,7 +530,7 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) { expr_ty, ty::ReScope(CodeExtent::from_node_id(expr.id))); let method_call = MethodCall::expr(expr.id); - let has_method_map = rcx.fcx.inh.method_map.borrow().contains_key(&method_call); + let has_method_map = rcx.check_env.method_map.contains_key(&method_call); // Check any autoderefs or autorefs that appear. if let Some(adjustment) = rcx.fcx.inh.adjustments.borrow().get(&expr.id) { @@ -678,12 +678,13 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) { ast::ExprUnary(ast::UnDeref, ref base) => { // For *a, the lifetime of a must enclose the deref let method_call = MethodCall::expr(expr.id); - let base_ty = match rcx.fcx.inh.method_map.borrow().get(&method_call) { - Some(method) => { + let method_ty = rcx.check_env.method_map.get(&method_call).map( |method| method.ty ); + let base_ty = match method_ty { + Some(method_ty) => { constrain_call(rcx, expr, Some(&**base), None::.iter(), true); let fn_ret = // late-bound regions in overloaded method calls are instantiated - ty::no_late_bound_regions(rcx.tcx(), &ty::ty_fn_ret(method.ty)).unwrap(); + ty::no_late_bound_regions(rcx.tcx(), &ty::ty_fn_ret(method_ty)).unwrap(); fn_ret.unwrap() } None => rcx.resolve_node_type(base.id) @@ -906,7 +907,7 @@ fn constrain_autoderefs<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>, let method_call = MethodCall::autoderef(deref_expr.id, i as u32); debug!("constrain_autoderefs: method_call={:?} (of {:?} total)", method_call, derefs); - derefd_ty = match rcx.fcx.inh.method_map.borrow().get(&method_call) { + let result = match rcx.check_env.method_map.get(&method_call) { Some(method) => { debug!("constrain_autoderefs: #{} is overloaded, method={}", i, method.repr(rcx.tcx())); @@ -930,30 +931,30 @@ fn constrain_autoderefs<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>, debug!("constrain_autoderefs: receiver r={:?} m={:?}", r.repr(rcx.tcx()), m); - { - let typer = FnCtxtTyper::new(rcx.check_env, rcx.fcx); - let mc = mc::MemCategorizationContext::new(&typer); - let self_cmt = ignore_err!(mc.cat_expr_autoderefd(deref_expr, i)); - debug!("constrain_autoderefs: self_cmt={:?}", - self_cmt.repr(rcx.tcx())); - link_region(rcx, deref_expr.span, r, - ty::BorrowKind::from_mutbl(m), self_cmt); - } - - // Specialized version of constrain_call. - type_must_outlive(rcx, infer::CallRcvr(deref_expr.span), - self_ty, r_deref_expr); - match fn_sig.output { - ty::FnConverging(return_type) => { - type_must_outlive(rcx, infer::CallReturn(deref_expr.span), - return_type, r_deref_expr); - return_type - } - ty::FnDiverging => unreachable!() - } + let typer = FnCtxtTyper::new(rcx.check_env, rcx.fcx); + let mc = mc::MemCategorizationContext::new(&typer); + let self_cmt = ignore_err!(mc.cat_expr_autoderefd(deref_expr, i)); + debug!("constrain_autoderefs: self_cmt={:?}", + self_cmt.repr(rcx.tcx())); + link_region(rcx, deref_expr.span, r, + ty::BorrowKind::from_mutbl(m), self_cmt); + Some((fn_sig, self_ty)) } - None => derefd_ty + None => None }; + if let Some((fn_sig, self_ty)) = result { + // Specialized version of constrain_call. + type_must_outlive(rcx, infer::CallRcvr(deref_expr.span), + self_ty, r_deref_expr); + derefd_ty = match fn_sig.output { + ty::FnConverging(return_type) => { + type_must_outlive(rcx, infer::CallReturn(deref_expr.span), + return_type, r_deref_expr); + return_type + } + ty::FnDiverging => unreachable!() + }; + } if let ty::ty_rptr(r_ptr, _) = derefd_ty.sty { mk_subregion_due_to_dereference(rcx, deref_expr.span, diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 9b72ccbf0cb0d..8cc00ea246a9f 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -104,7 +104,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { let rhs_ty = self.fcx.infcx().resolve_type_vars_if_possible(&rhs_ty); if ty::type_is_scalar(lhs_ty) && ty::type_is_scalar(rhs_ty) { - self.fcx.inh.method_map.borrow_mut().remove(&MethodCall::expr(e.id)); + self.check_env.method_map.remove(&MethodCall::expr(e.id)); // weird but true: the by-ref binops put an // adjustment on the lhs but not the rhs; the @@ -265,7 +265,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { } } - fn visit_node_id(&self, reason: ResolveReason, id: ast::NodeId) { + fn visit_node_id(&mut self, reason: ResolveReason, id: ast::NodeId) { // Resolve any borrowings for the node with id `id` self.visit_adjustments(reason, id); @@ -282,7 +282,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { }); } - fn visit_adjustments(&self, reason: ResolveReason, id: ast::NodeId) { + fn visit_adjustments(&mut self, reason: ResolveReason, id: ast::NodeId) { match self.fcx.inh.adjustments.borrow_mut().remove(&id) { None => { debug!("No adjustments for node {}", id); @@ -316,11 +316,11 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { } } - fn visit_method_map_entry(&self, + fn visit_method_map_entry(&mut self, reason: ResolveReason, method_call: MethodCall) { // Resolve any method map entry - match self.fcx.inh.method_map.borrow_mut().remove(&method_call) { + match self.check_env.method_map.remove(&method_call) { Some(method) => { debug!("writeback::resolve_method_map_entry(call={:?}, entry={})", method_call, From 69a3d514587921e7769fee0c90c24910f8f5e2c6 Mon Sep 17 00:00:00 2001 From: Joshua Yanovski Date: Fri, 8 May 2015 11:43:24 -0700 Subject: [PATCH 07/14] Replace RefCell with Cell for UnsafetyState. --- src/librustc_typeck/check/mod.rs | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 5b0928ddef008..f993e61ae622b 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -252,9 +252,9 @@ impl<'tcx> Expectation<'tcx> { } #[derive(Copy, Clone)] -pub struct UnsafetyState { - pub def: ast::NodeId, - pub unsafety: ast::Unsafety, +struct UnsafetyState { + def: ast::NodeId, + unsafety: ast::Unsafety, from_fn: bool } @@ -263,7 +263,7 @@ impl UnsafetyState { UnsafetyState { def: def, unsafety: unsafety, from_fn: true } } - pub fn recurse(&mut self, blk: &ast::Block) -> UnsafetyState { + pub fn recurse(&self, blk: &ast::Block) -> UnsafetyState { match self.unsafety { // If this unsafe, then if the outer function was already marked as // unsafe we shouldn't attribute the unsafe'ness to the block. This @@ -300,7 +300,7 @@ pub struct FnCtxt<'a, 'tcx: 'a> { ret_ty: ty::FnOutput<'tcx>, - ps: RefCell, + ps: Cell, inh: &'a Inherited<'a, 'tcx>, @@ -606,7 +606,7 @@ pub fn blank_fn_ctxt<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>, writeback_errors: Cell::new(false), err_count_on_creation: ccx.tcx.sess.err_count(), ret_ty: rty, - ps: RefCell::new(UnsafetyState::function(ast::Unsafety::Normal, 0)), + ps: Cell::new(UnsafetyState::function(ast::Unsafety::Normal, 0)), inh: inh, ccx: ccx } @@ -838,7 +838,7 @@ fn check_fn<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, writeback_errors: Cell::new(false), err_count_on_creation: err_count_on_creation, ret_ty: ret_ty, - ps: RefCell::new(UnsafetyState::function(unsafety, unsafety_id)), + ps: Cell::new(UnsafetyState::function(unsafety, unsafety_id)), inh: inherited, ccx: ccx }; @@ -4066,9 +4066,10 @@ fn check_block_with_expected<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, blk: &'tcx ast::Block, expected: Expectation<'tcx>) { let prev = { - let mut fcx_ps = fcx.ps.borrow_mut(); + let fcx_ps = fcx.ps.get(); let unsafety_state = fcx_ps.recurse(blk); - replace(&mut *fcx_ps, unsafety_state) + fcx.ps.set(unsafety_state); + fcx_ps }; let mut warned = false; @@ -4139,7 +4140,7 @@ fn check_block_with_expected<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, } }; - *fcx.ps.borrow_mut() = prev; + fcx.ps.set(prev); } /// Checks a constant appearing in a type. At the moment this is just the From d2fef6635ae5674101fcd6d5d2cb30c6ed9d680f Mon Sep 17 00:00:00 2001 From: Joshua Yanovski Date: Fri, 8 May 2015 12:00:29 -0700 Subject: [PATCH 08/14] Remove object_cast_map. It turns out not to have ever been written to, so visit_object_cast_map never actually processed any items. --- src/librustc_typeck/check/mod.rs | 4 +--- src/librustc_typeck/check/writeback.rs | 23 ----------------------- 2 files changed, 1 insertion(+), 26 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index f993e61ae622b..6a808469f7bdc 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -98,7 +98,7 @@ use middle::ty::{FnSig, GenericPredicates, TypeScheme}; use middle::ty::{Disr, ParamTy, ParameterEnvironment}; use middle::ty::{self, HasProjectionTypes, RegionEscape, ToPolyTraitRef, Ty}; use middle::ty::liberate_late_bound_regions; -use middle::ty::{MethodCall, MethodCallee, ObjectCastMap}; +use middle::ty::{MethodCall, MethodCallee}; use middle::ty_fold::{TypeFolder, TypeFoldable}; use rscope::RegionScope; use session::Session; @@ -162,7 +162,6 @@ pub struct Inherited<'a, 'tcx: 'a> { upvar_capture_map: RefCell, closure_tys: RefCell>>, closure_kinds: RefCell>, - object_cast_map: ObjectCastMap<'tcx>, // Tracks trait obligations incurred during this function body. fulfillment_cx: RefCell>, @@ -536,7 +535,6 @@ impl<'a, 'tcx> Inherited<'a, 'tcx> { param_env: param_env, item_substs: RefCell::new(NodeMap()), adjustments: RefCell::new(NodeMap()), - object_cast_map: RefCell::new(NodeMap()), upvar_capture_map: RefCell::new(FnvHashMap()), closure_tys: RefCell::new(DefIdMap()), closure_kinds: RefCell::new(DefIdMap()), diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 8cc00ea246a9f..e232e997464c7 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -42,7 +42,6 @@ pub fn resolve_type_vars_in_expr<'a, 'ctx>(check_env: &mut CheckEnv<'ctx>, wbcx.visit_expr(e); wbcx.visit_upvar_borrow_map(); wbcx.visit_closures(); - wbcx.visit_object_cast_map(); } pub fn resolve_type_vars_in_fn<'a, 'ctx>(check_env: &mut CheckEnv<'ctx>, @@ -64,7 +63,6 @@ pub fn resolve_type_vars_in_fn<'a, 'ctx>(check_env: &mut CheckEnv<'ctx>, } wbcx.visit_upvar_borrow_map(); wbcx.visit_closures(); - wbcx.visit_object_cast_map(); } /////////////////////////////////////////////////////////////////////////// @@ -244,27 +242,6 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { } } - fn visit_object_cast_map(&self) { - if self.fcx.writeback_errors.get() { - return - } - - for (&node_id, trait_ref) in self.fcx - .inh - .object_cast_map - .borrow() - .iter() - { - let span = ty::expr_span(self.tcx(), node_id); - let reason = ResolvingExpr(span); - let closure_ty = self.resolve(trait_ref, reason); - self.tcx() - .object_cast_map - .borrow_mut() - .insert(node_id, closure_ty); - } - } - fn visit_node_id(&mut self, reason: ResolveReason, id: ast::NodeId) { // Resolve any borrowings for the node with id `id` self.visit_adjustments(reason, id); From 5ade277d0fa3c76814a840b7a7b0040d1f3dcb8b Mon Sep 17 00:00:00 2001 From: Joshua Yanovski Date: Fri, 8 May 2015 12:43:54 -0700 Subject: [PATCH 09/14] De-RefCell closure_tys. --- src/librustc_typeck/check/closure.rs | 2 +- src/librustc_typeck/check/mod.rs | 6 +++--- src/librustc_typeck/check/writeback.rs | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 0d642eebf3580..705d7f70bd6c4 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -97,7 +97,7 @@ fn check_closure<'a,'tcx>(check_env: &mut CheckEnv<'tcx>, fn_ty.sig.repr(fcx.tcx()), opt_kind); - fcx.inh.closure_tys.borrow_mut().insert(expr_def_id, fn_ty); + check_env.closure_tys.insert(expr_def_id, fn_ty); match opt_kind { Some(kind) => { fcx.inh.closure_kinds.borrow_mut().insert(expr_def_id, kind); } None => { } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 6a808469f7bdc..13083eaf9f4bc 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -160,7 +160,6 @@ pub struct Inherited<'a, 'tcx: 'a> { item_substs: RefCell>>, adjustments: RefCell>>, upvar_capture_map: RefCell, - closure_tys: RefCell>>, closure_kinds: RefCell>, // Tracks trait obligations incurred during this function body. @@ -173,6 +172,7 @@ pub struct CheckEnv<'tcx> { // Temporary tables: node_types: NodeMap>, method_map: FnvHashMap>, + closure_tys: DefIdMap>, // A mapping from each fn's id to its signature, with all bound // regions replaced with free ones. Unlike the other tables, this @@ -514,7 +514,7 @@ impl<'a, 'tcx> ty::ClosureTyper<'tcx> for FnCtxtTyper<'a, 'tcx> { substs: &subst::Substs<'tcx>) -> ty::ClosureTy<'tcx> { - self.fcx.inh.closure_tys.borrow().get(&def_id).unwrap().subst(self.fcx.tcx(), substs) + self.check_env.closure_tys.get(&def_id).unwrap().subst(self.fcx.tcx(), substs) } fn closure_upvars(&self, @@ -536,7 +536,6 @@ impl<'a, 'tcx> Inherited<'a, 'tcx> { item_substs: RefCell::new(NodeMap()), adjustments: RefCell::new(NodeMap()), upvar_capture_map: RefCell::new(FnvHashMap()), - closure_tys: RefCell::new(DefIdMap()), closure_kinds: RefCell::new(DefIdMap()), fulfillment_cx: RefCell::new(traits::FulfillmentContext::new()), } @@ -565,6 +564,7 @@ impl<'tcx> CheckEnv<'tcx> { locals: NodeMap(), node_types: NodeMap(), method_map: FnvHashMap(), + closure_tys: DefIdMap(), fn_sig_map: NodeMap(), deferred_call_resolutions: DefIdMap(), deferred_cast_checks: Vec::new(), diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index e232e997464c7..59dd461406a3e 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -232,7 +232,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { return } - for (def_id, closure_ty) in &*self.fcx.inh.closure_tys.borrow() { + for (def_id, closure_ty) in &self.check_env.closure_tys { let closure_ty = self.resolve(closure_ty, ResolvingClosure(*def_id)); self.fcx.tcx().closure_tys.borrow_mut().insert(*def_id, closure_ty); } From 98bf5695cc07becd11bd4cf9231b677b3124ad53 Mon Sep 17 00:00:00 2001 From: Joshua Yanovski Date: Sat, 9 May 2015 05:41:50 -0700 Subject: [PATCH 10/14] Removed RefCell from fulfillment_cx in typeck. --- src/librustc_typeck/astconv.rs | 245 +++++----- src/librustc_typeck/check/_match.rs | 42 +- src/librustc_typeck/check/callee.rs | 13 +- src/librustc_typeck/check/closure.rs | 19 +- src/librustc_typeck/check/coercion.rs | 6 +- src/librustc_typeck/check/demand.rs | 2 +- src/librustc_typeck/check/method/confirm.rs | 33 +- src/librustc_typeck/check/method/mod.rs | 26 +- src/librustc_typeck/check/method/probe.rs | 8 +- src/librustc_typeck/check/mod.rs | 493 +++++++++++--------- src/librustc_typeck/check/op.rs | 12 +- src/librustc_typeck/check/regionck.rs | 53 ++- src/librustc_typeck/check/upvar.rs | 12 +- src/librustc_typeck/check/vtable.rs | 28 +- src/librustc_typeck/check/wf.rs | 71 +-- src/librustc_typeck/check/writeback.rs | 12 +- src/librustc_typeck/collect.rs | 90 ++-- 17 files changed, 619 insertions(+), 546 deletions(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 694993cdc0aae..612e8b379d10f 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -92,7 +92,7 @@ pub trait AstConv<'tcx> { /// Returns the set of bounds in scope for the type parameter with /// the given id. - fn get_type_parameter_bounds(&self, span: Span, def_id: ast::NodeId) + fn get_type_parameter_bounds(&mut self, span: Span, def_id: ast::NodeId) -> Result>, ErrorReported>; /// Returns true if the trait with id `trait_def_id` defines an @@ -118,7 +118,7 @@ pub trait AstConv<'tcx> { /// signatures for that reason. In a function body, we can always /// handle it because we can use inference variables to remove the /// late-bound regions. - fn projected_ty_from_poly_trait_ref(&self, + fn projected_ty_from_poly_trait_ref(&mut self, span: Span, poly_trait_ref: ty::PolyTraitRef<'tcx>, item_name: ast::Name) @@ -137,7 +137,7 @@ pub trait AstConv<'tcx> { /// Project an associated type from a non-higher-ranked trait reference. /// This is fairly straightforward and can be accommodated in any context. - fn projected_ty(&self, + fn projected_ty(&mut self, span: Span, _trait_ref: ty::TraitRef<'tcx>, _item_name: ast::Name) @@ -187,7 +187,7 @@ pub fn ast_region_to_region(tcx: &ty::ctxt, lifetime: &ast::Lifetime) } pub fn opt_ast_region_to_region<'tcx>( - this: &AstConv<'tcx>, + this: &mut AstConv<'tcx>, rscope: &RegionScope, default_span: Span, opt_lifetime: &Option) -> ty::Region @@ -266,7 +266,7 @@ pub fn opt_ast_region_to_region<'tcx>( /// Given a path `path` that refers to an item `I` with the declared generics `decl_generics`, /// returns an appropriate set of substitutions for this particular reference to `I`. pub fn ast_path_substs_for_ty<'tcx>( - this: &AstConv<'tcx>, + this: &mut AstConv<'tcx>, rscope: &RegionScope, span: Span, param_mode: PathParamMode, @@ -274,8 +274,6 @@ pub fn ast_path_substs_for_ty<'tcx>( item_segment: &ast::PathSegment) -> Substs<'tcx> { - let tcx = this.tcx(); - // ast_path_substs() is only called to convert paths that are // known to refer to traits, types, or structs. In these cases, // all type parameters defined for the item being referenced will @@ -292,7 +290,7 @@ pub fn ast_path_substs_for_ty<'tcx>( convert_angle_bracketed_parameters(this, rscope, span, decl_generics, data) } ast::ParenthesizedParameters(ref data) => { - span_err!(tcx.sess, span, E0214, + span_err!(this.tcx().sess, span, E0214, "parenthesized parameters may only be used with a trait"); convert_parenthesized_parameters(this, rscope, span, decl_generics, data) } @@ -318,7 +316,7 @@ pub enum PathParamMode { } fn create_region_substs<'tcx>( - this: &AstConv<'tcx>, + this: &mut AstConv<'tcx>, rscope: &RegionScope, span: Span, decl_generics: &ty::Generics<'tcx>, @@ -362,7 +360,7 @@ fn create_region_substs<'tcx>( /// -- that is, a substitution with no types but the correct number of /// regions. fn create_substs_for_ast_path<'tcx>( - this: &AstConv<'tcx>, + this: &mut AstConv<'tcx>, span: Span, param_mode: PathParamMode, decl_generics: &ty::Generics<'tcx>, @@ -466,7 +464,7 @@ struct ConvertedBinding<'tcx> { span: Span, } -fn convert_angle_bracketed_parameters<'tcx>(this: &AstConv<'tcx>, +fn convert_angle_bracketed_parameters<'tcx>(this: &mut AstConv<'tcx>, rscope: &RegionScope, span: Span, decl_generics: &ty::Generics<'tcx>, @@ -533,7 +531,7 @@ fn find_implied_output_region(input_tys: &[Ty], input_pats: Vec) (implied_output_region, lifetimes_for_params) } -fn convert_ty_with_lifetime_elision<'tcx>(this: &AstConv<'tcx>, +fn convert_ty_with_lifetime_elision<'tcx>(this: &mut AstConv<'tcx>, implied_output_region: Option, param_lifetimes: Vec<(String, usize)>, ty: &ast::Ty) @@ -554,7 +552,7 @@ fn convert_ty_with_lifetime_elision<'tcx>(this: &AstConv<'tcx>, } } -fn convert_parenthesized_parameters<'tcx>(this: &AstConv<'tcx>, +fn convert_parenthesized_parameters<'tcx>(this: &mut AstConv<'tcx>, rscope: &RegionScope, span: Span, decl_generics: &ty::Generics<'tcx>, @@ -602,7 +600,7 @@ fn convert_parenthesized_parameters<'tcx>(this: &AstConv<'tcx>, } pub fn instantiate_poly_trait_ref<'tcx>( - this: &AstConv<'tcx>, + this: &mut AstConv<'tcx>, rscope: &RegionScope, ast_trait_ref: &ast::PolyTraitRef, self_ty: Option>, @@ -628,7 +626,7 @@ pub fn instantiate_poly_trait_ref<'tcx>( /// If the `projections` argument is `None`, then assoc type bindings like `Foo` /// are disallowed. Otherwise, they are pushed onto the vector given. pub fn instantiate_mono_trait_ref<'tcx>( - this: &AstConv<'tcx>, + this: &mut AstConv<'tcx>, rscope: &RegionScope, trait_ref: &ast::TraitRef, self_ty: Option>) @@ -644,7 +642,7 @@ pub fn instantiate_mono_trait_ref<'tcx>( trait_ref.path.segments.last().unwrap()) } -fn trait_def_id<'tcx>(this: &AstConv<'tcx>, trait_ref: &ast::TraitRef) -> ast::DefId { +fn trait_def_id<'tcx>(this: &mut AstConv<'tcx>, trait_ref: &ast::TraitRef) -> ast::DefId { let path = &trait_ref.path; match ::lookup_full_def(this.tcx(), path.span, trait_ref.ref_id) { def::DefTrait(trait_def_id) => trait_def_id, @@ -656,7 +654,7 @@ fn trait_def_id<'tcx>(this: &AstConv<'tcx>, trait_ref: &ast::TraitRef) -> ast::D } fn object_path_to_poly_trait_ref<'a,'tcx>( - this: &AstConv<'tcx>, + this: &mut AstConv<'tcx>, rscope: &RegionScope, span: Span, param_mode: PathParamMode, @@ -676,7 +674,7 @@ fn object_path_to_poly_trait_ref<'a,'tcx>( } fn ast_path_to_poly_trait_ref<'a,'tcx>( - this: &AstConv<'tcx>, + this: &mut AstConv<'tcx>, rscope: &RegionScope, span: Span, param_mode: PathParamMode, @@ -722,7 +720,7 @@ fn ast_path_to_poly_trait_ref<'a,'tcx>( poly_trait_ref } -fn ast_path_to_mono_trait_ref<'a,'tcx>(this: &AstConv<'tcx>, +fn ast_path_to_mono_trait_ref<'a,'tcx>(this: &mut AstConv<'tcx>, rscope: &RegionScope, span: Span, param_mode: PathParamMode, @@ -743,7 +741,7 @@ fn ast_path_to_mono_trait_ref<'a,'tcx>(this: &AstConv<'tcx>, ty::TraitRef::new(trait_def_id, substs) } -fn create_substs_for_ast_trait_ref<'a,'tcx>(this: &AstConv<'tcx>, +fn create_substs_for_ast_trait_ref<'a,'tcx>(this: &mut AstConv<'tcx>, rscope: &RegionScope, span: Span, param_mode: PathParamMode, @@ -807,14 +805,12 @@ fn create_substs_for_ast_trait_ref<'a,'tcx>(this: &AstConv<'tcx>, } fn ast_type_binding_to_poly_projection_predicate<'tcx>( - this: &AstConv<'tcx>, + this: &mut AstConv<'tcx>, mut trait_ref: ty::PolyTraitRef<'tcx>, self_ty: Option>, binding: &ConvertedBinding<'tcx>) -> Result, ErrorReported> { - let tcx = this.tcx(); - // Given something like `U : SomeTrait`, we want to produce a // predicate like `::T = X`. This is somewhat // subtle in the event that `T` is defined in a supertrait of @@ -850,19 +846,19 @@ fn ast_type_binding_to_poly_projection_predicate<'tcx>( // this, we currently insert a dummy type and then remove it // later. Yuck. - let dummy_self_ty = ty::mk_infer(tcx, ty::FreshTy(0)); + let dummy_self_ty = ty::mk_infer(this.tcx(), ty::FreshTy(0)); if self_ty.is_none() { // if converting for an object type let mut dummy_substs = trait_ref.skip_binder().substs.clone(); // binder moved here -+ assert!(dummy_substs.self_ty().is_none()); // | dummy_substs.types.push(SelfSpace, dummy_self_ty); // | trait_ref = ty::Binder(ty::TraitRef::new(trait_ref.def_id(), // <------------+ - tcx.mk_substs(dummy_substs))); + this.tcx().mk_substs(dummy_substs))); } try!(this.ensure_super_predicates(binding.span, trait_ref.def_id())); let mut candidates: Vec = - traits::supertraits(tcx, trait_ref.clone()) + traits::supertraits(this.tcx(), trait_ref.clone()) .filter(|r| this.trait_defines_associated_type_named(r.def_id(), binding.item_name)) .collect(); @@ -874,13 +870,13 @@ fn ast_type_binding_to_poly_projection_predicate<'tcx>( assert!(dummy_substs.self_ty() == Some(dummy_self_ty)); dummy_substs.types.pop(SelfSpace); *candidate = ty::Binder(ty::TraitRef::new(candidate.def_id(), - tcx.mk_substs(dummy_substs))); + this.tcx().mk_substs(dummy_substs))); } } - let candidate = try!(one_bound_for_assoc_type(tcx, + let candidate = try!(one_bound_for_assoc_type(this.tcx(), candidates, - &trait_ref.user_string(tcx), + &trait_ref.user_string(this.tcx()), &token::get_name(binding.item_name), binding.span)); @@ -894,7 +890,7 @@ fn ast_type_binding_to_poly_projection_predicate<'tcx>( } fn ast_path_to_ty<'tcx>( - this: &AstConv<'tcx>, + this: &mut AstConv<'tcx>, rscope: &RegionScope, span: Span, param_mode: PathParamMode, @@ -902,13 +898,12 @@ fn ast_path_to_ty<'tcx>( item_segment: &ast::PathSegment) -> Ty<'tcx> { - let tcx = this.tcx(); let (generics, decl_ty) = match this.get_item_type_scheme(span, did) { Ok(ty::TypeScheme { generics, ty: decl_ty }) => { (generics, decl_ty) } Err(ErrorReported) => { - return tcx.types.err; + return this.tcx().types.err; } }; @@ -930,7 +925,7 @@ fn ast_path_to_ty<'tcx>( type TraitAndProjections<'tcx> = (ty::PolyTraitRef<'tcx>, Vec>); -fn ast_ty_to_trait_ref<'tcx>(this: &AstConv<'tcx>, +fn ast_ty_to_trait_ref<'tcx>(this: &mut AstConv<'tcx>, rscope: &RegionScope, ty: &ast::Ty, bounds: &[ast::TyParamBound]) @@ -1013,7 +1008,7 @@ fn ast_ty_to_trait_ref<'tcx>(this: &AstConv<'tcx>, } } -fn trait_ref_to_object_type<'tcx>(this: &AstConv<'tcx>, +fn trait_ref_to_object_type<'tcx>(this: &mut AstConv<'tcx>, rscope: &RegionScope, span: Span, trait_ref: ty::PolyTraitRef<'tcx>, @@ -1035,7 +1030,7 @@ fn trait_ref_to_object_type<'tcx>(this: &AstConv<'tcx>, result } -fn make_object_type<'tcx>(this: &AstConv<'tcx>, +fn make_object_type<'tcx>(this: &mut AstConv<'tcx>, span: Span, principal: ty::PolyTraitRef<'tcx>, bounds: ty::ExistentialBounds<'tcx>) @@ -1096,14 +1091,12 @@ fn report_ambiguous_associated_type(tcx: &ty::ctxt, // (which might be `Self`, but only if it is the `Self` of a trait, not an // impl). This function will fail if there are no suitable bounds or there is // any ambiguity. -fn find_bound_for_assoc_item<'tcx>(this: &AstConv<'tcx>, +fn find_bound_for_assoc_item<'tcx>(this: &mut AstConv<'tcx>, ty_param_node_id: ast::NodeId, assoc_name: ast::Name, span: Span) -> Result, ErrorReported> { - let tcx = this.tcx(); - let bounds = match this.get_type_parameter_bounds(span, ty_param_node_id) { Ok(v) => v, Err(ErrorReported) => { @@ -1119,12 +1112,12 @@ fn find_bound_for_assoc_item<'tcx>(this: &AstConv<'tcx>, // Check that there is exactly one way to find an associated type with the // correct name. let suitable_bounds: Vec<_> = - traits::transitive_bounds(tcx, &bounds) + traits::transitive_bounds(this.tcx(), &bounds) .filter(|b| this.trait_defines_associated_type_named(b.def_id(), assoc_name)) .collect(); - let ty_param_name = tcx.type_parameter_def(ty_param_node_id).name; - one_bound_for_assoc_type(tcx, + let ty_param_name = this.tcx().type_parameter_def(ty_param_node_id).name; + one_bound_for_assoc_type(this.tcx(), suitable_bounds, &token::get_name(ty_param_name), &token::get_name(assoc_name), @@ -1172,19 +1165,18 @@ fn one_bound_for_assoc_type<'tcx>(tcx: &ty::ctxt<'tcx>, // the whole path. // Will fail except for T::A and Self::A; i.e., if ty/ty_path_def are not a type // parameter or Self. -fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>, +fn associated_path_def_to_ty<'tcx>(this: &mut AstConv<'tcx>, span: Span, ty: Ty<'tcx>, ty_path_def: def::Def, item_segment: &ast::PathSegment) -> (Ty<'tcx>, def::Def) { - let tcx = this.tcx(); let assoc_name = item_segment.identifier.name; - debug!("associated_path_def_to_ty: {}::{}", ty.repr(tcx), token::get_name(assoc_name)); + debug!("associated_path_def_to_ty: {}::{}", ty.repr(this.tcx()), token::get_name(assoc_name)); - check_path_args(tcx, slice::ref_slice(item_segment), NO_TPS | NO_REGIONS); + check_path_args(this.tcx(), slice::ref_slice(item_segment), NO_TPS | NO_REGIONS); // Find the type of the associated item, and the trait where the associated // item is declared. @@ -1192,10 +1184,10 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>, (_, def::DefSelfTy(Some(trait_did), Some((impl_id, _)))) => { // `Self` in an impl of a trait - we have a concrete self type and a // trait reference. - match tcx.map.expect_item(impl_id).node { + match this.tcx().map.expect_item(impl_id).node { ast::ItemImpl(_, _, _, Some(ref trait_ref), _, _) => { if this.ensure_super_predicates(span, trait_did).is_err() { - return (tcx.types.err, ty_path_def); + return (this.tcx().types.err, ty_path_def); } let trait_segment = &trait_ref.path.segments.last().unwrap(); @@ -1208,18 +1200,18 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>, trait_segment); let candidates: Vec = - traits::supertraits(tcx, ty::Binder(trait_ref.clone())) + traits::supertraits(this.tcx(), ty::Binder(trait_ref.clone())) .filter(|r| this.trait_defines_associated_type_named(r.def_id(), assoc_name)) .collect(); - match one_bound_for_assoc_type(tcx, + match one_bound_for_assoc_type(this.tcx(), candidates, "Self", &token::get_name(assoc_name), span) { Ok(bound) => bound, - Err(ErrorReported) => return (tcx.types.err, ty_path_def), + Err(ErrorReported) => return (this.tcx().types.err, ty_path_def), } } _ => unreachable!() @@ -1232,16 +1224,16 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>, let ty_param_node_id = ty_path_def.local_node_id(); match find_bound_for_assoc_item(this, ty_param_node_id, assoc_name, span) { Ok(bound) => bound, - Err(ErrorReported) => return (tcx.types.err, ty_path_def), + Err(ErrorReported) => return (this.tcx().types.err, ty_path_def), } } _ => { - report_ambiguous_associated_type(tcx, + report_ambiguous_associated_type(this.tcx(), span, - &ty.user_string(tcx), + &ty.user_string(this.tcx()), "Trait", &token::get_name(assoc_name)); - return (tcx.types.err, ty_path_def); + return (this.tcx().types.err, ty_path_def); } }; @@ -1251,7 +1243,7 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>, let item_did = if trait_did.krate == ast::LOCAL_CRATE { // `ty::trait_items` used below requires information generated // by type collection, which may be in progress at this point. - match tcx.map.expect_item(trait_did.node).node { + match this.tcx().map.expect_item(trait_did.node).node { ast::ItemTrait(_, _, _, ref trait_items) => { let item = trait_items.iter() .find(|i| i.ident.name == assoc_name) @@ -1261,7 +1253,7 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>, _ => unreachable!() } } else { - let trait_items = ty::trait_items(tcx, trait_did); + let trait_items = ty::trait_items(this.tcx(), trait_did); let item = trait_items.iter().find(|i| i.name() == assoc_name); item.expect("missing associated type").def_id() }; @@ -1269,7 +1261,7 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>, (ty, def::DefAssociatedTy(trait_did, item_did)) } -fn qpath_to_ty<'tcx>(this: &AstConv<'tcx>, +fn qpath_to_ty<'tcx>(this: &mut AstConv<'tcx>, rscope: &RegionScope, span: Span, param_mode: PathParamMode, @@ -1279,23 +1271,21 @@ fn qpath_to_ty<'tcx>(this: &AstConv<'tcx>, item_segment: &ast::PathSegment) -> Ty<'tcx> { - let tcx = this.tcx(); - - check_path_args(tcx, slice::ref_slice(item_segment), NO_TPS | NO_REGIONS); + check_path_args(this.tcx(), slice::ref_slice(item_segment), NO_TPS | NO_REGIONS); let self_ty = if let Some(ty) = opt_self_ty { ty } else { - let path_str = ty::item_path_str(tcx, trait_def_id); - report_ambiguous_associated_type(tcx, + let path_str = ty::item_path_str(this.tcx(), trait_def_id); + report_ambiguous_associated_type(this.tcx(), span, "Type", &path_str, &token::get_ident(item_segment.identifier)); - return tcx.types.err; + return this.tcx().types.err; }; - debug!("qpath_to_ty: self_type={}", self_ty.repr(tcx)); + debug!("qpath_to_ty: self_type={}", self_ty.repr(this.tcx())); let trait_ref = ast_path_to_mono_trait_ref(this, rscope, @@ -1305,7 +1295,7 @@ fn qpath_to_ty<'tcx>(this: &AstConv<'tcx>, Some(self_ty), trait_segment); - debug!("qpath_to_ty: trait_ref={}", trait_ref.repr(tcx)); + debug!("qpath_to_ty: trait_ref={}", trait_ref.repr(this.tcx())); this.projected_ty(span, trait_ref, item_segment.identifier.name) } @@ -1324,7 +1314,7 @@ fn qpath_to_ty<'tcx>(this: &AstConv<'tcx>, /// * `region_substs`: a partial substitution consisting of /// only the region type parameters being supplied to this type. /// * `ast_ty`: the ast representation of the type being supplied -pub fn ast_ty_arg_to_ty<'tcx>(this: &AstConv<'tcx>, +pub fn ast_ty_arg_to_ty<'tcx>(this: &mut AstConv<'tcx>, rscope: &RegionScope, decl_generics: &ty::Generics<'tcx>, index: usize, @@ -1332,10 +1322,8 @@ pub fn ast_ty_arg_to_ty<'tcx>(this: &AstConv<'tcx>, ast_ty: &ast::Ty) -> Ty<'tcx> { - let tcx = this.tcx(); - if let Some(def) = decl_generics.types.opt_get(TypeSpace, index) { - let object_lifetime_default = def.object_lifetime_default.subst(tcx, region_substs); + let object_lifetime_default = def.object_lifetime_default.subst(this.tcx(), region_substs); let rscope1 = &ObjectLifetimeDefaultRscope::new(rscope, object_lifetime_default); ast_ty_to_ty(this, rscope1, ast_ty) } else { @@ -1346,7 +1334,7 @@ pub fn ast_ty_arg_to_ty<'tcx>(this: &AstConv<'tcx>, // Check the base def in a PathResolution and convert it to a Ty. If there are // associated types in the PathResolution, these will need to be seperately // resolved. -fn base_def_to_ty<'tcx>(this: &AstConv<'tcx>, +fn base_def_to_ty<'tcx>(this: &mut AstConv<'tcx>, rscope: &RegionScope, span: Span, param_mode: PathParamMode, @@ -1354,8 +1342,6 @@ fn base_def_to_ty<'tcx>(this: &AstConv<'tcx>, opt_self_ty: Option>, base_segments: &[ast::PathSegment]) -> Ty<'tcx> { - let tcx = this.tcx(); - match *def { def::DefTrait(trait_def_id) => { // N.B. this case overlaps somewhat with @@ -1370,7 +1356,7 @@ fn base_def_to_ty<'tcx>(this: &AstConv<'tcx>, base_segments.last().unwrap(), &mut projection_bounds); - check_path_args(tcx, base_segments.init(), NO_TPS | NO_REGIONS); + check_path_args(this.tcx(), base_segments.init(), NO_TPS | NO_REGIONS); trait_ref_to_object_type(this, rscope, span, @@ -1379,7 +1365,7 @@ fn base_def_to_ty<'tcx>(this: &AstConv<'tcx>, &[]) } def::DefTy(did, _) | def::DefStruct(did) => { - check_path_args(tcx, base_segments.init(), NO_TPS | NO_REGIONS); + check_path_args(this.tcx(), base_segments.init(), NO_TPS | NO_REGIONS); ast_path_to_ty(this, rscope, span, @@ -1388,25 +1374,25 @@ fn base_def_to_ty<'tcx>(this: &AstConv<'tcx>, base_segments.last().unwrap()) } def::DefTyParam(space, index, _, name) => { - check_path_args(tcx, base_segments, NO_TPS | NO_REGIONS); - ty::mk_param(tcx, space, index, name) + check_path_args(this.tcx(), base_segments, NO_TPS | NO_REGIONS); + ty::mk_param(this.tcx(), space, index, name) } def::DefSelfTy(_, Some((_, self_ty_id))) => { // Self in impl (we know the concrete type). - check_path_args(tcx, base_segments, NO_TPS | NO_REGIONS); - if let Some(&ty) = tcx.ast_ty_to_ty_cache.borrow().get(&self_ty_id) { + check_path_args(this.tcx(), base_segments, NO_TPS | NO_REGIONS); + if let Some(&ty) = this.tcx().ast_ty_to_ty_cache.borrow().get(&self_ty_id) { ty } else { - tcx.sess.span_bug(span, "self type has not been fully resolved") + this.tcx().sess.span_bug(span, "self type has not been fully resolved") } } def::DefSelfTy(Some(_), None) => { // Self in trait. - check_path_args(tcx, base_segments, NO_TPS | NO_REGIONS); - ty::mk_self_type(tcx) + check_path_args(this.tcx(), base_segments, NO_TPS | NO_REGIONS); + ty::mk_self_type(this.tcx()) } def::DefAssociatedTy(trait_did, _) => { - check_path_args(tcx, &base_segments[..base_segments.len()-2], NO_TPS | NO_REGIONS); + check_path_args(this.tcx(), &base_segments[..base_segments.len()-2], NO_TPS | NO_REGIONS); qpath_to_ty(this, rscope, span, @@ -1426,21 +1412,21 @@ fn base_def_to_ty<'tcx>(this: &AstConv<'tcx>, // we don't have the trait information around, which is just sad. if !base_segments.is_empty() { - span_err!(tcx.sess, + span_err!(this.tcx().sess, span, E0247, "found module name used as a type: {}", - tcx.map.node_to_string(id.node)); + this.tcx().map.node_to_string(id.node)); return this.tcx().types.err; } opt_self_ty.expect("missing T in ::a::b::c") } def::DefPrimTy(prim_ty) => { - prim_ty_to_ty(tcx, base_segments, prim_ty) + prim_ty_to_ty(this.tcx(), base_segments, prim_ty) } _ => { - span_err!(tcx.sess, span, E0248, + span_err!(this.tcx().sess, span, E0248, "found value name used as a type: {:?}", *def); return this.tcx().types.err; } @@ -1449,7 +1435,7 @@ fn base_def_to_ty<'tcx>(this: &AstConv<'tcx>, // Note that both base_segments and assoc_segments may be empty, although not at // the same time. -pub fn finish_resolving_def_to_ty<'tcx>(this: &AstConv<'tcx>, +pub fn finish_resolving_def_to_ty<'tcx>(this: &mut AstConv<'tcx>, rscope: &RegionScope, span: Span, param_mode: PathParamMode, @@ -1485,7 +1471,7 @@ pub fn finish_resolving_def_to_ty<'tcx>(this: &AstConv<'tcx>, /// Parses the programmer's textual representation of a type into our /// internal notion of a type. -pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>, +pub fn ast_ty_to_ty<'tcx>(this: &mut AstConv<'tcx>, rscope: &RegionScope, ast_ty: &ast::Ty) -> Ty<'tcx> @@ -1493,15 +1479,14 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>, debug!("ast_ty_to_ty(ast_ty={})", ast_ty.repr(this.tcx())); - let tcx = this.tcx(); - - if let Some(&ty) = tcx.ast_ty_to_ty_cache.borrow().get(&ast_ty.id) { + if let Some(&ty) = this.tcx().ast_ty_to_ty_cache.borrow().get(&ast_ty.id) { return ty; } let typ = match ast_ty.node { ast::TyVec(ref ty) => { - ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty), None) + let ast_ty = ast_ty_to_ty(this, rscope, &**ty); + ty::mk_vec(this.tcx(), ast_ty, None) } ast::TyObjectSum(ref ty, ref bounds) => { match ast_ty_to_trait_ref(this, rscope, &**ty, bounds) { @@ -1519,8 +1504,9 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>, } } ast::TyPtr(ref mt) => { - ty::mk_ptr(tcx, ty::mt { - ty: ast_ty_to_ty(this, rscope, &*mt.ty), + let ast_ty = ast_ty_to_ty(this, rscope, &*mt.ty); + ty::mk_ptr(this.tcx(), ty::mt { + ty: ast_ty, mutbl: mt.mutbl }) } @@ -1532,28 +1518,28 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>, rscope, Some(ty::ObjectLifetimeDefault::Specific(r))); let t = ast_ty_to_ty(this, rscope1, &*mt.ty); - ty::mk_rptr(tcx, tcx.mk_region(r), ty::mt {ty: t, mutbl: mt.mutbl}) + ty::mk_rptr(this.tcx(), this.tcx().mk_region(r), ty::mt {ty: t, mutbl: mt.mutbl}) } ast::TyTup(ref fields) => { let flds = fields.iter() .map(|t| ast_ty_to_ty(this, rscope, &**t)) .collect(); - ty::mk_tup(tcx, flds) + ty::mk_tup(this.tcx(), flds) } ast::TyParen(ref typ) => ast_ty_to_ty(this, rscope, &**typ), ast::TyBareFn(ref bf) => { if bf.decl.variadic && bf.abi != abi::C { - span_err!(tcx.sess, ast_ty.span, E0222, + span_err!(this.tcx().sess, ast_ty.span, E0222, "variadic function must have C calling convention"); } let bare_fn = ty_of_bare_fn(this, bf.unsafety, bf.abi, &*bf.decl); - ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(bare_fn)) + ty::mk_bare_fn(this.tcx(), None, this.tcx().mk_bare_fn(bare_fn)) } ast::TyPolyTraitRef(ref bounds) => { conv_ty_poly_trait_ref(this, rscope, ast_ty.span, bounds) } ast::TyPath(ref maybe_qself, ref path) => { - let path_res = if let Some(&d) = tcx.def_map.borrow().get(&ast_ty.id) { + let path_res = if let Some(&d) = this.tcx().def_map.borrow().get(&ast_ty.id) { d } else if let Some(ast::QSelf { position: 0, .. }) = *maybe_qself { // Create some fake resolution that can't possibly be a type. @@ -1563,8 +1549,8 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>, depth: path.segments.len() } } else { - tcx.sess.span_bug(ast_ty.span, - &format!("unbound path {}", ast_ty.repr(tcx))) + this.tcx().sess.span_bug(ast_ty.span, + &format!("unbound path {}", ast_ty.repr(this.tcx()))) }; let def = path_res.base_def; let base_ty_end = path.segments.len() - path_res.depth; @@ -1582,7 +1568,7 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>, if path_res.depth != 0 && ty.sty != ty::ty_err { // Write back the new resolution. - tcx.def_map.borrow_mut().insert(ast_ty.id, def::PathResolution { + this.tcx().def_map.borrow_mut().insert(ast_ty.id, def::PathResolution { base_def: def, last_private: path_res.last_private, depth: 0 @@ -1592,17 +1578,21 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>, ty } ast::TyFixedLengthVec(ref ty, ref e) => { - match const_eval::eval_const_expr_partial(tcx, &**e, Some(tcx.types.usize)) { + match const_eval::eval_const_expr_partial(this.tcx(), &**e, Some(this.tcx().types.usize)) { Ok(r) => { match r { - const_eval::const_int(i) => - ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty), - Some(i as usize)), - const_eval::const_uint(i) => - ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty), - Some(i as usize)), + const_eval::const_int(i) => { + let ast_ty = ast_ty_to_ty(this, rscope, &**ty); + ty::mk_vec(this.tcx(), ast_ty, + Some(i as usize)) + }, + const_eval::const_uint(i) => { + let ast_ty = ast_ty_to_ty(this, rscope, &**ty); + ty::mk_vec(this.tcx(), ast_ty, + Some(i as usize)) + }, _ => { - span_err!(tcx.sess, ast_ty.span, E0249, + span_err!(this.tcx().sess, ast_ty.span, E0249, "expected constant expr for array length"); this.tcx().types.err } @@ -1611,18 +1601,18 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>, Err(ref r) => { let subspan = ast_ty.span.lo <= r.span.lo && r.span.hi <= ast_ty.span.hi; - span_err!(tcx.sess, r.span, E0250, + span_err!(this.tcx().sess, r.span, E0250, "array length constant evaluation error: {}", r.description()); if !subspan { - span_note!(tcx.sess, ast_ty.span, "for array length here") + span_note!(this.tcx().sess, ast_ty.span, "for array length here") } this.tcx().types.err } } } ast::TyTypeof(ref _e) => { - tcx.sess.span_bug(ast_ty.span, "typeof is reserved but unimplemented"); + this.tcx().sess.span_bug(ast_ty.span, "typeof is reserved but unimplemented"); } ast::TyInfer => { // TyInfer also appears as the type of arguments or return @@ -1633,11 +1623,11 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>, } }; - tcx.ast_ty_to_ty_cache.borrow_mut().insert(ast_ty.id, typ); + this.tcx().ast_ty_to_ty_cache.borrow_mut().insert(ast_ty.id, typ); return typ; } -pub fn ty_of_arg<'tcx>(this: &AstConv<'tcx>, +pub fn ty_of_arg<'tcx>(this: &mut AstConv<'tcx>, rscope: &RegionScope, a: &ast::Arg, expected_ty: Option>) @@ -1655,7 +1645,7 @@ struct SelfInfo<'a, 'tcx> { explicit_self: &'a ast::ExplicitSelf, } -pub fn ty_of_method<'tcx>(this: &AstConv<'tcx>, +pub fn ty_of_method<'tcx>(this: &mut AstConv<'tcx>, sig: &ast::MethodSig, untransformed_self_ty: Ty<'tcx>) -> (ty::BareFnTy<'tcx>, ty::ExplicitSelfCategory) { @@ -1672,13 +1662,13 @@ pub fn ty_of_method<'tcx>(this: &AstConv<'tcx>, (bare_fn_ty, optional_explicit_self_category.unwrap()) } -pub fn ty_of_bare_fn<'tcx>(this: &AstConv<'tcx>, unsafety: ast::Unsafety, abi: abi::Abi, +pub fn ty_of_bare_fn<'tcx>(this: &mut AstConv<'tcx>, unsafety: ast::Unsafety, abi: abi::Abi, decl: &ast::FnDecl) -> ty::BareFnTy<'tcx> { let (bare_fn_ty, _) = ty_of_method_or_bare_fn(this, unsafety, abi, None, decl); bare_fn_ty } -fn ty_of_method_or_bare_fn<'a, 'tcx>(this: &AstConv<'tcx>, +fn ty_of_method_or_bare_fn<'a, 'tcx>(this: &mut AstConv<'tcx>, unsafety: ast::Unsafety, abi: abi::Abi, opt_self_info: Option>, @@ -1737,12 +1727,13 @@ fn ty_of_method_or_bare_fn<'a, 'tcx>(this: &AstConv<'tcx>, } else { &decl.inputs[..] }; - let input_tys = input_params.iter().map(|a| ty_of_arg(this, &rb, a, None)); let input_pats: Vec = input_params.iter() .map(|a| pprust::pat_to_string(&*a.pat)) .collect(); - let self_and_input_tys: Vec = - self_ty.into_iter().chain(input_tys).collect(); + let self_and_input_tys: Vec = { + let input_tys = input_params.iter().map(|a| ty_of_arg(this, &rb, a, None)); + self_ty.into_iter().chain(input_tys).collect() + }; // Second, if there was exactly one lifetime (either a substitution or a @@ -1786,7 +1777,7 @@ fn ty_of_method_or_bare_fn<'a, 'tcx>(this: &AstConv<'tcx>, }, explicit_self_category_result) } -fn determine_explicit_self_category<'a, 'tcx>(this: &AstConv<'tcx>, +fn determine_explicit_self_category<'a, 'tcx>(this: &mut AstConv<'tcx>, rscope: &RegionScope, self_info: &SelfInfo<'a, 'tcx>) -> ty::ExplicitSelfCategory @@ -1867,7 +1858,7 @@ fn determine_explicit_self_category<'a, 'tcx>(this: &AstConv<'tcx>, } pub fn ty_of_closure<'tcx>( - this: &AstConv<'tcx>, + this: &mut AstConv<'tcx>, unsafety: ast::Unsafety, decl: &ast::FnDecl, abi: abi::Abi, @@ -1930,7 +1921,7 @@ pub fn ty_of_closure<'tcx>( /// for closures. Eventually this should all be normalized, I think, so that there is no "main /// trait ref" and instead we just have a flat list of bounds as the existential type. fn conv_existential_bounds<'tcx>( - this: &AstConv<'tcx>, + this: &mut AstConv<'tcx>, rscope: &RegionScope, span: Span, principal_trait_ref: ty::PolyTraitRef<'tcx>, @@ -1946,7 +1937,7 @@ fn conv_existential_bounds<'tcx>( } fn conv_ty_poly_trait_ref<'tcx>( - this: &AstConv<'tcx>, + this: &mut AstConv<'tcx>, rscope: &RegionScope, span: Span, ast_bounds: &[ast::TyParamBound]) @@ -1980,7 +1971,7 @@ fn conv_ty_poly_trait_ref<'tcx>( } pub fn conv_existential_bounds_from_partitioned_bounds<'tcx>( - this: &AstConv<'tcx>, + this: &mut AstConv<'tcx>, rscope: &RegionScope, span: Span, principal_trait_ref: ty::PolyTraitRef<'tcx>, @@ -2020,7 +2011,7 @@ pub fn conv_existential_bounds_from_partitioned_bounds<'tcx>( /// user provided, if they provided one, and otherwise search the supertypes of trait bounds for /// region bounds. It may be that we can derive no bound at all, in which case we return `None`. fn compute_object_lifetime_bound<'tcx>( - this: &AstConv<'tcx>, + this: &mut AstConv<'tcx>, rscope: &RegionScope, span: Span, explicit_region_bounds: &[&ast::Lifetime], diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index bb85fb3debeec..7afba53bf3c97 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -17,7 +17,7 @@ use middle::privacy::{AllPublic, LastMod}; use middle::subst::Substs; use middle::ty::{self, Ty}; use super::{check_expr, check_expr_has_type, check_expr_with_expectation}; -use super::{check_expr_coercable_to_type, demand, CheckEnv, FnCtxt, FnCtxtTyper, Expectation}; +use super::{check_expr_coercable_to_type, demand, CheckEnv, FnCtxt, FnCtxtJoined, Expectation}; use super::{instantiate_path, resolve_ty_and_def_ufcs, structurally_resolved_type}; use require_same_types; use util::nodemap::FnvHashMap; @@ -50,7 +50,7 @@ pub fn check_pat<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, } ast::PatLit(ref lt) => { check_expr(check_env, fcx, &**lt); - let expr_ty = fcx.expr_ty(check_env, &**lt); + let expr_ty = fcx.expr_ty(&check_env.tt.node_types, &**lt); // Byte string patterns behave the same way as array patterns // They can denote both statically and dynamically sized byte arrays @@ -88,8 +88,8 @@ pub fn check_pat<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, check_expr(check_env, fcx, &**begin); check_expr(check_env, fcx, &**end); - let lhs_ty = fcx.expr_ty(check_env, &**begin); - let rhs_ty = fcx.expr_ty(check_env, &**end); + let lhs_ty = fcx.expr_ty(&check_env.tt.node_types, &**begin); + let rhs_ty = fcx.expr_ty(&check_env.tt.node_types, &**end); let lhs_eq_rhs = require_same_types( @@ -127,8 +127,8 @@ pub fn check_pat<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, let const_scheme = ty::lookup_item_type(tcx, const_did); assert!(const_scheme.generics.is_empty()); let const_ty = { - let typer = FnCtxtTyper::new(check_env, fcx); - typer.instantiate_type_scheme(pat.span, + let mut joined = FnCtxtJoined::new(check_env, fcx); + joined.instantiate_type_scheme(pat.span, &Substs::empty(), &const_scheme.ty) }; @@ -190,8 +190,8 @@ pub fn check_pat<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, } ast::PatQPath(ref qself, ref path) => { let self_ty = { - let typer = FnCtxtTyper::new(check_env, fcx); - typer.to_ty(&qself.ty) + let mut joined = FnCtxtJoined::new(check_env, fcx); + joined.to_ty(&qself.ty) }; let path_res = if let Some(&d) = tcx.def_map.borrow().get(&pat.id) { d @@ -215,7 +215,7 @@ pub fn check_pat<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, instantiate_path(check_env, fcx, segments, scheme, &predicates, opt_ty, def, pat.span, pat.id); - let const_ty = fcx.node_ty(check_env, pat.id); + let const_ty = fcx.node_ty(&check_env.tt.node_types, pat.id); demand::suptype(fcx, pat.span, expected, const_ty); } else { fcx.write_error(check_env, pat.id) @@ -426,7 +426,7 @@ pub fn check_match<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, let discrim_ty; if contains_ref_bindings { check_expr(check_env, fcx, discrim); - discrim_ty = fcx.expr_ty(check_env, discrim); + discrim_ty = fcx.expr_ty(&check_env.tt.node_types, discrim); } else { // ...but otherwise we want to use any supertype of the // discriminant. This is sort of a workaround, see note (*) in @@ -470,7 +470,7 @@ pub fn check_match<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, } _ => { check_expr_with_expectation(check_env, fcx, &*arm.body, expected); - fcx.node_ty(check_env, arm.body.id) + fcx.node_ty(&check_env.tt.node_types, arm.body.id) } }; @@ -567,7 +567,7 @@ fn check_pat_struct<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, pat.span, pat.id); - let pat_ty = fcx.node_ty(check_env, pat.id); + let pat_ty = fcx.node_ty(&check_env.tt.node_types, pat.id); demand::eqtype(fcx, pat.span, expected, pat_ty); let item_substs = fcx @@ -632,32 +632,32 @@ fn check_pat_enum<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, // associated const, and we should quit now, since the rest of this // function uses checks specific to structs and enums. if path_res.depth != 0 { - let pat_ty = fcx.node_ty(check_env, pat.id); + let pat_ty = fcx.node_ty(&check_env.tt.node_types, pat.id); demand::suptype(fcx, pat.span, expected, pat_ty); return; } - let pat_ty = fcx.node_ty(check_env, pat.id); + let pat_ty = fcx.node_ty(&check_env.tt.node_types, pat.id); demand::eqtype(fcx, pat.span, expected, pat_ty); - let real_path_ty = fcx.node_ty(check_env, pat.id); + let real_path_ty = fcx.node_ty(&check_env.tt.node_types, pat.id); let (arg_tys, kind_name): (Vec<_>, &'static str) = match real_path_ty.sty { ty::ty_enum(enum_def_id, expected_substs) if def == def::DefVariant(enum_def_id, def.def_id(), false) => { let variant = ty::enum_variant_with_id(tcx, enum_def_id, def.def_id()); - let typer = FnCtxtTyper::new(check_env, fcx); + let mut joined = FnCtxtJoined::new(check_env, fcx); (variant.args.iter() - .map(|t| typer.instantiate_type_scheme(pat.span, expected_substs, t)) + .map(|t| joined.instantiate_type_scheme(pat.span, expected_substs, t)) .collect(), "variant") } ty::ty_struct(struct_def_id, expected_substs) => { let struct_fields = ty::struct_fields(tcx, struct_def_id, expected_substs); - let typer = FnCtxtTyper::new(check_env, fcx); + let mut joined = FnCtxtJoined::new(check_env, fcx); (struct_fields.iter() - .map(|field| typer.instantiate_type_scheme(pat.span, + .map(|field| joined.instantiate_type_scheme(pat.span, expected_substs, &field.mt.ty)) .collect(), @@ -754,8 +754,8 @@ fn check_struct_pat_fields<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, }; let field_type = { - let typer = FnCtxtTyper::new(check_env, pcx.fcx); - typer.normalize_associated_types_in(span, &field_type) + let mut joined = FnCtxtJoined::new(check_env, pcx.fcx); + joined.normalize_associated_types_in(span, &field_type) }; check_pat(check_env, pcx, &*field.pat, field_type); diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index 03fcd3bbe9342..8b3f9437c0dee 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -20,6 +20,7 @@ use super::Expectation; use super::expected_types_for_fn_args; use super::FnCtxt; use super::FnCtxtTyper; +use super::FnCtxtJoined; use super::LvaluePreference; use super::method; use super::structurally_resolved_type; @@ -77,7 +78,7 @@ pub fn check_call<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, expected: Expectation<'tcx>) { check_expr(check_env, fcx, callee_expr); - let original_callee_ty = fcx.expr_ty(check_env, callee_expr); + let original_callee_ty = fcx.expr_ty(&check_env.tt.node_types, callee_expr); let (callee_ty, _, result) = autoderef(check_env, fcx, @@ -145,7 +146,7 @@ fn try_overloaded_call_step<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, // haven't yet decided on whether the closure is fn vs // fnmut vs fnonce. If so, we have to defer further processing. let fn_sig = { - let typer = FnCtxtTyper::new(check_env, fcx); + let typer = FnCtxtTyper::new(&check_env.tt, fcx); match typer.closure_kind(def_id) { Some(_) => None, None => Some({ @@ -269,8 +270,8 @@ fn confirm_builtin_call<'a,'tcx>(check_env: &mut CheckEnv<'tcx>, infer::FnCall, fn_sig).0; let fn_sig = { - let typer = FnCtxtTyper::new(check_env, fcx); - typer.normalize_associated_types_in(call_expr.span, &fn_sig) + let mut joined = FnCtxtJoined::new(check_env, fcx); + joined.normalize_associated_types_in(call_expr.span, &fn_sig) }; // Call the generic checker. @@ -352,7 +353,7 @@ fn write_overloaded_call_method_map<'a,'tcx>(check_env: &mut CheckEnv<'tcx>, call_expr: &ast::Expr, method_callee: ty::MethodCallee<'tcx>) { let method_call = ty::MethodCall::expr(call_expr.id); - check_env.method_map.insert(method_call, method_callee); + check_env.tt.method_map.insert(method_call, method_callee); } struct CallResolution<'tcx> { @@ -385,7 +386,7 @@ impl<'tcx> DeferredCallResolution<'tcx> for CallResolution<'tcx> { // we should not be invoked until the closure kind has been // determined by upvar inference { - let typer = FnCtxtTyper::new(check_env, fcx); + let typer = FnCtxtTyper::new(&check_env.tt, fcx); assert!(typer.closure_kind(self.closure_def_id).is_some()); } diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 705d7f70bd6c4..c3ef630f3bc14 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -10,7 +10,7 @@ //! Code for type-checking closure expressions. -use super::{check_fn, CheckEnv, Expectation, FnCtxt, FnCtxtTyper}; +use super::{check_fn, CheckEnv, Expectation, FnCtxt, FnCtxtJoined}; use astconv; use middle::region; @@ -37,7 +37,7 @@ pub fn check_expr_closure<'a,'tcx>(check_env: &mut CheckEnv<'tcx>, // closure sooner rather than later, so first examine the expected // type, and see if can glean a closure kind from there. let (expected_sig,expected_kind) = match expected.to_option(fcx) { - Some(ty) => deduce_expectations_from_expected_type(fcx, ty), + Some(ty) => deduce_expectations_from_expected_type(check_env, fcx, ty), None => (None, None) }; check_closure(check_env, fcx, expr, expected_kind, decl, body, expected_sig) @@ -57,9 +57,9 @@ fn check_closure<'a,'tcx>(check_env: &mut CheckEnv<'tcx>, expected_sig.repr(fcx.tcx())); let mut fn_ty = { - let typer = FnCtxtTyper::new(check_env, fcx); + let mut joined = FnCtxtJoined::new(check_env, fcx); astconv::ty_of_closure( - &typer, + &mut joined, ast::Unsafety::Normal, decl, abi::RustCall, @@ -97,7 +97,7 @@ fn check_closure<'a,'tcx>(check_env: &mut CheckEnv<'tcx>, fn_ty.sig.repr(fcx.tcx()), opt_kind); - check_env.closure_tys.insert(expr_def_id, fn_ty); + check_env.tt.closure_tys.insert(expr_def_id, fn_ty); match opt_kind { Some(kind) => { fcx.inh.closure_kinds.borrow_mut().insert(expr_def_id, kind); } None => { } @@ -105,6 +105,7 @@ fn check_closure<'a,'tcx>(check_env: &mut CheckEnv<'tcx>, } fn deduce_expectations_from_expected_type<'a,'tcx>( + check_env: &mut CheckEnv<'tcx>, fcx: &FnCtxt<'a,'tcx>, expected_ty: Ty<'tcx>) -> (Option>,Option) @@ -123,7 +124,7 @@ fn deduce_expectations_from_expected_type<'a,'tcx>( (sig, kind) } ty::ty_infer(ty::TyVar(vid)) => { - deduce_expectations_from_obligations(fcx, vid) + deduce_expectations_from_obligations(check_env, fcx, vid) } _ => { (None, None) @@ -132,15 +133,15 @@ fn deduce_expectations_from_expected_type<'a,'tcx>( } fn deduce_expectations_from_obligations<'a,'tcx>( + check_env: &mut CheckEnv<'tcx>, fcx: &FnCtxt<'a,'tcx>, expected_vid: ty::TyVid) -> (Option>, Option) { - let fulfillment_cx = fcx.inh.fulfillment_cx.borrow(); // Here `expected_ty` is known to be a type inference variable. let expected_sig = - fulfillment_cx + check_env.fulfillment_cx .pending_obligations() .iter() .filter_map(|obligation| { @@ -167,7 +168,7 @@ fn deduce_expectations_from_obligations<'a,'tcx>( // like `F : Fn`. Note that due to subtyping we could encounter // many viable options, so pick the most restrictive. let expected_kind = - fulfillment_cx + check_env.fulfillment_cx .pending_obligations() .iter() .filter_map(|obligation| { diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index 9994a32620d27..033afd04570a9 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -522,7 +522,8 @@ pub fn mk_assignty<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, // If the type is `Foo+'a`, ensures that the type // being cast to `Foo+'a` implements `Foo`: - vtable::register_object_cast_obligations(fcx, + vtable::register_object_cast_obligations(check_env, + fcx, expr.span, ty_trait, source); @@ -534,7 +535,8 @@ pub fn mk_assignty<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, body_id: fcx.body_id, code: traits::ObjectCastObligation(source) }; - fcx.register_region_obligation(source, ty_trait.bounds.region_bound, cause); + fcx.register_region_obligation(check_env, + source, ty_trait.bounds.region_bound, cause); } } } diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index fd9c4859affb2..b3c76b56b282b 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -59,7 +59,7 @@ pub fn coerce<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, sp: Span, expected: Ty<'tcx>, expr: &ast::Expr) { - let expr_ty = fcx.expr_ty(check_env, expr); + let expr_ty = fcx.expr_ty(&check_env.tt.node_types, expr); debug!("demand::coerce(expected = {}, expr_ty = {})", expected.repr(fcx.ccx.tcx), expr_ty.repr(fcx.ccx.tcx)); diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 57362e2800bbb..e1e1b9e49fa4b 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -10,7 +10,7 @@ use super::probe; -use check::{self, CheckEnv, FnCtxt, FnCtxtTyper, NoPreference, PreferMutLvalue, callee, demand}; +use check::{self, CheckEnv, FnCtxt, FnCtxtTyper, FnCtxtJoined, NoPreference, PreferMutLvalue, callee, demand}; use check::UnresolvedTypeAction; use middle::mem_categorization::Typer; use middle::subst::{self}; @@ -112,7 +112,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { self.unify_receivers(self_ty, method_self_ty); // Add any trait/regions obligations specified on the method's type parameters. - self.add_obligations(&pick, &all_substs, &method_predicates); + self.add_obligations(check_env, &pick, &all_substs, &method_predicates); // Create the final `MethodCallee`. let method_ty = pick.item.as_opt_method().unwrap(); @@ -263,9 +263,9 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { // the impl ([$A,$B,$C]) not the receiver type ([$C]). let impl_polytype = check::impl_self_ty(check_env, self.fcx, self.span, impl_def_id); - let typer = FnCtxtTyper::new(check_env, self.fcx); + let mut joined = FnCtxtJoined::new(check_env, self.fcx); let impl_trait_ref = - typer.instantiate_type_scheme( + joined.instantiate_type_scheme( self.span, &impl_polytype.substs, &ty::impl_trait_ref(self.tcx(), impl_def_id).unwrap()); @@ -420,9 +420,9 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { // be no late-bound regions appearing here. let method_predicates = pick.item.as_opt_method().unwrap() .predicates.instantiate(self.tcx(), &all_substs); - let typer = FnCtxtTyper::new(check_env, self.fcx); - let method_predicates = typer.normalize_associated_types_in(self.span, - &method_predicates); + let mut joined = FnCtxtJoined::new(check_env, self.fcx); + let method_predicates = joined.normalize_associated_types_in(self.span, + &method_predicates); debug!("method_predicates after subst = {}", method_predicates.repr(self.tcx())); @@ -438,8 +438,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { debug!("late-bound lifetimes from method instantiated, method_sig={}", method_sig.repr(self.tcx())); - let typer = FnCtxtTyper::new(check_env, self.fcx); - let method_sig = typer.instantiate_type_scheme(self.span, &all_substs, &method_sig); + let method_sig = joined.instantiate_type_scheme(self.span, &all_substs, &method_sig); debug!("type scheme substituted, method_sig={}", method_sig.repr(self.tcx())); @@ -451,6 +450,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { } fn add_obligations(&mut self, + check_env: &mut CheckEnv<'tcx>, pick: &probe::Pick<'tcx>, all_substs: &subst::Substs<'tcx>, method_predicates: &ty::InstantiatedPredicates<'tcx>) { @@ -460,10 +460,12 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { method_predicates.repr(self.tcx())); self.fcx.add_obligations_for_parameters( + check_env, traits::ObligationCause::misc(self.span, self.fcx.body_id), method_predicates); self.fcx.add_default_region_param_bounds( + check_env, all_substs, self.call_expr); } @@ -524,7 +526,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { i, expr.repr(self.tcx()), autoderef_count); if autoderef_count > 0 { - let expr_ty = self.fcx.expr_ty(check_env, expr); + let expr_ty = self.fcx.expr_ty(&check_env.tt.node_types, expr); check::autoderef(check_env, self.fcx, expr.span, @@ -584,14 +586,15 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { let (adjusted_base_ty, unsize) = if let Some(target) = unsize { (target, true) } else { - (self.fcx.adjust_expr_ty(check_env, base_expr, + let typer = FnCtxtTyper::new(&check_env.tt, self.fcx); + (typer.adjust_expr_ty(base_expr, Some(&ty::AdjustDerefRef(ty::AutoDerefRef { autoderefs: autoderefs, autoref: None, unsize: None }))), false) }; - let index_expr_ty = self.fcx.expr_ty(check_env, &**index_expr); + let index_expr_ty = self.fcx.expr_ty(&check_env.tt.node_types, &**index_expr); let result = check::try_index_step( check_env, @@ -608,7 +611,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { if let Some((input_ty, return_ty)) = result { demand::suptype(self.fcx, index_expr.span, input_ty, index_expr_ty); - let expr_ty = self.fcx.expr_ty(check_env, &*expr); + let expr_ty = self.fcx.expr_ty(&check_env.tt.node_types, &*expr); demand::suptype(self.fcx, expr.span, expr_ty, return_ty); } } @@ -616,8 +619,8 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { // if this is an overloaded deref, then re-evaluate with // a preference for mut let method_call = MethodCall::expr(expr.id); - let expr_ty = self.fcx.expr_ty(check_env, &**base_expr); - if check_env.method_map.contains_key(&method_call) { + let expr_ty = self.fcx.expr_ty(&check_env.tt.node_types, &**base_expr); + if check_env.tt.method_map.contains_key(&method_call) { check::try_overloaded_deref( check_env, self.fcx, diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 2572ee7005f5a..39d5fdaeb7a80 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -14,6 +14,7 @@ use astconv::AstConv; use super::CheckEnv; use super::FnCtxt; use super::FnCtxtTyper; +use super::FnCtxtJoined; use super::vtable; use super::vtable::select_new_fcx_obligations; use middle::def; @@ -191,12 +192,14 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, fcx.body_id, poly_trait_ref.as_predicate()); - // Now we want to know if this can be matched - let typer = FnCtxtTyper::new(check_env, fcx); - let mut selcx = traits::SelectionContext::new(fcx.infcx(), &typer); - if !selcx.evaluate_obligation(&obligation) { - debug!("--> Cannot match obligation"); - return None; // Cannot be matched, no such method resolution is possible. + { + // Now we want to know if this can be matched + let typer = FnCtxtTyper::new(&check_env.tt, fcx); + let mut selcx = traits::SelectionContext::new(fcx.infcx(), &typer); + if !selcx.evaluate_obligation(&obligation) { + debug!("--> Cannot match obligation"); + return None; // Cannot be matched, no such method resolution is possible. + } } // Trait must have a method named `m_name` and it should not have @@ -218,7 +221,10 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, let fn_sig = fcx.infcx().replace_late_bound_regions_with_fresh_var(span, infer::FnCall, &method_ty.fty.sig).0; - let fn_sig = typer.instantiate_type_scheme(span, trait_ref.substs, &fn_sig); + let fn_sig = { + let mut joined = FnCtxtJoined::new(check_env, fcx); + joined.instantiate_type_scheme(span, trait_ref.substs, &fn_sig) + }; let transformed_self_ty = fn_sig.inputs[0]; let fty = ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(ty::BareFnTy { sig: ty::Binder(fn_sig), @@ -238,9 +244,13 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, // // Note that as the method comes from a trait, it should not have // any late-bound regions appearing in its bounds. - let method_bounds = typer.instantiate_bounds(span, trait_ref.substs, &method_ty.predicates); + let method_bounds = { + let mut joined = FnCtxtJoined::new(check_env, fcx); + joined.instantiate_bounds(span, trait_ref.substs, &method_ty.predicates) + }; assert!(!method_bounds.has_escaping_regions()); fcx.add_obligations_for_parameters( + check_env, traits::ObligationCause::misc(span, fcx.body_id), &method_bounds); diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 94842512936ee..2c3893968b517 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -14,7 +14,7 @@ use super::{CandidateSource,ImplSource,TraitSource}; use super::suggest; use check; -use check::{CheckEnv, FnCtxt, FnCtxtTyper, NoPreference, UnresolvedTypeAction}; +use check::{CheckEnv, FnCtxt, FnCtxtTyper, FnCtxtJoined, NoPreference, UnresolvedTypeAction}; use middle::fast_reject; use middle::subst; use middle::subst::Subst; @@ -411,8 +411,8 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { } let (impl_ty, impl_substs) = self.impl_ty_and_substs(impl_def_id); - let typer = FnCtxtTyper::new(check_env, self.fcx); - let impl_ty = typer.instantiate_type_scheme(self.span, &impl_substs, &impl_ty); + let mut joined = FnCtxtJoined::new(check_env, self.fcx); + let impl_ty = joined.instantiate_type_scheme(self.span, &impl_substs, &impl_ty); // Determine the receiver type that the method itself expects. let xform_self_ty = @@ -1055,7 +1055,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { match probe.kind { InherentImplCandidate(impl_def_id, ref substs) | ExtensionImplCandidate(impl_def_id, _, ref substs, _) => { - let typer = FnCtxtTyper::new(check_env, self.fcx); + let typer = FnCtxtTyper::new(&check_env.tt, self.fcx); let selcx = &mut traits::SelectionContext::new(self.infcx(), &typer); let cause = traits::ObligationCause::misc(self.span, self.fcx.body_id); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 13083eaf9f4bc..3f4f49d520331 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -161,24 +161,31 @@ pub struct Inherited<'a, 'tcx: 'a> { adjustments: RefCell>>, upvar_capture_map: RefCell, closure_kinds: RefCell>, +} - // Tracks trait obligations incurred during this function body. - fulfillment_cx: RefCell>, +type MethodMap<'tcx> = FnvHashMap>; + +/// Temporary tables +struct CheckEnvTables<'tcx> { + node_types: NodeMap>, + method_map: MethodMap<'tcx>, + closure_tys: DefIdMap>, } pub struct CheckEnv<'tcx> { locals: NodeMap>, // Temporary tables: - node_types: NodeMap>, - method_map: FnvHashMap>, - closure_tys: DefIdMap>, + tt: CheckEnvTables<'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: NodeMap>>, + // Tracks trait obligations incurred during this function body. + fulfillment_cx: traits::FulfillmentContext<'tcx>, + // When we process a call like `c()` where `c` is a closure type, // we may not have decided yet whether `c` is a `Fn`, `FnMut`, or // `FnOnce` closure. In that case, we defer full resolution of the @@ -258,11 +265,11 @@ struct UnsafetyState { } impl UnsafetyState { - pub fn function(unsafety: ast::Unsafety, def: ast::NodeId) -> UnsafetyState { + fn function(unsafety: ast::Unsafety, def: ast::NodeId) -> UnsafetyState { UnsafetyState { def: def, unsafety: unsafety, from_fn: true } } - pub fn recurse(&self, blk: &ast::Block) -> UnsafetyState { + fn recurse(&self, blk: &ast::Block) -> UnsafetyState { match self.unsafety { // If this unsafe, then if the outer function was already marked as // unsafe we shouldn't attribute the unsafe'ness to the block. This @@ -306,26 +313,27 @@ pub struct FnCtxt<'a, 'tcx: 'a> { ccx: &'a CrateCtxt<'a, 'tcx>, } -// FIXME: Determine whether we actually need these. -#[derive(Clone, Copy)] -pub struct FnCtxtTyper<'a, 'tcx: 'a> { +pub struct FnCtxtJoined<'a, 'tcx: 'a> { fcx: &'a FnCtxt<'a, 'tcx>, - check_env: &'a CheckEnv<'tcx> + check_env: &'a mut CheckEnv<'tcx>, } -impl<'a, 'tcx> FnCtxtTyper<'a, 'tcx> { - fn new(check_env: &'a CheckEnv<'tcx>, fcx: &'a FnCtxt<'a, 'tcx>) -> Self { - FnCtxtTyper { check_env: check_env, fcx: fcx } +impl<'a, 'tcx> FnCtxtJoined<'a, 'tcx> { + fn new(check_env: &'a mut CheckEnv<'tcx>, fcx: &'a FnCtxt<'a, 'tcx>) -> Self { + FnCtxtJoined { check_env: check_env, fcx: fcx } } - fn normalize_associated_types_in(&self, span: Span, value: &T) -> T + fn normalize_associated_types_in(&mut self, span: Span, value: &T) -> T where T : TypeFoldable<'tcx> + Clone + HasProjectionTypes + Repr<'tcx> { - self.fcx.inh.normalize_associated_types_in(self, span, self.fcx.body_id, value) + let typer = FnCtxtTyper::new(&self.check_env.tt, self.fcx); + self.fcx.inh.normalize_associated_types_in(&typer, + &mut self.check_env.fulfillment_cx, + span, self.fcx.body_id, value) } - fn normalize_associated_type(&self, + fn normalize_associated_type(&mut self, span: Span, trait_ref: ty::TraitRef<'tcx>, item_name: ast::Name) @@ -334,10 +342,10 @@ impl<'a, 'tcx> FnCtxtTyper<'a, 'tcx> { let cause = traits::ObligationCause::new(span, self.fcx.body_id, traits::ObligationCauseCode::MiscObligation); - self.fcx.inh.fulfillment_cx - .borrow_mut() + let typer = FnCtxtTyper::new(&self.check_env.tt, self.fcx); + self.check_env.fulfillment_cx .normalize_projection_type(self.fcx.infcx(), - self, + &typer, ty::ProjectionTy { trait_ref: trait_ref, item_name: item_name, @@ -348,7 +356,7 @@ impl<'a, 'tcx> FnCtxtTyper<'a, 'tcx> { /// Basically whenever we are converting from a type scheme into /// the fn body space, we always want to normalize associated /// types as well. This function combines the two. - fn instantiate_type_scheme(&self, + fn instantiate_type_scheme(&mut self, span: Span, substs: &Substs<'tcx>, value: &T) @@ -356,8 +364,7 @@ impl<'a, 'tcx> FnCtxtTyper<'a, 'tcx> { where T : TypeFoldable<'tcx> + Clone + HasProjectionTypes + Repr<'tcx> { let value = value.subst(self.tcx(), substs); - let typer = FnCtxtTyper::new(self.check_env, self.fcx); - let result = typer.normalize_associated_types_in(span, &value); + let result = self.normalize_associated_types_in(span, &value); debug!("instantiate_type_scheme(value={}, substs={}) = {}", value.repr(self.tcx()), substs.repr(self.tcx()), @@ -367,7 +374,7 @@ impl<'a, 'tcx> FnCtxtTyper<'a, 'tcx> { /// As `instantiate_type_scheme`, but for the bounds found in a /// generic type scheme. - fn instantiate_bounds(&self, + fn instantiate_bounds(&mut self, span: Span, substs: &Substs<'tcx>, bounds: &ty::GenericPredicates<'tcx>) @@ -385,7 +392,7 @@ impl<'a, 'tcx> FnCtxtTyper<'a, 'tcx> { /// /// Note that function is only intended to be used with types (notably, not fns). This is /// because it doesn't do any instantiation of late-bound regions. - pub fn instantiate_type(&self, + fn instantiate_type(&mut self, span: Span, def_id: ast::DefId) -> TypeAndSubsts<'tcx> @@ -401,6 +408,7 @@ impl<'a, 'tcx> FnCtxtTyper<'a, 'tcx> { let bounds = self.instantiate_bounds(span, &substs, &type_predicates); self.fcx.add_obligations_for_parameters( + self.check_env, traits::ObligationCause::new( span, self.fcx.body_id, @@ -420,15 +428,15 @@ impl<'a, 'tcx> FnCtxtTyper<'a, 'tcx> { /// and/or region variables are substituted. /// /// This is used when checking the constructor in struct literals. - fn instantiate_struct_literal_ty(&self, + fn instantiate_struct_literal_ty(&mut self, did: ast::DefId, path: &ast::Path) -> TypeAndSubsts<'tcx> { - let tcx = self.tcx(); - - let ty::TypeScheme { generics, ty: decl_ty } = - ty::lookup_item_type(tcx, did); + let ty::TypeScheme { generics, ty: decl_ty } = { + let tcx = self.tcx(); + ty::lookup_item_type(tcx, did) + }; let substs = astconv::ast_path_substs_for_ty(self, self.fcx, path.span, @@ -441,7 +449,7 @@ impl<'a, 'tcx> FnCtxtTyper<'a, 'tcx> { TypeAndSubsts { substs: substs, ty: ty } } - pub fn to_ty(&self, ast_t: &ast::Ty) -> Ty<'tcx> { + fn to_ty(&mut self, ast_t: &ast::Ty) -> Ty<'tcx> { let t = ast_ty_to_ty(self, self.fcx, ast_t); let mut bounds_checker = wf::BoundsChecker::new(self.check_env, @@ -455,14 +463,49 @@ impl<'a, 'tcx> FnCtxtTyper<'a, 'tcx> { } } +// FIXME: Determine whether we actually need these. +#[derive(Clone,Copy)] +struct FnCtxtTyper<'a, 'tcx: 'a> { + tt: &'a CheckEnvTables<'tcx>, + + fcx: &'a FnCtxt<'a, 'tcx>, +} + +impl<'a, 'tcx> FnCtxtTyper<'a, 'tcx> { + fn new(tt: &'a CheckEnvTables<'tcx>, fcx: &'a FnCtxt<'a, 'tcx>) -> Self { + FnCtxtTyper { + tt: tt, + fcx: fcx, + } + } + + /// Apply `adjustment` to the type of `expr` + fn adjust_expr_ty(&self, + expr: &ast::Expr, + adjustment: Option<&ty::AutoAdjustment<'tcx>>) + -> Ty<'tcx> + { + let raw_ty = self.fcx.expr_ty(&self.tt.node_types, expr); + let raw_ty = self.fcx.infcx().shallow_resolve(raw_ty); + let resolve_ty = |ty: Ty<'tcx>| self.fcx.infcx().resolve_type_vars_if_possible(&ty); + ty::adjust_ty(self.fcx.ccx.tcx, + expr.span, + expr.id, + raw_ty, + adjustment, + |method_call| self.tt.method_map.get(&method_call) + .map(|method| resolve_ty(method.ty))) + } +} + impl<'a, 'tcx> mc::Typer<'tcx> for FnCtxtTyper<'a, 'tcx> { fn node_ty(&self, id: ast::NodeId) -> McResult> { - let ty = self.fcx.node_ty(&self.check_env, id); + let ty = self.fcx.node_ty(&self.tt.node_types, id); self.fcx.resolve_type_vars_or_error(&ty) } fn expr_ty_adjusted(&self, expr: &ast::Expr) -> McResult> { - let ty = self.fcx.adjust_expr_ty(&self.check_env, expr, - self.fcx.inh.adjustments.borrow().get(&expr.id)); + let ty = self.adjust_expr_ty(expr, + self.fcx.inh.adjustments.borrow().get(&expr.id)); self.fcx.resolve_type_vars_or_error(&ty) } fn type_moves_by_default(&self, span: Span, ty: Ty<'tcx>) -> bool { @@ -471,23 +514,23 @@ impl<'a, 'tcx> mc::Typer<'tcx> for FnCtxtTyper<'a, 'tcx> { } fn node_method_ty(&self, method_call: ty::MethodCall) -> Option> { - self.check_env.method_map.get(&method_call) - .map(|method| method.ty) - .map(|ty| self.fcx - .infcx() - .resolve_type_vars_if_possible(&ty)) + self.tt.method_map.get(&method_call) + .map(|method| method.ty) + .map(|ty| self.fcx + .infcx() + .resolve_type_vars_if_possible(&ty)) } fn node_method_origin(&self, method_call: ty::MethodCall) -> Option> { - self.check_env.method_map.get(&method_call) - .map(|method| method.origin.clone()) + self.tt.method_map.get(&method_call) + .map(|method| method.origin.clone()) } fn adjustments(&self) -> &RefCell>> { &self.fcx.inh.adjustments } fn is_method_call(&self, id: ast::NodeId) -> bool { - self.check_env.method_map.contains_key(&ty::MethodCall::expr(id)) + self.tt.method_map.contains_key(&ty::MethodCall::expr(id)) } fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option { self.fcx.param_env().temporary_scope(rvalue_id) @@ -514,7 +557,7 @@ impl<'a, 'tcx> ty::ClosureTyper<'tcx> for FnCtxtTyper<'a, 'tcx> { substs: &subst::Substs<'tcx>) -> ty::ClosureTy<'tcx> { - self.check_env.closure_tys.get(&def_id).unwrap().subst(self.fcx.tcx(), substs) + self.tt.closure_tys.get(&def_id).unwrap().subst(self.fcx.tcx(), substs) } fn closure_upvars(&self, @@ -537,22 +580,21 @@ impl<'a, 'tcx> Inherited<'a, 'tcx> { adjustments: RefCell::new(NodeMap()), upvar_capture_map: RefCell::new(FnvHashMap()), closure_kinds: RefCell::new(DefIdMap()), - fulfillment_cx: RefCell::new(traits::FulfillmentContext::new()), } } fn normalize_associated_types_in(&self, typer: &ty::ClosureTyper<'tcx>, + fulfillment_cx: &mut traits::FulfillmentContext<'tcx>, span: Span, body_id: ast::NodeId, value: &T) -> T where T : TypeFoldable<'tcx> + Clone + HasProjectionTypes + Repr<'tcx> { - let mut fulfillment_cx = self.fulfillment_cx.borrow_mut(); assoc::normalize_associated_types_in(&self.infcx, typer, - &mut *fulfillment_cx, span, + fulfillment_cx, span, body_id, value) } @@ -562,10 +604,13 @@ impl<'tcx> CheckEnv<'tcx> { fn new() -> Self { CheckEnv { locals: NodeMap(), - node_types: NodeMap(), - method_map: FnvHashMap(), - closure_tys: DefIdMap(), + tt: CheckEnvTables { + node_types: NodeMap(), + method_map: FnvHashMap(), + closure_tys: DefIdMap(), + }, fn_sig_map: NodeMap(), + fulfillment_cx: traits::FulfillmentContext::new(), deferred_call_resolutions: DefIdMap(), deferred_cast_checks: Vec::new(), } @@ -594,7 +639,7 @@ impl<'tcx> CheckEnv<'tcx> { } // Used by check_const and check_enum_variants -pub fn blank_fn_ctxt<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>, +fn blank_fn_ctxt<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>, inh: &'a Inherited<'a, 'tcx>, rty: ty::FnOutput<'tcx>, body_id: ast::NodeId) @@ -701,7 +746,11 @@ fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, region::DestructionScopeData::new(body.id), &fn_sig); let fn_sig = - inh.normalize_associated_types_in(&inh.param_env, body.span, body.id, &fn_sig); + inh.normalize_associated_types_in(&inh.param_env, + &mut check_env.fulfillment_cx, + body.span, + body.id, + &fn_sig); let fcx = check_fn(&mut check_env, ccx, fn_ty.unsafety, fn_id, &fn_sig, decl, fn_id, body, &inh); @@ -745,8 +794,8 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> { // Add explicitly-declared locals. fn visit_local(&mut self, local: &'tcx ast::Local) { let o_ty = local.ty.as_ref().map( |ty| { - let typer = FnCtxtTyper::new(self.check_env, self.fcx); - typer.to_ty(&**ty) + let mut joined = FnCtxtJoined::new(self.check_env, self.fcx); + joined.to_ty(&**ty) } ); self.assign(local.span, local.id, o_ty); debug!("Local variable {} is assigned type {}", @@ -762,7 +811,8 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> { if pat_util::pat_is_binding(&self.fcx.ccx.tcx.def_map, p) { let var_ty = self.assign(p.span, p.id, None); - self.fcx.require_type_is_sized(var_ty, p.span, + self.fcx.require_type_is_sized(self.check_env, + var_ty, p.span, traits::VariableType(p.id)); debug!("Pattern binding {} is assigned to {} with type {}", @@ -848,7 +898,7 @@ fn check_fn<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, .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(check_env, ret_ty, decl.output.span(), traits::ReturnType); fn_sig_tys.push(ret_ty); } @@ -869,7 +919,8 @@ fn check_fn<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, &*input.pat, |_bm, pat_id, sp, _path| { let var_ty = visit.assign(sp, pat_id, None); - fcx.require_type_is_sized(var_ty, sp, + fcx.require_type_is_sized(visit.check_env, + var_ty, sp, traits::VariableType(pat_id)); }); @@ -896,7 +947,7 @@ fn check_fn<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, fcx } -pub fn check_struct(ccx: &CrateCtxt, id: ast::NodeId, span: Span) { +fn check_struct(ccx: &CrateCtxt, id: ast::NodeId, span: Span) { let tcx = ccx.tcx; check_representable(tcx, span, id, "struct"); @@ -907,7 +958,7 @@ pub fn check_struct(ccx: &CrateCtxt, id: ast::NodeId, span: Span) { } } -pub fn check_item_type<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) { +fn check_item_type<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) { debug!("check_item_type(it.id={}, it.ident={})", it.id, ty::item_path_str(ccx.tcx, local_def(it.id))); @@ -971,7 +1022,7 @@ pub fn check_item_type<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) { } } -pub fn check_item_body<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) { +fn check_item_body<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) { debug!("check_item_body(it.id={}, it.ident={})", it.id, ty::item_path_str(ccx.tcx, local_def(it.id))); @@ -1347,7 +1398,7 @@ fn report_cast_to_unsized_type<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, } -impl<'a, 'tcx> AstConv<'tcx> for FnCtxtTyper<'a, 'tcx> { +impl<'a, 'tcx> AstConv<'tcx> for FnCtxtJoined<'a, 'tcx> { fn tcx(&self) -> &ty::ctxt<'tcx> { self.fcx.ccx.tcx } fn get_item_type_scheme(&self, _: Span, id: ast::DefId) @@ -1371,7 +1422,7 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxtTyper<'a, 'tcx> { Some(&self.fcx.inh.param_env.free_substs) } - fn get_type_parameter_bounds(&self, + fn get_type_parameter_bounds(&mut self, _: Span, node_id: ast::NodeId) -> Result>, ErrorReported> @@ -1411,7 +1462,7 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxtTyper<'a, 'tcx> { self.fcx.infcx().next_ty_var() } - fn projected_ty_from_poly_trait_ref(&self, + fn projected_ty_from_poly_trait_ref(&mut self, span: Span, poly_trait_ref: ty::PolyTraitRef<'tcx>, item_name: ast::Name) @@ -1426,7 +1477,7 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxtTyper<'a, 'tcx> { self.normalize_associated_type(span, trait_ref, item_name) } - fn projected_ty(&self, + fn projected_ty(&mut self, span: Span, trait_ref: ty::TraitRef<'tcx>, item_name: ast::Name) @@ -1439,26 +1490,26 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxtTyper<'a, 'tcx> { impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn tcx(&self) -> &ty::ctxt<'tcx> { self.ccx.tcx } - pub fn infcx(&self) -> &infer::InferCtxt<'a,'tcx> { + fn infcx(&self) -> &infer::InferCtxt<'a,'tcx> { &self.inh.infcx } - pub fn param_env(&self) -> &ty::ParameterEnvironment<'a,'tcx> { + fn param_env(&self) -> &ty::ParameterEnvironment<'a,'tcx> { &self.inh.param_env } - pub fn sess(&self) -> &Session { + fn sess(&self) -> &Session { &self.tcx().sess } - pub fn err_count_since_creation(&self) -> usize { + fn err_count_since_creation(&self) -> usize { self.ccx.tcx.sess.err_count() - self.err_count_on_creation } /// Resolves type variables in `ty` if possible. Unlike the infcx /// version, this version will also select obligations if it seems /// useful, in an effort to get more type information. - fn resolve_type_vars_if_possible(&self, check_env: &CheckEnv<'tcx>, + fn resolve_type_vars_if_possible(&self, check_env: &mut CheckEnv<'tcx>, mut ty: Ty<'tcx>) -> Ty<'tcx> { debug!("resolve_type_vars_if_possible(ty={})", ty.repr(self.tcx())); @@ -1504,12 +1555,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if ty::type_has_ty_infer(t) || ty::type_is_error(t) { Err(()) } else { Ok(t) } } - pub fn tag(&self) -> String { + fn tag(&self) -> String { let self_ptr: *const FnCtxt = self; format!("{:?}", self_ptr) } - pub fn local_ty(&self, + fn local_ty(&self, check_env: &mut CheckEnv<'tcx>, span: Span, nid: ast::NodeId) -> Ty<'tcx> { @@ -1526,9 +1577,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Apply "fallbacks" to some types /// ! gets replaced with (), unconstrained ints with i32, and unconstrained floats with f64. - pub fn default_type_parameters(&self, check_env: &mut CheckEnv<'tcx>) { + fn default_type_parameters(&self, check_env: &mut CheckEnv<'tcx>) { use middle::ty::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat, Neither}; - for (_, &mut ref ty) in &mut check_env.node_types { + for (_, &mut ref ty) in &mut check_env.tt.node_types { let resolved = self.infcx().resolve_type_vars_if_possible(ty); if self.infcx().type_var_diverges(resolved) { demand::eqtype(self, codemap::DUMMY_SP, *ty, ty::mk_nil(self.tcx())); @@ -1547,13 +1598,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } #[inline] - pub fn write_ty(&self, check_env: &mut CheckEnv<'tcx>, node_id: ast::NodeId, ty: Ty<'tcx>) { + fn write_ty(&self, check_env: &mut CheckEnv<'tcx>, node_id: ast::NodeId, ty: Ty<'tcx>) { debug!("write_ty({}, {}) in fcx {}", node_id, ppaux::ty_to_string(self.tcx(), ty), self.tag()); - check_env.node_types.insert(node_id, ty); + check_env.tt.node_types.insert(node_id, ty); } - pub fn write_substs(&self, node_id: ast::NodeId, substs: ty::ItemSubsts<'tcx>) { + fn write_substs(&self, node_id: ast::NodeId, substs: ty::ItemSubsts<'tcx>) { if !substs.substs.is_noop() { debug!("write_substs({}, {}) in fcx {}", node_id, @@ -1564,7 +1615,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub fn write_autoderef_adjustment(&self, + fn write_autoderef_adjustment(&self, node_id: ast::NodeId, derefs: usize) { self.write_adjustment( @@ -1577,7 +1628,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } - pub fn write_adjustment(&self, + fn write_adjustment(&self, node_id: ast::NodeId, adj: ty::AutoAdjustment<'tcx>) { debug!("write_adjustment(node_id={}, adj={})", node_id, adj.repr(self.tcx())); @@ -1589,42 +1640,46 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.inh.adjustments.borrow_mut().insert(node_id, adj); } - pub fn write_nil(&self, check_env: &mut CheckEnv<'tcx>, node_id: ast::NodeId) { + fn write_nil(&self, check_env: &mut CheckEnv<'tcx>, node_id: ast::NodeId) { self.write_ty(check_env, node_id, ty::mk_nil(self.tcx())); } - pub fn write_error(&self, check_env: &mut CheckEnv<'tcx>, node_id: ast::NodeId) { + fn write_error(&self, check_env: &mut CheckEnv<'tcx>, node_id: ast::NodeId) { self.write_ty(check_env, node_id, self.tcx().types.err); } - pub fn require_type_meets(&self, + fn require_type_meets(&self, + check_env: &mut CheckEnv<'tcx>, ty: Ty<'tcx>, span: Span, code: traits::ObligationCauseCode<'tcx>, bound: ty::BuiltinBound) { self.register_builtin_bound( + check_env, ty, bound, traits::ObligationCause::new(span, self.body_id, code)); } - pub fn require_type_is_sized(&self, + fn require_type_is_sized(&self, + check_env: &mut CheckEnv<'tcx>, ty: Ty<'tcx>, span: Span, code: traits::ObligationCauseCode<'tcx>) { - self.require_type_meets(ty, span, code, ty::BoundSized); + self.require_type_meets(check_env, ty, span, code, ty::BoundSized); } - pub fn require_expr_have_sized_type(&self, + fn require_expr_have_sized_type(&self, check_env: &mut CheckEnv<'tcx>, expr: &ast::Expr, code: traits::ObligationCauseCode<'tcx>) { - self.require_type_is_sized(self.expr_ty(check_env, expr), expr.span, code); + let expr_ty = self.expr_ty(&check_env.tt.node_types, expr); + self.require_type_is_sized(check_env, expr_ty, expr.span, code); } - pub fn type_is_known_to_be_sized(&self, + fn type_is_known_to_be_sized(&self, ty: Ty<'tcx>, span: Span) -> bool @@ -1636,38 +1691,39 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span) } - pub fn type_is_fat_ptr(&self, ty: Ty<'tcx>, span: Span) -> bool { + fn type_is_fat_ptr(&self, ty: Ty<'tcx>, span: Span) -> bool { if let Some(mt) = ty::deref(ty, true) { return !self.type_is_known_to_be_sized(mt.ty, span); } false } - pub fn register_builtin_bound(&self, + fn register_builtin_bound(&self, + check_env: &mut CheckEnv<'tcx>, ty: Ty<'tcx>, builtin_bound: ty::BuiltinBound, cause: traits::ObligationCause<'tcx>) { - self.inh.fulfillment_cx.borrow_mut() + check_env.fulfillment_cx .register_builtin_bound(self.infcx(), ty, builtin_bound, cause); } - pub fn register_predicate(&self, + fn register_predicate(&self, + check_env: &mut CheckEnv<'tcx>, obligation: traits::PredicateObligation<'tcx>) { debug!("register_predicate({})", obligation.repr(self.tcx())); - self.inh.fulfillment_cx - .borrow_mut() + check_env.fulfillment_cx .register_predicate_obligation(self.infcx(), obligation); } - pub fn pat_to_string(&self, pat: &ast::Pat) -> String { + fn pat_to_string(&self, pat: &ast::Pat) -> String { pat.repr(self.tcx()) } - pub fn expr_ty(&self, check_env: &CheckEnv<'tcx>, ex: &ast::Expr) -> Ty<'tcx> { - match check_env.node_types.get(&ex.id) { + fn expr_ty(&self, node_types: &NodeMap>, ex: &ast::Expr) -> Ty<'tcx> { + match node_types.get(&ex.id) { Some(&t) => t, None => { self.tcx().sess.bug(&format!("no type for expr in fcx {}", @@ -1676,27 +1732,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - /// Apply `adjustment` to the type of `expr` - pub fn adjust_expr_ty(&self, - check_env: &CheckEnv<'tcx>, - expr: &ast::Expr, - adjustment: Option<&ty::AutoAdjustment<'tcx>>) - -> Ty<'tcx> - { - let raw_ty = self.expr_ty(check_env, expr); - let raw_ty = self.infcx().shallow_resolve(raw_ty); - let resolve_ty = |ty: Ty<'tcx>| self.infcx().resolve_type_vars_if_possible(&ty); - ty::adjust_ty(self.tcx(), - expr.span, - expr.id, - raw_ty, - adjustment, - |method_call| check_env.method_map.get(&method_call) - .map(|method| resolve_ty(method.ty))) - } - - pub fn node_ty(&self, check_env: &CheckEnv<'tcx>, id: ast::NodeId) -> Ty<'tcx> { - match check_env.node_types.get(&id) { + fn node_ty(&self, node_types: &NodeMap>, id: ast::NodeId) -> Ty<'tcx> { + match node_types.get(&id) { Some(&t) => t, None if self.err_count_since_creation() != 0 => self.tcx().types.err, None => { @@ -1708,11 +1745,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub fn item_substs(&self) -> Ref>> { + fn item_substs(&self) -> Ref>> { self.inh.item_substs.borrow() } - pub fn opt_node_ty_substs(&self, + fn opt_node_ty_substs(&self, id: ast::NodeId, f: F) where F: FnOnce(&ty::ItemSubsts<'tcx>), @@ -1723,7 +1760,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub fn mk_subty(&self, + fn mk_subty(&self, a_is_expected: bool, origin: infer::TypeOrigin, sub: Ty<'tcx>, @@ -1732,7 +1769,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { infer::mk_subty(self.infcx(), a_is_expected, origin, sub, sup) } - pub fn mk_eqty(&self, + fn mk_eqty(&self, a_is_expected: bool, origin: infer::TypeOrigin, sub: Ty<'tcx>, @@ -1741,14 +1778,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { infer::mk_eqty(self.infcx(), a_is_expected, origin, sub, sup) } - pub fn mk_subr(&self, + fn mk_subr(&self, origin: infer::SubregionOrigin<'tcx>, sub: ty::Region, sup: ty::Region) { infer::mk_subr(self.infcx(), origin, sub, sup) } - pub fn type_error_message(&self, + fn type_error_message(&self, sp: Span, mk_msg: M, actual_ty: Ty<'tcx>, @@ -1758,7 +1795,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.infcx().type_error_message(sp, mk_msg, actual_ty, err); } - pub fn report_mismatched_types(&self, + fn report_mismatched_types(&self, sp: Span, e: Ty<'tcx>, a: Ty<'tcx>, @@ -1768,16 +1805,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Registers an obligation for checking later, during regionck, that the type `ty` must /// outlive the region `r`. - pub fn register_region_obligation(&self, + fn register_region_obligation(&self, + check_env: &mut CheckEnv<'tcx>, ty: Ty<'tcx>, region: ty::Region, cause: traits::ObligationCause<'tcx>) { - let mut fulfillment_cx = self.inh.fulfillment_cx.borrow_mut(); - fulfillment_cx.register_region_obligation(self.infcx(), ty, region, cause); + check_env.fulfillment_cx + .register_region_obligation(self.infcx(), ty, region, cause); } - pub fn add_default_region_param_bounds(&self, + fn add_default_region_param_bounds(&self, + check_env: &mut CheckEnv<'tcx>, substs: &Substs<'tcx>, expr: &ast::Expr) { @@ -1785,7 +1824,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let default_bound = ty::ReScope(CodeExtent::from_node_id(expr.id)); let cause = traits::ObligationCause::new(expr.span, self.body_id, traits::MiscObligation); - self.register_region_obligation(ty, default_bound, cause); + self.register_region_obligation(check_env, ty, default_bound, cause); } } @@ -1807,7 +1846,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// /// Then we will create a fresh region variable `'$0` and a fresh type variable `$1` for `'a` /// and `T`. This routine will add a region obligation `$1:'$0` and register it locally. - pub fn add_obligations_for_parameters(&self, + fn add_obligations_for_parameters(&self, + check_env: &mut CheckEnv<'tcx>, cause: traits::ObligationCause<'tcx>, predicates: &ty::InstantiatedPredicates<'tcx>) { @@ -1820,12 +1860,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { cause, predicates); - obligations.map_move(|o| self.register_predicate(o)); + obligations.map_move(|o| self.register_predicate(check_env, o)); } // Only for fields! Returns for methods> // Indifferent to privacy flags - pub fn lookup_field_ty(&self, + fn lookup_field_ty(&self, check_env: &mut CheckEnv<'tcx>, span: Span, class_id: ast::DefId, @@ -1837,12 +1877,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let o_field = items.iter().find(|f| f.name == fieldname); o_field.map(|f| ty::lookup_field_type(self.tcx(), class_id, f.id, substs)) .map(|t| { - let typer = FnCtxtTyper::new(check_env, self); - typer.normalize_associated_types_in(span, &t) + let mut joined = FnCtxtJoined::new(check_env, self); + joined.normalize_associated_types_in(span, &t) }) } - pub fn lookup_tup_field_ty(&self, + fn lookup_tup_field_ty(&self, check_env: &mut CheckEnv<'tcx>, span: Span, class_id: ast::DefId, @@ -1854,8 +1894,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let o_field = if idx < items.len() { Some(&items[idx]) } else { None }; o_field.map(|f| ty::lookup_field_type(self.tcx(), class_id, f.id, substs)) .map(|t| { - let typer = FnCtxtTyper::new(check_env, self); - typer.normalize_associated_types_in(span, &t) + let mut joined = FnCtxtJoined::new(check_env, self); + joined.normalize_associated_types_in(span, &t) }) } } @@ -1902,7 +1942,7 @@ pub enum UnresolvedTypeAction { /// /// Note: this method does not modify the adjustments table. The caller is responsible for /// inserting an AutoAdjustment record into the `fcx` using one of the suitable methods. -pub fn autoderef<'a, 'tcx, T, F>(check_env: &mut CheckEnv<'tcx>, +fn autoderef<'a, 'tcx, T, F>(check_env: &mut CheckEnv<'tcx>, fcx: &FnCtxt<'a, 'tcx>, sp: Span, base_ty: Ty<'tcx>, @@ -2030,7 +2070,7 @@ fn make_overloaded_lvalue_return_type<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, let ret_ty = ty::no_late_bound_regions(fcx.tcx(), &ret_ty).unwrap().unwrap(); if let Some(method_call) = method_call { - check_env.method_map.insert(method_call, method); + check_env.tt.method_map.insert(method_call, method); } // method returns &T, but the type as visible to user is T, so deref @@ -2372,7 +2412,7 @@ fn check_argument_types<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, // There are a few types which get autopromoted when passed via varargs // in C but we just error out instead and require explicit casts. - let expr_ty = fcx.expr_ty(check_env, &**arg); + let expr_ty = fcx.expr_ty(&check_env.tt.node_types, &**arg); let arg_ty = structurally_resolved_type(check_env, fcx, arg.span, expr_ty); match arg_ty.sty { ty::ty_float(ast::TyF32) => { @@ -2471,7 +2511,7 @@ fn check_expr_has_type<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, expected: Ty<'tcx>) { check_expr_with_unifier( check_env, fcx, expr, ExpectHasType(expected), NoPreference, - |check_env| demand::suptype(fcx, expr.span, expected, fcx.expr_ty(check_env, expr))); + |check_env| demand::suptype(fcx, expr.span, expected, fcx.expr_ty(&check_env.tt.node_types, expr))); } fn check_expr_coercable_to_type<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, @@ -2540,8 +2580,8 @@ fn impl_self_ty<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, let rps = fcx.inh.infcx.region_vars_for_defs(span, rps); let tps = fcx.inh.infcx.next_ty_vars(n_tps); let substs = subst::Substs::new_type(tps, rps); - let typer = FnCtxtTyper::new(check_env, fcx); - let substd_ty = typer.instantiate_type_scheme(span, &substs, &raw_ty); + let mut joined = FnCtxtJoined::new(check_env, fcx); + let substd_ty = joined.instantiate_type_scheme(span, &substs, &raw_ty); TypeAndSubsts { substs: substs, ty: substd_ty } } @@ -2643,12 +2683,12 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, check_expr_with_lvalue_pref(check_env, fcx, &*rcvr, lvalue_pref); // no need to check for bot/err -- callee does that - let expr_ty = fcx.expr_ty(check_env, &*rcvr); + let expr_ty = fcx.expr_ty(&check_env.tt.node_types, &*rcvr); let expr_t = structurally_resolved_type(check_env, fcx, expr.span, expr_ty); let tps = { - let typer = FnCtxtTyper::new(check_env, fcx); - tps.iter().map(|ast_ty| typer.to_ty(&**ast_ty)).collect::>() + let mut joined = FnCtxtJoined::new(check_env, fcx); + tps.iter().map(|ast_ty| joined.to_ty(&**ast_ty)).collect::>() }; let fn_ty = match method::lookup(check_env, fcx, @@ -2661,7 +2701,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, Ok(method) => { let method_ty = method.ty; let method_call = MethodCall::expr(expr.id); - check_env.method_map.insert(method_call, method); + check_env.tt.method_map.insert(method_call, method); method_ty } Err(error) => { @@ -2699,12 +2739,12 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, let expected = expected.adjust_for_branches(fcx); check_block_with_expected(check_env, fcx, then_blk, expected); - let then_ty = fcx.node_ty(check_env, then_blk.id); + let then_ty = fcx.node_ty(&check_env.tt.node_types, then_blk.id); let branches_ty = match opt_else_expr { Some(ref else_expr) => { check_expr_with_expectation(check_env, fcx, &**else_expr, expected); - let else_ty = fcx.expr_ty(check_env, &**else_expr); + let else_ty = fcx.expr_ty(&check_env.tt.node_types, &**else_expr); infer::common_supertype(fcx.infcx(), infer::IfExpression(sp), true, @@ -2720,7 +2760,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, } }; - let cond_ty = fcx.expr_ty(check_env, cond_expr); + let cond_ty = fcx.expr_ty(&check_env.tt.node_types, cond_expr); let if_ty = if ty::type_is_error(cond_ty) { fcx.tcx().types.err } else { @@ -2739,7 +2779,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, field: &ast::SpannedIdent) { let tcx = fcx.ccx.tcx; check_expr_with_lvalue_pref(check_env, fcx, base, lvalue_pref); - let expr_ty = fcx.expr_ty(check_env, base); + let expr_ty = fcx.expr_ty(&check_env.tt.node_types, base); let expr_t = structurally_resolved_type(check_env, fcx, expr.span, expr_ty); // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop. let (_, autoderefs, field_ty) = autoderef(check_env, fcx, @@ -2842,7 +2882,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, idx: codemap::Spanned) { let tcx = fcx.ccx.tcx; check_expr_with_lvalue_pref(check_env, fcx, base, lvalue_pref); - let expr_ty = fcx.expr_ty(check_env, base); + let expr_ty = fcx.expr_ty(&check_env.tt.node_types, base); let expr_t = structurally_resolved_type(check_env, fcx, expr.span, expr_ty); let mut tuple_like = false; // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop. @@ -2967,9 +3007,9 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, expected_field_type = ty::lookup_field_type( tcx, class_id, field_id, substitutions); - let typer = FnCtxtTyper::new(check_env, fcx); + let mut joined = FnCtxtJoined::new(check_env, fcx); expected_field_type = - typer.normalize_associated_types_in( + joined.normalize_associated_types_in( field.span, &expected_field_type); class_field_map.insert( field.ident.node.name, (field_id, true)); @@ -3027,8 +3067,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, ty: mut struct_type, substs: struct_substs } = { - let typer = FnCtxtTyper::new(check_env, fcx); - typer.instantiate_type(span, class_id) + let mut joined = FnCtxtJoined::new(check_env, fcx); + joined.instantiate_type(span, class_id) }; // Look up and check the fields. @@ -3044,7 +3084,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, fields, base_expr.is_none(), None); - if ty::type_is_error(fcx.node_ty(check_env, id)) { + if ty::type_is_error(fcx.node_ty(&check_env.tt.node_types, id)) { struct_type = tcx.types.err; } @@ -3075,8 +3115,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, ty: enum_type, substs: substitutions } = { - let typer = FnCtxtTyper::new(check_env, fcx); - typer.instantiate_type(span, enum_id) + let mut joined = FnCtxtJoined::new(check_env, fcx); + joined.instantiate_type(span, enum_id) }; // Look up and check the enum variant fields. @@ -3128,7 +3168,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, // places: the exchange heap and the managed heap. let definition = lookup_full_def(tcx, path.span, place.id); let def_id = definition.def_id(); - let referent_ty = fcx.expr_ty(check_env, &**subexpr); + let referent_ty = fcx.expr_ty(&check_env.tt.node_types, &**subexpr); if tcx.lang_items.exchange_heap() == Some(def_id) { fcx.write_ty(check_env, id, ty::mk_uniq(tcx, referent_ty)); checked = true @@ -3179,7 +3219,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, }; check_expr_with_expectation_and_lvalue_pref( check_env, fcx, &**oprnd, expected_inner, lvalue_pref); - let mut oprnd_t = fcx.expr_ty(check_env, &**oprnd); + let mut oprnd_t = fcx.expr_ty(&check_env.tt.node_types, &**oprnd); if !ty::type_is_error(oprnd_t) { match unop { @@ -3279,7 +3319,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, hint, lvalue_pref); - let tm = ty::mt { ty: fcx.expr_ty(check_env, &**oprnd), mutbl: mutbl }; + let tm = ty::mt { ty: fcx.expr_ty(&check_env.tt.node_types, &**oprnd), mutbl: mutbl }; let oprnd_t = if ty::type_is_error(tm.ty) { tcx.types.err } else { @@ -3303,8 +3343,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, } ast::ExprPath(ref maybe_qself, ref path) => { let opt_self_ty = maybe_qself.as_ref().map(|qself| { - let typer = FnCtxtTyper::new(check_env, fcx); - typer.to_ty(&qself.ty) + let mut joined = FnCtxtJoined::new(check_env, fcx); + joined.to_ty(&qself.ty) }); let path_res = if let Some(&d) = tcx.def_map.borrow().get(&id) { @@ -3341,7 +3381,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, // We always require that the type provided as the value for // a type parameter outlives the moment of instantiation. - constrain_path_type_parameters(fcx, expr); + constrain_path_type_parameters(check_env, fcx, expr); } ast::ExprInlineAsm(ref ia) => { for &(_, ref input) in &ia.inputs { @@ -3386,7 +3426,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, &**a, expected, lvalue_pref); - let expr_ty = fcx.expr_ty(check_env, &**a); + let expr_ty = fcx.expr_ty(&check_env.tt.node_types, &**a); fcx.write_ty(check_env, id, expr_ty); } ast::ExprAssign(ref lhs, ref rhs) => { @@ -3398,9 +3438,9 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, "illegal left-hand side expression"); } - let lhs_ty = fcx.expr_ty(check_env, &**lhs); + let lhs_ty = fcx.expr_ty(&check_env.tt.node_types, &**lhs); check_expr_coercable_to_type(check_env, fcx, &**rhs, lhs_ty); - let rhs_ty = fcx.expr_ty(check_env, &**rhs); + let rhs_ty = fcx.expr_ty(&check_env.tt.node_types, &**rhs); fcx.require_expr_have_sized_type(check_env, &**lhs, traits::AssignmentLhsSized); @@ -3420,8 +3460,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, ast::ExprWhile(ref cond, ref body, _) => { check_expr_has_type(check_env, fcx, &**cond, tcx.types.bool); check_block_no_value(check_env, fcx, &**body); - let cond_ty = fcx.expr_ty(check_env, &**cond); - let body_ty = fcx.node_ty(check_env, body.id); + let cond_ty = fcx.expr_ty(&check_env.tt.node_types, &**cond); + let body_ty = fcx.node_ty(&check_env.tt.node_types, body.id); if ty::type_is_error(cond_ty) || ty::type_is_error(body_ty) { fcx.write_error(check_env, id); } @@ -3451,7 +3491,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, } ast::ExprBlock(ref b) => { check_block_with_expected(check_env, fcx, &**b, expected); - let node_ty = fcx.node_ty(check_env, b.id); + let node_ty = fcx.node_ty(&check_env.tt.node_types, b.id); fcx.write_ty(check_env, id, node_ty); } ast::ExprCall(ref callee, ref args) => { @@ -3460,7 +3500,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, ast::ExprMethodCall(ident, ref tps, ref args) => { check_method_call(check_env, fcx, expr, ident, &args[..], &tps[..], expected, lvalue_pref); let args_err = { - let arg_tys = args.iter().map(|a| fcx.expr_ty(check_env, &**a)); + let arg_tys = args.iter().map(|a| fcx.expr_ty(&check_env.tt.node_types, &**a)); arg_tys.fold(false, |rest_err, a| rest_err || ty::type_is_error(a)) }; if args_err { @@ -3475,12 +3515,12 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, // Find the type of `e`. Supply hints based on the type we are casting to, // if appropriate. let t_1 = { - let typer = FnCtxtTyper::new(check_env, fcx); - typer.to_ty(t) + let mut joined = FnCtxtJoined::new(check_env, fcx); + joined.to_ty(t) }; let t_1 = structurally_resolved_type(check_env, fcx, expr.span, t_1); check_expr_with_expectation(check_env, fcx, e, ExpectCastableToType(t_1)); - let t_e = fcx.expr_ty(check_env, e); + let t_e = fcx.expr_ty(&check_env.tt.node_types, e); // Eagerly check for some obvious errors. if ty::type_is_error(t_e) { @@ -3545,7 +3585,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, None => { let t: Ty = fcx.infcx().next_ty_var(); check_expr_has_type(check_env, fcx, &**element, t); - (fcx.expr_ty(check_env, &**element), t) + (fcx.expr_ty(&check_env.tt.node_types, &**element), t) } }; @@ -3553,6 +3593,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, // For [foo, ..n] where n > 1, `foo` must have // Copy type: fcx.require_type_meets( + check_env, t, expr.span, traits::RepeatVec, @@ -3584,7 +3625,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, } _ => { check_expr_with_expectation(check_env, fcx, &**e, NoExpectation); - fcx.expr_ty(check_env, &**e) + fcx.expr_ty(&check_env.tt.node_types, &**e) } }; err_field = err_field || ty::type_is_error(t); @@ -3649,10 +3690,10 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, // Turn the path into a type and verify that that type unifies with // the resulting structure type. This is needed to handle type // parameters correctly. - let actual_structure_type = fcx.expr_ty(check_env, &*expr); + let actual_structure_type = fcx.expr_ty(&check_env.tt.node_types, &*expr); if !ty::type_is_error(actual_structure_type) { - let typer = FnCtxtTyper::new(check_env, fcx); - let type_and_substs = typer.instantiate_struct_literal_ty(struct_id, path); + let mut joined = FnCtxtJoined::new(check_env, fcx); + let type_and_substs = joined.instantiate_struct_literal_ty(struct_id, path); match fcx.mk_subty(false, infer::Misc(path.span), actual_structure_type, @@ -3688,8 +3729,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, check_expr_with_lvalue_pref(check_env, fcx, &**base, lvalue_pref); check_expr(check_env, fcx, &**idx); - let base_t = fcx.expr_ty(check_env, &**base); - let idx_t = fcx.expr_ty(check_env, &**idx); + let base_t = fcx.expr_ty(&check_env.tt.node_types, &**base); + let idx_t = fcx.expr_ty(&check_env.tt.node_types, &**idx); if ty::type_is_error(base_t) { fcx.write_ty(check_env, id, base_t); @@ -3699,7 +3740,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, let base_t = structurally_resolved_type(check_env, fcx, expr.span, base_t); match lookup_indexing(check_env, fcx, expr, base, base_t, idx_t, lvalue_pref) { Some((index_ty, element_ty)) => { - let idx_expr_ty = fcx.expr_ty(check_env, idx); + let idx_expr_ty = fcx.expr_ty(&check_env.tt.node_types, idx); demand::eqtype(fcx, expr.span, index_ty, idx_expr_ty); fcx.write_ty(check_env, id, element_ty); } @@ -3721,11 +3762,11 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, ast::ExprRange(ref start, ref end) => { let t_start = start.as_ref().map(|e| { check_expr(check_env, fcx, &**e); - fcx.expr_ty(check_env, &**e) + fcx.expr_ty(&check_env.tt.node_types, &**e) }); let t_end = end.as_ref().map(|e| { check_expr(check_env, fcx, &**e); - fcx.expr_ty(check_env, &**e) + fcx.expr_ty(&check_env.tt.node_types, &**e) }); let idx_type = match (t_start, t_end) { @@ -3768,9 +3809,12 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, if let Some(did) = did { let predicates = ty::lookup_predicates(tcx, did); let substs = Substs::new_type(vec![idx_type], vec![]); - let typer = FnCtxtTyper::new(check_env, fcx); - let bounds = typer.instantiate_bounds(expr.span, &substs, &predicates); + let bounds = { + let mut joined = FnCtxtJoined::new(check_env, fcx); + joined.instantiate_bounds(expr.span, &substs, &predicates) + }; fcx.add_obligations_for_parameters( + check_env, traits::ObligationCause::new(expr.span, fcx.body_id, traits::ItemObligation(did)), @@ -3802,13 +3846,13 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, debug!("type of expr({}) {} is...", expr.id, syntax::print::pprust::expr_to_string(expr)); debug!("... {}, expected is {}", - ppaux::ty_to_string(tcx, fcx.expr_ty(check_env, expr)), + ppaux::ty_to_string(tcx, fcx.expr_ty(&check_env.tt.node_types, expr)), expected.repr(tcx)); unifier(check_env); } -pub fn resolve_ty_and_def_ufcs<'a, 'b, 'tcx>(check_env: &mut CheckEnv<'tcx>, +fn resolve_ty_and_def_ufcs<'a, 'b, 'tcx>(check_env: &mut CheckEnv<'tcx>, fcx: &FnCtxt<'b, 'tcx>, path_res: def::PathResolution, opt_self_ty: Option>, @@ -3827,8 +3871,8 @@ pub fn resolve_ty_and_def_ufcs<'a, 'b, 'tcx>(check_env: &mut CheckEnv<'tcx>, let ty_segments = path.segments.init(); let base_ty_end = path.segments.len() - path_res.depth; let ty = { - let typer = FnCtxtTyper::new(check_env, fcx); - astconv::finish_resolving_def_to_ty(&typer, fcx, span, + let mut joined = FnCtxtJoined::new(check_env, fcx); + astconv::finish_resolving_def_to_ty(&mut joined, fcx, span, PathParamMode::Optional, &mut def, opt_self_ty, @@ -3858,11 +3902,12 @@ pub fn resolve_ty_and_def_ufcs<'a, 'b, 'tcx>(check_env: &mut CheckEnv<'tcx>, } } -fn constrain_path_type_parameters(fcx: &FnCtxt, - expr: &ast::Expr) +fn constrain_path_type_parameters<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a, 'tcx>, + expr: &ast::Expr) { fcx.opt_node_ty_substs(expr.id, |item_substs| { - fcx.add_default_region_param_bounds(&item_substs.substs, expr); + fcx.add_default_region_param_bounds(check_env, &item_substs.substs, expr); }); } @@ -3970,7 +4015,7 @@ fn check_decl_initializer<'a,'tcx>(check_env: &mut CheckEnv<'tcx>, // type of the lvalue it is referencing, and not some // supertype thereof. check_expr(check_env, fcx, init); - let init_ty = fcx.expr_ty(check_env, init); + let init_ty = fcx.expr_ty(&check_env.tt.node_types, init); demand::eqtype(fcx, init.span, init_ty, local_ty); }; } @@ -3984,7 +4029,7 @@ fn check_decl_local<'a,'tcx>(check_env: &mut CheckEnv<'tcx>, if let Some(ref init) = local.init { check_decl_initializer(check_env, fcx, local, &**init); - let init_ty = fcx.expr_ty(check_env, &**init); + let init_ty = fcx.expr_ty(&check_env.tt.node_types, &**init); if ty::type_is_error(init_ty) { fcx.write_ty(check_env, local.id, init_ty); } @@ -3995,7 +4040,7 @@ fn check_decl_local<'a,'tcx>(check_env: &mut CheckEnv<'tcx>, map: pat_id_map(&tcx.def_map, &*local.pat), }; _match::check_pat(check_env, &pcx, &*local.pat, t); - let pat_ty = fcx.node_ty(check_env, local.pat.id); + let pat_ty = fcx.node_ty(&check_env.tt.node_types, local.pat.id); if ty::type_is_error(pat_ty) { fcx.write_ty(check_env, local.id, pat_ty); } @@ -4012,7 +4057,7 @@ fn check_stmt<'a,'tcx>(check_env: &mut CheckEnv<'tcx>, match decl.node { ast::DeclLocal(ref l) => { check_decl_local(check_env, fcx, &**l); - let l_t = fcx.node_ty(check_env, l.id); + let l_t = fcx.node_ty(&check_env.tt.node_types, l.id); saw_bot = saw_bot || fcx.infcx().type_var_diverges(l_t); saw_err = saw_err || ty::type_is_error(l_t); } @@ -4023,14 +4068,14 @@ fn check_stmt<'a,'tcx>(check_env: &mut CheckEnv<'tcx>, node_id = id; // Check with expected type of () check_expr_has_type(check_env, fcx, &**expr, ty::mk_nil(fcx.tcx())); - let expr_ty = fcx.expr_ty(check_env, &**expr); + let expr_ty = fcx.expr_ty(&check_env.tt.node_types, &**expr); saw_bot = saw_bot || fcx.infcx().type_var_diverges(expr_ty); saw_err = saw_err || ty::type_is_error(expr_ty); } ast::StmtSemi(ref expr, id) => { node_id = id; check_expr(check_env, fcx, &**expr); - let expr_ty = fcx.expr_ty(check_env, &**expr); + let expr_ty = fcx.expr_ty(&check_env.tt.node_types, &**expr); saw_bot |= fcx.infcx().type_var_diverges(expr_ty); saw_err |= ty::type_is_error(expr_ty); } @@ -4050,7 +4095,7 @@ fn check_stmt<'a,'tcx>(check_env: &mut CheckEnv<'tcx>, fn check_block_no_value<'a,'tcx>(check_env: &mut CheckEnv<'tcx>, fcx: &FnCtxt<'a,'tcx>, blk: &'tcx ast::Block) { check_block_with_expected(check_env, fcx, blk, ExpectHasType(ty::mk_nil(fcx.tcx()))); - let blkty = fcx.node_ty(check_env, blk.id); + let blkty = fcx.node_ty(&check_env.tt.node_types, blk.id); if ty::type_is_error(blkty) { fcx.write_error(check_env, blk.id); } else { @@ -4076,7 +4121,7 @@ fn check_block_with_expected<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, for s in &blk.stmts { check_stmt(check_env, fcx, &**s); let s_id = ast_util::stmt_id(&**s); - let s_ty = fcx.node_ty(check_env, s_id); + let s_ty = fcx.node_ty(&check_env.tt.node_types, s_id); if any_diverges && !warned && match s.node { ast::StmtDecl(ref decl, _) => { match decl.node { @@ -4124,7 +4169,7 @@ fn check_block_with_expected<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, } _ => { check_expr_with_expectation(check_env, fcx, &**e, expected); - fcx.expr_ty(check_env, &**e) + fcx.expr_ty(&check_env.tt.node_types, &**e) } }; @@ -4187,7 +4232,7 @@ fn check_const_with_ty<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, /// pointer, which would mean their size is unbounded. This is different from /// the question of whether a type can be instantiated. See the definition of /// `check_instantiable`. -pub fn check_representable(tcx: &ty::ctxt, +fn check_representable(tcx: &ty::ctxt, sp: Span, item_id: ast::NodeId, designation: &str) -> bool { @@ -4222,7 +4267,7 @@ pub fn check_representable(tcx: &ty::ctxt, /// enum foo { Some(@foo) } /// /// is representable, but not instantiable. -pub fn check_instantiable(tcx: &ty::ctxt, +fn check_instantiable(tcx: &ty::ctxt, sp: Span, item_id: ast::NodeId) -> bool { @@ -4239,7 +4284,7 @@ pub fn check_instantiable(tcx: &ty::ctxt, } } -pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) { +fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) { let t = ty::node_id_to_type(tcx, id); if ty::type_needs_subst(t) { span_err!(tcx.sess, sp, E0074, "SIMD vector cannot be generic"); @@ -4268,7 +4313,7 @@ pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) { } } -pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, +fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, sp: Span, vs: &'tcx [P], id: ast::NodeId) { @@ -4416,7 +4461,7 @@ fn type_scheme_and_predicates_for_def<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, // Instantiates the given path, which must refer to an item with the given // number of type parameters and type. -pub fn instantiate_path<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, +fn instantiate_path<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, fcx: &FnCtxt<'a, 'tcx>, segments: &[ast::PathSegment], type_scheme: TypeScheme<'tcx>, @@ -4646,15 +4691,19 @@ pub fn instantiate_path<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, // Add all the obligations that are required, substituting and // normalized appropriately. let ty_substituted = { - let typer = FnCtxtTyper::new(check_env, fcx); - let bounds = typer.instantiate_bounds(span, &substs, &type_predicates); + let bounds = { + let mut joined = FnCtxtJoined::new(check_env, fcx); + joined.instantiate_bounds(span, &substs, &type_predicates) + }; fcx.add_obligations_for_parameters( + check_env, traits::ObligationCause::new(span, fcx.body_id, traits::ItemObligation(def.def_id())), &bounds); - // Substitute the values for the type parameters into the type of - // the referenced item. - typer.instantiate_type_scheme(span, &substs, &type_scheme.ty) + // Substitute the values for the type parameters into the type of + // the referenced item. + let mut joined = FnCtxtJoined::new(check_env, fcx); + joined.instantiate_type_scheme(span, &substs, &type_scheme.ty) }; if let Some((def::FromImpl(impl_def_id), self_ty)) = ufcs_method { @@ -4668,8 +4717,8 @@ pub fn instantiate_path<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, assert_eq!(substs.regions().len(subst::TypeSpace), impl_scheme.generics.regions.len(subst::TypeSpace)); - let typer = FnCtxtTyper::new(check_env, fcx); - let impl_ty = typer.instantiate_type_scheme(span, &substs, &impl_scheme.ty); + let mut joined = FnCtxtJoined::new(check_env, fcx); + let impl_ty = joined.instantiate_type_scheme(span, &substs, &impl_scheme.ty); if fcx.mk_subty(false, infer::Misc(span), self_ty, impl_ty).is_err() { fcx.tcx().sess.span_bug(span, &format!( @@ -4730,8 +4779,8 @@ pub fn instantiate_path<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, let type_count = type_defs.len(space); assert_eq!(substs.types.len(space), 0); for (i, typ) in data.types.iter().enumerate() { - let typer = FnCtxtTyper::new(check_env, fcx); - let t = typer.to_ty(&**typ); + let mut joined = FnCtxtJoined::new(check_env, fcx); + let t = joined.to_ty(&**typ); if i < type_count { substs.types.push(space, t); } else if i == type_count { @@ -4795,9 +4844,9 @@ pub fn instantiate_path<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, type_count); } - let typer = FnCtxtTyper::new(check_env, fcx); + let mut joined = FnCtxtJoined::new(check_env, fcx); let input_tys: Vec = - data.inputs.iter().map(|ty| typer.to_ty(&**ty)).collect(); + data.inputs.iter().map(|ty| joined.to_ty(&**ty)).collect(); let tuple_ty = ty::mk_tup(fcx.tcx(), input_tys); @@ -4807,7 +4856,7 @@ pub fn instantiate_path<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, } let output_ty: Option = - data.output.as_ref().map(|ty| typer.to_ty(&**ty)); + data.output.as_ref().map(|ty| joined.to_ty(&**ty)); let output_ty = output_ty.unwrap_or(ty::mk_nil(fcx.tcx())); @@ -4949,7 +4998,7 @@ fn structurally_resolve_type_or_else<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx> // 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<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, +fn structurally_resolved_type<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, fcx: &FnCtxt<'a, 'tcx>, sp: Span, ty: Ty<'tcx>) @@ -4961,7 +5010,7 @@ pub fn structurally_resolved_type<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, } // Returns true if b contains a break that can exit from b -pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: &ast::Block) -> bool { +fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: &ast::Block) -> bool { // First: is there an unlabeled break immediately // inside the loop? (loop_query(&*b, |e| { @@ -4981,7 +5030,7 @@ pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: &ast::Block) -> bool { })) } -pub fn check_bounds_are_used<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, +fn check_bounds_are_used<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, span: Span, tps: &OwnedSlice, ty: Ty<'tcx>) { @@ -5013,7 +5062,7 @@ pub fn check_bounds_are_used<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, /// Remember to add all intrinsics here, in librustc_trans/trans/intrinsic.rs, /// and in libcore/intrinsics.rs -pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) { +fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) { fn param<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, n: u32) -> Ty<'tcx> { let name = token::intern(&format!("P{}", n)); ty::mk_param(ccx.tcx, subst::FnSpace, n, name) diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index 441431ec6d3f6..35e8773cd9ae4 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -41,9 +41,9 @@ pub fn check_binop_assign<'a,'tcx>(check_env: &mut CheckEnv<'tcx>, check_expr_with_lvalue_pref(check_env, fcx, lhs_expr, PreferMutLvalue); check_expr(check_env, fcx, rhs_expr); - let expr_ty = fcx.expr_ty(check_env, lhs_expr); + let expr_ty = fcx.expr_ty(&check_env.tt.node_types, lhs_expr); let lhs_ty = structurally_resolved_type(check_env, fcx, lhs_expr.span, expr_ty); - let expr_ty = fcx.expr_ty(check_env, rhs_expr); + let expr_ty = fcx.expr_ty(&check_env.tt.node_types, rhs_expr); let rhs_ty = structurally_resolved_type(check_env, fcx, rhs_expr.span, expr_ty); if is_builtin_binop(fcx.tcx(), lhs_ty, rhs_ty, op) { @@ -86,7 +86,8 @@ pub fn check_binop<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, rhs_expr.repr(tcx)); check_expr(check_env, fcx, lhs_expr); - let lhs_ty = fcx.resolve_type_vars_if_possible(check_env, fcx.expr_ty(check_env, lhs_expr)); + let expr_ty = fcx.expr_ty(&check_env.tt.node_types, lhs_expr); + let lhs_ty = fcx.resolve_type_vars_if_possible(check_env, expr_ty); // Annoyingly, SIMD ops don't fit into the PartialEq/PartialOrd // traits, because their return type is not bool. Perhaps this @@ -94,7 +95,8 @@ pub fn check_binop<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, // different path that bypassess all traits. if ty::type_is_simd(fcx.tcx(), lhs_ty) { check_expr_coercable_to_type(check_env, fcx, rhs_expr, lhs_ty); - let rhs_ty = fcx.resolve_type_vars_if_possible(check_env, fcx.expr_ty(check_env, lhs_expr)); + let expr_ty = fcx.expr_ty(&check_env.tt.node_types, lhs_expr); + let rhs_ty = fcx.resolve_type_vars_if_possible(check_env, expr_ty); let return_ty = enforce_builtin_binop_types(fcx, lhs_expr, lhs_ty, rhs_expr, rhs_ty, op); fcx.write_ty(check_env, expr.id, return_ty); return; @@ -343,7 +345,7 @@ fn lookup_op_method<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, // HACK(eddyb) Fully qualified path to work around a resolve bug. let method_call = ::middle::ty::MethodCall::expr(expr.id); - check_env.method_map.insert(method_call, method); + check_env.tt.method_map.insert(method_call, method); // extract return type for method; all late bound regions // should have been instantiated by now diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 01b094bf64cbf..70be9ba177797 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -87,6 +87,7 @@ use super::dropck; use super::CheckEnv; use super::FnCtxt; use super::FnCtxtTyper; +use super::FnCtxtJoined; use super::vtable; use middle::free_region::FreeRegionMap; use middle::implicator; @@ -253,7 +254,7 @@ fn relate_free_regions<'a, 'tcx>(check_env: &CheckEnv<'tcx>, debug!("relate_free_regions(t={})", ty.repr(tcx)); let body_scope = CodeExtent::from_node_id(body_id); let body_scope = ty::ReScope(body_scope); - let typer = FnCtxtTyper::new(check_env, fcx); + let typer = FnCtxtTyper::new(&check_env.tt, fcx); let implications = implicator::implications(fcx.infcx(), &typer, body_id, ty, body_scope, span); @@ -328,12 +329,12 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> { /// Try to resolve the type for the given node. fn resolve_node_type(&self, id: ast::NodeId) -> Ty<'tcx> { - let t = self.fcx.node_ty(self.check_env, id); + let t = self.fcx.node_ty(&self.check_env.tt.node_types, id); resolve_type(self.fcx, t) } fn resolve_method_type(&self, method_call: MethodCall) -> Option> { - let method_ty = self.check_env.method_map + let method_ty = self.check_env.tt.method_map .get(&method_call).map(|method| method.ty); method_ty.map(|method_ty| resolve_type(self.fcx, method_ty)) } @@ -398,9 +399,7 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> { // Make a copy of the region obligations vec because we'll need // to be able to borrow the fulfillment-cx below when projecting. let region_obligations = - self.fcx.inh.fulfillment_cx.borrow() - .region_obligations(node_id) - .to_vec(); + self.check_env.fulfillment_cx.region_obligations(node_id).to_vec(); for r_o in ®ion_obligations { debug!("visit_region_obligations: r_o={}", @@ -412,7 +411,7 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> { // Processing the region obligations should not cause the list to grow further: assert_eq!(region_obligations.len(), - self.fcx.inh.fulfillment_cx.borrow().region_obligations(node_id).len()); + self.check_env.fulfillment_cx.region_obligations(node_id).len()); } fn resolve_regions_and_report_errors(&self) { @@ -530,7 +529,7 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) { expr_ty, ty::ReScope(CodeExtent::from_node_id(expr.id))); let method_call = MethodCall::expr(expr.id); - let has_method_map = rcx.check_env.method_map.contains_key(&method_call); + let has_method_map = rcx.check_env.tt.method_map.contains_key(&method_call); // Check any autoderefs or autorefs that appear. if let Some(adjustment) = rcx.fcx.inh.adjustments.borrow().get(&expr.id) { @@ -567,7 +566,7 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) { // If necessary, constrain destructors in the unadjusted form of this // expression. let cmt_result = { - let typer = FnCtxtTyper::new(rcx.check_env, rcx.fcx); + let typer = FnCtxtTyper::new(&rcx.check_env.tt, rcx.fcx); let mc = mc::MemCategorizationContext::new(&typer); mc.cat_expr_unadjusted(expr) }; @@ -587,7 +586,7 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) { // If necessary, constrain destructors in this expression. This will be // the adjusted form if there is an adjustment. let cmt_result = { - let typer = FnCtxtTyper::new(rcx.check_env, rcx.fcx); + let typer = FnCtxtTyper::new(&rcx.check_env.tt, rcx.fcx); let mc = mc::MemCategorizationContext::new(&typer); mc.cat_expr(expr) }; @@ -678,7 +677,7 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) { ast::ExprUnary(ast::UnDeref, ref base) => { // For *a, the lifetime of a must enclose the deref let method_call = MethodCall::expr(expr.id); - let method_ty = rcx.check_env.method_map.get(&method_call).map( |method| method.ty ); + let method_ty = rcx.check_env.tt.method_map.get(&method_call).map( |method| method.ty ); let base_ty = match method_ty { Some(method_ty) => { constrain_call(rcx, expr, Some(&**base), @@ -907,7 +906,7 @@ fn constrain_autoderefs<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>, let method_call = MethodCall::autoderef(deref_expr.id, i as u32); debug!("constrain_autoderefs: method_call={:?} (of {:?} total)", method_call, derefs); - let result = match rcx.check_env.method_map.get(&method_call) { + let result = match rcx.check_env.tt.method_map.get(&method_call) { Some(method) => { debug!("constrain_autoderefs: #{} is overloaded, method={}", i, method.repr(rcx.tcx())); @@ -931,7 +930,7 @@ fn constrain_autoderefs<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>, debug!("constrain_autoderefs: receiver r={:?} m={:?}", r.repr(rcx.tcx()), m); - let typer = FnCtxtTyper::new(rcx.check_env, rcx.fcx); + let typer = FnCtxtTyper::new(&rcx.check_env.tt, rcx.fcx); let mc = mc::MemCategorizationContext::new(&typer); let self_cmt = ignore_err!(mc.cat_expr_autoderefd(deref_expr, i)); debug!("constrain_autoderefs: self_cmt={:?}", @@ -1058,7 +1057,7 @@ fn link_addr_of(rcx: &mut Rcx, expr: &ast::Expr, debug!("link_addr_of(expr={}, base={})", expr.repr(rcx.tcx()), base.repr(rcx.tcx())); let cmt = { - let typer = FnCtxtTyper::new(rcx.check_env, rcx.fcx); + let typer = FnCtxtTyper::new(&rcx.check_env.tt, rcx.fcx); let mc = mc::MemCategorizationContext::new(&typer); ignore_err!(mc.cat_expr(base)) }; @@ -1077,7 +1076,7 @@ fn link_local(rcx: &Rcx, local: &ast::Local) { None => { return; } Some(ref expr) => &**expr, }; - let typer = FnCtxtTyper::new(rcx.check_env, rcx.fcx); + let typer = FnCtxtTyper::new(&rcx.check_env.tt, rcx.fcx); let mc = mc::MemCategorizationContext::new(&typer); let discr_cmt = ignore_err!(mc.cat_expr(init_expr)); link_pattern(rcx, mc, discr_cmt, &*local.pat); @@ -1088,7 +1087,7 @@ fn link_local(rcx: &Rcx, local: &ast::Local) { /// linked to the lifetime of its guarantor (if any). fn link_match(rcx: &Rcx, discr: &ast::Expr, arms: &[ast::Arm]) { debug!("regionck::for_match()"); - let typer = FnCtxtTyper::new(rcx.check_env, rcx.fcx); + let typer = FnCtxtTyper::new(&rcx.check_env.tt, rcx.fcx); let mc = mc::MemCategorizationContext::new(&typer); let discr_cmt = ignore_err!(mc.cat_expr(discr)); debug!("discr_cmt={}", discr_cmt.repr(rcx.tcx())); @@ -1104,10 +1103,10 @@ fn link_match(rcx: &Rcx, discr: &ast::Expr, arms: &[ast::Arm]) { /// linked to the lifetime of its guarantor (if any). fn link_fn_args(rcx: &Rcx, body_scope: CodeExtent, args: &[ast::Arg]) { debug!("regionck::link_fn_args(body_scope={:?})", body_scope); - let typer = FnCtxtTyper::new(rcx.check_env, rcx.fcx); + let typer = FnCtxtTyper::new(&rcx.check_env.tt, rcx.fcx); let mc = mc::MemCategorizationContext::new(&typer); for arg in args { - let arg_ty = rcx.fcx.node_ty(rcx.check_env, arg.id); + let arg_ty = rcx.fcx.node_ty(&rcx.check_env.tt.node_types, arg.id); let re_scope = ty::ReScope(body_scope); let arg_cmt = mc.cat_rvalue(arg.id, arg.ty.span, re_scope, arg_ty); debug!("arg_ty={} arg_cmt={}", @@ -1159,7 +1158,7 @@ fn link_autoref(rcx: &Rcx, autoref: &ty::AutoRef) { debug!("link_autoref(autoref={:?})", autoref); - let typer = FnCtxtTyper::new(rcx.check_env, rcx.fcx); + let typer = FnCtxtTyper::new(&rcx.check_env.tt, rcx.fcx); let mc = mc::MemCategorizationContext::new(&typer); let expr_cmt = ignore_err!(mc.cat_expr_autoderefd(expr, autoderefs)); debug!("expr_cmt={}", expr_cmt.repr(rcx.tcx())); @@ -1185,7 +1184,7 @@ fn link_by_ref(rcx: &Rcx, let tcx = rcx.tcx(); debug!("link_by_ref(expr={}, callee_scope={:?})", expr.repr(tcx), callee_scope); - let typer = FnCtxtTyper::new(rcx.check_env, rcx.fcx); + let typer = FnCtxtTyper::new(&rcx.check_env.tt, rcx.fcx); let mc = mc::MemCategorizationContext::new(&typer); let expr_cmt = ignore_err!(mc.cat_expr(expr)); let borrow_region = ty::ReScope(callee_scope); @@ -1433,7 +1432,7 @@ pub fn type_must_outlive<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>, region.repr(rcx.tcx())); let implications = { - let typer = FnCtxtTyper::new(rcx.check_env, rcx.fcx); + let typer = FnCtxtTyper::new(&rcx.check_env.tt, rcx.fcx); implicator::implications(rcx.fcx.infcx(), &typer, rcx.body_id, ty, region, origin.span()) }; @@ -1462,7 +1461,7 @@ pub fn type_must_outlive<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>, rcx.body_id, traits::ItemObligation(def_id)); let obligation = traits::Obligation::new(cause, predicate); - rcx.fcx.register_predicate(obligation); + rcx.fcx.register_predicate(rcx.check_env, obligation); } } } @@ -1477,7 +1476,7 @@ fn closure_must_outlive<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>, region.repr(rcx.tcx()), def_id.repr(rcx.tcx()), substs.repr(rcx.tcx())); let upvars = { - let typer = FnCtxtTyper::new(rcx.check_env, rcx.fcx); + let typer = FnCtxtTyper::new(&rcx.check_env.tt, rcx.fcx); typer.closure_upvars(def_id, substs).unwrap() }; for upvar in upvars { @@ -1488,7 +1487,7 @@ fn closure_must_outlive<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>, } } -fn generic_must_outlive<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>, +fn generic_must_outlive<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>, origin: infer::SubregionOrigin<'tcx>, region: ty::Region, generic: &GenericKind<'tcx>) { @@ -1545,7 +1544,7 @@ fn generic_must_outlive<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>, param_bounds); } -fn projection_bounds<'a,'tcx>(rcx: &Rcx<'a, 'tcx>, +fn projection_bounds<'a,'tcx>(rcx: &mut Rcx<'a, 'tcx>, span: Span, projection_ty: &ty::ProjectionTy<'tcx>) -> Vec @@ -1583,8 +1582,8 @@ fn projection_bounds<'a,'tcx>(rcx: &Rcx<'a, 'tcx>, outlives.repr(tcx)); // apply the substitutions (and normalize any projected types) - let typer = FnCtxtTyper::new(rcx.check_env, fcx); - let outlives = typer.instantiate_type_scheme(span, + let mut joined = FnCtxtJoined::new(rcx.check_env, fcx); + let outlives = joined.instantiate_type_scheme(span, projection_ty.trait_ref.substs, &outlives); diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs index d873a09072b18..02cbe9e13a148 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -182,7 +182,7 @@ impl<'a,'tcx> AdjustBorrowDelegate<'a,'tcx> { fn tcx(&self) -> &'a ty::ctxt<'tcx> { self.fcx.tcx() } - fn adjust_upvar_borrow_kind_for_consume(&self, + fn adjust_upvar_borrow_kind_for_consume(&mut self, cmt: mc::cmt<'tcx>, mode: euv::ConsumeMode) { @@ -270,7 +270,7 @@ impl<'a,'tcx> AdjustBorrowDelegate<'a,'tcx> { } } - fn adjust_upvar_borrow_kind_for_unique(&self, cmt: mc::cmt<'tcx>) { + fn adjust_upvar_borrow_kind_for_unique(&mut self, cmt: mc::cmt<'tcx>) { debug!("adjust_upvar_borrow_kind_for_unique(cmt={})", cmt.repr(self.tcx())); @@ -301,7 +301,7 @@ impl<'a,'tcx> AdjustBorrowDelegate<'a,'tcx> { } } - fn try_adjust_upvar_deref(&self, + fn try_adjust_upvar_deref(&mut self, note: &mc::Note, borrow_kind: ty::BorrowKind) -> bool @@ -348,7 +348,7 @@ impl<'a,'tcx> AdjustBorrowDelegate<'a,'tcx> { /// basically follows a lattice of `imm < unique-imm < mut`, moving from left to right as needed /// (but never right to left). Here the argument `mutbl` is the borrow_kind that is required by /// some particular use. - fn adjust_upvar_borrow_kind(&self, + fn adjust_upvar_borrow_kind(&mut self, upvar_id: ty::UpvarId, upvar_capture: &mut ty::UpvarCapture, kind: ty::BorrowKind) { @@ -378,7 +378,7 @@ impl<'a,'tcx> AdjustBorrowDelegate<'a,'tcx> { } } - fn adjust_closure_kind(&self, + fn adjust_closure_kind(&mut self, closure_id: ast::NodeId, new_kind: ty::ClosureKind) { debug!("adjust_closure_kind(closure_id={}, new_kind={:?})", @@ -439,7 +439,7 @@ impl<'a,'tcx> AdjustBorrowKind<'a,'tcx> { fcx: self.fcx, closures_with_inferred_kinds: self.closures_with_inferred_kinds, }; - let typer = FnCtxtTyper::new(self.check_env, self.fcx); + let typer = FnCtxtTyper::new(&self.check_env.tt, self.fcx); let mut euv = euv::ExprUseVisitor::new(&mut delegate, &typer); euv.walk_fn(decl, body); } diff --git a/src/librustc_typeck/check/vtable.rs b/src/librustc_typeck/check/vtable.rs index 5e3dcbfdc0e5c..112649ba579aa 100644 --- a/src/librustc_typeck/check/vtable.rs +++ b/src/librustc_typeck/check/vtable.rs @@ -77,7 +77,8 @@ pub fn check_object_safety<'tcx>(tcx: &ty::ctxt<'tcx>, } } -pub fn register_object_cast_obligations<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, +pub fn register_object_cast_obligations<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a, 'tcx>, span: Span, object_trait: &ty::TyTrait<'tcx>, referent_ty: Ty<'tcx>) @@ -85,6 +86,7 @@ pub fn register_object_cast_obligations<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, { // We can only make objects from sized types. fcx.register_builtin_bound( + check_env, referent_ty, ty::BoundSized, traits::ObligationCause::new(span, fcx.body_id, traits::ObjectSized)); @@ -109,7 +111,7 @@ pub fn register_object_cast_obligations<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, object_trait.principal_trait_ref_with_self_ty(fcx.tcx(), referent_ty); let object_obligation = Obligation::new(cause.clone(), object_trait_ref.as_predicate()); - fcx.register_predicate(object_obligation); + fcx.register_predicate(check_env, object_obligation); // Create additional obligations for all the various builtin // bounds attached to the object cast. (In other words, if the @@ -117,6 +119,7 @@ pub fn register_object_cast_obligations<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, // for the Send check.) for builtin_bound in &object_trait.bounds.builtin_bounds { fcx.register_builtin_bound( + check_env, referent_ty, builtin_bound, cause.clone()); @@ -128,7 +131,7 @@ pub fn register_object_cast_obligations<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, for projection_bound in &projection_bounds { let projection_obligation = Obligation::new(cause.clone(), projection_bound.as_predicate()); - fcx.register_predicate(projection_obligation); + fcx.register_predicate(check_env, projection_obligation); } object_trait_ref @@ -152,9 +155,8 @@ pub fn select_all_fcx_obligations_or_error<'a, 'ctx>(check_env: &mut CheckEnv<'c assert!(check_env.deferred_call_resolutions.is_empty()); select_all_fcx_obligations_and_apply_defaults(check_env, fcx); - let mut fulfillment_cx = fcx.inh.fulfillment_cx.borrow_mut(); - let typer = FnCtxtTyper::new(check_env, fcx); - let r = fulfillment_cx.select_all_or_error(fcx.infcx(), &typer); + let typer = FnCtxtTyper::new(&check_env.tt, fcx); + let r = check_env.fulfillment_cx.select_all_or_error(fcx.infcx(), &typer); match r { Ok(()) => { } Err(errors) => { report_fulfillment_errors(fcx.infcx(), &errors); } @@ -162,13 +164,12 @@ pub fn select_all_fcx_obligations_or_error<'a, 'ctx>(check_env: &mut CheckEnv<'c } /// Select as many obligations as we can at present. -pub fn select_fcx_obligations_where_possible<'a, 'ctx>(check_env: &CheckEnv<'ctx>, +pub fn select_fcx_obligations_where_possible<'a, 'ctx>(check_env: &mut CheckEnv<'ctx>, fcx: &FnCtxt<'a, 'ctx>) { - let typer = FnCtxtTyper::new(check_env, fcx); + let typer = FnCtxtTyper::new(&check_env.tt, fcx); match - fcx.inh.fulfillment_cx - .borrow_mut() + check_env.fulfillment_cx .select_where_possible(fcx.infcx(), &typer) { Ok(()) => { } @@ -179,13 +180,12 @@ pub fn select_fcx_obligations_where_possible<'a, 'ctx>(check_env: &CheckEnv<'ctx /// Try to select any fcx obligation that we haven't tried yet, in an effort to improve inference. /// You could just call `select_fcx_obligations_where_possible` except that it leads to repeated /// work. -pub fn select_new_fcx_obligations<'a, 'ctx>(check_env: &CheckEnv<'ctx>, +pub fn select_new_fcx_obligations<'a, 'ctx>(check_env: &mut CheckEnv<'ctx>, fcx: &FnCtxt<'a, 'ctx>) { - let typer = FnCtxtTyper::new(check_env, fcx); + let typer = FnCtxtTyper::new(&check_env.tt, fcx); match - fcx.inh.fulfillment_cx - .borrow_mut() + check_env.fulfillment_cx .select_new_obligations(fcx.infcx(), &typer) { Ok(()) => { } diff --git a/src/librustc_typeck/check/wf.rs b/src/librustc_typeck/check/wf.rs index fb27858bd5199..69625d3ea37cc 100644 --- a/src/librustc_typeck/check/wf.rs +++ b/src/librustc_typeck/check/wf.rs @@ -9,7 +9,7 @@ // except according to those terms. use astconv::AstConv; -use super::{CheckEnv, FnCtxt, FnCtxtTyper, Inherited, blank_fn_ctxt, vtable, regionck}; +use super::{CheckEnv, FnCtxt, FnCtxtTyper, FnCtxtJoined, Inherited, blank_fn_ctxt, vtable, regionck}; use constrained_type_params::{identify_constrained_type_params, Parameter}; use CrateCtxt; use middle::region; @@ -181,6 +181,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { if !variant.fields.is_empty() { for field in variant.fields.init() { fcx.register_builtin_bound( + bounds_checker.check_env, field.ty, ty::BoundSized, traits::ObligationCause::new(field.span, @@ -211,10 +212,12 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { debug!("check_item_type at bounds_checker.scope: {:?}", bounds_checker.scope); let type_scheme = ty::lookup_item_type(fcx.tcx(), local_def(item.id)); - let typer = FnCtxtTyper::new(check_env, fcx); - let item_ty = typer.instantiate_type_scheme(item.span, - &fcx.inh.param_env.free_substs, - &type_scheme.ty); + let item_ty = { + let mut joined = FnCtxtJoined::new(bounds_checker.check_env, fcx); + joined.instantiate_type_scheme(item.span, + &fcx.inh.param_env.free_substs, + &type_scheme.ty) + }; bounds_checker.check_traits_in_ty(item_ty); }); @@ -235,10 +238,12 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { // that is, with all type parameters converted from bound // to free. let self_ty = ty::node_id_to_type(fcx.tcx(), item.id); - let typer = FnCtxtTyper::new(check_env, fcx); - let self_ty = typer.instantiate_type_scheme(item.span, - &fcx.inh.param_env.free_substs, - &self_ty); + let self_ty = { + let mut joined = FnCtxtJoined::new(bounds_checker.check_env, fcx); + joined.instantiate_type_scheme(item.span, + &fcx.inh.param_env.free_substs, + &self_ty) + }; bounds_checker.check_traits_in_ty(self_ty); @@ -249,9 +254,12 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { Some(t) => { t } }; - let trait_ref = typer.instantiate_type_scheme(item.span, - &fcx.inh.param_env.free_substs, - &trait_ref); + let trait_ref = { + let mut joined = FnCtxtJoined::new(bounds_checker.check_env, fcx); + joined.instantiate_type_scheme(item.span, + &fcx.inh.param_env.free_substs, + &trait_ref) + }; // We are stricter on the trait-ref in an impl than the // self-type. In particular, we enforce region @@ -274,14 +282,16 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { let predicates = ty::lookup_super_predicates(fcx.tcx(), poly_trait_ref.def_id()); let predicates = predicates.instantiate_supertrait(fcx.tcx(), &poly_trait_ref); let predicates = { + let typer = FnCtxtTyper::new(&bounds_checker.check_env.tt, fcx); let selcx = &mut traits::SelectionContext::new(fcx.infcx(), &typer); traits::normalize(selcx, cause.clone(), &predicates) }; for predicate in predicates.value.predicates { - fcx.register_predicate(traits::Obligation::new(cause.clone(), predicate)); + fcx.register_predicate(bounds_checker.check_env, + traits::Obligation::new(cause.clone(), predicate)); } for obligation in predicates.obligations { - fcx.register_predicate(obligation); + fcx.register_predicate(bounds_checker.check_env, obligation); } }); } @@ -480,7 +490,7 @@ impl<'ccx, 'tcx, 'v> Visitor<'v> for CheckTypeWellFormedVisitor<'ccx, 'tcx> { } pub struct BoundsChecker<'cx,'tcx:'cx> { - check_env: &'cx CheckEnv<'tcx>, + check_env: &'cx mut CheckEnv<'tcx>, fcx: &'cx FnCtxt<'cx,'tcx>, span: Span, @@ -494,7 +504,7 @@ pub struct BoundsChecker<'cx,'tcx:'cx> { } impl<'cx,'tcx> BoundsChecker<'cx,'tcx> { - pub fn new(check_env: &'cx CheckEnv<'tcx>, + pub fn new(check_env: &'cx mut CheckEnv<'tcx>, fcx: &'cx FnCtxt<'cx,'tcx>, span: Span, scope: ast::NodeId, @@ -517,12 +527,15 @@ impl<'cx,'tcx> BoundsChecker<'cx,'tcx> { pub fn check_trait_ref(&mut self, trait_ref: &ty::TraitRef<'tcx>) { let trait_predicates = ty::lookup_predicates(self.fcx.tcx(), trait_ref.def_id); - let typer = FnCtxtTyper::new(self.check_env, self.fcx); - let bounds = typer.instantiate_bounds(self.span, - trait_ref.substs, - &trait_predicates); + let bounds = { + let mut joined = FnCtxtJoined::new(self.check_env, self.fcx); + joined.instantiate_bounds(self.span, + trait_ref.substs, + &trait_predicates) + }; self.fcx.add_obligations_for_parameters( + self.check_env, traits::ObligationCause::new( self.span, self.fcx.body_id, @@ -586,12 +599,15 @@ impl<'cx,'tcx> TypeFolder<'tcx> for BoundsChecker<'cx,'tcx> { ty::ty_struct(type_id, substs) | ty::ty_enum(type_id, substs) => { let type_predicates = ty::lookup_predicates(self.fcx.tcx(), type_id); - let typer = FnCtxtTyper::new(self.check_env, self.fcx); - let bounds = typer.instantiate_bounds(self.span, substs, - &type_predicates); + let bounds = { + let mut joined = FnCtxtJoined::new(self.check_env, self.fcx); + joined.instantiate_bounds(self.span, substs, + &type_predicates) + }; if self.binding_count == 0 { self.fcx.add_obligations_for_parameters( + self.check_env, traits::ObligationCause::new(self.span, self.fcx.body_id, traits::ItemObligation(type_id)), @@ -621,6 +637,7 @@ impl<'cx,'tcx> TypeFolder<'tcx> for BoundsChecker<'cx,'tcx> { // that will require an RFC. -nmatsakis) let bounds = filter_to_trait_obligations(bounds); self.fcx.add_obligations_for_parameters( + self.check_env, traits::ObligationCause::new(self.span, self.fcx.body_id, traits::ItemObligation(type_id)), @@ -659,8 +676,8 @@ fn struct_variant<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, .iter() .map(|field| { let field_ty = ty::node_id_to_type(fcx.tcx(), field.node.id); - let typer = FnCtxtTyper::new(check_env, fcx); - let field_ty = typer.instantiate_type_scheme(field.span, + let mut joined = FnCtxtJoined::new(check_env, fcx); + let field_ty = joined.instantiate_type_scheme(field.span, &fcx.inh.param_env.free_substs, &field_ty); AdtField { ty: field_ty, span: field.span } @@ -687,9 +704,9 @@ fn enum_variants<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, AdtVariant { fields: args.iter().enumerate().map(|(index, arg)| { let arg_ty = arg_tys[index]; - let typer = FnCtxtTyper::new(check_env, fcx); + let mut joined = FnCtxtJoined::new(check_env, fcx); let arg_ty = - typer.instantiate_type_scheme(variant.span, + joined.instantiate_type_scheme(variant.span, &fcx.inh.param_env.free_substs, &arg_ty); AdtField { diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 59dd461406a3e..0c5b2420fcc9b 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -95,14 +95,14 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { // operating on scalars, we clear the overload. fn fix_scalar_binary_expr(&mut self, e: &ast::Expr) { if let ast::ExprBinary(ref op, ref lhs, ref rhs) = e.node { - let lhs_ty = self.fcx.node_ty(self.check_env, lhs.id); + let lhs_ty = self.fcx.node_ty(&self.check_env.tt.node_types, lhs.id); let lhs_ty = self.fcx.infcx().resolve_type_vars_if_possible(&lhs_ty); - let rhs_ty = self.fcx.node_ty(self.check_env, rhs.id); + let rhs_ty = self.fcx.node_ty(&self.check_env.tt.node_types, rhs.id); let rhs_ty = self.fcx.infcx().resolve_type_vars_if_possible(&rhs_ty); if ty::type_is_scalar(lhs_ty) && ty::type_is_scalar(rhs_ty) { - self.check_env.method_map.remove(&MethodCall::expr(e.id)); + self.check_env.tt.method_map.remove(&MethodCall::expr(e.id)); // weird but true: the by-ref binops put an // adjustment on the lhs but not the rhs; the @@ -232,7 +232,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { return } - for (def_id, closure_ty) in &self.check_env.closure_tys { + for (def_id, closure_ty) in &self.check_env.tt.closure_tys { let closure_ty = self.resolve(closure_ty, ResolvingClosure(*def_id)); self.fcx.tcx().closure_tys.borrow_mut().insert(*def_id, closure_ty); } @@ -247,7 +247,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { self.visit_adjustments(reason, id); // Resolve the type of the node with id `id` - let n_ty = self.fcx.node_ty(self.check_env, id); + let n_ty = self.fcx.node_ty(&self.check_env.tt.node_types, id); let n_ty = self.resolve(&n_ty, reason); write_ty_to_tcx(self.tcx(), id, n_ty); debug!("Node {} has type {}", id, n_ty.repr(self.tcx())); @@ -297,7 +297,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { reason: ResolveReason, method_call: MethodCall) { // Resolve any method map entry - match self.check_env.method_map.remove(&method_call) { + match self.check_env.tt.method_map.remove(&method_call) { Some(method) => { debug!("writeback::resolve_method_map_entry(call={:?}, entry={})", method_call, diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 014991f7ea560..fb9685c35372f 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -344,7 +344,7 @@ impl<'a,'tcx> CrateCtxt<'a,'tcx> { } impl<'a,'tcx> ItemCtxt<'a,'tcx> { - fn to_ty(&self, rs: &RS, ast_ty: &ast::Ty) -> Ty<'tcx> { + fn to_ty(&mut self, rs: &RS, ast_ty: &ast::Ty) -> Ty<'tcx> { ast_ty_to_ty(self, rs, ast_ty) } } @@ -380,7 +380,7 @@ impl<'a, 'tcx> AstConv<'tcx> for ItemCtxt<'a, 'tcx> { } - fn get_type_parameter_bounds(&self, + fn get_type_parameter_bounds(&mut self, span: Span, node_id: ast::NodeId) -> Result>, ErrorReported> @@ -413,7 +413,7 @@ impl<'a, 'tcx> AstConv<'tcx> for ItemCtxt<'a, 'tcx> { self.tcx().types.err } - fn projected_ty(&self, + fn projected_ty(&mut self, _span: Span, trait_ref: ty::TraitRef<'tcx>, item_name: ast::Name) @@ -427,7 +427,7 @@ impl<'a, 'tcx> AstConv<'tcx> for ItemCtxt<'a, 'tcx> { /// an `ItemCtxt`. This allows us to use multiple kinds of sources. trait GetTypeParameterBounds<'tcx> { fn get_type_parameter_bounds(&self, - astconv: &AstConv<'tcx>, + astconv: &mut AstConv<'tcx>, span: Span, node_id: ast::NodeId) -> Vec>; @@ -438,7 +438,7 @@ impl<'a,'b,'tcx,A,B> GetTypeParameterBounds<'tcx> for (&'a A,&'b B) where A : GetTypeParameterBounds<'tcx>, B : GetTypeParameterBounds<'tcx> { fn get_type_parameter_bounds(&self, - astconv: &AstConv<'tcx>, + astconv: &mut AstConv<'tcx>, span: Span, node_id: ast::NodeId) -> Vec> @@ -452,7 +452,7 @@ impl<'a,'b,'tcx,A,B> GetTypeParameterBounds<'tcx> for (&'a A,&'b B) /// Empty set of bounds. impl<'tcx> GetTypeParameterBounds<'tcx> for () { fn get_type_parameter_bounds(&self, - _astconv: &AstConv<'tcx>, + _astconv: &mut AstConv<'tcx>, _span: Span, _node_id: ast::NodeId) -> Vec> @@ -466,7 +466,7 @@ impl<'tcx> GetTypeParameterBounds<'tcx> for () { /// from the trait/impl have been fully converted. impl<'tcx> GetTypeParameterBounds<'tcx> for ty::GenericPredicates<'tcx> { fn get_type_parameter_bounds(&self, - astconv: &AstConv<'tcx>, + astconv: &mut AstConv<'tcx>, _span: Span, node_id: ast::NodeId) -> Vec> @@ -501,7 +501,7 @@ impl<'tcx> GetTypeParameterBounds<'tcx> for ty::GenericPredicates<'tcx> { /// bounds for those a type parameter `X` if `X::Foo` is used. impl<'tcx> GetTypeParameterBounds<'tcx> for ast::Generics { fn get_type_parameter_bounds(&self, - astconv: &AstConv<'tcx>, + astconv: &mut AstConv<'tcx>, _: Span, node_id: ast::NodeId) -> Vec> @@ -513,26 +513,25 @@ impl<'tcx> GetTypeParameterBounds<'tcx> for ast::Generics { let def = astconv.tcx().type_parameter_def(node_id); let ty = ty::mk_param_from_def(astconv.tcx(), &def); - let from_ty_params = + let mut bounds = self.ty_params .iter() .filter(|p| p.id == node_id) .flat_map(|p| p.bounds.iter()) - .flat_map(|b| predicates_from_bound(astconv, ty, b).into_iter()); + .flat_map(|b| predicates_from_bound(astconv, ty, b).into_iter()) + .collect::>(); + + for wp in &self.where_clause.predicates { + if let ast::WherePredicate::BoundPredicate(ref bp) = *wp { + if is_param(astconv.tcx(), &bp.bounded_ty, node_id) { + for b in bp.bounds.iter() { + bounds.extend(predicates_from_bound(astconv, ty, b)); + } + } + } + } - let from_where_clauses = - self.where_clause - .predicates - .iter() - .filter_map(|wp| match *wp { - ast::WherePredicate::BoundPredicate(ref bp) => Some(bp), - _ => None - }) - .filter(|bp| is_param(astconv.tcx(), &bp.bounded_ty, node_id)) - .flat_map(|bp| bp.bounds.iter()) - .flat_map(|b| predicates_from_bound(astconv, ty, b).into_iter()); - - from_ty_params.chain(from_where_clauses).collect() + bounds } } @@ -568,7 +567,7 @@ fn get_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, enum_predicates: ty::GenericPredicates<'tcx>, variants: &[P]) { let tcx = ccx.tcx; - let icx = ccx.icx(&enum_predicates); + let mut icx = ccx.icx(&enum_predicates); // Create a set of parameter types shared among all the variants. for variant in variants { @@ -620,7 +619,7 @@ fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, ty_generic_predicates_for_fn(ccx, &sig.generics, rcvr_ty_predicates); let (fty, explicit_self_category) = - astconv::ty_of_method(&ccx.icx(&(rcvr_ty_predicates, &sig.generics)), + astconv::ty_of_method(&mut ccx.icx(&(rcvr_ty_predicates, &sig.generics)), sig, untransformed_rcvr_ty); let def_id = local_def(id); @@ -813,7 +812,7 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) { }, ast::ItemDefaultImpl(_, ref ast_trait_ref) => { let trait_ref = - astconv::instantiate_mono_trait_ref(&ccx.icx(&()), + astconv::instantiate_mono_trait_ref(&mut ccx.icx(&()), &ExplicitRscope, ast_trait_ref, None); @@ -928,7 +927,7 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) { if let Some(ref ast_trait_ref) = *opt_trait_ref { let trait_ref = - astconv::instantiate_mono_trait_ref(&ccx.icx(&ty_predicates), + astconv::instantiate_mono_trait_ref(&mut ccx.icx(&ty_predicates), &ExplicitRscope, ast_trait_ref, Some(selfty)); @@ -1175,13 +1174,13 @@ fn ensure_super_predicates_step(ccx: &CrateCtxt, // Convert the bounds that follow the colon, e.g. `Bar+Zed` in `trait Foo : Bar+Zed`. let self_param_ty = ty::mk_self_type(tcx); - let superbounds1 = compute_bounds(&ccx.icx(scope), self_param_ty, bounds, + let superbounds1 = compute_bounds(&mut ccx.icx(scope), self_param_ty, bounds, SizedByDefault::No, item.span); let superbounds1 = ty::predicates(tcx, self_param_ty, &superbounds1); // Convert any explicit superbounds in the where clause, // e.g. `trait Foo where Self : Bar`: - let superbounds2 = generics.get_type_parameter_bounds(&ccx.icx(scope), item.span, item.id); + let superbounds2 = generics.get_type_parameter_bounds(&mut ccx.icx(scope), item.span, item.id); // Combine the two lists to form the complete set of superbounds: let superbounds = superbounds1.into_iter().chain(superbounds2.into_iter()).collect(); @@ -1386,7 +1385,7 @@ fn convert_trait_predicates<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &ast::Item) self_trait_ref, trait_item.ident.name); - let bounds = compute_bounds(&ccx.icx(&(ast_generics, trait_predicates)), + let bounds = compute_bounds(&mut ccx.icx(&(ast_generics, trait_predicates)), assoc_ty, bounds, SizedByDefault::Yes, @@ -1442,7 +1441,7 @@ fn compute_type_scheme_of_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, } ast::ItemFn(ref decl, unsafety, abi, ref generics, _) => { let ty_generics = ty_generics_for_fn(ccx, generics, &ty::Generics::empty()); - let tofd = astconv::ty_of_bare_fn(&ccx.icx(generics), unsafety, abi, &**decl); + let tofd = astconv::ty_of_bare_fn(&mut ccx.icx(generics), unsafety, abi, &**decl); let ty = ty::mk_bare_fn(tcx, Some(local_def(it.id)), tcx.mk_bare_fn(tofd)); ty::TypeScheme { ty: ty, generics: ty_generics } } @@ -1566,7 +1565,7 @@ fn compute_type_scheme_of_foreign_item<'a, 'tcx>( ast::ForeignItemStatic(ref t, _) => { ty::TypeScheme { generics: ty::Generics::empty(), - ty: ast_ty_to_ty(&ccx.icx(&()), &ExplicitRscope, t) + ty: ast_ty_to_ty(&mut ccx.icx(&()), &ExplicitRscope, t) } } } @@ -1661,7 +1660,7 @@ fn ty_generic_predicates_for_fn<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, } // Add the Sized bound, unless the type parameter is marked as `?Sized`. -fn add_unsized_bound<'tcx>(astconv: &AstConv<'tcx>, +fn add_unsized_bound<'tcx>(astconv: &mut AstConv<'tcx>, bounds: &mut ty::BuiltinBounds, ast_bounds: &[ast::TyParamBound], span: Span) @@ -1736,7 +1735,7 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, for (index, param) in ast_generics.ty_params.iter().enumerate() { let index = index as u32; let param_ty = ty::ParamTy::new(space, index, param.ident.name).to_ty(ccx.tcx); - let bounds = compute_bounds(&ccx.icx(&(base_predicates, ast_generics)), + let bounds = compute_bounds(&mut ccx.icx(&(base_predicates, ast_generics)), param_ty, ¶m.bounds, SizedByDefault::Yes, @@ -1770,7 +1769,7 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, for predicate in &where_clause.predicates { match predicate { &ast::WherePredicate::BoundPredicate(ref bound_pred) => { - let ty = ast_ty_to_ty(&ccx.icx(&(base_predicates, ast_generics)), + let ty = ast_ty_to_ty(&mut ccx.icx(&(base_predicates, ast_generics)), &ExplicitRscope, &*bound_pred.bounded_ty); @@ -1780,7 +1779,7 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, let mut projections = Vec::new(); let trait_ref = - conv_poly_trait_ref(&ccx.icx(&(base_predicates, ast_generics)), + conv_poly_trait_ref(&mut ccx.icx(&(base_predicates, ast_generics)), ty, poly_trait_ref, &mut projections); @@ -1873,7 +1872,7 @@ fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, let default = match param.default { None => None, Some(ref path) => { - let ty = ast_ty_to_ty(&ccx.icx(&()), &ExplicitRscope, &**path); + let ty = ast_ty_to_ty(&mut ccx.icx(&()), &ExplicitRscope, &**path); let cur_idx = index; ty::walk_ty(ty, |t| { @@ -1982,7 +1981,7 @@ enum SizedByDefault { Yes, No, } /// Translate the AST's notion of ty param bounds (which are an enum consisting of a newtyped Ty or /// a region) to ty's notion of ty param bounds, which can either be user-defined traits, or the /// built-in trait (formerly known as kind): Send. -fn compute_bounds<'tcx>(astconv: &AstConv<'tcx>, +fn compute_bounds<'tcx>(astconv: &mut AstConv<'tcx>, param_ty: ty::Ty<'tcx>, ast_bounds: &[ast::TyParamBound], sized_by_default: SizedByDefault, @@ -2011,7 +2010,7 @@ fn compute_bounds<'tcx>(astconv: &AstConv<'tcx>, /// because this can be anywhere from 0 predicates (`T:?Sized` adds no /// predicates) to 1 (`T:Foo`) to many (`T:Bar` adds `T:Bar` /// and `::X == i32`). -fn predicates_from_bound<'tcx>(astconv: &AstConv<'tcx>, +fn predicates_from_bound<'tcx>(astconv: &mut AstConv<'tcx>, param_ty: Ty<'tcx>, bound: &ast::TyParamBound) -> Vec> @@ -2036,7 +2035,7 @@ fn predicates_from_bound<'tcx>(astconv: &AstConv<'tcx>, } } -fn conv_poly_trait_ref<'tcx>(astconv: &AstConv<'tcx>, +fn conv_poly_trait_ref<'tcx>(astconv: &mut AstConv<'tcx>, param_ty: Ty<'tcx>, trait_ref: &ast::PolyTraitRef, projections: &mut Vec>) @@ -2049,18 +2048,17 @@ fn conv_poly_trait_ref<'tcx>(astconv: &AstConv<'tcx>, projections) } -fn conv_param_bounds<'a,'tcx>(astconv: &AstConv<'tcx>, +fn conv_param_bounds<'a,'tcx>(astconv: &mut AstConv<'tcx>, span: Span, param_ty: ty::Ty<'tcx>, ast_bounds: &[ast::TyParamBound]) -> ty::ParamBounds<'tcx> { - let tcx = astconv.tcx(); let astconv::PartitionedBounds { builtin_bounds, trait_bounds, region_bounds - } = astconv::partition_bounds(tcx, span, &ast_bounds); + } = astconv::partition_bounds(astconv.tcx(), span, &ast_bounds); let mut projection_bounds = Vec::new(); @@ -2074,7 +2072,7 @@ fn conv_param_bounds<'a,'tcx>(astconv: &AstConv<'tcx>, let region_bounds: Vec = region_bounds.into_iter() - .map(|r| ast_region_to_region(tcx, r)) + .map(|r| ast_region_to_region(astconv.tcx(), r)) .collect(); ty::ParamBounds { @@ -2108,12 +2106,12 @@ fn compute_type_scheme_of_foreign_fn_decl<'a, 'tcx>( let rb = BindingRscope::new(); let input_tys = decl.inputs .iter() - .map(|a| ty_of_arg(&ccx.icx(ast_generics), &rb, a, None)) + .map(|a| ty_of_arg(&mut ccx.icx(ast_generics), &rb, a, None)) .collect(); let output = match decl.output { ast::Return(ref ty) => - ty::FnConverging(ast_ty_to_ty(&ccx.icx(ast_generics), &rb, &**ty)), + ty::FnConverging(ast_ty_to_ty(&mut ccx.icx(ast_generics), &rb, &**ty)), ast::DefaultReturn(..) => ty::FnConverging(ty::mk_nil(ccx.tcx)), ast::NoReturn(..) => From 2ab93a432745f5b61f67b55b5d7e804d265ecc75 Mon Sep 17 00:00:00 2001 From: Joshua Yanovski Date: Sat, 9 May 2015 05:53:19 -0700 Subject: [PATCH 11/14] Fix whitespace issues introduced by previous commit. --- src/librustc_typeck/check/mod.rs | 210 +++++++++++++++---------------- 1 file changed, 105 insertions(+), 105 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 3f4f49d520331..884800957d2d6 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -393,9 +393,9 @@ impl<'a, 'tcx> FnCtxtJoined<'a, 'tcx> { /// Note that function is only intended to be used with types (notably, not fns). This is /// because it doesn't do any instantiation of late-bound regions. fn instantiate_type(&mut self, - span: Span, - def_id: ast::DefId) - -> TypeAndSubsts<'tcx> + span: Span, + def_id: ast::DefId) + -> TypeAndSubsts<'tcx> { let type_scheme = ty::lookup_item_type(self.tcx(), def_id); @@ -1616,8 +1616,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } fn write_autoderef_adjustment(&self, - node_id: ast::NodeId, - derefs: usize) { + node_id: ast::NodeId, + derefs: usize) { self.write_adjustment( node_id, ty::AdjustDerefRef(ty::AutoDerefRef { @@ -1629,8 +1629,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } fn write_adjustment(&self, - node_id: ast::NodeId, - adj: ty::AutoAdjustment<'tcx>) { + node_id: ast::NodeId, + adj: ty::AutoAdjustment<'tcx>) { debug!("write_adjustment(node_id={}, adj={})", node_id, adj.repr(self.tcx())); if adj.is_identity() { @@ -1648,11 +1648,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } fn require_type_meets(&self, - check_env: &mut CheckEnv<'tcx>, - ty: Ty<'tcx>, - span: Span, - code: traits::ObligationCauseCode<'tcx>, - bound: ty::BuiltinBound) + check_env: &mut CheckEnv<'tcx>, + ty: Ty<'tcx>, + span: Span, + code: traits::ObligationCauseCode<'tcx>, + bound: ty::BuiltinBound) { self.register_builtin_bound( check_env, @@ -1662,27 +1662,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } fn require_type_is_sized(&self, - check_env: &mut CheckEnv<'tcx>, - ty: Ty<'tcx>, - span: Span, - code: traits::ObligationCauseCode<'tcx>) + check_env: &mut CheckEnv<'tcx>, + ty: Ty<'tcx>, + span: Span, + code: traits::ObligationCauseCode<'tcx>) { self.require_type_meets(check_env, ty, span, code, ty::BoundSized); } fn require_expr_have_sized_type(&self, - check_env: &mut CheckEnv<'tcx>, - expr: &ast::Expr, - code: traits::ObligationCauseCode<'tcx>) + check_env: &mut CheckEnv<'tcx>, + expr: &ast::Expr, + code: traits::ObligationCauseCode<'tcx>) { let expr_ty = self.expr_ty(&check_env.tt.node_types, expr); self.require_type_is_sized(check_env, expr_ty, expr.span, code); } fn type_is_known_to_be_sized(&self, - ty: Ty<'tcx>, - span: Span) - -> bool + ty: Ty<'tcx>, + span: Span) + -> bool { traits::type_known_to_meet_builtin_bound(self.infcx(), self.param_env(), @@ -1699,18 +1699,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } fn register_builtin_bound(&self, - check_env: &mut CheckEnv<'tcx>, - ty: Ty<'tcx>, - builtin_bound: ty::BuiltinBound, - cause: traits::ObligationCause<'tcx>) + check_env: &mut CheckEnv<'tcx>, + ty: Ty<'tcx>, + builtin_bound: ty::BuiltinBound, + cause: traits::ObligationCause<'tcx>) { check_env.fulfillment_cx .register_builtin_bound(self.infcx(), ty, builtin_bound, cause); } fn register_predicate(&self, - check_env: &mut CheckEnv<'tcx>, - obligation: traits::PredicateObligation<'tcx>) + check_env: &mut CheckEnv<'tcx>, + obligation: traits::PredicateObligation<'tcx>) { debug!("register_predicate({})", obligation.repr(self.tcx())); @@ -1761,64 +1761,64 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } fn mk_subty(&self, - a_is_expected: bool, - origin: infer::TypeOrigin, - sub: Ty<'tcx>, - sup: Ty<'tcx>) - -> Result<(), ty::type_err<'tcx>> { + a_is_expected: bool, + origin: infer::TypeOrigin, + sub: Ty<'tcx>, + sup: Ty<'tcx>) + -> Result<(), ty::type_err<'tcx>> { infer::mk_subty(self.infcx(), a_is_expected, origin, sub, sup) } fn mk_eqty(&self, - a_is_expected: bool, - origin: infer::TypeOrigin, - sub: Ty<'tcx>, - sup: Ty<'tcx>) - -> Result<(), ty::type_err<'tcx>> { + a_is_expected: bool, + origin: infer::TypeOrigin, + sub: Ty<'tcx>, + sup: Ty<'tcx>) + -> Result<(), ty::type_err<'tcx>> { infer::mk_eqty(self.infcx(), a_is_expected, origin, sub, sup) } fn mk_subr(&self, - origin: infer::SubregionOrigin<'tcx>, - sub: ty::Region, - sup: ty::Region) { + origin: infer::SubregionOrigin<'tcx>, + sub: ty::Region, + sup: ty::Region) { infer::mk_subr(self.infcx(), origin, sub, sup) } fn type_error_message(&self, - sp: Span, - mk_msg: M, - actual_ty: Ty<'tcx>, - err: Option<&ty::type_err<'tcx>>) where + sp: Span, + mk_msg: M, + actual_ty: Ty<'tcx>, + err: Option<&ty::type_err<'tcx>>) where M: FnOnce(String) -> String, { self.infcx().type_error_message(sp, mk_msg, actual_ty, err); } fn report_mismatched_types(&self, - sp: Span, - e: Ty<'tcx>, - a: Ty<'tcx>, - err: &ty::type_err<'tcx>) { + sp: Span, + e: Ty<'tcx>, + a: Ty<'tcx>, + err: &ty::type_err<'tcx>) { self.infcx().report_mismatched_types(sp, e, a, err) } /// Registers an obligation for checking later, during regionck, that the type `ty` must /// outlive the region `r`. fn register_region_obligation(&self, - check_env: &mut CheckEnv<'tcx>, - ty: Ty<'tcx>, - region: ty::Region, - cause: traits::ObligationCause<'tcx>) + check_env: &mut CheckEnv<'tcx>, + ty: Ty<'tcx>, + region: ty::Region, + cause: traits::ObligationCause<'tcx>) { check_env.fulfillment_cx .register_region_obligation(self.infcx(), ty, region, cause); } fn add_default_region_param_bounds(&self, - check_env: &mut CheckEnv<'tcx>, - substs: &Substs<'tcx>, - expr: &ast::Expr) + check_env: &mut CheckEnv<'tcx>, + substs: &Substs<'tcx>, + expr: &ast::Expr) { for &ty in substs.types.iter() { let default_bound = ty::ReScope(CodeExtent::from_node_id(expr.id)); @@ -1847,9 +1847,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Then we will create a fresh region variable `'$0` and a fresh type variable `$1` for `'a` /// and `T`. This routine will add a region obligation `$1:'$0` and register it locally. fn add_obligations_for_parameters(&self, - check_env: &mut CheckEnv<'tcx>, - cause: traits::ObligationCause<'tcx>, - predicates: &ty::InstantiatedPredicates<'tcx>) + check_env: &mut CheckEnv<'tcx>, + cause: traits::ObligationCause<'tcx>, + predicates: &ty::InstantiatedPredicates<'tcx>) { assert!(!predicates.has_escaping_regions()); @@ -1866,13 +1866,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Only for fields! Returns for methods> // Indifferent to privacy flags fn lookup_field_ty(&self, - check_env: &mut CheckEnv<'tcx>, - span: Span, - class_id: ast::DefId, - items: &[ty::field_ty], - fieldname: ast::Name, - substs: &subst::Substs<'tcx>) - -> Option> + check_env: &mut CheckEnv<'tcx>, + span: Span, + class_id: ast::DefId, + items: &[ty::field_ty], + fieldname: ast::Name, + substs: &subst::Substs<'tcx>) + -> Option> { let o_field = items.iter().find(|f| f.name == fieldname); o_field.map(|f| ty::lookup_field_type(self.tcx(), class_id, f.id, substs)) @@ -1883,13 +1883,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } fn lookup_tup_field_ty(&self, - check_env: &mut CheckEnv<'tcx>, - span: Span, - class_id: ast::DefId, - items: &[ty::field_ty], - idx: usize, - substs: &subst::Substs<'tcx>) - -> Option> + check_env: &mut CheckEnv<'tcx>, + span: Span, + class_id: ast::DefId, + items: &[ty::field_ty], + idx: usize, + substs: &subst::Substs<'tcx>) + -> Option> { let o_field = if idx < items.len() { Some(&items[idx]) } else { None }; o_field.map(|f| ty::lookup_field_type(self.tcx(), class_id, f.id, substs)) @@ -1943,14 +1943,14 @@ pub enum UnresolvedTypeAction { /// Note: this method does not modify the adjustments table. The caller is responsible for /// inserting an AutoAdjustment record into the `fcx` using one of the suitable methods. fn autoderef<'a, 'tcx, T, F>(check_env: &mut CheckEnv<'tcx>, - fcx: &FnCtxt<'a, 'tcx>, - sp: Span, - base_ty: Ty<'tcx>, - opt_expr: Option<&ast::Expr>, - unresolved_type_action: UnresolvedTypeAction, - mut lvalue_pref: LvaluePreference, - mut should_stop: F) - -> (Ty<'tcx>, usize, Option) + fcx: &FnCtxt<'a, 'tcx>, + sp: Span, + base_ty: Ty<'tcx>, + opt_expr: Option<&ast::Expr>, + unresolved_type_action: UnresolvedTypeAction, + mut lvalue_pref: LvaluePreference, + mut should_stop: F) + -> (Ty<'tcx>, usize, Option) where F: FnMut(&mut CheckEnv<'tcx>, Ty<'tcx>, usize) -> Option, { debug!("autoderef(base_ty={}, opt_expr={}, lvalue_pref={:?})", @@ -4233,9 +4233,9 @@ fn check_const_with_ty<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, /// the question of whether a type can be instantiated. See the definition of /// `check_instantiable`. fn check_representable(tcx: &ty::ctxt, - sp: Span, - item_id: ast::NodeId, - designation: &str) -> bool { + sp: Span, + item_id: ast::NodeId, + designation: &str) -> bool { let rty = ty::node_id_to_type(tcx, item_id); // Check that it is possible to represent this type. This call identifies @@ -4268,9 +4268,9 @@ fn check_representable(tcx: &ty::ctxt, /// /// is representable, but not instantiable. fn check_instantiable(tcx: &ty::ctxt, - sp: Span, - item_id: ast::NodeId) - -> bool { + sp: Span, + item_id: ast::NodeId) + -> bool { let item_ty = ty::node_id_to_type(tcx, item_id); if !ty::is_instantiable(tcx, item_ty) { span_err!(tcx.sess, sp, E0073, @@ -4314,9 +4314,9 @@ fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) { } fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, - sp: Span, - vs: &'tcx [P], - id: ast::NodeId) { + sp: Span, + vs: &'tcx [P], + id: ast::NodeId) { fn disr_in_range(ccx: &CrateCtxt, ty: attr::IntType, @@ -4462,14 +4462,14 @@ fn type_scheme_and_predicates_for_def<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, // Instantiates the given path, which must refer to an item with the given // number of type parameters and type. fn instantiate_path<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, - fcx: &FnCtxt<'a, 'tcx>, - segments: &[ast::PathSegment], - type_scheme: TypeScheme<'tcx>, - type_predicates: &ty::GenericPredicates<'tcx>, - opt_self_ty: Option>, - def: def::Def, - span: Span, - node_id: ast::NodeId) { + fcx: &FnCtxt<'a, 'tcx>, + segments: &[ast::PathSegment], + type_scheme: TypeScheme<'tcx>, + type_predicates: &ty::GenericPredicates<'tcx>, + opt_self_ty: Option>, + def: def::Def, + span: Span, + node_id: ast::NodeId) { debug!("instantiate_path(path={:?}, def={}, node_id={}, type_scheme={})", segments, def.repr(fcx.tcx()), @@ -4999,10 +4999,10 @@ fn structurally_resolve_type_or_else<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx> // Resolves `typ` by a single level if `typ` is a type variable. If no // resolution is possible, then an error is reported. fn structurally_resolved_type<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, - fcx: &FnCtxt<'a, 'tcx>, - sp: Span, - ty: Ty<'tcx>) - -> Ty<'tcx> + fcx: &FnCtxt<'a, 'tcx>, + sp: Span, + ty: Ty<'tcx>) + -> Ty<'tcx> { structurally_resolve_type_or_else(check_env, fcx, sp, ty, || { fcx.tcx().types.err @@ -5031,9 +5031,9 @@ fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: &ast::Block) -> bool { } fn check_bounds_are_used<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, - span: Span, - tps: &OwnedSlice, - ty: Ty<'tcx>) { + span: Span, + tps: &OwnedSlice, + ty: Ty<'tcx>) { debug!("check_bounds_are_used(n_tps={}, ty={})", tps.len(), ppaux::ty_to_string(ccx.tcx, ty)); From ffb128493591ee5213e82c8b1d69c2d47a677409 Mon Sep 17 00:00:00 2001 From: Joshua Yanovski Date: Sat, 9 May 2015 08:05:07 -0700 Subject: [PATCH 12/14] Remove RefCell from inh.adjustments in typeck. --- src/librustc/middle/expr_use_visitor.rs | 13 ++++++------ src/librustc/middle/mem_categorization.rs | 15 +++++++------- src/librustc/middle/ty.rs | 14 +++++++------ src/librustc_trans/trans/common.rs | 5 +++-- src/librustc_typeck/check/callee.rs | 2 +- src/librustc_typeck/check/coercion.rs | 2 +- src/librustc_typeck/check/method/confirm.rs | 10 +++------- src/librustc_typeck/check/method/mod.rs | 4 ++-- src/librustc_typeck/check/mod.rs | 22 ++++++++++++--------- src/librustc_typeck/check/regionck.rs | 17 +++++++++------- src/librustc_typeck/check/writeback.rs | 4 ++-- 11 files changed, 58 insertions(+), 50 deletions(-) diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index d740d24e23672..3b965542eb9bf 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -787,7 +787,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { // process. fn walk_adjustment(&mut self, expr: &ast::Expr) { let typer = self.typer; - if let Some(adjustment) = typer.adjustments().borrow().get(&expr.id) { + typer.adjustments( |adjustments| if let Some(adjustment) = adjustments.get(&expr.id) { match *adjustment { ty::AdjustReifyFnPointer | ty::AdjustUnsafeFnPointer => { @@ -802,7 +802,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { self.walk_autoderefref(expr, adj); } } - } + }) } /// Autoderefs for overloaded Deref calls in fact reference their receiver. That is, if we have @@ -1283,10 +1283,11 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { } } -fn copy_or_move<'tcx>(typer: &mc::Typer<'tcx>, - cmt: &mc::cmt<'tcx>, - move_reason: MoveReason) - -> ConsumeMode +fn copy_or_move<'tcx,T>(typer: &T, + cmt: &mc::cmt<'tcx>, + move_reason: MoveReason) + -> ConsumeMode + where T: mc::Typer<'tcx> { if typer.type_moves_by_default(cmt.span, cmt.ty) { Move(move_reason) diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 3fff15049930b..7d5aeb337637e 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -87,7 +87,6 @@ use syntax::codemap::Span; use syntax::print::pprust; use syntax::parse::token; -use std::cell::RefCell; use std::rc::Rc; #[derive(Clone, PartialEq, Debug)] @@ -292,7 +291,8 @@ pub trait Typer<'tcx> : ty::ClosureTyper<'tcx> { fn node_method_ty(&self, method_call: ty::MethodCall) -> Option>; fn node_method_origin(&self, method_call: ty::MethodCall) -> Option>; - fn adjustments<'a>(&'a self) -> &'a RefCell>>; + fn adjustments(&self, closure: F) -> T + where F: FnOnce(&NodeMap>) -> T; fn is_method_call(&self, id: ast::NodeId) -> bool; fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option; fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option; @@ -409,9 +409,10 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { fn expr_ty_adjusted(&self, expr: &ast::Expr) -> McResult> { let unadjusted_ty = try!(self.expr_ty(expr)); - Ok(ty::adjust_ty(self.tcx(), expr.span, expr.id, unadjusted_ty, - self.typer.adjustments().borrow().get(&expr.id), - |method_call| self.typer.node_method_ty(method_call))) + self.typer.adjustments( |adjustments| + Ok(ty::adjust_ty(self.tcx(), expr.span, expr.id, unadjusted_ty, + adjustments.get(&expr.id), + |method_call| self.typer.node_method_ty(method_call)))) } fn node_ty(&self, id: ast::NodeId) -> McResult> { @@ -443,7 +444,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { } pub fn cat_expr(&self, expr: &ast::Expr) -> McResult> { - match self.typer.adjustments().borrow().get(&expr.id) { + self.typer.adjustments( |adjustments| match adjustments.get(&expr.id) { None => { // No adjustments. self.cat_expr_unadjusted(expr) @@ -470,7 +471,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { } } } - } + } ) } pub fn cat_expr_autoderefd(&self, diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 5298c9682b48c..f40b5abd0a6f6 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -6127,10 +6127,11 @@ pub struct ClosureUpvar<'tcx> { } // Returns a list of `ClosureUpvar`s for each upvar. -pub fn closure_upvars<'tcx>(typer: &mc::Typer<'tcx>, - closure_id: ast::DefId, - substs: &Substs<'tcx>) - -> Option>> +pub fn closure_upvars<'tcx,T>(typer: &T, + closure_id: ast::DefId, + substs: &Substs<'tcx>) + -> Option>> + where T: mc::Typer<'tcx> { // Presently an unboxed closure type cannot "escape" out of a // function, so we will only encounter ones that originated in the @@ -6831,8 +6832,9 @@ impl<'a,'tcx> mc::Typer<'tcx> for ParameterEnvironment<'a,'tcx> { self.tcx.method_map.borrow().get(&method_call).map(|method| method.origin.clone()) } - fn adjustments(&self) -> &RefCell>> { - &self.tcx.adjustments + fn adjustments(&self, closure: F) -> T + where F: FnOnce(&NodeMap>) -> T { + closure(&self.tcx.adjustments.borrow()) } fn is_method_call(&self, id: ast::NodeId) -> bool { diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs index 2ba963a42efbe..5ea692b858438 100644 --- a/src/librustc_trans/trans/common.rs +++ b/src/librustc_trans/trans/common.rs @@ -669,8 +669,9 @@ impl<'blk, 'tcx> mc::Typer<'tcx> for BlockS<'blk, 'tcx> { .map(|method| method.origin.clone()) } - fn adjustments<'a>(&'a self) -> &'a RefCell>> { - &self.tcx().adjustments + fn adjustments(&self, closure: F) -> T + where F: FnOnce(&NodeMap>) -> T { + closure(&self.tcx().adjustments.borrow()) } fn is_method_call(&self, id: ast::NodeId) -> bool { diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index 8b3f9437c0dee..a79f404729458 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -135,7 +135,7 @@ fn try_overloaded_call_step<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, // If the callee is a bare function or a closure, then we're all set. match structurally_resolved_type(check_env, fcx, callee_expr.span, adjusted_ty).sty { ty::ty_bare_fn(..) => { - fcx.write_autoderef_adjustment(callee_expr.id, autoderefs); + fcx.write_autoderef_adjustment(check_env, callee_expr.id, autoderefs); return Some(CallStep::Builtin); } diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index 033afd04570a9..95c10b1ff21de 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -543,7 +543,7 @@ pub fn mk_assignty<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, if let Some(adjustment) = adjustment { debug!("Success, coerced with {}", adjustment.repr(fcx.tcx())); - fcx.write_adjustment(expr.id, adjustment); + fcx.write_adjustment(check_env, expr.id, adjustment); } Ok(()) } diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index e1e1b9e49fa4b..7cac392fbb7f5 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -179,7 +179,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { assert_eq!(result, Some(())); // Write out the final adjustment. - self.fcx.write_adjustment(self.self_expr.id, + self.fcx.write_adjustment(check_env, self.self_expr.id, ty::AdjustDerefRef(ty::AutoDerefRef { autoderefs: pick.autoderefs, autoref: autoref, @@ -513,11 +513,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { // Fix up autoderefs and derefs. for (i, &expr) in exprs.iter().rev().enumerate() { // Count autoderefs. - let autoderef_count = match self.fcx - .inh - .adjustments - .borrow() - .get(&expr.id) { + let autoderef_count = match check_env.tt.adjustments.get(&expr.id) { Some(&ty::AdjustDerefRef(ref adj)) => adj.autoderefs, Some(_) | None => 0, }; @@ -555,7 +551,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { // expects. This is annoying and horrible. We // ought to recode this routine so it doesn't // (ab)use the normal type checking paths. - let adj = self.fcx.inh.adjustments.borrow().get(&base_expr.id).cloned(); + let adj = check_env.tt.adjustments.get(&base_expr.id).cloned(); let (autoderefs, unsize) = match adj { Some(ty::AdjustDerefRef(adr)) => match adr.autoref { None => { diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 39d5fdaeb7a80..5e04338226f3a 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -273,7 +273,7 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, ty::ByValueExplicitSelfCategory => { // Trait method is fn(self), no transformation needed. assert!(!unsize); - fcx.write_autoderef_adjustment(self_expr.id, autoderefs); + fcx.write_autoderef_adjustment(check_env, self_expr.id, autoderefs); } ty::ByReferenceExplicitSelfCategory(..) => { @@ -281,7 +281,7 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, // autoref. Pull the region etc out of the type of first argument. match transformed_self_ty.sty { ty::ty_rptr(region, ty::mt { mutbl, ty: _ }) => { - fcx.write_adjustment(self_expr.id, + fcx.write_adjustment(check_env, self_expr.id, ty::AdjustDerefRef(ty::AutoDerefRef { autoderefs: autoderefs, autoref: Some(ty::AutoPtr(region, mutbl)), diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 884800957d2d6..39de1d29dd80d 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -158,7 +158,6 @@ pub struct Inherited<'a, 'tcx: 'a> { // Temporary tables: item_substs: RefCell>>, - adjustments: RefCell>>, upvar_capture_map: RefCell, closure_kinds: RefCell>, } @@ -168,6 +167,7 @@ type MethodMap<'tcx> = FnvHashMap>; /// Temporary tables struct CheckEnvTables<'tcx> { node_types: NodeMap>, + adjustments: NodeMap>, method_map: MethodMap<'tcx>, closure_tys: DefIdMap>, } @@ -505,7 +505,7 @@ impl<'a, 'tcx> mc::Typer<'tcx> for FnCtxtTyper<'a, 'tcx> { } fn expr_ty_adjusted(&self, expr: &ast::Expr) -> McResult> { let ty = self.adjust_expr_ty(expr, - self.fcx.inh.adjustments.borrow().get(&expr.id)); + self.tt.adjustments.get(&expr.id)); self.fcx.resolve_type_vars_or_error(&ty) } fn type_moves_by_default(&self, span: Span, ty: Ty<'tcx>) -> bool { @@ -526,8 +526,9 @@ impl<'a, 'tcx> mc::Typer<'tcx> for FnCtxtTyper<'a, 'tcx> { self.tt.method_map.get(&method_call) .map(|method| method.origin.clone()) } - fn adjustments(&self) -> &RefCell>> { - &self.fcx.inh.adjustments + fn adjustments(&self, closure: F) -> T + where F: FnOnce(&NodeMap>) -> T { + closure(&self.tt.adjustments) } fn is_method_call(&self, id: ast::NodeId) -> bool { self.tt.method_map.contains_key(&ty::MethodCall::expr(id)) @@ -577,7 +578,6 @@ impl<'a, 'tcx> Inherited<'a, 'tcx> { infcx: infer::new_infer_ctxt(tcx), param_env: param_env, item_substs: RefCell::new(NodeMap()), - adjustments: RefCell::new(NodeMap()), upvar_capture_map: RefCell::new(FnvHashMap()), closure_kinds: RefCell::new(DefIdMap()), } @@ -606,6 +606,7 @@ impl<'tcx> CheckEnv<'tcx> { locals: NodeMap(), tt: CheckEnvTables { node_types: NodeMap(), + adjustments: NodeMap(), method_map: FnvHashMap(), closure_tys: DefIdMap(), }, @@ -1616,9 +1617,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } fn write_autoderef_adjustment(&self, + check_env: &mut CheckEnv<'tcx>, node_id: ast::NodeId, derefs: usize) { self.write_adjustment( + check_env, node_id, ty::AdjustDerefRef(ty::AutoDerefRef { autoderefs: derefs, @@ -1629,6 +1632,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } fn write_adjustment(&self, + check_env: &mut CheckEnv<'tcx>, node_id: ast::NodeId, adj: ty::AutoAdjustment<'tcx>) { debug!("write_adjustment(node_id={}, adj={})", node_id, adj.repr(self.tcx())); @@ -1637,7 +1641,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return; } - self.inh.adjustments.borrow_mut().insert(node_id, adj); + check_env.tt.adjustments.insert(node_id, adj); } fn write_nil(&self, check_env: &mut CheckEnv<'tcx>, node_id: ast::NodeId) { @@ -2154,7 +2158,7 @@ fn try_index_step<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, debug!("try_index_step: success, using built-in indexing"); // If we had `[T; N]`, we should've caught it before unsizing to `[T]`. assert!(!unsize); - fcx.write_autoderef_adjustment(base_expr.id, autoderefs); + fcx.write_autoderef_adjustment(check_env, base_expr.id, autoderefs); return Some((tcx.types.usize, ty)); } _ => {} @@ -2803,7 +2807,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, match field_ty { Some(field_ty) => { fcx.write_ty(check_env, expr.id, field_ty); - fcx.write_autoderef_adjustment(base.id, autoderefs); + fcx.write_autoderef_adjustment(check_env, base.id, autoderefs); return; } None => {} @@ -2916,7 +2920,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(check_env: &mut CheckEnv<'tcx>, match field_ty { Some(field_ty) => { fcx.write_ty(check_env, expr.id, field_ty); - fcx.write_autoderef_adjustment(base.id, autoderefs); + fcx.write_autoderef_adjustment(check_env, base.id, autoderefs); return; } None => {} diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 70be9ba177797..195174f4b8d15 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -347,7 +347,7 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> { } else { let tcx = self.fcx.tcx(); ty::adjust_ty(tcx, expr.span, expr.id, ty_unadjusted, - self.fcx.inh.adjustments.borrow().get(&expr.id), + self.check_env.tt.adjustments.get(&expr.id), |method_call| self.resolve_method_type(method_call)) } } @@ -532,14 +532,17 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) { let has_method_map = rcx.check_env.tt.method_map.contains_key(&method_call); // Check any autoderefs or autorefs that appear. - if let Some(adjustment) = rcx.fcx.inh.adjustments.borrow().get(&expr.id) { + let adjustment = { + rcx.check_env.tt.adjustments.get(&expr.id).map( |&adj| adj ) + }; + if let Some(adjustment) = adjustment { debug!("adjustment={:?}", adjustment); - match *adjustment { - ty::AdjustDerefRef(ty::AutoDerefRef {autoderefs, ref autoref, ..}) => { + match adjustment { + ty::AdjustDerefRef(ty::AutoDerefRef {autoderefs, autoref, ..}) => { let expr_ty = rcx.resolve_node_type(expr.id); constrain_autoderefs(rcx, expr, autoderefs, expr_ty); - if let Some(ref autoref) = *autoref { - link_autoref(rcx, expr, autoderefs, autoref); + if let Some(autoref) = autoref { + link_autoref(rcx, expr, autoderefs, &autoref); // Require that the resulting region encompasses // the current node. @@ -1041,7 +1044,7 @@ fn type_of_node_must_outlive<'a, 'tcx>( // report errors later on in the writeback phase. let ty0 = rcx.resolve_node_type(id); let ty = ty::adjust_ty(tcx, origin.span(), id, ty0, - rcx.fcx.inh.adjustments.borrow().get(&id), + rcx.check_env.tt.adjustments.get(&id), |method_call| rcx.resolve_method_type(method_call)); debug!("constrain_regions_in_type_of_node(\ ty={}, ty0={}, id={}, minimum_lifetime={:?})", diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 0c5b2420fcc9b..10133f21d387f 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -109,7 +109,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { // adjustment for rhs is kind of baked into the // system. if !ast_util::is_by_value_binop(op.node) { - self.fcx.inh.adjustments.borrow_mut().remove(&lhs.id); + self.check_env.tt.adjustments.remove(&lhs.id); } } } @@ -260,7 +260,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { } fn visit_adjustments(&mut self, reason: ResolveReason, id: ast::NodeId) { - match self.fcx.inh.adjustments.borrow_mut().remove(&id) { + match self.check_env.tt.adjustments.remove(&id) { None => { debug!("No adjustments for node {}", id); } From e9b5137296cbd1d7175ac54f675e2fcf6eb944f2 Mon Sep 17 00:00:00 2001 From: Joshua Yanovski Date: Sat, 9 May 2015 08:51:15 -0700 Subject: [PATCH 13/14] Remove RefCell from fulfillment_cx in typeck. --- src/librustc_typeck/check/_match.rs | 2 +- src/librustc_typeck/check/coercion.rs | 2 +- src/librustc_typeck/check/method/confirm.rs | 2 +- src/librustc_typeck/check/mod.rs | 42 ++++++++++++--------- src/librustc_typeck/check/writeback.rs | 31 ++++++++------- 5 files changed, 44 insertions(+), 35 deletions(-) diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 7afba53bf3c97..03b3b1935b7d5 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -571,7 +571,7 @@ fn check_pat_struct<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, demand::eqtype(fcx, pat.span, expected, pat_ty); let item_substs = fcx - .item_substs() + .item_substs(check_env) .get(&pat.id) .map(|substs| substs.substs.clone()) .unwrap_or_else(|| Substs::empty()); diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index 95c10b1ff21de..eb12129f193d4 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -535,7 +535,7 @@ pub fn mk_assignty<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, body_id: fcx.body_id, code: traits::ObjectCastObligation(source) }; - fcx.register_region_obligation(check_env, + fcx.register_region_obligation(&mut check_env.fulfillment_cx, source, ty_trait.bounds.region_bound, cause); } } diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 7cac392fbb7f5..8ff80c59411e6 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -465,7 +465,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { method_predicates); self.fcx.add_default_region_param_bounds( - check_env, + &mut check_env.fulfillment_cx, all_substs, self.call_expr); } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 39de1d29dd80d..84ca383640826 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -110,7 +110,7 @@ use util::ppaux::{self, Repr}; use util::nodemap::{DefIdMap, FnvHashMap, NodeMap}; use util::lev_distance::lev_distance; -use std::cell::{Cell, Ref, RefCell}; +use std::cell::{Cell, RefCell}; use std::mem::replace; use std::iter::repeat; use std::slice; @@ -157,7 +157,6 @@ pub struct Inherited<'a, 'tcx: 'a> { param_env: ty::ParameterEnvironment<'a, 'tcx>, // Temporary tables: - item_substs: RefCell>>, upvar_capture_map: RefCell, closure_kinds: RefCell>, } @@ -167,6 +166,7 @@ type MethodMap<'tcx> = FnvHashMap>; /// Temporary tables struct CheckEnvTables<'tcx> { node_types: NodeMap>, + item_substs: NodeMap>, adjustments: NodeMap>, method_map: MethodMap<'tcx>, closure_tys: DefIdMap>, @@ -577,7 +577,6 @@ impl<'a, 'tcx> Inherited<'a, 'tcx> { Inherited { infcx: infer::new_infer_ctxt(tcx), param_env: param_env, - item_substs: RefCell::new(NodeMap()), upvar_capture_map: RefCell::new(FnvHashMap()), closure_kinds: RefCell::new(DefIdMap()), } @@ -606,6 +605,7 @@ impl<'tcx> CheckEnv<'tcx> { locals: NodeMap(), tt: CheckEnvTables { node_types: NodeMap(), + item_substs: NodeMap(), adjustments: NodeMap(), method_map: FnvHashMap(), closure_tys: DefIdMap(), @@ -1605,14 +1605,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { check_env.tt.node_types.insert(node_id, ty); } - fn write_substs(&self, node_id: ast::NodeId, substs: ty::ItemSubsts<'tcx>) { + fn write_substs(&self, + check_env: &mut CheckEnv<'tcx>, + node_id: ast::NodeId, + substs: ty::ItemSubsts<'tcx>) + { if !substs.substs.is_noop() { debug!("write_substs({}, {}) in fcx {}", node_id, substs.repr(self.tcx()), self.tag()); - self.inh.item_substs.borrow_mut().insert(node_id, substs); + check_env.tt.item_substs.insert(node_id, substs); } } @@ -1749,16 +1753,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - fn item_substs(&self) -> Ref>> { - self.inh.item_substs.borrow() + fn item_substs<'b>(&'b self, + check_env: &'b CheckEnv<'tcx>) -> &'b NodeMap> { + &check_env.tt.item_substs } fn opt_node_ty_substs(&self, - id: ast::NodeId, - f: F) where + tt: &CheckEnvTables<'tcx>, + id: ast::NodeId, + f: F) where F: FnOnce(&ty::ItemSubsts<'tcx>), { - match self.inh.item_substs.borrow().get(&id) { + match tt.item_substs.get(&id) { Some(s) => { f(s) } None => { } } @@ -1810,17 +1816,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Registers an obligation for checking later, during regionck, that the type `ty` must /// outlive the region `r`. fn register_region_obligation(&self, - check_env: &mut CheckEnv<'tcx>, + fulfillment_cx: &mut traits::FulfillmentContext<'tcx>, ty: Ty<'tcx>, region: ty::Region, cause: traits::ObligationCause<'tcx>) { - check_env.fulfillment_cx - .register_region_obligation(self.infcx(), ty, region, cause); + fulfillment_cx.register_region_obligation(self.infcx(), ty, region, cause); } fn add_default_region_param_bounds(&self, - check_env: &mut CheckEnv<'tcx>, + fulfillment_cx: &mut traits::FulfillmentContext<'tcx>, substs: &Substs<'tcx>, expr: &ast::Expr) { @@ -1828,7 +1833,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let default_bound = ty::ReScope(CodeExtent::from_node_id(expr.id)); let cause = traits::ObligationCause::new(expr.span, self.body_id, traits::MiscObligation); - self.register_region_obligation(check_env, ty, default_bound, cause); + self.register_region_obligation(fulfillment_cx, ty, default_bound, cause); } } @@ -3910,8 +3915,9 @@ fn constrain_path_type_parameters<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, fcx: &FnCtxt<'a, 'tcx>, expr: &ast::Expr) { - fcx.opt_node_ty_substs(expr.id, |item_substs| { - fcx.add_default_region_param_bounds(check_env, &item_substs.substs, expr); + let CheckEnv { ref tt, ref mut fulfillment_cx, .. } = *check_env; + fcx.opt_node_ty_substs(tt, expr.id, |item_substs| { + fcx.add_default_region_param_bounds(fulfillment_cx, &item_substs.substs, expr); }); } @@ -4733,7 +4739,7 @@ fn instantiate_path<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, } fcx.write_ty(check_env, node_id, ty_substituted); - fcx.write_substs(node_id, ty::ItemSubsts { substs: substs }); + fcx.write_substs(check_env, node_id, ty::ItemSubsts { substs: substs }); return; /// Finds the parameters that the user provided and adds them to `substs`. If too many diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 10133f21d387f..10c7561d3c66c 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -188,7 +188,7 @@ impl<'cx, 'tcx, 'v> Visitor<'v> for WritebackCx<'cx, 'tcx> { } let var_ty = self.fcx.local_ty(self.check_env, l.span, l.id); - let var_ty = self.resolve(&var_ty, ResolvingLocal(l.span)); + let var_ty = resolve(self.fcx, &var_ty, ResolvingLocal(l.span)); write_ty_to_tcx(self.tcx(), l.id, var_ty); visit::walk_local(self, l); } @@ -215,7 +215,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { ty::UpvarCapture::ByValue => ty::UpvarCapture::ByValue, ty::UpvarCapture::ByRef(ref upvar_borrow) => { let r = upvar_borrow.region; - let r = self.resolve(&r, ResolvingUpvar(*upvar_id)); + let r = resolve(self.fcx, &r, ResolvingUpvar(*upvar_id)); ty::UpvarCapture::ByRef( ty::UpvarBorrow { kind: upvar_borrow.kind, region: r }) } @@ -233,7 +233,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { } for (def_id, closure_ty) in &self.check_env.tt.closure_tys { - let closure_ty = self.resolve(closure_ty, ResolvingClosure(*def_id)); + let closure_ty = resolve(self.fcx, closure_ty, ResolvingClosure(*def_id)); self.fcx.tcx().closure_tys.borrow_mut().insert(*def_id, closure_ty); } @@ -248,14 +248,14 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { // Resolve the type of the node with id `id` let n_ty = self.fcx.node_ty(&self.check_env.tt.node_types, id); - let n_ty = self.resolve(&n_ty, reason); + let n_ty = resolve(self.fcx, &n_ty, reason); write_ty_to_tcx(self.tcx(), id, n_ty); debug!("Node {} has type {}", id, n_ty.repr(self.tcx())); // Resolve any substitutions - self.fcx.opt_node_ty_substs(id, |item_substs| { + self.fcx.opt_node_ty_substs(&self.check_env.tt, id, |item_substs| { write_substs_to_tcx(self.tcx(), id, - self.resolve(item_substs, reason)); + resolve(self.fcx, item_substs, reason)); }); } @@ -281,8 +281,8 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { ty::AdjustDerefRef(ty::AutoDerefRef { autoderefs: adj.autoderefs, - autoref: self.resolve(&adj.autoref, reason), - unsize: self.resolve(&adj.unsize, reason), + autoref: resolve(self.fcx, &adj.autoref, reason), + unsize: resolve(self.fcx, &adj.unsize, reason), }) } }; @@ -303,9 +303,9 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { method_call, method.repr(self.tcx())); let new_method = MethodCallee { - origin: self.resolve(&method.origin, reason), - ty: self.resolve(&method.ty, reason), - substs: self.resolve(&method.substs, reason), + origin: resolve(self.fcx, &method.origin, reason), + ty: resolve(self.fcx, &method.ty, reason), + substs: resolve(self.fcx, &method.substs, reason), }; self.tcx().method_map.borrow_mut().insert( @@ -316,9 +316,12 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { } } - fn resolve>(&self, t: &T, reason: ResolveReason) -> T { - t.fold_with(&mut Resolver::new(self.fcx, reason)) - } +} + +fn resolve<'a, 'tcx, T:TypeFoldable<'tcx>>(fcx: &FnCtxt<'a, 'tcx>, + t: &T, reason: ResolveReason) -> T +{ + t.fold_with(&mut Resolver::new(fcx, reason)) } /////////////////////////////////////////////////////////////////////////// From d717614f0424ddcb0ed629b8178bd4ba967865e0 Mon Sep 17 00:00:00 2001 From: Joshua Yanovski Date: Sat, 9 May 2015 09:20:15 -0700 Subject: [PATCH 14/14] Fix make tidy --- src/librustc_typeck/astconv.rs | 6 ++++-- src/librustc_typeck/check/method/confirm.rs | 6 ++++-- src/librustc_typeck/check/mod.rs | 6 ++++-- src/librustc_typeck/check/regionck.rs | 6 ++++-- src/librustc_typeck/check/wf.rs | 3 ++- src/librustc_typeck/collect.rs | 3 ++- 6 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 612e8b379d10f..084d61f44f500 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1392,7 +1392,8 @@ fn base_def_to_ty<'tcx>(this: &mut AstConv<'tcx>, ty::mk_self_type(this.tcx()) } def::DefAssociatedTy(trait_did, _) => { - check_path_args(this.tcx(), &base_segments[..base_segments.len()-2], NO_TPS | NO_REGIONS); + check_path_args(this.tcx(), + &base_segments[..base_segments.len()-2], NO_TPS | NO_REGIONS); qpath_to_ty(this, rscope, span, @@ -1578,7 +1579,8 @@ pub fn ast_ty_to_ty<'tcx>(this: &mut AstConv<'tcx>, ty } ast::TyFixedLengthVec(ref ty, ref e) => { - match const_eval::eval_const_expr_partial(this.tcx(), &**e, Some(this.tcx().types.usize)) { + match const_eval::eval_const_expr_partial(this.tcx(), &**e, + Some(this.tcx().types.usize)) { Ok(r) => { match r { const_eval::const_int(i) => { diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 8ff80c59411e6..b6a85798f233a 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -10,7 +10,8 @@ use super::probe; -use check::{self, CheckEnv, FnCtxt, FnCtxtTyper, FnCtxtJoined, NoPreference, PreferMutLvalue, callee, demand}; +use check::{self, CheckEnv, FnCtxt, FnCtxtTyper, FnCtxtJoined, NoPreference, PreferMutLvalue, + callee, demand}; use check::UnresolvedTypeAction; use middle::mem_categorization::Typer; use middle::subst::{self}; @@ -590,7 +591,8 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { unsize: None }))), false) }; - let index_expr_ty = self.fcx.expr_ty(&check_env.tt.node_types, &**index_expr); + let index_expr_ty = self.fcx.expr_ty(&check_env.tt.node_types, + &**index_expr); let result = check::try_index_step( check_env, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 84ca383640826..bdd4167617f80 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -839,7 +839,8 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> { match t.node { ast::TyFixedLengthVec(ref ty, ref count_expr) => { self.visit_ty(&**ty); - check_expr_with_hint(self.check_env, self.fcx, &**count_expr, self.fcx.tcx().types.usize); + check_expr_with_hint(self.check_env, self.fcx, &**count_expr, + self.fcx.tcx().types.usize); } _ => visit::walk_ty(self, t) } @@ -2520,7 +2521,8 @@ fn check_expr_has_type<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, expected: Ty<'tcx>) { check_expr_with_unifier( check_env, fcx, expr, ExpectHasType(expected), NoPreference, - |check_env| demand::suptype(fcx, expr.span, expected, fcx.expr_ty(&check_env.tt.node_types, expr))); + |check_env| demand::suptype(fcx, expr.span, expected, + fcx.expr_ty(&check_env.tt.node_types, expr))); } fn check_expr_coercable_to_type<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 195174f4b8d15..7d63528060067 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -116,7 +116,8 @@ macro_rules! ignore_err { /////////////////////////////////////////////////////////////////////////// // PUBLIC ENTRY POINTS -pub fn regionck_expr<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, fcx: &FnCtxt<'a, 'tcx>, e: &ast::Expr) { +pub fn regionck_expr<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a, 'tcx>, e: &ast::Expr) { let mut rcx = Rcx::new(check_env, fcx, RepeatingScope(e.id), e.id, Subject(e.id)); if fcx.err_count_since_creation() == 0 { // regionck assumes typeck succeeded @@ -126,7 +127,8 @@ pub fn regionck_expr<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, fcx: &FnCtxt<'a, rcx.resolve_regions_and_report_errors(); } -pub fn regionck_item<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, fcx: &FnCtxt<'a, 'tcx>, item: &ast::Item) { +pub fn regionck_item<'a, 'tcx>(check_env: &mut CheckEnv<'tcx>, + fcx: &FnCtxt<'a, 'tcx>, item: &ast::Item) { let mut rcx = Rcx::new(check_env, fcx, RepeatingScope(item.id), item.id, Subject(item.id)); let tcx = fcx.tcx(); rcx.free_region_map.relate_free_regions_from_predicates(tcx, &fcx.inh.param_env.caller_bounds); diff --git a/src/librustc_typeck/check/wf.rs b/src/librustc_typeck/check/wf.rs index 69625d3ea37cc..6f2422c7401c9 100644 --- a/src/librustc_typeck/check/wf.rs +++ b/src/librustc_typeck/check/wf.rs @@ -9,7 +9,8 @@ // except according to those terms. use astconv::AstConv; -use super::{CheckEnv, FnCtxt, FnCtxtTyper, FnCtxtJoined, Inherited, blank_fn_ctxt, vtable, regionck}; +use super::{CheckEnv, FnCtxt, FnCtxtTyper, FnCtxtJoined, Inherited, blank_fn_ctxt, vtable, + regionck}; use constrained_type_params::{identify_constrained_type_params, Parameter}; use CrateCtxt; use middle::region; diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index fb9685c35372f..d6bc1246332ee 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1180,7 +1180,8 @@ fn ensure_super_predicates_step(ccx: &CrateCtxt, // Convert any explicit superbounds in the where clause, // e.g. `trait Foo where Self : Bar`: - let superbounds2 = generics.get_type_parameter_bounds(&mut ccx.icx(scope), item.span, item.id); + let superbounds2 = generics.get_type_parameter_bounds(&mut ccx.icx(scope), item.span, + item.id); // Combine the two lists to form the complete set of superbounds: let superbounds = superbounds1.into_iter().chain(superbounds2.into_iter()).collect();