mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-27 09:14:20 +00:00
parent
1661947014
commit
b8dad48435
@ -664,7 +664,7 @@ fn is_useful(cx: &MatchCheckCtxt,
|
|||||||
|
|
||||||
match real_pat.node {
|
match real_pat.node {
|
||||||
hir::PatIdent(hir::BindByRef(..), _, _) => {
|
hir::PatIdent(hir::BindByRef(..), _, _) => {
|
||||||
left_ty.builtin_deref(false).unwrap().ty
|
left_ty.builtin_deref(false, NoPreference).unwrap().ty
|
||||||
}
|
}
|
||||||
_ => left_ty,
|
_ => left_ty,
|
||||||
}
|
}
|
||||||
|
@ -400,7 +400,7 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
|
|||||||
// a bind-by-ref means that the base_ty will be the type of the ident itself,
|
// a bind-by-ref means that the base_ty will be the type of the ident itself,
|
||||||
// but what we want here is the type of the underlying value being borrowed.
|
// but what we want here is the type of the underlying value being borrowed.
|
||||||
// So peel off one-level, turning the &T into T.
|
// So peel off one-level, turning the &T into T.
|
||||||
match base_ty.builtin_deref(false) {
|
match base_ty.builtin_deref(false, ty::NoPreference) {
|
||||||
Some(t) => t.ty,
|
Some(t) => t.ty,
|
||||||
None => { return Err(()); }
|
None => { return Err(()); }
|
||||||
}
|
}
|
||||||
@ -897,7 +897,7 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
|
|||||||
None => base_cmt
|
None => base_cmt
|
||||||
};
|
};
|
||||||
let base_cmt_ty = base_cmt.ty;
|
let base_cmt_ty = base_cmt.ty;
|
||||||
match base_cmt_ty.builtin_deref(true) {
|
match base_cmt_ty.builtin_deref(true, ty::NoPreference) {
|
||||||
Some(mt) => {
|
Some(mt) => {
|
||||||
let ret = self.cat_deref_common(node, base_cmt, deref_cnt,
|
let ret = self.cat_deref_common(node, base_cmt, deref_cnt,
|
||||||
mt.ty,
|
mt.ty,
|
||||||
@ -1044,7 +1044,7 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
|
|||||||
span:elt.span(),
|
span:elt.span(),
|
||||||
cat:cat_deref(base_cmt.clone(), 0, ptr),
|
cat:cat_deref(base_cmt.clone(), 0, ptr),
|
||||||
mutbl:m,
|
mutbl:m,
|
||||||
ty: match base_cmt.ty.builtin_deref(false) {
|
ty: match base_cmt.ty.builtin_deref(false, ty::NoPreference) {
|
||||||
Some(mt) => mt.ty,
|
Some(mt) => mt.ty,
|
||||||
None => self.tcx().sess.bug("Found non-derefable type")
|
None => self.tcx().sess.bug("Found non-derefable type")
|
||||||
},
|
},
|
||||||
|
@ -29,6 +29,7 @@ pub use self::BoundRegion::*;
|
|||||||
pub use self::TypeVariants::*;
|
pub use self::TypeVariants::*;
|
||||||
pub use self::IntVarValue::*;
|
pub use self::IntVarValue::*;
|
||||||
pub use self::CopyImplementationError::*;
|
pub use self::CopyImplementationError::*;
|
||||||
|
pub use self::LvaluePreference::*;
|
||||||
|
|
||||||
pub use self::BuiltinBound::Send as BoundSend;
|
pub use self::BuiltinBound::Send as BoundSend;
|
||||||
pub use self::BuiltinBound::Sized as BoundSized;
|
pub use self::BuiltinBound::Sized as BoundSized;
|
||||||
@ -4828,6 +4829,21 @@ impl<'tcx> TyS<'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub enum LvaluePreference {
|
||||||
|
PreferMutLvalue,
|
||||||
|
NoPreference
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LvaluePreference {
|
||||||
|
pub fn from_mutbl(m: hir::Mutability) -> Self {
|
||||||
|
match m {
|
||||||
|
hir::MutMutable => PreferMutLvalue,
|
||||||
|
hir::MutImmutable => NoPreference,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Describes whether a type is representable. For types that are not
|
/// Describes whether a type is representable. For types that are not
|
||||||
/// representable, 'SelfRecursive' and 'ContainsRecursive' are used to
|
/// representable, 'SelfRecursive' and 'ContainsRecursive' are used to
|
||||||
/// distinguish between types that are recursive with themselves and types that
|
/// distinguish between types that are recursive with themselves and types that
|
||||||
@ -5073,12 +5089,15 @@ impl<'tcx> TyS<'tcx> {
|
|||||||
//
|
//
|
||||||
// The parameter `explicit` indicates if this is an *explicit* dereference.
|
// The parameter `explicit` indicates if this is an *explicit* dereference.
|
||||||
// Some types---notably unsafe ptrs---can only be dereferenced explicitly.
|
// Some types---notably unsafe ptrs---can only be dereferenced explicitly.
|
||||||
pub fn builtin_deref(&self, explicit: bool) -> Option<TypeAndMut<'tcx>> {
|
pub fn builtin_deref(&self, explicit: bool, pref: LvaluePreference)
|
||||||
|
-> Option<TypeAndMut<'tcx>>
|
||||||
|
{
|
||||||
match self.sty {
|
match self.sty {
|
||||||
TyBox(ty) => {
|
TyBox(ty) => {
|
||||||
Some(TypeAndMut {
|
Some(TypeAndMut {
|
||||||
ty: ty,
|
ty: ty,
|
||||||
mutbl: hir::MutImmutable,
|
mutbl:
|
||||||
|
if pref == PreferMutLvalue { hir::MutMutable } else { hir::MutImmutable },
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
TyRef(_, mt) => Some(mt),
|
TyRef(_, mt) => Some(mt),
|
||||||
@ -5183,7 +5202,7 @@ impl<'tcx> TyS<'tcx> {
|
|||||||
}
|
}
|
||||||
None => {}
|
None => {}
|
||||||
}
|
}
|
||||||
match adjusted_ty.builtin_deref(true) {
|
match adjusted_ty.builtin_deref(true, NoPreference) {
|
||||||
Some(mt) => { adjusted_ty = mt.ty; }
|
Some(mt) => { adjusted_ty = mt.ty; }
|
||||||
None => {
|
None => {
|
||||||
cx.sess.span_bug(
|
cx.sess.span_bug(
|
||||||
|
@ -155,7 +155,7 @@ fn const_deref<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|||||||
v: ValueRef,
|
v: ValueRef,
|
||||||
ty: Ty<'tcx>)
|
ty: Ty<'tcx>)
|
||||||
-> (ValueRef, Ty<'tcx>) {
|
-> (ValueRef, Ty<'tcx>) {
|
||||||
match ty.builtin_deref(true) {
|
match ty.builtin_deref(true, ty::NoPreference) {
|
||||||
Some(mt) => {
|
Some(mt) => {
|
||||||
if type_is_sized(cx.tcx(), mt.ty) {
|
if type_is_sized(cx.tcx(), mt.ty) {
|
||||||
(const_deref_ptr(cx, v), mt.ty)
|
(const_deref_ptr(cx, v), mt.ty)
|
||||||
@ -329,7 +329,7 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|||||||
param_substs,
|
param_substs,
|
||||||
&target);
|
&target);
|
||||||
|
|
||||||
let pointee_ty = ty.builtin_deref(true)
|
let pointee_ty = ty.builtin_deref(true, ty::NoPreference)
|
||||||
.expect("consts: unsizing got non-pointer type").ty;
|
.expect("consts: unsizing got non-pointer type").ty;
|
||||||
let (base, old_info) = if !type_is_sized(cx.tcx(), pointee_ty) {
|
let (base, old_info) = if !type_is_sized(cx.tcx(), pointee_ty) {
|
||||||
// Normally, the source is a thin pointer and we are
|
// Normally, the source is a thin pointer and we are
|
||||||
@ -344,7 +344,7 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|||||||
(llconst, None)
|
(llconst, None)
|
||||||
};
|
};
|
||||||
|
|
||||||
let unsized_ty = target.builtin_deref(true)
|
let unsized_ty = target.builtin_deref(true, ty::NoPreference)
|
||||||
.expect("consts: unsizing got non-pointer target type").ty;
|
.expect("consts: unsizing got non-pointer target type").ty;
|
||||||
let ptr_ty = type_of::in_memory_type_of(cx, unsized_ty).ptr_to();
|
let ptr_ty = type_of::in_memory_type_of(cx, unsized_ty).ptr_to();
|
||||||
let base = ptrcast(base, ptr_ty);
|
let base = ptrcast(base, ptr_ty);
|
||||||
@ -642,7 +642,8 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|||||||
}
|
}
|
||||||
if type_is_fat_ptr(cx.tcx(), t_expr) {
|
if type_is_fat_ptr(cx.tcx(), t_expr) {
|
||||||
// Fat pointer casts.
|
// Fat pointer casts.
|
||||||
let t_cast_inner = t_cast.builtin_deref(true).expect("cast to non-pointer").ty;
|
let t_cast_inner =
|
||||||
|
t_cast.builtin_deref(true, ty::NoPreference).expect("cast to non-pointer").ty;
|
||||||
let ptr_ty = type_of::in_memory_type_of(cx, t_cast_inner).ptr_to();
|
let ptr_ty = type_of::in_memory_type_of(cx, t_cast_inner).ptr_to();
|
||||||
let addr = ptrcast(const_get_elt(cx, v, &[abi::FAT_PTR_ADDR as u32]),
|
let addr = ptrcast(const_get_elt(cx, v, &[abi::FAT_PTR_ADDR as u32]),
|
||||||
ptr_ty);
|
ptr_ty);
|
||||||
|
@ -780,7 +780,7 @@ fn trans_index<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
|||||||
|
|
||||||
let ref_ty = // invoked methods have LB regions instantiated:
|
let ref_ty = // invoked methods have LB regions instantiated:
|
||||||
bcx.tcx().no_late_bound_regions(&method_ty.fn_ret()).unwrap().unwrap();
|
bcx.tcx().no_late_bound_regions(&method_ty.fn_ret()).unwrap().unwrap();
|
||||||
let elt_ty = match ref_ty.builtin_deref(true) {
|
let elt_ty = match ref_ty.builtin_deref(true, ty::NoPreference) {
|
||||||
None => {
|
None => {
|
||||||
bcx.tcx().sess.span_bug(index_expr.span,
|
bcx.tcx().sess.span_bug(index_expr.span,
|
||||||
"index method didn't return a \
|
"index method didn't return a \
|
||||||
@ -1971,7 +1971,8 @@ pub fn cast_is_noop<'tcx>(tcx: &ty::ctxt<'tcx>,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
match (t_in.builtin_deref(true), t_out.builtin_deref(true)) {
|
match (t_in.builtin_deref(true, ty::NoPreference),
|
||||||
|
t_out.builtin_deref(true, ty::NoPreference)) {
|
||||||
(Some(ty::TypeAndMut{ ty: t_in, .. }), Some(ty::TypeAndMut{ ty: t_out, .. })) => {
|
(Some(ty::TypeAndMut{ ty: t_in, .. }), Some(ty::TypeAndMut{ ty: t_out, .. })) => {
|
||||||
t_in == t_out
|
t_in == t_out
|
||||||
}
|
}
|
||||||
|
@ -15,10 +15,10 @@ use middle::pat_util::{PatIdMap, pat_id_map, pat_is_binding};
|
|||||||
use middle::pat_util::pat_is_resolved_const;
|
use middle::pat_util::pat_is_resolved_const;
|
||||||
use middle::privacy::{AllPublic, LastMod};
|
use middle::privacy::{AllPublic, LastMod};
|
||||||
use middle::subst::Substs;
|
use middle::subst::Substs;
|
||||||
use middle::ty::{self, Ty, HasTypeFlags};
|
use middle::ty::{self, Ty, HasTypeFlags, LvaluePreference};
|
||||||
use check::{check_expr, check_expr_has_type, check_expr_with_expectation};
|
use check::{check_expr, check_expr_has_type, check_expr_with_expectation};
|
||||||
use check::{check_expr_coercable_to_type, demand, FnCtxt, Expectation};
|
use check::{check_expr_coercable_to_type, demand, FnCtxt, Expectation};
|
||||||
use check::{check_expr_with_lvalue_pref, LvaluePreference};
|
use check::{check_expr_with_lvalue_pref};
|
||||||
use check::{instantiate_path, resolve_ty_and_def_ufcs, structurally_resolved_type};
|
use check::{instantiate_path, resolve_ty_and_def_ufcs, structurally_resolved_type};
|
||||||
use require_same_types;
|
use require_same_types;
|
||||||
use util::nodemap::FnvHashMap;
|
use util::nodemap::FnvHashMap;
|
||||||
@ -292,7 +292,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
|
|||||||
let region = fcx.infcx().next_region_var(infer::PatternRegion(pat.span));
|
let region = fcx.infcx().next_region_var(infer::PatternRegion(pat.span));
|
||||||
tcx.mk_ref(tcx.mk_region(region), ty::TypeAndMut {
|
tcx.mk_ref(tcx.mk_region(region), ty::TypeAndMut {
|
||||||
ty: tcx.mk_slice(inner_ty),
|
ty: tcx.mk_slice(inner_ty),
|
||||||
mutbl: expected_ty.builtin_deref(true).map(|mt| mt.mutbl)
|
mutbl: expected_ty.builtin_deref(true, ty::NoPreference).map(|mt| mt.mutbl)
|
||||||
.unwrap_or(hir::MutImmutable)
|
.unwrap_or(hir::MutImmutable)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -310,7 +310,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
|
|||||||
}
|
}
|
||||||
if let Some(ref slice) = *slice {
|
if let Some(ref slice) = *slice {
|
||||||
let region = fcx.infcx().next_region_var(infer::PatternRegion(pat.span));
|
let region = fcx.infcx().next_region_var(infer::PatternRegion(pat.span));
|
||||||
let mutbl = expected_ty.builtin_deref(true)
|
let mutbl = expected_ty.builtin_deref(true, ty::NoPreference)
|
||||||
.map_or(hir::MutImmutable, |mt| mt.mutbl);
|
.map_or(hir::MutImmutable, |mt| mt.mutbl);
|
||||||
|
|
||||||
let slice_ty = tcx.mk_ref(tcx.mk_region(region), ty::TypeAndMut {
|
let slice_ty = tcx.mk_ref(tcx.mk_region(region), ty::TypeAndMut {
|
||||||
@ -399,7 +399,7 @@ pub fn check_dereferencable<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
|
|||||||
let tcx = pcx.fcx.ccx.tcx;
|
let tcx = pcx.fcx.ccx.tcx;
|
||||||
if pat_is_binding(&tcx.def_map, inner) {
|
if pat_is_binding(&tcx.def_map, inner) {
|
||||||
let expected = fcx.infcx().shallow_resolve(expected);
|
let expected = fcx.infcx().shallow_resolve(expected);
|
||||||
expected.builtin_deref(true).map_or(true, |mt| match mt.ty.sty {
|
expected.builtin_deref(true, ty::NoPreference).map_or(true, |mt| match mt.ty.sty {
|
||||||
ty::TyTrait(_) => {
|
ty::TyTrait(_) => {
|
||||||
// This is "x = SomeTrait" being reduced from
|
// This is "x = SomeTrait" being reduced from
|
||||||
// "let &x = &SomeTrait" or "let box x = Box<SomeTrait>", an error.
|
// "let &x = &SomeTrait" or "let box x = Box<SomeTrait>", an error.
|
||||||
|
@ -18,7 +18,6 @@ use super::err_args;
|
|||||||
use super::Expectation;
|
use super::Expectation;
|
||||||
use super::expected_types_for_fn_args;
|
use super::expected_types_for_fn_args;
|
||||||
use super::FnCtxt;
|
use super::FnCtxt;
|
||||||
use super::LvaluePreference;
|
|
||||||
use super::method;
|
use super::method;
|
||||||
use super::structurally_resolved_type;
|
use super::structurally_resolved_type;
|
||||||
use super::TupleArgumentsFlag;
|
use super::TupleArgumentsFlag;
|
||||||
@ -28,7 +27,7 @@ use super::write_call;
|
|||||||
use CrateCtxt;
|
use CrateCtxt;
|
||||||
use middle::def_id::{DefId, LOCAL_CRATE};
|
use middle::def_id::{DefId, LOCAL_CRATE};
|
||||||
use middle::infer;
|
use middle::infer;
|
||||||
use middle::ty::{self, Ty};
|
use middle::ty::{self, LvaluePreference, Ty};
|
||||||
use syntax::codemap::Span;
|
use syntax::codemap::Span;
|
||||||
use syntax::parse::token;
|
use syntax::parse::token;
|
||||||
use syntax::ptr::P;
|
use syntax::ptr::P;
|
||||||
|
@ -60,13 +60,13 @@
|
|||||||
//! 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::{autoderef, FnCtxt, LvaluePreference, UnresolvedTypeAction};
|
use check::{autoderef, FnCtxt, UnresolvedTypeAction};
|
||||||
|
|
||||||
use middle::infer::{self, Coercion};
|
use middle::infer::{self, Coercion};
|
||||||
use middle::traits::{self, ObligationCause};
|
use middle::traits::{self, ObligationCause};
|
||||||
use middle::traits::{predicate_for_trait_def, report_selection_error};
|
use middle::traits::{predicate_for_trait_def, report_selection_error};
|
||||||
use middle::ty::{AutoDerefRef, AdjustDerefRef};
|
use middle::ty::{AutoDerefRef, AdjustDerefRef};
|
||||||
use middle::ty::{self, TypeAndMut, Ty, TypeError};
|
use middle::ty::{self, LvaluePreference, TypeAndMut, Ty, TypeError};
|
||||||
use middle::ty_relate::RelateResult;
|
use middle::ty_relate::RelateResult;
|
||||||
use util::common::indent;
|
use util::common::indent;
|
||||||
|
|
||||||
|
@ -10,12 +10,12 @@
|
|||||||
|
|
||||||
use super::probe;
|
use super::probe;
|
||||||
|
|
||||||
use check::{self, FnCtxt, NoPreference, PreferMutLvalue, callee, demand};
|
use check::{self, FnCtxt, callee, demand};
|
||||||
use check::UnresolvedTypeAction;
|
use check::UnresolvedTypeAction;
|
||||||
use middle::def_id::DefId;
|
use middle::def_id::DefId;
|
||||||
use middle::subst::{self};
|
use middle::subst::{self};
|
||||||
use middle::traits;
|
use middle::traits;
|
||||||
use middle::ty::{self, Ty};
|
use middle::ty::{self, NoPreference, PreferMutLvalue, Ty};
|
||||||
use middle::ty_fold::TypeFoldable;
|
use middle::ty_fold::TypeFoldable;
|
||||||
use middle::infer;
|
use middle::infer;
|
||||||
use middle::infer::InferCtxt;
|
use middle::infer::InferCtxt;
|
||||||
@ -534,7 +534,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
|
|||||||
}
|
}
|
||||||
Some(ty::AutoPtr(_, _)) => {
|
Some(ty::AutoPtr(_, _)) => {
|
||||||
(adr.autoderefs, adr.unsize.map(|target| {
|
(adr.autoderefs, adr.unsize.map(|target| {
|
||||||
target.builtin_deref(false)
|
target.builtin_deref(false, NoPreference)
|
||||||
.expect("fixup: AutoPtr is not &T").ty
|
.expect("fixup: AutoPtr is not &T").ty
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
@ -14,13 +14,13 @@ use super::{CandidateSource, ImplSource, TraitSource};
|
|||||||
use super::suggest;
|
use super::suggest;
|
||||||
|
|
||||||
use check;
|
use check;
|
||||||
use check::{FnCtxt, NoPreference, UnresolvedTypeAction};
|
use check::{FnCtxt, UnresolvedTypeAction};
|
||||||
use middle::def_id::DefId;
|
use middle::def_id::DefId;
|
||||||
use middle::fast_reject;
|
use middle::fast_reject;
|
||||||
use middle::subst;
|
use middle::subst;
|
||||||
use middle::subst::Subst;
|
use middle::subst::Subst;
|
||||||
use middle::traits;
|
use middle::traits;
|
||||||
use middle::ty::{self, RegionEscape, Ty, ToPolyTraitRef, TraitRef};
|
use middle::ty::{self, NoPreference, RegionEscape, Ty, ToPolyTraitRef, TraitRef};
|
||||||
use middle::ty::HasTypeFlags;
|
use middle::ty::HasTypeFlags;
|
||||||
use middle::ty_fold::TypeFoldable;
|
use middle::ty_fold::TypeFoldable;
|
||||||
use middle::infer;
|
use middle::infer;
|
||||||
|
@ -324,7 +324,7 @@ fn type_derefs_to_local<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
|||||||
}
|
}
|
||||||
|
|
||||||
check::autoderef(fcx, span, rcvr_ty, None,
|
check::autoderef(fcx, span, rcvr_ty, None,
|
||||||
check::UnresolvedTypeAction::Ignore, check::NoPreference,
|
check::UnresolvedTypeAction::Ignore, ty::NoPreference,
|
||||||
|ty, _| {
|
|ty, _| {
|
||||||
if is_local(ty) {
|
if is_local(ty) {
|
||||||
Some(())
|
Some(())
|
||||||
|
@ -76,7 +76,6 @@ type parameter).
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
pub use self::LvaluePreference::*;
|
|
||||||
pub use self::Expectation::*;
|
pub use self::Expectation::*;
|
||||||
pub use self::compare_method::{compare_impl_method, compare_const_impl};
|
pub use self::compare_method::{compare_impl_method, compare_const_impl};
|
||||||
use self::TupleArgumentsFlag::*;
|
use self::TupleArgumentsFlag::*;
|
||||||
@ -95,6 +94,7 @@ use middle::subst::{self, Subst, Substs, VecPerParamSpace, ParamSpace, TypeSpace
|
|||||||
use middle::traits::{self, report_fulfillment_errors};
|
use middle::traits::{self, report_fulfillment_errors};
|
||||||
use middle::ty::{FnSig, GenericPredicates, TypeScheme};
|
use middle::ty::{FnSig, GenericPredicates, TypeScheme};
|
||||||
use middle::ty::{Disr, ParamTy, ParameterEnvironment};
|
use middle::ty::{Disr, ParamTy, ParameterEnvironment};
|
||||||
|
use middle::ty::{LvaluePreference, NoPreference, PreferMutLvalue};
|
||||||
use middle::ty::{self, HasTypeFlags, RegionEscape, ToPolyTraitRef, Ty};
|
use middle::ty::{self, HasTypeFlags, RegionEscape, ToPolyTraitRef, Ty};
|
||||||
use middle::ty::{MethodCall, MethodCallee};
|
use middle::ty::{MethodCall, MethodCallee};
|
||||||
use middle::ty_fold::{TypeFolder, TypeFoldable};
|
use middle::ty_fold::{TypeFolder, TypeFoldable};
|
||||||
@ -2086,21 +2086,6 @@ impl<'a, 'tcx> RegionScope for FnCtxt<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
|
||||||
pub enum LvaluePreference {
|
|
||||||
PreferMutLvalue,
|
|
||||||
NoPreference
|
|
||||||
}
|
|
||||||
|
|
||||||
impl LvaluePreference {
|
|
||||||
pub fn from_mutbl(m: hir::Mutability) -> Self {
|
|
||||||
match m {
|
|
||||||
hir::MutMutable => PreferMutLvalue,
|
|
||||||
hir::MutImmutable => NoPreference,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Whether `autoderef` requires types to resolve.
|
/// Whether `autoderef` requires types to resolve.
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
pub enum UnresolvedTypeAction {
|
pub enum UnresolvedTypeAction {
|
||||||
@ -2156,7 +2141,7 @@ pub fn autoderef<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, deref if type is derefable:
|
// Otherwise, deref if type is derefable:
|
||||||
let mt = match resolved_t.builtin_deref(false) {
|
let mt = match resolved_t.builtin_deref(false, lvalue_pref) {
|
||||||
Some(mt) => Some(mt),
|
Some(mt) => Some(mt),
|
||||||
None => {
|
None => {
|
||||||
let method_call =
|
let method_call =
|
||||||
@ -2245,7 +2230,7 @@ fn make_overloaded_lvalue_return_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// method returns &T, but the type as visible to user is T, so deref
|
// method returns &T, but the type as visible to user is T, so deref
|
||||||
ret_ty.builtin_deref(true)
|
ret_ty.builtin_deref(true, NoPreference)
|
||||||
}
|
}
|
||||||
None => None,
|
None => None,
|
||||||
}
|
}
|
||||||
@ -3293,7 +3278,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
|
|||||||
}
|
}
|
||||||
hir::UnDeref => {
|
hir::UnDeref => {
|
||||||
oprnd_t = structurally_resolved_type(fcx, expr.span, oprnd_t);
|
oprnd_t = structurally_resolved_type(fcx, expr.span, oprnd_t);
|
||||||
oprnd_t = match oprnd_t.builtin_deref(true) {
|
oprnd_t = match oprnd_t.builtin_deref(true, NoPreference) {
|
||||||
Some(mt) => mt.ty,
|
Some(mt) => mt.ty,
|
||||||
None => match try_overloaded_deref(fcx, expr.span,
|
None => match try_overloaded_deref(fcx, expr.span,
|
||||||
Some(MethodCall::expr(expr.id)),
|
Some(MethodCall::expr(expr.id)),
|
||||||
|
@ -17,12 +17,11 @@ use super::{
|
|||||||
demand,
|
demand,
|
||||||
method,
|
method,
|
||||||
FnCtxt,
|
FnCtxt,
|
||||||
PreferMutLvalue,
|
|
||||||
structurally_resolved_type,
|
structurally_resolved_type,
|
||||||
};
|
};
|
||||||
use middle::def_id::DefId;
|
use middle::def_id::DefId;
|
||||||
use middle::traits;
|
use middle::traits;
|
||||||
use middle::ty::{Ty, HasTypeFlags};
|
use middle::ty::{Ty, HasTypeFlags, PreferMutLvalue};
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
use syntax::parse::token;
|
use syntax::parse::token;
|
||||||
use rustc_front::hir;
|
use rustc_front::hir;
|
||||||
|
@ -1031,7 +1031,7 @@ fn constrain_autoderefs<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>,
|
|||||||
r_deref_expr, *r_ptr);
|
r_deref_expr, *r_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
match derefd_ty.builtin_deref(true) {
|
match derefd_ty.builtin_deref(true, ty::NoPreference) {
|
||||||
Some(mt) => derefd_ty = mt.ty,
|
Some(mt) => derefd_ty = mt.ty,
|
||||||
/* if this type can't be dereferenced, then there's already an error
|
/* if this type can't be dereferenced, then there's already an error
|
||||||
in the session saying so. Just bail out for now */
|
in the session saying so. Just bail out for now */
|
||||||
|
39
src/test/run-pass/issue-26205.rs
Normal file
39
src/test/run-pass/issue-26205.rs
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
use std::ops::{Deref, DerefMut};
|
||||||
|
|
||||||
|
struct Foo;
|
||||||
|
|
||||||
|
impl Foo {
|
||||||
|
fn foo_mut(&mut self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Bar(Foo);
|
||||||
|
|
||||||
|
impl Deref for Bar {
|
||||||
|
type Target = Foo;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Foo {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DerefMut for Bar {
|
||||||
|
fn deref_mut(&mut self) -> &mut Foo {
|
||||||
|
&mut self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test(mut bar: Box<Bar>) {
|
||||||
|
bar.foo_mut();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
Loading…
Reference in New Issue
Block a user