Partial fix for #2687---impl method must only be subtype of trait method, not exact match.
This commit is contained in:
parent
2ab614f356
commit
2093952847
@ -288,15 +288,10 @@ fn compare_impl_method(tcx: ty::ctxt,
|
||||
|
||||
let impl_m = &cm.mty;
|
||||
|
||||
if impl_m.fty.meta.purity != trait_m.fty.meta.purity {
|
||||
tcx.sess.span_err(
|
||||
cm.span,
|
||||
fmt!("method `%s`'s purity does \
|
||||
not match the trait method's \
|
||||
purity", tcx.sess.str_of(impl_m.ident)));
|
||||
}
|
||||
|
||||
// is this check right?
|
||||
// FIXME(#2687)---this check is too strict. For example, a trait
|
||||
// method with self type `&self` or `&mut self` should be
|
||||
// implementable by an `&const self` method (the impl assumes less
|
||||
// than the trait provides).
|
||||
if impl_m.self_ty != trait_m.self_ty {
|
||||
tcx.sess.span_err(
|
||||
cm.span,
|
||||
@ -328,6 +323,9 @@ fn compare_impl_method(tcx: ty::ctxt,
|
||||
return;
|
||||
}
|
||||
|
||||
// FIXME(#2687)---we should be checking that the bounds of the
|
||||
// trait imply the bounds of the subtype, but it appears
|
||||
// we are...not checking this.
|
||||
for trait_m.tps.eachi() |i, trait_param_bounds| {
|
||||
// For each of the corresponding impl ty param's bounds...
|
||||
let impl_param_bounds = impl_m.tps[i];
|
||||
@ -389,11 +387,19 @@ fn compare_impl_method(tcx: ty::ctxt,
|
||||
debug!("trait_fty (pre-subst): %s", ty_to_str(tcx, trait_fty));
|
||||
ty::subst(tcx, &substs, trait_fty)
|
||||
};
|
||||
debug!("trait_fty: %s", ty_to_str(tcx, trait_fty));
|
||||
require_same_types(
|
||||
tcx, None, false, cm.span, impl_fty, trait_fty,
|
||||
|| fmt!("method `%s` has an incompatible type",
|
||||
tcx.sess.str_of(trait_m.ident)));
|
||||
|
||||
let infcx = infer::new_infer_ctxt(tcx);
|
||||
match infer::mk_subty(infcx, false, cm.span, impl_fty, trait_fty) {
|
||||
result::Ok(()) => {}
|
||||
result::Err(ref terr) => {
|
||||
tcx.sess.span_err(
|
||||
cm.span,
|
||||
fmt!("method `%s` has an incompatible type: %s",
|
||||
tcx.sess.str_of(trait_m.ident),
|
||||
ty::type_err_to_str(tcx, terr)));
|
||||
ty::note_and_explain_type_err(tcx, terr);
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
||||
// Replaces bound references to the self region with `with_r`.
|
||||
|
25
src/test/compile-fail/trait-impl-method-mismatch.rs
Normal file
25
src/test/compile-fail/trait-impl-method-mismatch.rs
Normal file
@ -0,0 +1,25 @@
|
||||
trait Mumbo {
|
||||
pure fn jumbo(&self, x: @uint) -> uint;
|
||||
fn jambo(&self, x: @const uint) -> uint;
|
||||
fn jbmbo(&self) -> @uint;
|
||||
}
|
||||
|
||||
impl uint: Mumbo {
|
||||
// Cannot have a larger effect than the trait:
|
||||
fn jumbo(&self, x: @uint) { *self + *x; }
|
||||
//~^ ERROR expected pure fn but found impure fn
|
||||
|
||||
// Cannot accept a narrower range of parameters:
|
||||
fn jambo(&self, x: @uint) { *self + *x; }
|
||||
//~^ ERROR values differ in mutability
|
||||
|
||||
// Cannot return a wider range of values:
|
||||
fn jbmbo(&self) -> @const uint { @const 0 }
|
||||
//~^ ERROR values differ in mutability
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
||||
|
||||
|
||||
|
21
src/test/compile-fail/trait-impl-subtype.rs
Normal file
21
src/test/compile-fail/trait-impl-subtype.rs
Normal file
@ -0,0 +1,21 @@
|
||||
trait Mumbo {
|
||||
fn jumbo(&self, x: @uint) -> uint;
|
||||
}
|
||||
|
||||
impl uint: Mumbo {
|
||||
// Note: this method def is ok, it is more accepting and
|
||||
// less effecting than the trait method:
|
||||
pure fn jumbo(&self, x: @const uint) -> uint { *self + *x }
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let a = 3u;
|
||||
let b = a.jumbo(@mut 6);
|
||||
|
||||
let x = @a as @Mumbo;
|
||||
let y = x.jumbo(@mut 6); //~ ERROR values differ in mutability
|
||||
let z = x.jumbo(@6);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user