mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-10 14:57:14 +00:00
rustc_typeck: rename LvaluePreference::PreferMutLvalue
to Needs::MutPlace
.
This commit is contained in:
parent
800166cf96
commit
2c4a75bf09
@ -15,7 +15,7 @@ use rustc::infer;
|
|||||||
use rustc::infer::type_variable::TypeVariableOrigin;
|
use rustc::infer::type_variable::TypeVariableOrigin;
|
||||||
use rustc::traits::ObligationCauseCode;
|
use rustc::traits::ObligationCauseCode;
|
||||||
use rustc::ty::{self, Ty, TypeFoldable};
|
use rustc::ty::{self, Ty, TypeFoldable};
|
||||||
use check::{FnCtxt, Expectation, Diverges, LvaluePreference};
|
use check::{FnCtxt, Expectation, Diverges, Needs};
|
||||||
use check::coercion::CoerceMany;
|
use check::coercion::CoerceMany;
|
||||||
use util::nodemap::FxHashMap;
|
use util::nodemap::FxHashMap;
|
||||||
|
|
||||||
@ -584,7 +584,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||||||
});
|
});
|
||||||
let discrim_ty;
|
let discrim_ty;
|
||||||
if let Some(m) = contains_ref_bindings {
|
if let Some(m) = contains_ref_bindings {
|
||||||
discrim_ty = self.check_expr_with_lvalue_pref(discrim, LvaluePreference::from_mutbl(m));
|
discrim_ty = self.check_expr_with_needs(discrim, Needs::maybe_mut_place(m));
|
||||||
} else {
|
} else {
|
||||||
// ...but otherwise we want to use any supertype of the
|
// ...but otherwise we want to use any supertype of the
|
||||||
// discriminant. This is sort of a workaround, see note (*) in
|
// discriminant. This is sort of a workaround, see note (*) in
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
use astconv::AstConv;
|
use astconv::AstConv;
|
||||||
|
|
||||||
use super::{FnCtxt, LvalueOp, LvaluePreference};
|
use super::{FnCtxt, LvalueOp, Needs};
|
||||||
use super::method::MethodCallee;
|
use super::method::MethodCallee;
|
||||||
|
|
||||||
use rustc::infer::InferOk;
|
use rustc::infer::InferOk;
|
||||||
@ -162,19 +162,19 @@ impl<'a, 'gcx, 'tcx> Autoderef<'a, 'gcx, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the adjustment steps.
|
/// Returns the adjustment steps.
|
||||||
pub fn adjust_steps(&self, pref: LvaluePreference)
|
pub fn adjust_steps(&self, needs: Needs)
|
||||||
-> Vec<Adjustment<'tcx>> {
|
-> Vec<Adjustment<'tcx>> {
|
||||||
self.fcx.register_infer_ok_obligations(self.adjust_steps_as_infer_ok(pref))
|
self.fcx.register_infer_ok_obligations(self.adjust_steps_as_infer_ok(needs))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn adjust_steps_as_infer_ok(&self, pref: LvaluePreference)
|
pub fn adjust_steps_as_infer_ok(&self, needs: Needs)
|
||||||
-> InferOk<'tcx, Vec<Adjustment<'tcx>>> {
|
-> InferOk<'tcx, Vec<Adjustment<'tcx>>> {
|
||||||
let mut obligations = vec![];
|
let mut obligations = vec![];
|
||||||
let targets = self.steps.iter().skip(1).map(|&(ty, _)| ty)
|
let targets = self.steps.iter().skip(1).map(|&(ty, _)| ty)
|
||||||
.chain(iter::once(self.cur_ty));
|
.chain(iter::once(self.cur_ty));
|
||||||
let steps: Vec<_> = self.steps.iter().map(|&(source, kind)| {
|
let steps: Vec<_> = self.steps.iter().map(|&(source, kind)| {
|
||||||
if let AutoderefKind::Overloaded = kind {
|
if let AutoderefKind::Overloaded = kind {
|
||||||
self.fcx.try_overloaded_deref(self.span, source, pref)
|
self.fcx.try_overloaded_deref(self.span, source, needs)
|
||||||
.and_then(|InferOk { value: method, obligations: o }| {
|
.and_then(|InferOk { value: method, obligations: o }| {
|
||||||
obligations.extend(o);
|
obligations.extend(o);
|
||||||
if let ty::TyRef(region, mt) = method.sig.output().sty {
|
if let ty::TyRef(region, mt) = method.sig.output().sty {
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use super::{Expectation, FnCtxt, LvaluePreference, TupleArgumentsFlag};
|
use super::{Expectation, FnCtxt, Needs, TupleArgumentsFlag};
|
||||||
use super::autoderef::Autoderef;
|
use super::autoderef::Autoderef;
|
||||||
use super::method::MethodCallee;
|
use super::method::MethodCallee;
|
||||||
|
|
||||||
@ -96,7 +96,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||||||
// If the callee is a bare function or a closure, then we're all set.
|
// If the callee is a bare function or a closure, then we're all set.
|
||||||
match adjusted_ty.sty {
|
match adjusted_ty.sty {
|
||||||
ty::TyFnDef(..) | ty::TyFnPtr(_) => {
|
ty::TyFnDef(..) | ty::TyFnPtr(_) => {
|
||||||
let adjustments = autoderef.adjust_steps(LvaluePreference::NoPreference);
|
let adjustments = autoderef.adjust_steps(Needs::None);
|
||||||
self.apply_adjustments(callee_expr, adjustments);
|
self.apply_adjustments(callee_expr, adjustments);
|
||||||
return Some(CallStep::Builtin(adjusted_ty));
|
return Some(CallStep::Builtin(adjusted_ty));
|
||||||
}
|
}
|
||||||
@ -113,7 +113,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||||||
infer::FnCall,
|
infer::FnCall,
|
||||||
&closure_ty)
|
&closure_ty)
|
||||||
.0;
|
.0;
|
||||||
let adjustments = autoderef.adjust_steps(LvaluePreference::NoPreference);
|
let adjustments = autoderef.adjust_steps(Needs::None);
|
||||||
self.record_deferred_call_resolution(def_id, DeferredCallResolution {
|
self.record_deferred_call_resolution(def_id, DeferredCallResolution {
|
||||||
call_expr,
|
call_expr,
|
||||||
callee_expr,
|
callee_expr,
|
||||||
@ -143,7 +143,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.try_overloaded_call_traits(call_expr, adjusted_ty).map(|(autoref, method)| {
|
self.try_overloaded_call_traits(call_expr, adjusted_ty).map(|(autoref, method)| {
|
||||||
let mut adjustments = autoderef.adjust_steps(LvaluePreference::NoPreference);
|
let mut adjustments = autoderef.adjust_steps(Needs::None);
|
||||||
adjustments.extend(autoref);
|
adjustments.extend(autoref);
|
||||||
self.apply_adjustments(callee_expr, adjustments);
|
self.apply_adjustments(callee_expr, adjustments);
|
||||||
CallStep::Overloaded(method)
|
CallStep::Overloaded(method)
|
||||||
|
@ -60,7 +60,7 @@
|
|||||||
//! sort of a minor point so I've opted to leave it for later---after all
|
//! 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.
|
//! we may want to adjust precisely when coercions occur.
|
||||||
|
|
||||||
use check::{Diverges, FnCtxt, LvaluePreference};
|
use check::{Diverges, FnCtxt, Needs};
|
||||||
|
|
||||||
use rustc::hir;
|
use rustc::hir;
|
||||||
use rustc::hir::def_id::DefId;
|
use rustc::hir::def_id::DefId;
|
||||||
@ -409,9 +409,9 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
|
|||||||
return success(vec![], ty, obligations);
|
return success(vec![], ty, obligations);
|
||||||
}
|
}
|
||||||
|
|
||||||
let pref = LvaluePreference::from_mutbl(mt_b.mutbl);
|
let needs = Needs::maybe_mut_place(mt_b.mutbl);
|
||||||
let InferOk { value: mut adjustments, obligations: o }
|
let InferOk { value: mut adjustments, obligations: o }
|
||||||
= autoderef.adjust_steps_as_infer_ok(pref);
|
= autoderef.adjust_steps_as_infer_ok(needs);
|
||||||
obligations.extend(o);
|
obligations.extend(o);
|
||||||
obligations.extend(autoderef.into_obligations());
|
obligations.extend(autoderef.into_obligations());
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
use super::{probe, MethodCallee};
|
use super::{probe, MethodCallee};
|
||||||
|
|
||||||
use astconv::AstConv;
|
use astconv::AstConv;
|
||||||
use check::{FnCtxt, LvalueOp, callee, LvaluePreference, PreferMutLvalue};
|
use check::{FnCtxt, LvalueOp, callee, Needs};
|
||||||
use hir::def_id::DefId;
|
use hir::def_id::DefId;
|
||||||
use rustc::ty::subst::Substs;
|
use rustc::ty::subst::Substs;
|
||||||
use rustc::traits;
|
use rustc::traits;
|
||||||
@ -155,7 +155,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
|||||||
let (_, n) = autoderef.nth(pick.autoderefs).unwrap();
|
let (_, n) = autoderef.nth(pick.autoderefs).unwrap();
|
||||||
assert_eq!(n, pick.autoderefs);
|
assert_eq!(n, pick.autoderefs);
|
||||||
|
|
||||||
let mut adjustments = autoderef.adjust_steps(LvaluePreference::NoPreference);
|
let mut adjustments = autoderef.adjust_steps(Needs::None);
|
||||||
|
|
||||||
let mut target = autoderef.unambiguous_final_ty();
|
let mut target = autoderef.unambiguous_final_ty();
|
||||||
|
|
||||||
@ -449,10 +449,10 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
|||||||
.adjustments_mut()
|
.adjustments_mut()
|
||||||
.remove(expr.hir_id);
|
.remove(expr.hir_id);
|
||||||
if let Some(mut adjustments) = previous_adjustments {
|
if let Some(mut adjustments) = previous_adjustments {
|
||||||
let pref = LvaluePreference::PreferMutLvalue;
|
let needs = Needs::MutPlace;
|
||||||
for adjustment in &mut adjustments {
|
for adjustment in &mut adjustments {
|
||||||
if let Adjust::Deref(Some(ref mut deref)) = adjustment.kind {
|
if let Adjust::Deref(Some(ref mut deref)) = adjustment.kind {
|
||||||
if let Some(ok) = self.try_overloaded_deref(expr.span, source, pref) {
|
if let Some(ok) = self.try_overloaded_deref(expr.span, source, needs) {
|
||||||
let method = self.register_infer_ok_obligations(ok);
|
let method = self.register_infer_ok_obligations(ok);
|
||||||
if let ty::TyRef(region, mt) = method.sig.output().sty {
|
if let ty::TyRef(region, mt) = method.sig.output().sty {
|
||||||
*deref = OverloadedDeref {
|
*deref = OverloadedDeref {
|
||||||
@ -505,7 +505,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
|||||||
.ty;
|
.ty;
|
||||||
|
|
||||||
let method = self.try_overloaded_lvalue_op(
|
let method = self.try_overloaded_lvalue_op(
|
||||||
expr.span, base_ty, arg_tys, PreferMutLvalue, op);
|
expr.span, base_ty, arg_tys, Needs::MutPlace, op);
|
||||||
let method = match method {
|
let method = match method {
|
||||||
Some(ok) => self.register_infer_ok_obligations(ok),
|
Some(ok) => self.register_infer_ok_obligations(ok),
|
||||||
None => return self.tcx.sess.delay_span_bug(expr.span, "re-trying op failed")
|
None => return self.tcx.sess.delay_span_bug(expr.span, "re-trying op failed")
|
||||||
|
@ -77,7 +77,6 @@ type parameter).
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
pub use self::Expectation::*;
|
pub use self::Expectation::*;
|
||||||
use self::LvaluePreference::*;
|
|
||||||
use self::autoderef::Autoderef;
|
use self::autoderef::Autoderef;
|
||||||
use self::callee::DeferredCallResolution;
|
use self::callee::DeferredCallResolution;
|
||||||
use self::coercion::{CoerceMany, DynamicCoerceMany};
|
use self::coercion::{CoerceMany, DynamicCoerceMany};
|
||||||
@ -369,16 +368,16 @@ impl<'a, 'gcx, 'tcx> Expectation<'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
pub enum LvaluePreference {
|
pub enum Needs {
|
||||||
PreferMutLvalue,
|
MutPlace,
|
||||||
NoPreference
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LvaluePreference {
|
impl Needs {
|
||||||
fn from_mutbl(m: hir::Mutability) -> Self {
|
fn maybe_mut_place(m: hir::Mutability) -> Self {
|
||||||
match m {
|
match m {
|
||||||
hir::MutMutable => PreferMutLvalue,
|
hir::MutMutable => Needs::MutPlace,
|
||||||
hir::MutImmutable => NoPreference,
|
hir::MutImmutable => Needs::None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2242,7 +2241,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||||||
base_expr: &'gcx hir::Expr,
|
base_expr: &'gcx hir::Expr,
|
||||||
base_ty: Ty<'tcx>,
|
base_ty: Ty<'tcx>,
|
||||||
idx_ty: Ty<'tcx>,
|
idx_ty: Ty<'tcx>,
|
||||||
lvalue_pref: LvaluePreference)
|
needs: Needs)
|
||||||
-> Option<(/*index type*/ Ty<'tcx>, /*element type*/ Ty<'tcx>)>
|
-> Option<(/*index type*/ Ty<'tcx>, /*element type*/ Ty<'tcx>)>
|
||||||
{
|
{
|
||||||
// FIXME(#18741) -- this is almost but not quite the same as the
|
// FIXME(#18741) -- this is almost but not quite the same as the
|
||||||
@ -2252,7 +2251,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||||||
let mut autoderef = self.autoderef(base_expr.span, base_ty);
|
let mut autoderef = self.autoderef(base_expr.span, base_ty);
|
||||||
let mut result = None;
|
let mut result = None;
|
||||||
while result.is_none() && autoderef.next().is_some() {
|
while result.is_none() && autoderef.next().is_some() {
|
||||||
result = self.try_index_step(expr, base_expr, &autoderef, lvalue_pref, idx_ty);
|
result = self.try_index_step(expr, base_expr, &autoderef, needs, idx_ty);
|
||||||
}
|
}
|
||||||
autoderef.finalize();
|
autoderef.finalize();
|
||||||
result
|
result
|
||||||
@ -2267,7 +2266,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||||||
expr: &hir::Expr,
|
expr: &hir::Expr,
|
||||||
base_expr: &hir::Expr,
|
base_expr: &hir::Expr,
|
||||||
autoderef: &Autoderef<'a, 'gcx, 'tcx>,
|
autoderef: &Autoderef<'a, 'gcx, 'tcx>,
|
||||||
lvalue_pref: LvaluePreference,
|
needs: Needs,
|
||||||
index_ty: Ty<'tcx>)
|
index_ty: Ty<'tcx>)
|
||||||
-> Option<(/*index type*/ Ty<'tcx>, /*element type*/ Ty<'tcx>)>
|
-> Option<(/*index type*/ Ty<'tcx>, /*element type*/ Ty<'tcx>)>
|
||||||
{
|
{
|
||||||
@ -2295,13 +2294,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||||||
// If some lookup succeeded, install method in table
|
// If some lookup succeeded, install method in table
|
||||||
let input_ty = self.next_ty_var(TypeVariableOrigin::AutoDeref(base_expr.span));
|
let input_ty = self.next_ty_var(TypeVariableOrigin::AutoDeref(base_expr.span));
|
||||||
let method = self.try_overloaded_lvalue_op(
|
let method = self.try_overloaded_lvalue_op(
|
||||||
expr.span, self_ty, &[input_ty], lvalue_pref, LvalueOp::Index);
|
expr.span, self_ty, &[input_ty], needs, LvalueOp::Index);
|
||||||
|
|
||||||
let result = method.map(|ok| {
|
let result = method.map(|ok| {
|
||||||
debug!("try_index_step: success, using overloaded indexing");
|
debug!("try_index_step: success, using overloaded indexing");
|
||||||
let method = self.register_infer_ok_obligations(ok);
|
let method = self.register_infer_ok_obligations(ok);
|
||||||
|
|
||||||
let mut adjustments = autoderef.adjust_steps(lvalue_pref);
|
let mut adjustments = autoderef.adjust_steps(needs);
|
||||||
if let ty::TyRef(region, mt) = method.sig.inputs()[0].sty {
|
if let ty::TyRef(region, mt) = method.sig.inputs()[0].sty {
|
||||||
adjustments.push(Adjustment {
|
adjustments.push(Adjustment {
|
||||||
kind: Adjust::Borrow(AutoBorrow::Ref(region, mt.mutbl)),
|
kind: Adjust::Borrow(AutoBorrow::Ref(region, mt.mutbl)),
|
||||||
@ -2348,20 +2347,20 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||||||
span: Span,
|
span: Span,
|
||||||
base_ty: Ty<'tcx>,
|
base_ty: Ty<'tcx>,
|
||||||
arg_tys: &[Ty<'tcx>],
|
arg_tys: &[Ty<'tcx>],
|
||||||
lvalue_pref: LvaluePreference,
|
needs: Needs,
|
||||||
op: LvalueOp)
|
op: LvalueOp)
|
||||||
-> Option<InferOk<'tcx, MethodCallee<'tcx>>>
|
-> Option<InferOk<'tcx, MethodCallee<'tcx>>>
|
||||||
{
|
{
|
||||||
debug!("try_overloaded_lvalue_op({:?},{:?},{:?},{:?})",
|
debug!("try_overloaded_lvalue_op({:?},{:?},{:?},{:?})",
|
||||||
span,
|
span,
|
||||||
base_ty,
|
base_ty,
|
||||||
lvalue_pref,
|
needs,
|
||||||
op);
|
op);
|
||||||
|
|
||||||
// Try Mut first, if preferred.
|
// Try Mut first, if needed.
|
||||||
let (mut_tr, mut_op) = self.resolve_lvalue_op(op, true);
|
let (mut_tr, mut_op) = self.resolve_lvalue_op(op, true);
|
||||||
let method = match (lvalue_pref, mut_tr) {
|
let method = match (needs, mut_tr) {
|
||||||
(PreferMutLvalue, Some(trait_did)) => {
|
(Needs::MutPlace, Some(trait_did)) => {
|
||||||
self.lookup_method_in_trait(span, mut_op, trait_did, base_ty, Some(arg_tys))
|
self.lookup_method_in_trait(span, mut_op, trait_did, base_ty, Some(arg_tys))
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
@ -2753,18 +2752,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||||||
fn check_expr_coercable_to_type(&self,
|
fn check_expr_coercable_to_type(&self,
|
||||||
expr: &'gcx hir::Expr,
|
expr: &'gcx hir::Expr,
|
||||||
expected: Ty<'tcx>) -> Ty<'tcx> {
|
expected: Ty<'tcx>) -> Ty<'tcx> {
|
||||||
self.check_expr_coercable_to_type_with_lvalue_pref(expr, expected, NoPreference)
|
self.check_expr_coercable_to_type_with_needs(expr, expected, Needs::None)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_expr_coercable_to_type_with_lvalue_pref(&self,
|
fn check_expr_coercable_to_type_with_needs(&self,
|
||||||
expr: &'gcx hir::Expr,
|
expr: &'gcx hir::Expr,
|
||||||
expected: Ty<'tcx>,
|
expected: Ty<'tcx>,
|
||||||
lvalue_pref: LvaluePreference)
|
needs: Needs)
|
||||||
-> Ty<'tcx> {
|
-> Ty<'tcx> {
|
||||||
let ty = self.check_expr_with_expectation_and_lvalue_pref(
|
let ty = self.check_expr_with_expectation_and_needs(
|
||||||
expr,
|
expr,
|
||||||
ExpectHasType(expected),
|
ExpectHasType(expected),
|
||||||
lvalue_pref);
|
needs);
|
||||||
self.demand_coerce(expr, ty, expected)
|
self.demand_coerce(expr, ty, expected)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2776,16 +2775,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||||||
fn check_expr_with_expectation(&self,
|
fn check_expr_with_expectation(&self,
|
||||||
expr: &'gcx hir::Expr,
|
expr: &'gcx hir::Expr,
|
||||||
expected: Expectation<'tcx>) -> Ty<'tcx> {
|
expected: Expectation<'tcx>) -> Ty<'tcx> {
|
||||||
self.check_expr_with_expectation_and_lvalue_pref(expr, expected, NoPreference)
|
self.check_expr_with_expectation_and_needs(expr, expected, Needs::None)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_expr(&self, expr: &'gcx hir::Expr) -> Ty<'tcx> {
|
fn check_expr(&self, expr: &'gcx hir::Expr) -> Ty<'tcx> {
|
||||||
self.check_expr_with_expectation(expr, NoExpectation)
|
self.check_expr_with_expectation(expr, NoExpectation)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_expr_with_lvalue_pref(&self, expr: &'gcx hir::Expr,
|
fn check_expr_with_needs(&self, expr: &'gcx hir::Expr, needs: Needs) -> Ty<'tcx> {
|
||||||
lvalue_pref: LvaluePreference) -> Ty<'tcx> {
|
self.check_expr_with_expectation_and_needs(expr, NoExpectation, needs)
|
||||||
self.check_expr_with_expectation_and_lvalue_pref(expr, NoExpectation, lvalue_pref)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// determine the `self` type, using fresh variables for all variables
|
// determine the `self` type, using fresh variables for all variables
|
||||||
@ -2868,9 +2866,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||||||
span: Span,
|
span: Span,
|
||||||
args: &'gcx [hir::Expr],
|
args: &'gcx [hir::Expr],
|
||||||
expected: Expectation<'tcx>,
|
expected: Expectation<'tcx>,
|
||||||
lvalue_pref: LvaluePreference) -> Ty<'tcx> {
|
needs: Needs) -> Ty<'tcx> {
|
||||||
let rcvr = &args[0];
|
let rcvr = &args[0];
|
||||||
let rcvr_t = self.check_expr_with_lvalue_pref(&rcvr, lvalue_pref);
|
let rcvr_t = self.check_expr_with_needs(&rcvr, needs);
|
||||||
// no need to check for bot/err -- callee does that
|
// no need to check for bot/err -- callee does that
|
||||||
let rcvr_t = self.structurally_resolved_type(expr.span, rcvr_t);
|
let rcvr_t = self.structurally_resolved_type(expr.span, rcvr_t);
|
||||||
|
|
||||||
@ -2980,10 +2978,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||||||
// Check field access expressions
|
// Check field access expressions
|
||||||
fn check_field(&self,
|
fn check_field(&self,
|
||||||
expr: &'gcx hir::Expr,
|
expr: &'gcx hir::Expr,
|
||||||
lvalue_pref: LvaluePreference,
|
needs: Needs,
|
||||||
base: &'gcx hir::Expr,
|
base: &'gcx hir::Expr,
|
||||||
field: &Spanned<ast::Name>) -> Ty<'tcx> {
|
field: &Spanned<ast::Name>) -> Ty<'tcx> {
|
||||||
let expr_t = self.check_expr_with_lvalue_pref(base, lvalue_pref);
|
let expr_t = self.check_expr_with_needs(base, needs);
|
||||||
let expr_t = self.structurally_resolved_type(expr.span,
|
let expr_t = self.structurally_resolved_type(expr.span,
|
||||||
expr_t);
|
expr_t);
|
||||||
let mut private_candidate = None;
|
let mut private_candidate = None;
|
||||||
@ -2998,7 +2996,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||||||
if let Some(field) = fields.iter().find(|f| f.name.to_ident() == ident) {
|
if let Some(field) = fields.iter().find(|f| f.name.to_ident() == ident) {
|
||||||
let field_ty = self.field_ty(expr.span, field, substs);
|
let field_ty = self.field_ty(expr.span, field, substs);
|
||||||
if field.vis.is_accessible_from(def_scope, self.tcx) {
|
if field.vis.is_accessible_from(def_scope, self.tcx) {
|
||||||
let adjustments = autoderef.adjust_steps(lvalue_pref);
|
let adjustments = autoderef.adjust_steps(needs);
|
||||||
self.apply_adjustments(base, adjustments);
|
self.apply_adjustments(base, adjustments);
|
||||||
autoderef.finalize();
|
autoderef.finalize();
|
||||||
|
|
||||||
@ -3117,10 +3115,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||||||
// Check tuple index expressions
|
// Check tuple index expressions
|
||||||
fn check_tup_field(&self,
|
fn check_tup_field(&self,
|
||||||
expr: &'gcx hir::Expr,
|
expr: &'gcx hir::Expr,
|
||||||
lvalue_pref: LvaluePreference,
|
needs: Needs,
|
||||||
base: &'gcx hir::Expr,
|
base: &'gcx hir::Expr,
|
||||||
idx: codemap::Spanned<usize>) -> Ty<'tcx> {
|
idx: codemap::Spanned<usize>) -> Ty<'tcx> {
|
||||||
let expr_t = self.check_expr_with_lvalue_pref(base, lvalue_pref);
|
let expr_t = self.check_expr_with_needs(base, needs);
|
||||||
let expr_t = self.structurally_resolved_type(expr.span,
|
let expr_t = self.structurally_resolved_type(expr.span,
|
||||||
expr_t);
|
expr_t);
|
||||||
let mut private_candidate = None;
|
let mut private_candidate = None;
|
||||||
@ -3161,7 +3159,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if let Some(field_ty) = field {
|
if let Some(field_ty) = field {
|
||||||
let adjustments = autoderef.adjust_steps(lvalue_pref);
|
let adjustments = autoderef.adjust_steps(needs);
|
||||||
self.apply_adjustments(base, adjustments);
|
self.apply_adjustments(base, adjustments);
|
||||||
autoderef.finalize();
|
autoderef.finalize();
|
||||||
return field_ty;
|
return field_ty;
|
||||||
@ -3491,10 +3489,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||||||
/// Note that inspecting a type's structure *directly* may expose the fact
|
/// Note that inspecting a type's structure *directly* may expose the fact
|
||||||
/// that there are actually multiple representations for `TyError`, so avoid
|
/// that there are actually multiple representations for `TyError`, so avoid
|
||||||
/// that when err needs to be handled differently.
|
/// that when err needs to be handled differently.
|
||||||
fn check_expr_with_expectation_and_lvalue_pref(&self,
|
fn check_expr_with_expectation_and_needs(&self,
|
||||||
expr: &'gcx hir::Expr,
|
expr: &'gcx hir::Expr,
|
||||||
expected: Expectation<'tcx>,
|
expected: Expectation<'tcx>,
|
||||||
lvalue_pref: LvaluePreference) -> Ty<'tcx> {
|
needs: Needs) -> Ty<'tcx> {
|
||||||
debug!(">> typechecking: expr={:?} expected={:?}",
|
debug!(">> typechecking: expr={:?} expected={:?}",
|
||||||
expr, expected);
|
expr, expected);
|
||||||
|
|
||||||
@ -3507,7 +3505,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||||||
self.diverges.set(Diverges::Maybe);
|
self.diverges.set(Diverges::Maybe);
|
||||||
self.has_errors.set(false);
|
self.has_errors.set(false);
|
||||||
|
|
||||||
let ty = self.check_expr_kind(expr, expected, lvalue_pref);
|
let ty = self.check_expr_kind(expr, expected, needs);
|
||||||
|
|
||||||
// Warn for non-block expressions with diverging children.
|
// Warn for non-block expressions with diverging children.
|
||||||
match expr.node {
|
match expr.node {
|
||||||
@ -3541,7 +3539,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||||||
fn check_expr_kind(&self,
|
fn check_expr_kind(&self,
|
||||||
expr: &'gcx hir::Expr,
|
expr: &'gcx hir::Expr,
|
||||||
expected: Expectation<'tcx>,
|
expected: Expectation<'tcx>,
|
||||||
lvalue_pref: LvaluePreference) -> Ty<'tcx> {
|
needs: Needs) -> Ty<'tcx> {
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
let id = expr.id;
|
let id = expr.id;
|
||||||
match expr.node {
|
match expr.node {
|
||||||
@ -3575,13 +3573,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||||||
NoExpectation
|
NoExpectation
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let lvalue_pref = match unop {
|
let needs = match unop {
|
||||||
hir::UnDeref => lvalue_pref,
|
hir::UnDeref => needs,
|
||||||
_ => NoPreference
|
_ => Needs::None
|
||||||
};
|
};
|
||||||
let mut oprnd_t = self.check_expr_with_expectation_and_lvalue_pref(&oprnd,
|
let mut oprnd_t = self.check_expr_with_expectation_and_needs(&oprnd,
|
||||||
expected_inner,
|
expected_inner,
|
||||||
lvalue_pref);
|
needs);
|
||||||
|
|
||||||
if !oprnd_t.references_error() {
|
if !oprnd_t.references_error() {
|
||||||
oprnd_t = self.structurally_resolved_type(expr.span, oprnd_t);
|
oprnd_t = self.structurally_resolved_type(expr.span, oprnd_t);
|
||||||
@ -3590,7 +3588,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||||||
if let Some(mt) = oprnd_t.builtin_deref(true) {
|
if let Some(mt) = oprnd_t.builtin_deref(true) {
|
||||||
oprnd_t = mt.ty;
|
oprnd_t = mt.ty;
|
||||||
} else if let Some(ok) = self.try_overloaded_deref(
|
} else if let Some(ok) = self.try_overloaded_deref(
|
||||||
expr.span, oprnd_t, lvalue_pref) {
|
expr.span, oprnd_t, needs) {
|
||||||
let method = self.register_infer_ok_obligations(ok);
|
let method = self.register_infer_ok_obligations(ok);
|
||||||
if let ty::TyRef(region, mt) = method.sig.inputs()[0].sty {
|
if let ty::TyRef(region, mt) = method.sig.inputs()[0].sty {
|
||||||
self.apply_adjustments(oprnd, vec![Adjustment {
|
self.apply_adjustments(oprnd, vec![Adjustment {
|
||||||
@ -3641,8 +3639,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||||||
_ => NoExpectation
|
_ => NoExpectation
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
let lvalue_pref = LvaluePreference::from_mutbl(mutbl);
|
let needs = Needs::maybe_mut_place(mutbl);
|
||||||
let ty = self.check_expr_with_expectation_and_lvalue_pref(&oprnd, hint, lvalue_pref);
|
let ty = self.check_expr_with_expectation_and_needs(&oprnd, hint, needs);
|
||||||
|
|
||||||
let tm = ty::TypeAndMut { ty: ty, mutbl: mutbl };
|
let tm = ty::TypeAndMut { ty: ty, mutbl: mutbl };
|
||||||
if tm.ty.references_error() {
|
if tm.ty.references_error() {
|
||||||
@ -3786,7 +3784,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||||||
tcx.types.never
|
tcx.types.never
|
||||||
}
|
}
|
||||||
hir::ExprAssign(ref lhs, ref rhs) => {
|
hir::ExprAssign(ref lhs, ref rhs) => {
|
||||||
let lhs_ty = self.check_expr_with_lvalue_pref(&lhs, PreferMutLvalue);
|
let lhs_ty = self.check_expr_with_needs(&lhs, Needs::MutPlace);
|
||||||
|
|
||||||
let rhs_ty = self.check_expr_coercable_to_type(&rhs, lhs_ty);
|
let rhs_ty = self.check_expr_coercable_to_type(&rhs, lhs_ty);
|
||||||
|
|
||||||
@ -3887,7 +3885,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||||||
self.check_call(expr, &callee, args, expected)
|
self.check_call(expr, &callee, args, expected)
|
||||||
}
|
}
|
||||||
hir::ExprMethodCall(ref segment, span, ref args) => {
|
hir::ExprMethodCall(ref segment, span, ref args) => {
|
||||||
self.check_method_call(expr, segment, span, args, expected, lvalue_pref)
|
self.check_method_call(expr, segment, span, args, expected, needs)
|
||||||
}
|
}
|
||||||
hir::ExprCast(ref e, ref t) => {
|
hir::ExprCast(ref e, ref t) => {
|
||||||
// Find the type of `e`. Supply hints based on the type we are casting to,
|
// Find the type of `e`. Supply hints based on the type we are casting to,
|
||||||
@ -4030,13 +4028,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||||||
self.check_expr_struct(expr, expected, qpath, fields, base_expr)
|
self.check_expr_struct(expr, expected, qpath, fields, base_expr)
|
||||||
}
|
}
|
||||||
hir::ExprField(ref base, ref field) => {
|
hir::ExprField(ref base, ref field) => {
|
||||||
self.check_field(expr, lvalue_pref, &base, field)
|
self.check_field(expr, needs, &base, field)
|
||||||
}
|
}
|
||||||
hir::ExprTupField(ref base, idx) => {
|
hir::ExprTupField(ref base, idx) => {
|
||||||
self.check_tup_field(expr, lvalue_pref, &base, idx)
|
self.check_tup_field(expr, needs, &base, idx)
|
||||||
}
|
}
|
||||||
hir::ExprIndex(ref base, ref idx) => {
|
hir::ExprIndex(ref base, ref idx) => {
|
||||||
let base_t = self.check_expr_with_lvalue_pref(&base, lvalue_pref);
|
let base_t = self.check_expr_with_needs(&base, needs);
|
||||||
let idx_t = self.check_expr(&idx);
|
let idx_t = self.check_expr(&idx);
|
||||||
|
|
||||||
if base_t.references_error() {
|
if base_t.references_error() {
|
||||||
@ -4045,7 +4043,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||||||
idx_t
|
idx_t
|
||||||
} else {
|
} else {
|
||||||
let base_t = self.structurally_resolved_type(expr.span, base_t);
|
let base_t = self.structurally_resolved_type(expr.span, base_t);
|
||||||
match self.lookup_indexing(expr, base, base_t, idx_t, lvalue_pref) {
|
match self.lookup_indexing(expr, base, base_t, idx_t, needs) {
|
||||||
Some((index_ty, element_ty)) => {
|
Some((index_ty, element_ty)) => {
|
||||||
self.demand_coerce(idx, idx_t, index_ty);
|
self.demand_coerce(idx, idx_t, index_ty);
|
||||||
element_ty
|
element_ty
|
||||||
@ -4195,7 +4193,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||||||
// referent for the reference that results is *equal to* the
|
// referent for the reference that results is *equal to* the
|
||||||
// type of the lvalue it is referencing, and not some
|
// type of the lvalue it is referencing, and not some
|
||||||
// supertype thereof.
|
// supertype thereof.
|
||||||
let init_ty = self.check_expr_with_lvalue_pref(init, LvaluePreference::from_mutbl(m));
|
let init_ty = self.check_expr_with_needs(init, Needs::maybe_mut_place(m));
|
||||||
self.demand_eqtype(init.span, local_ty, init_ty);
|
self.demand_eqtype(init.span, local_ty, init_ty);
|
||||||
init_ty
|
init_ty
|
||||||
} else {
|
} else {
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
//! Code related to processing overloaded binary and unary operators.
|
//! Code related to processing overloaded binary and unary operators.
|
||||||
|
|
||||||
use super::{FnCtxt, NoPreference, PreferMutLvalue};
|
use super::{FnCtxt, Needs};
|
||||||
use super::method::MethodCallee;
|
use super::method::MethodCallee;
|
||||||
use rustc::ty::{self, Ty, TypeFoldable, TypeVariants};
|
use rustc::ty::{self, Ty, TypeFoldable, TypeVariants};
|
||||||
use rustc::ty::TypeVariants::{TyStr, TyRef};
|
use rustc::ty::TypeVariants::{TyStr, TyRef};
|
||||||
@ -166,18 +166,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||||||
op,
|
op,
|
||||||
is_assign);
|
is_assign);
|
||||||
|
|
||||||
let lhs_pref = match is_assign {
|
let lhs_needs = match is_assign {
|
||||||
IsAssign::Yes => PreferMutLvalue,
|
IsAssign::Yes => Needs::MutPlace,
|
||||||
IsAssign::No => NoPreference
|
IsAssign::No => Needs::None
|
||||||
};
|
};
|
||||||
// Find a suitable supertype of the LHS expression's type, by coercing to
|
// Find a suitable supertype of the LHS expression's type, by coercing to
|
||||||
// a type variable, to pass as the `Self` to the trait, avoiding invariant
|
// a type variable, to pass as the `Self` to the trait, avoiding invariant
|
||||||
// trait matching creating lifetime constraints that are too strict.
|
// trait matching creating lifetime constraints that are too strict.
|
||||||
// E.g. adding `&'a T` and `&'b T`, given `&'x T: Add<&'x T>`, will result
|
// E.g. adding `&'a T` and `&'b T`, given `&'x T: Add<&'x T>`, will result
|
||||||
// in `&'a T <: &'x T` and `&'b T <: &'x T`, instead of `'a = 'b = 'x`.
|
// in `&'a T <: &'x T` and `&'b T <: &'x T`, instead of `'a = 'b = 'x`.
|
||||||
let lhs_ty = self.check_expr_coercable_to_type_with_lvalue_pref(lhs_expr,
|
let lhs_ty = self.check_expr_coercable_to_type_with_needs(lhs_expr,
|
||||||
self.next_ty_var(TypeVariableOrigin::MiscVariable(lhs_expr.span)),
|
self.next_ty_var(TypeVariableOrigin::MiscVariable(lhs_expr.span)),
|
||||||
lhs_pref);
|
lhs_needs);
|
||||||
let lhs_ty = self.resolve_type_vars_with_obligations(lhs_ty);
|
let lhs_ty = self.resolve_type_vars_with_obligations(lhs_ty);
|
||||||
|
|
||||||
// NB: As we have not yet type-checked the RHS, we don't have the
|
// NB: As we have not yet type-checked the RHS, we don't have the
|
||||||
|
Loading…
Reference in New Issue
Block a user