From 832ac110df0f58627ec1134bb9caf60d41f93f3c Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Sat, 15 Sep 2018 18:10:10 +0300 Subject: [PATCH] remove the typeck::autoderef::Autoderef fcx field This allows using it in an fcx-independent context --- src/librustc_typeck/check/autoderef.rs | 49 +++++++++++---------- src/librustc_typeck/check/callee.rs | 10 ++--- src/librustc_typeck/check/coercion.rs | 2 +- src/librustc_typeck/check/method/confirm.rs | 6 +-- src/librustc_typeck/check/mod.rs | 16 +++---- src/librustc_typeck/check/wfcheck.rs | 2 +- 6 files changed, 43 insertions(+), 42 deletions(-) diff --git a/src/librustc_typeck/check/autoderef.rs b/src/librustc_typeck/check/autoderef.rs index 7a84634d2a3e..c13ed1bd9d0e 100644 --- a/src/librustc_typeck/check/autoderef.rs +++ b/src/librustc_typeck/check/autoderef.rs @@ -8,12 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use astconv::AstConv; - use super::{FnCtxt, PlaceOp, Needs}; use super::method::MethodCallee; -use rustc::infer::InferOk; +use rustc::infer::{InferCtxt, InferOk}; use rustc::session::DiagnosticMessageId; use rustc::traits::{self, TraitEngine}; use rustc::ty::{self, Ty, TraitRef}; @@ -21,7 +19,7 @@ use rustc::ty::{ToPredicate, TypeFoldable}; use rustc::ty::adjustment::{Adjustment, Adjust, OverloadedDeref}; use syntax_pos::Span; -use syntax::ast::Ident; +use syntax::ast::{NodeId, Ident}; use std::iter; @@ -32,7 +30,9 @@ enum AutoderefKind { } pub struct Autoderef<'a, 'gcx: 'tcx, 'tcx: 'a> { - fcx: &'a FnCtxt<'a, 'gcx, 'tcx>, + infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, + body_id: NodeId, + param_env: ty::ParamEnv<'tcx>, steps: Vec<(Ty<'tcx>, AutoderefKind)>, cur_ty: Ty<'tcx>, obligations: Vec>, @@ -45,7 +45,7 @@ impl<'a, 'gcx, 'tcx> Iterator for Autoderef<'a, 'gcx, 'tcx> { type Item = (Ty<'tcx>, usize); fn next(&mut self) -> Option { - let tcx = self.fcx.tcx; + let tcx = self.infcx.tcx; debug!("autoderef: steps={:?}, cur_ty={:?}", self.steps, @@ -110,7 +110,7 @@ impl<'a, 'gcx, 'tcx> Autoderef<'a, 'gcx, 'tcx> { fn overloaded_deref_ty(&mut self, ty: Ty<'tcx>) -> Option> { debug!("overloaded_deref_ty({:?})", ty); - let tcx = self.fcx.tcx(); + let tcx = self.infcx.tcx; // let trait_ref = TraitRef { @@ -118,27 +118,27 @@ impl<'a, 'gcx, 'tcx> Autoderef<'a, 'gcx, 'tcx> { substs: tcx.mk_substs_trait(self.cur_ty, &[]), }; - let cause = traits::ObligationCause::misc(self.span, self.fcx.body_id); + let cause = traits::ObligationCause::misc(self.span, self.body_id); let obligation = traits::Obligation::new(cause.clone(), - self.fcx.param_env, + self.param_env, trait_ref.to_predicate()); - if !self.fcx.predicate_may_hold(&obligation) { + if !self.infcx.predicate_may_hold(&obligation) { debug!("overloaded_deref_ty: cannot match obligation"); return None; } let mut fulfillcx = traits::FulfillmentContext::new_in_snapshot(); let normalized_ty = fulfillcx.normalize_projection_type( - &self.fcx, - self.fcx.param_env, + &self.infcx, + self.param_env, ty::ProjectionTy::from_ref_and_name( tcx, trait_ref, Ident::from_str("Target"), ), cause); - if let Err(e) = fulfillcx.select_where_possible(&self.fcx) { + if let Err(e) = fulfillcx.select_where_possible(&self.infcx) { // This shouldn't happen, except for evaluate/fulfill mismatches, // but that's not a reason for an ICE (`predicate_may_hold` is conservative // by design). @@ -151,19 +151,19 @@ impl<'a, 'gcx, 'tcx> Autoderef<'a, 'gcx, 'tcx> { ty, normalized_ty, obligations); self.obligations.extend(obligations); - Some(self.fcx.resolve_type_vars_if_possible(&normalized_ty)) + Some(self.infcx.resolve_type_vars_if_possible(&normalized_ty)) } /// Returns the final type, generating an error if it is an /// unresolved inference variable. - pub fn unambiguous_final_ty(&self) -> Ty<'tcx> { - self.fcx.structurally_resolved_type(self.span, self.cur_ty) + pub fn unambiguous_final_ty(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> { + fcx.structurally_resolved_type(self.span, self.cur_ty) } /// Returns the final type we ended up with, which may well be an /// inference variable (we will resolve it first, if possible). pub fn maybe_ambiguous_final_ty(&self) -> Ty<'tcx> { - self.fcx.resolve_type_vars_if_possible(&self.cur_ty) + self.infcx.resolve_type_vars_if_possible(&self.cur_ty) } pub fn step_count(&self) -> usize { @@ -171,19 +171,19 @@ impl<'a, 'gcx, 'tcx> Autoderef<'a, 'gcx, 'tcx> { } /// Returns the adjustment steps. - pub fn adjust_steps(&self, needs: Needs) + pub fn adjust_steps(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>, needs: Needs) -> Vec> { - self.fcx.register_infer_ok_obligations(self.adjust_steps_as_infer_ok(needs)) + fcx.register_infer_ok_obligations(self.adjust_steps_as_infer_ok(fcx, needs)) } - pub fn adjust_steps_as_infer_ok(&self, needs: Needs) + pub fn adjust_steps_as_infer_ok(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>, needs: Needs) -> InferOk<'tcx, Vec>> { let mut obligations = vec![]; let targets = self.steps.iter().skip(1).map(|&(ty, _)| ty) .chain(iter::once(self.cur_ty)); let steps: Vec<_> = self.steps.iter().map(|&(source, kind)| { if let AutoderefKind::Overloaded = kind { - self.fcx.try_overloaded_deref(self.span, source, needs) + fcx.try_overloaded_deref(self.span, source, needs) .and_then(|InferOk { value: method, obligations: o }| { obligations.extend(o); if let ty::Ref(region, _, mutbl) = method.sig.output().sty { @@ -220,8 +220,7 @@ impl<'a, 'gcx, 'tcx> Autoderef<'a, 'gcx, 'tcx> { self } - pub fn finalize(self) { - let fcx = self.fcx; + pub fn finalize(self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) { fcx.register_predicates(self.into_obligations()); } @@ -233,7 +232,9 @@ impl<'a, 'gcx, 'tcx> Autoderef<'a, 'gcx, 'tcx> { impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { pub fn autoderef(&'a self, span: Span, base_ty: Ty<'tcx>) -> Autoderef<'a, 'gcx, 'tcx> { Autoderef { - fcx: self, + infcx: &self.infcx, + body_id: self.body_id, + param_env: self.param_env, steps: vec![], cur_ty: self.resolve_type_vars_if_possible(&base_ty), obligations: vec![], diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index e4ce04916ce6..a139310b2076 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -57,7 +57,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { while result.is_none() && autoderef.next().is_some() { result = self.try_overloaded_call_step(call_expr, callee_expr, &autoderef); } - autoderef.finalize(); + autoderef.finalize(self); let output = match result { None => { @@ -89,7 +89,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { callee_expr: &'gcx hir::Expr, autoderef: &Autoderef<'a, 'gcx, 'tcx>) -> Option> { - let adjusted_ty = autoderef.unambiguous_final_ty(); + let adjusted_ty = autoderef.unambiguous_final_ty(self); debug!("try_overloaded_call_step(call_expr={:?}, adjusted_ty={:?})", call_expr, adjusted_ty); @@ -97,7 +97,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // If the callee is a bare function or a closure, then we're all set. match adjusted_ty.sty { ty::FnDef(..) | ty::FnPtr(_) => { - let adjustments = autoderef.adjust_steps(Needs::None); + let adjustments = autoderef.adjust_steps(self, Needs::None); self.apply_adjustments(callee_expr, adjustments); return Some(CallStep::Builtin(adjusted_ty)); } @@ -115,7 +115,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { infer::FnCall, &closure_ty ).0; - let adjustments = autoderef.adjust_steps(Needs::None); + let adjustments = autoderef.adjust_steps(self, Needs::None); self.record_deferred_call_resolution(def_id, DeferredCallResolution { call_expr, callee_expr, @@ -145,7 +145,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } self.try_overloaded_call_traits(call_expr, adjusted_ty).map(|(autoref, method)| { - let mut adjustments = autoderef.adjust_steps(Needs::None); + let mut adjustments = autoderef.adjust_steps(self, Needs::None); adjustments.extend(autoref); self.apply_adjustments(callee_expr, adjustments); CallStep::Overloaded(method) diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index 8d844fe3a69e..d616d88905bb 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -419,7 +419,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { let needs = Needs::maybe_mut_place(mt_b.mutbl); let InferOk { value: mut adjustments, obligations: o } - = autoderef.adjust_steps_as_infer_ok(needs); + = autoderef.adjust_steps_as_infer_ok(self, needs); obligations.extend(o); obligations.extend(autoderef.into_obligations()); diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 11fb3889a748..3902dddd0d47 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -161,9 +161,9 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { let (_, n) = autoderef.nth(pick.autoderefs).unwrap(); assert_eq!(n, pick.autoderefs); - let mut adjustments = autoderef.adjust_steps(Needs::None); + let mut adjustments = autoderef.adjust_steps(self, Needs::None); - let mut target = autoderef.unambiguous_final_ty(); + let mut target = autoderef.unambiguous_final_ty(self); if let Some(mutbl) = pick.autoref { let region = self.next_region_var(infer::Autoref(self.span)); @@ -202,7 +202,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { assert!(pick.unsize.is_none()); } - autoderef.finalize(); + autoderef.finalize(self); // Write out the final adjustments. self.apply_adjustments(self.self_expr, adjustments); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 8901f4b6b291..d4c010b45dfd 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -2554,7 +2554,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { while result.is_none() && autoderef.next().is_some() { result = self.try_index_step(expr, base_expr, &autoderef, needs, idx_ty); } - autoderef.finalize(); + autoderef.finalize(self); result } @@ -2571,7 +2571,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { index_ty: Ty<'tcx>) -> Option<(/*index type*/ Ty<'tcx>, /*element type*/ Ty<'tcx>)> { - let adjusted_ty = autoderef.unambiguous_final_ty(); + let adjusted_ty = autoderef.unambiguous_final_ty(self); debug!("try_index_step(expr={:?}, base_expr={:?}, adjusted_ty={:?}, \ index_ty={:?})", expr, @@ -2601,7 +2601,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { debug!("try_index_step: success, using overloaded indexing"); let method = self.register_infer_ok_obligations(ok); - let mut adjustments = autoderef.adjust_steps(needs); + let mut adjustments = autoderef.adjust_steps(self, needs); if let ty::Ref(region, _, r_mutbl) = method.sig.inputs()[0].sty { let mutbl = match r_mutbl { hir::MutImmutable => AutoBorrowMutability::Immutable, @@ -3295,9 +3295,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // of error recovery. self.write_field_index(expr.id, index); if field.vis.is_accessible_from(def_scope, self.tcx) { - let adjustments = autoderef.adjust_steps(needs); + let adjustments = autoderef.adjust_steps(self, needs); self.apply_adjustments(base, adjustments); - autoderef.finalize(); + autoderef.finalize(self); self.tcx.check_stability(field.did, Some(expr.id), expr.span); return field_ty; @@ -3310,9 +3310,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let Ok(index) = fstr.parse::() { if fstr == index.to_string() { if let Some(field_ty) = tys.get(index) { - let adjustments = autoderef.adjust_steps(needs); + let adjustments = autoderef.adjust_steps(self, needs); self.apply_adjustments(base, adjustments); - autoderef.finalize(); + autoderef.finalize(self); self.write_field_index(expr.id, index); return field_ty; @@ -3323,7 +3323,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { _ => {} } } - autoderef.unambiguous_final_ty(); + autoderef.unambiguous_final_ty(self); if let Some((did, field_ty)) = private_candidate { let struct_path = self.tcx().item_path_str(did); diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 6471e745aa6f..e24548cfb239 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -766,7 +766,7 @@ fn check_method_receiver<'fcx, 'gcx, 'tcx>(fcx: &FnCtxt<'fcx, 'gcx, 'tcx>, potential_self_ty, self_ty); if fcx.infcx.can_eq(fcx.param_env, self_ty, potential_self_ty).is_ok() { - autoderef.finalize(); + autoderef.finalize(fcx); if let Some(mut err) = fcx.demand_eqtype_with_origin( &cause, self_ty, potential_self_ty) { err.emit();