Change method lookup to require invariance for mutable references
Fixes #17033. Fixes #15965.
This commit is contained in:
parent
504ed55775
commit
28bc56828f
@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
13
src/test/compile-fail/issue-15965.rs
Normal file
13
src/test/compile-fail/issue-15965.rs
Normal 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 `!`
|
||||
}
|
15
src/test/compile-fail/issue-17033.rs
Normal file
15
src/test/compile-fail/issue-17033.rs
Normal 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() {}
|
Loading…
Reference in New Issue
Block a user