Change method lookup to require invariance for mutable references

Fixes #17033.
Fixes #15965.
This commit is contained in:
Jakub Wieczorek 2014-09-09 02:15:30 +02:00
parent 504ed55775
commit 28bc56828f
5 changed files with 69 additions and 6 deletions

View File

@ -348,6 +348,7 @@ struct Candidate {
pub enum RcvrMatchCondition {
RcvrMatchesIfObject(ast::DefId),
RcvrMatchesIfSubtype(ty::t),
RcvrMatchesIfEqtype(ty::t)
}
impl<'a, 'tcx> LookupContext<'a, 'tcx> {
@ -675,6 +676,14 @@ impl<'a, 'tcx> LookupContext<'a, 'tcx> {
}
_ => {}
}
let condition = match m.explicit_self {
ByReferenceExplicitSelfCategory(_, mt) if mt == MutMutable =>
RcvrMatchesIfEqtype(self_ty),
_ =>
RcvrMatchesIfSubtype(self_ty)
};
debug!("found match: trait_ref={} substs={} m={}",
trait_ref.repr(this.tcx()),
trait_ref.substs.repr(this.tcx()),
@ -688,7 +697,7 @@ impl<'a, 'tcx> LookupContext<'a, 'tcx> {
assert_eq!(m.generics.regions.get_slice(subst::SelfSpace).len(),
trait_ref.substs.regions().get_slice(subst::SelfSpace).len());
Some(Candidate {
rcvr_match_condition: RcvrMatchesIfSubtype(self_ty),
rcvr_match_condition: condition,
rcvr_substs: trait_ref.substs.clone(),
method_ty: m,
origin: MethodParam(MethodParam {
@ -822,6 +831,13 @@ impl<'a, 'tcx> LookupContext<'a, 'tcx> {
ty: impl_ty
} = impl_self_ty(&vcx, span, impl_did);
let condition = match method.explicit_self {
ByReferenceExplicitSelfCategory(_, mt) if mt == MutMutable =>
RcvrMatchesIfEqtype(impl_ty),
_ =>
RcvrMatchesIfSubtype(impl_ty)
};
let candidates = if is_extension {
&mut self.extension_candidates
} else {
@ -829,7 +845,7 @@ impl<'a, 'tcx> LookupContext<'a, 'tcx> {
};
candidates.push(Candidate {
rcvr_match_condition: RcvrMatchesIfSubtype(impl_ty),
rcvr_match_condition: condition,
rcvr_substs: impl_substs,
origin: MethodStatic(method.def_id),
method_ty: method,
@ -1525,7 +1541,7 @@ impl<'a, 'tcx> LookupContext<'a, 'tcx> {
RcvrMatchesIfObject(desired_did) => {
self_did == desired_did
}
RcvrMatchesIfSubtype(_) => {
RcvrMatchesIfSubtype(_) | RcvrMatchesIfEqtype(_) => {
false
}
}
@ -1541,6 +1557,9 @@ impl<'a, 'tcx> LookupContext<'a, 'tcx> {
RcvrMatchesIfSubtype(of_type) => {
fcx.can_mk_subty(rcvr_ty, of_type).is_ok()
}
RcvrMatchesIfEqtype(of_type) => {
fcx.can_mk_eqty(rcvr_ty, of_type).is_ok()
}
}
}
@ -1656,9 +1675,9 @@ impl Repr for RcvrMatchCondition {
RcvrMatchesIfSubtype(t) => {
format!("RcvrMatchesIfSubtype({})", t.repr(tcx))
}
RcvrMatchesIfEqtype(t) => {
format!("RcvrMatchesIfEqtype({})", t.repr(tcx))
}
}
}
}

View File

@ -1740,6 +1740,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
infer::can_mk_subty(self.infcx(), sub, sup)
}
pub fn can_mk_eqty(&self, sub: ty::t, sup: ty::t)
-> Result<(), ty::type_err> {
infer::can_mk_eqty(self.infcx(), sub, sup)
}
pub fn mk_assignty(&self,
expr: &ast::Expr,
sub: ty::t,

View File

@ -362,6 +362,17 @@ pub fn can_mk_subty(cx: &InferCtxt, a: ty::t, b: ty::t) -> ures {
}).to_ures()
}
pub fn can_mk_eqty(cx: &InferCtxt, a: ty::t, b: ty::t) -> ures {
debug!("can_mk_subty({} <: {})", a.repr(cx.tcx), b.repr(cx.tcx));
cx.probe(|| {
let trace = TypeTrace {
origin: Misc(codemap::DUMMY_SP),
values: Types(expected_found(true, a, b))
};
cx.equate(true, trace).tys(a, b)
}).to_ures()
}
pub fn mk_subr(cx: &InferCtxt,
origin: SubregionOrigin,
a: ty::Region,

View File

@ -0,0 +1,13 @@
// Copyright 2014 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.
fn main() {
return { return () } (); //~ ERROR expected function, found `!`
}

View File

@ -0,0 +1,15 @@
// Copyright 2014 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.
fn f<'r>(p: &'r mut fn(p: &mut ())) {
p(()) //~ ERROR expected function, found `&'r mut fn(&mut ())`
}
fn main() {}