Skip to content

Commit 2f77a59

Browse files
committed
Auto merge of #28201 - apasel422:issue-26205, r=nikomatsakis
Closes #26205. r? @eddyb
2 parents 94ddfc7 + b8dad48 commit 2f77a59

File tree

15 files changed

+93
-50
lines changed

15 files changed

+93
-50
lines changed

src/librustc/middle/check_match.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -664,7 +664,7 @@ fn is_useful(cx: &MatchCheckCtxt,
664664

665665
match real_pat.node {
666666
hir::PatIdent(hir::BindByRef(..), _, _) => {
667-
left_ty.builtin_deref(false).unwrap().ty
667+
left_ty.builtin_deref(false, NoPreference).unwrap().ty
668668
}
669669
_ => left_ty,
670670
}

src/librustc/middle/mem_categorization.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,7 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
400400
// a bind-by-ref means that the base_ty will be the type of the ident itself,
401401
// but what we want here is the type of the underlying value being borrowed.
402402
// So peel off one-level, turning the &T into T.
403-
match base_ty.builtin_deref(false) {
403+
match base_ty.builtin_deref(false, ty::NoPreference) {
404404
Some(t) => t.ty,
405405
None => { return Err(()); }
406406
}
@@ -897,7 +897,7 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
897897
None => base_cmt
898898
};
899899
let base_cmt_ty = base_cmt.ty;
900-
match base_cmt_ty.builtin_deref(true) {
900+
match base_cmt_ty.builtin_deref(true, ty::NoPreference) {
901901
Some(mt) => {
902902
let ret = self.cat_deref_common(node, base_cmt, deref_cnt,
903903
mt.ty,
@@ -1044,7 +1044,7 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
10441044
span:elt.span(),
10451045
cat:cat_deref(base_cmt.clone(), 0, ptr),
10461046
mutbl:m,
1047-
ty: match base_cmt.ty.builtin_deref(false) {
1047+
ty: match base_cmt.ty.builtin_deref(false, ty::NoPreference) {
10481048
Some(mt) => mt.ty,
10491049
None => self.tcx().sess.bug("Found non-derefable type")
10501050
},

src/librustc/middle/ty.rs

+22-3
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ pub use self::BoundRegion::*;
2929
pub use self::TypeVariants::*;
3030
pub use self::IntVarValue::*;
3131
pub use self::CopyImplementationError::*;
32+
pub use self::LvaluePreference::*;
3233

3334
pub use self::BuiltinBound::Send as BoundSend;
3435
pub use self::BuiltinBound::Sized as BoundSized;
@@ -4828,6 +4829,21 @@ impl<'tcx> TyS<'tcx> {
48284829
}
48294830
}
48304831

4832+
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
4833+
pub enum LvaluePreference {
4834+
PreferMutLvalue,
4835+
NoPreference
4836+
}
4837+
4838+
impl LvaluePreference {
4839+
pub fn from_mutbl(m: hir::Mutability) -> Self {
4840+
match m {
4841+
hir::MutMutable => PreferMutLvalue,
4842+
hir::MutImmutable => NoPreference,
4843+
}
4844+
}
4845+
}
4846+
48314847
/// Describes whether a type is representable. For types that are not
48324848
/// representable, 'SelfRecursive' and 'ContainsRecursive' are used to
48334849
/// distinguish between types that are recursive with themselves and types that
@@ -5073,12 +5089,15 @@ impl<'tcx> TyS<'tcx> {
50735089
//
50745090
// The parameter `explicit` indicates if this is an *explicit* dereference.
50755091
// Some types---notably unsafe ptrs---can only be dereferenced explicitly.
5076-
pub fn builtin_deref(&self, explicit: bool) -> Option<TypeAndMut<'tcx>> {
5092+
pub fn builtin_deref(&self, explicit: bool, pref: LvaluePreference)
5093+
-> Option<TypeAndMut<'tcx>>
5094+
{
50775095
match self.sty {
50785096
TyBox(ty) => {
50795097
Some(TypeAndMut {
50805098
ty: ty,
5081-
mutbl: hir::MutImmutable,
5099+
mutbl:
5100+
if pref == PreferMutLvalue { hir::MutMutable } else { hir::MutImmutable },
50825101
})
50835102
},
50845103
TyRef(_, mt) => Some(mt),
@@ -5183,7 +5202,7 @@ impl<'tcx> TyS<'tcx> {
51835202
}
51845203
None => {}
51855204
}
5186-
match adjusted_ty.builtin_deref(true) {
5205+
match adjusted_ty.builtin_deref(true, NoPreference) {
51875206
Some(mt) => { adjusted_ty = mt.ty; }
51885207
None => {
51895208
cx.sess.span_bug(

src/librustc_trans/trans/consts.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ fn const_deref<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
155155
v: ValueRef,
156156
ty: Ty<'tcx>)
157157
-> (ValueRef, Ty<'tcx>) {
158-
match ty.builtin_deref(true) {
158+
match ty.builtin_deref(true, ty::NoPreference) {
159159
Some(mt) => {
160160
if type_is_sized(cx.tcx(), mt.ty) {
161161
(const_deref_ptr(cx, v), mt.ty)
@@ -329,7 +329,7 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
329329
param_substs,
330330
&target);
331331

332-
let pointee_ty = ty.builtin_deref(true)
332+
let pointee_ty = ty.builtin_deref(true, ty::NoPreference)
333333
.expect("consts: unsizing got non-pointer type").ty;
334334
let (base, old_info) = if !type_is_sized(cx.tcx(), pointee_ty) {
335335
// Normally, the source is a thin pointer and we are
@@ -344,7 +344,7 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
344344
(llconst, None)
345345
};
346346

347-
let unsized_ty = target.builtin_deref(true)
347+
let unsized_ty = target.builtin_deref(true, ty::NoPreference)
348348
.expect("consts: unsizing got non-pointer target type").ty;
349349
let ptr_ty = type_of::in_memory_type_of(cx, unsized_ty).ptr_to();
350350
let base = ptrcast(base, ptr_ty);
@@ -642,7 +642,8 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
642642
}
643643
if type_is_fat_ptr(cx.tcx(), t_expr) {
644644
// Fat pointer casts.
645-
let t_cast_inner = t_cast.builtin_deref(true).expect("cast to non-pointer").ty;
645+
let t_cast_inner =
646+
t_cast.builtin_deref(true, ty::NoPreference).expect("cast to non-pointer").ty;
646647
let ptr_ty = type_of::in_memory_type_of(cx, t_cast_inner).ptr_to();
647648
let addr = ptrcast(const_get_elt(cx, v, &[abi::FAT_PTR_ADDR as u32]),
648649
ptr_ty);

src/librustc_trans/trans/expr.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -780,7 +780,7 @@ fn trans_index<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
780780

781781
let ref_ty = // invoked methods have LB regions instantiated:
782782
bcx.tcx().no_late_bound_regions(&method_ty.fn_ret()).unwrap().unwrap();
783-
let elt_ty = match ref_ty.builtin_deref(true) {
783+
let elt_ty = match ref_ty.builtin_deref(true, ty::NoPreference) {
784784
None => {
785785
bcx.tcx().sess.span_bug(index_expr.span,
786786
"index method didn't return a \
@@ -1971,7 +1971,8 @@ pub fn cast_is_noop<'tcx>(tcx: &ty::ctxt<'tcx>,
19711971
return true;
19721972
}
19731973

1974-
match (t_in.builtin_deref(true), t_out.builtin_deref(true)) {
1974+
match (t_in.builtin_deref(true, ty::NoPreference),
1975+
t_out.builtin_deref(true, ty::NoPreference)) {
19751976
(Some(ty::TypeAndMut{ ty: t_in, .. }), Some(ty::TypeAndMut{ ty: t_out, .. })) => {
19761977
t_in == t_out
19771978
}

src/librustc_typeck/check/_match.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@ use middle::pat_util::{PatIdMap, pat_id_map, pat_is_binding};
1515
use middle::pat_util::pat_is_resolved_const;
1616
use middle::privacy::{AllPublic, LastMod};
1717
use middle::subst::Substs;
18-
use middle::ty::{self, Ty, HasTypeFlags};
18+
use middle::ty::{self, Ty, HasTypeFlags, LvaluePreference};
1919
use check::{check_expr, check_expr_has_type, check_expr_with_expectation};
2020
use check::{check_expr_coercable_to_type, demand, FnCtxt, Expectation};
21-
use check::{check_expr_with_lvalue_pref, LvaluePreference};
21+
use check::{check_expr_with_lvalue_pref};
2222
use check::{instantiate_path, resolve_ty_and_def_ufcs, structurally_resolved_type};
2323
use require_same_types;
2424
use util::nodemap::FnvHashMap;
@@ -292,7 +292,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
292292
let region = fcx.infcx().next_region_var(infer::PatternRegion(pat.span));
293293
tcx.mk_ref(tcx.mk_region(region), ty::TypeAndMut {
294294
ty: tcx.mk_slice(inner_ty),
295-
mutbl: expected_ty.builtin_deref(true).map(|mt| mt.mutbl)
295+
mutbl: expected_ty.builtin_deref(true, ty::NoPreference).map(|mt| mt.mutbl)
296296
.unwrap_or(hir::MutImmutable)
297297
})
298298
}
@@ -310,7 +310,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
310310
}
311311
if let Some(ref slice) = *slice {
312312
let region = fcx.infcx().next_region_var(infer::PatternRegion(pat.span));
313-
let mutbl = expected_ty.builtin_deref(true)
313+
let mutbl = expected_ty.builtin_deref(true, ty::NoPreference)
314314
.map_or(hir::MutImmutable, |mt| mt.mutbl);
315315

316316
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>,
399399
let tcx = pcx.fcx.ccx.tcx;
400400
if pat_is_binding(&tcx.def_map, inner) {
401401
let expected = fcx.infcx().shallow_resolve(expected);
402-
expected.builtin_deref(true).map_or(true, |mt| match mt.ty.sty {
402+
expected.builtin_deref(true, ty::NoPreference).map_or(true, |mt| match mt.ty.sty {
403403
ty::TyTrait(_) => {
404404
// This is "x = SomeTrait" being reduced from
405405
// "let &x = &SomeTrait" or "let box x = Box<SomeTrait>", an error.

src/librustc_typeck/check/callee.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ use super::err_args;
1818
use super::Expectation;
1919
use super::expected_types_for_fn_args;
2020
use super::FnCtxt;
21-
use super::LvaluePreference;
2221
use super::method;
2322
use super::structurally_resolved_type;
2423
use super::TupleArgumentsFlag;
@@ -28,7 +27,7 @@ use super::write_call;
2827
use CrateCtxt;
2928
use middle::def_id::{DefId, LOCAL_CRATE};
3029
use middle::infer;
31-
use middle::ty::{self, Ty};
30+
use middle::ty::{self, LvaluePreference, Ty};
3231
use syntax::codemap::Span;
3332
use syntax::parse::token;
3433
use syntax::ptr::P;

src/librustc_typeck/check/coercion.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,13 @@
6060
//! sort of a minor point so I've opted to leave it for later---after all
6161
//! we may want to adjust precisely when coercions occur.
6262
63-
use check::{autoderef, FnCtxt, LvaluePreference, UnresolvedTypeAction};
63+
use check::{autoderef, FnCtxt, UnresolvedTypeAction};
6464

6565
use middle::infer::{self, Coercion};
6666
use middle::traits::{self, ObligationCause};
6767
use middle::traits::{predicate_for_trait_def, report_selection_error};
6868
use middle::ty::{AutoDerefRef, AdjustDerefRef};
69-
use middle::ty::{self, TypeAndMut, Ty, TypeError};
69+
use middle::ty::{self, LvaluePreference, TypeAndMut, Ty, TypeError};
7070
use middle::ty_relate::RelateResult;
7171
use util::common::indent;
7272

src/librustc_typeck/check/method/confirm.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@
1010

1111
use super::probe;
1212

13-
use check::{self, FnCtxt, NoPreference, PreferMutLvalue, callee, demand};
13+
use check::{self, FnCtxt, callee, demand};
1414
use check::UnresolvedTypeAction;
1515
use middle::def_id::DefId;
1616
use middle::subst::{self};
1717
use middle::traits;
18-
use middle::ty::{self, Ty};
18+
use middle::ty::{self, NoPreference, PreferMutLvalue, Ty};
1919
use middle::ty_fold::TypeFoldable;
2020
use middle::infer;
2121
use middle::infer::InferCtxt;
@@ -534,7 +534,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
534534
}
535535
Some(ty::AutoPtr(_, _)) => {
536536
(adr.autoderefs, adr.unsize.map(|target| {
537-
target.builtin_deref(false)
537+
target.builtin_deref(false, NoPreference)
538538
.expect("fixup: AutoPtr is not &T").ty
539539
}))
540540
}

src/librustc_typeck/check/method/probe.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,13 @@ use super::{CandidateSource, ImplSource, TraitSource};
1414
use super::suggest;
1515

1616
use check;
17-
use check::{FnCtxt, NoPreference, UnresolvedTypeAction};
17+
use check::{FnCtxt, UnresolvedTypeAction};
1818
use middle::def_id::DefId;
1919
use middle::fast_reject;
2020
use middle::subst;
2121
use middle::subst::Subst;
2222
use middle::traits;
23-
use middle::ty::{self, RegionEscape, Ty, ToPolyTraitRef, TraitRef};
23+
use middle::ty::{self, NoPreference, RegionEscape, Ty, ToPolyTraitRef, TraitRef};
2424
use middle::ty::HasTypeFlags;
2525
use middle::ty_fold::TypeFoldable;
2626
use middle::infer;

src/librustc_typeck/check/method/suggest.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ fn type_derefs_to_local<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
324324
}
325325

326326
check::autoderef(fcx, span, rcvr_ty, None,
327-
check::UnresolvedTypeAction::Ignore, check::NoPreference,
327+
check::UnresolvedTypeAction::Ignore, ty::NoPreference,
328328
|ty, _| {
329329
if is_local(ty) {
330330
Some(())

src/librustc_typeck/check/mod.rs

+4-19
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,6 @@ type parameter).
7676
7777
*/
7878

79-
pub use self::LvaluePreference::*;
8079
pub use self::Expectation::*;
8180
pub use self::compare_method::{compare_impl_method, compare_const_impl};
8281
use self::TupleArgumentsFlag::*;
@@ -95,6 +94,7 @@ use middle::subst::{self, Subst, Substs, VecPerParamSpace, ParamSpace, TypeSpace
9594
use middle::traits::{self, report_fulfillment_errors};
9695
use middle::ty::{FnSig, GenericPredicates, TypeScheme};
9796
use middle::ty::{Disr, ParamTy, ParameterEnvironment};
97+
use middle::ty::{LvaluePreference, NoPreference, PreferMutLvalue};
9898
use middle::ty::{self, HasTypeFlags, RegionEscape, ToPolyTraitRef, Ty};
9999
use middle::ty::{MethodCall, MethodCallee};
100100
use middle::ty_fold::{TypeFolder, TypeFoldable};
@@ -2086,21 +2086,6 @@ impl<'a, 'tcx> RegionScope for FnCtxt<'a, 'tcx> {
20862086
}
20872087
}
20882088

2089-
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
2090-
pub enum LvaluePreference {
2091-
PreferMutLvalue,
2092-
NoPreference
2093-
}
2094-
2095-
impl LvaluePreference {
2096-
pub fn from_mutbl(m: hir::Mutability) -> Self {
2097-
match m {
2098-
hir::MutMutable => PreferMutLvalue,
2099-
hir::MutImmutable => NoPreference,
2100-
}
2101-
}
2102-
}
2103-
21042089
/// Whether `autoderef` requires types to resolve.
21052090
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
21062091
pub enum UnresolvedTypeAction {
@@ -2156,7 +2141,7 @@ pub fn autoderef<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>,
21562141
}
21572142

21582143
// Otherwise, deref if type is derefable:
2159-
let mt = match resolved_t.builtin_deref(false) {
2144+
let mt = match resolved_t.builtin_deref(false, lvalue_pref) {
21602145
Some(mt) => Some(mt),
21612146
None => {
21622147
let method_call =
@@ -2245,7 +2230,7 @@ fn make_overloaded_lvalue_return_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
22452230
}
22462231

22472232
// method returns &T, but the type as visible to user is T, so deref
2248-
ret_ty.builtin_deref(true)
2233+
ret_ty.builtin_deref(true, NoPreference)
22492234
}
22502235
None => None,
22512236
}
@@ -3293,7 +3278,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
32933278
}
32943279
hir::UnDeref => {
32953280
oprnd_t = structurally_resolved_type(fcx, expr.span, oprnd_t);
3296-
oprnd_t = match oprnd_t.builtin_deref(true) {
3281+
oprnd_t = match oprnd_t.builtin_deref(true, NoPreference) {
32973282
Some(mt) => mt.ty,
32983283
None => match try_overloaded_deref(fcx, expr.span,
32993284
Some(MethodCall::expr(expr.id)),

src/librustc_typeck/check/op.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,11 @@ use super::{
1717
demand,
1818
method,
1919
FnCtxt,
20-
PreferMutLvalue,
2120
structurally_resolved_type,
2221
};
2322
use middle::def_id::DefId;
2423
use middle::traits;
25-
use middle::ty::{Ty, HasTypeFlags};
24+
use middle::ty::{Ty, HasTypeFlags, PreferMutLvalue};
2625
use syntax::ast;
2726
use syntax::parse::token;
2827
use rustc_front::hir;

src/librustc_typeck/check/regionck.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1031,7 +1031,7 @@ fn constrain_autoderefs<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>,
10311031
r_deref_expr, *r_ptr);
10321032
}
10331033

1034-
match derefd_ty.builtin_deref(true) {
1034+
match derefd_ty.builtin_deref(true, ty::NoPreference) {
10351035
Some(mt) => derefd_ty = mt.ty,
10361036
/* if this type can't be dereferenced, then there's already an error
10371037
in the session saying so. Just bail out for now */

src/test/run-pass/issue-26205.rs

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use std::ops::{Deref, DerefMut};
12+
13+
struct Foo;
14+
15+
impl Foo {
16+
fn foo_mut(&mut self) {}
17+
}
18+
19+
struct Bar(Foo);
20+
21+
impl Deref for Bar {
22+
type Target = Foo;
23+
24+
fn deref(&self) -> &Foo {
25+
&self.0
26+
}
27+
}
28+
29+
impl DerefMut for Bar {
30+
fn deref_mut(&mut self) -> &mut Foo {
31+
&mut self.0
32+
}
33+
}
34+
35+
fn test(mut bar: Box<Bar>) {
36+
bar.foo_mut();
37+
}
38+
39+
fn main() {}

0 commit comments

Comments
 (0)