librustc: Have coherence check Copy kind bounds when determining whether parameter substitutions could possibly unify. r=nmatsakis
This commit is contained in:
parent
d809e89c26
commit
732c39c183
3 changed files with 119 additions and 21 deletions
|
@ -141,7 +141,7 @@ export kind_can_be_copied, kind_can_be_sent, kind_can_be_implicitly_copied;
|
|||
export type_implicitly_moves;
|
||||
export kind_is_safe_for_default_mode;
|
||||
export kind_is_durable;
|
||||
export meta_kind, kind_lteq, type_kind;
|
||||
export meta_kind, kind_lteq, type_kind, type_kind_ext;
|
||||
export operators;
|
||||
export type_err, terr_vstore_kind;
|
||||
export terr_mismatch, terr_onceness_mismatch;
|
||||
|
@ -2101,6 +2101,12 @@ fn mutable_type_kind(cx: ctxt, ty: mt) -> Kind {
|
|||
}
|
||||
|
||||
fn type_kind(cx: ctxt, ty: t) -> Kind {
|
||||
type_kind_ext(cx, ty, false)
|
||||
}
|
||||
|
||||
// If `allow_ty_var` is true, then this is a conservative assumption; we
|
||||
// assume that type variables *do* have all kinds.
|
||||
fn type_kind_ext(cx: ctxt, ty: t, allow_ty_var: bool) -> Kind {
|
||||
match cx.kind_cache.find(ty) {
|
||||
Some(result) => return result,
|
||||
None => {/* fall through */ }
|
||||
|
@ -2135,7 +2141,12 @@ fn type_kind(cx: ctxt, ty: t) -> Kind {
|
|||
}
|
||||
|
||||
// Trait instances are (for now) like shared boxes, basically
|
||||
<<<<<<< HEAD
|
||||
ty_trait(_, _, _) => kind_safe_for_default_mode() | kind_durable(),
|
||||
=======
|
||||
// XXX: This is wrong for ~Trait and &Trait!
|
||||
ty_trait(_, _, _) => kind_safe_for_default_mode() | kind_owned(),
|
||||
>>>>>>> librustc: Have coherence check Copy kind bounds when determining whether parameter substitutions could possibly unify. r=nmatsakis
|
||||
|
||||
// Static region pointers are copyable and sendable, but not owned
|
||||
ty_rptr(re_static, mt) =>
|
||||
|
@ -2249,8 +2260,13 @@ fn type_kind(cx: ctxt, ty: t) -> Kind {
|
|||
ty_self => kind_noncopyable(),
|
||||
|
||||
ty_infer(_) => {
|
||||
cx.sess.bug(~"Asked to compute kind of a type variable");
|
||||
if allow_ty_var {
|
||||
kind_top()
|
||||
} else {
|
||||
cx.sess.bug(~"Asked to compute kind of a type variable")
|
||||
}
|
||||
}
|
||||
|
||||
ty_type | ty_opaque_closure_ptr(_)
|
||||
| ty_opaque_box | ty_unboxed_vec(_) | ty_err => {
|
||||
cx.sess.bug(~"Asked to compute kind of fictitious type");
|
||||
|
|
|
@ -19,16 +19,17 @@ use metadata::csearch::{get_impls_for_mod};
|
|||
use metadata::cstore::{CStore, iter_crate_data};
|
||||
use metadata::decoder::{dl_def, dl_field, dl_impl};
|
||||
use middle::resolve::{Impl, MethodInfo};
|
||||
use middle::ty::{ProvidedMethodSource,
|
||||
ProvidedMethodInfo, get};
|
||||
use middle::ty::{lookup_item_type, subst, t, ty_bot, ty_box, ty_struct};
|
||||
use middle::ty::{ty_bool, ty_enum, ty_int, ty_nil, ty_ptr, ty_rptr, ty_uint};
|
||||
use middle::ty::{ty_float, ty_estr, ty_evec, ty_rec, ty_uniq};
|
||||
use middle::ty::{ty_err, ty_fn, ty_trait, ty_tup, ty_infer};
|
||||
use middle::ty::{ty_param, ty_self, ty_type, ty_opaque_box};
|
||||
use middle::ty::{ty_opaque_closure_ptr, ty_unboxed_vec, type_is_ty_var};
|
||||
use middle::ty::{ProvidedMethodSource, ProvidedMethodInfo, bound_copy, get};
|
||||
use middle::ty::{kind_can_be_copied, lookup_item_type, param_bounds, subst};
|
||||
use middle::ty::{t, ty_bool, ty_bot, ty_box, ty_enum, ty_err, ty_estr};
|
||||
use middle::ty::{ty_evec, ty_float, ty_fn, ty_infer, ty_int, ty_nil, ty_ptr};
|
||||
use middle::ty::{ty_rec, ty_rptr, ty_struct, ty_trait, ty_tup, ty_uint};
|
||||
use middle::ty::{ty_param, ty_self, ty_type, ty_opaque_box, ty_uniq};
|
||||
use middle::ty::{ty_opaque_closure_ptr, ty_unboxed_vec, type_kind_ext};
|
||||
use middle::ty::{type_is_ty_var};
|
||||
use middle::typeck::infer::{infer_ctxt, can_mk_subty};
|
||||
use middle::typeck::infer::{new_infer_ctxt, resolve_ivar, resolve_type};
|
||||
use middle::typeck::infer::{new_infer_ctxt, resolve_ivar};
|
||||
use middle::typeck::infer::{resolve_nested_tvar, resolve_type};
|
||||
use syntax::ast::{crate, def_id, def_mod, def_ty};
|
||||
use syntax::ast::{item, item_struct, item_const, item_enum, item_fn};
|
||||
use syntax::ast::{item_foreign_mod, item_impl, item_mac, item_mod};
|
||||
|
@ -49,6 +50,12 @@ use std::map::HashMap;
|
|||
use core::uint::range;
|
||||
use core::vec::{len, push};
|
||||
|
||||
struct UniversalQuantificationResult {
|
||||
monotype: t,
|
||||
type_variables: ~[ty::t],
|
||||
bounds: @~[param_bounds]
|
||||
}
|
||||
|
||||
fn get_base_type(inference_context: infer_ctxt, span: span, original_type: t)
|
||||
-> Option<t> {
|
||||
|
||||
|
@ -465,19 +472,21 @@ impl CoherenceChecker {
|
|||
fn polytypes_unify(polytype_a: ty_param_bounds_and_ty,
|
||||
polytype_b: ty_param_bounds_and_ty)
|
||||
-> bool {
|
||||
let universally_quantified_a =
|
||||
self.universally_quantify_polytype(polytype_a);
|
||||
let universally_quantified_b =
|
||||
self.universally_quantify_polytype(polytype_b);
|
||||
|
||||
let monotype_a = self.universally_quantify_polytype(polytype_a);
|
||||
let monotype_b = self.universally_quantify_polytype(polytype_b);
|
||||
return can_mk_subty(self.inference_context,
|
||||
monotype_a, monotype_b).is_ok()
|
||||
|| can_mk_subty(self.inference_context,
|
||||
monotype_b, monotype_a).is_ok();
|
||||
return self.can_unify_universally_quantified(
|
||||
&universally_quantified_a, &universally_quantified_b) ||
|
||||
self.can_unify_universally_quantified(
|
||||
&universally_quantified_b, &universally_quantified_a);
|
||||
}
|
||||
|
||||
// Converts a polytype to a monotype by replacing all parameters with
|
||||
// type variables.
|
||||
|
||||
fn universally_quantify_polytype(polytype: ty_param_bounds_and_ty) -> t {
|
||||
// type variables. Returns the monotype and the type variables created.
|
||||
fn universally_quantify_polytype(polytype: ty_param_bounds_and_ty)
|
||||
-> UniversalQuantificationResult {
|
||||
// NDM--this span is bogus.
|
||||
let self_region =
|
||||
polytype.region_param.map(
|
||||
|
@ -493,7 +502,67 @@ impl CoherenceChecker {
|
|||
tps: type_parameters
|
||||
};
|
||||
|
||||
return subst(self.crate_context.tcx, &substitutions, polytype.ty);
|
||||
let monotype = subst(self.crate_context.tcx,
|
||||
&substitutions,
|
||||
polytype.ty);
|
||||
UniversalQuantificationResult {
|
||||
monotype: monotype,
|
||||
type_variables: move type_parameters,
|
||||
bounds: polytype.bounds
|
||||
}
|
||||
}
|
||||
|
||||
fn can_unify_universally_quantified(a: &a/UniversalQuantificationResult,
|
||||
b: &a/UniversalQuantificationResult)
|
||||
-> bool {
|
||||
let mut might_unify = true;
|
||||
let _ = do self.inference_context.probe {
|
||||
let result = self.inference_context.sub(true, dummy_sp())
|
||||
.tys(a.monotype, b.monotype);
|
||||
if result.is_ok() {
|
||||
// Check to ensure that each parameter binding respected its
|
||||
// kind bounds.
|
||||
for [ a, b ].each |result| {
|
||||
for vec::each2(result.type_variables, *result.bounds)
|
||||
|ty_var, bounds| {
|
||||
match resolve_type(self.inference_context,
|
||||
*ty_var,
|
||||
resolve_nested_tvar) {
|
||||
Ok(resolved_ty) => {
|
||||
for bounds.each |bound| {
|
||||
match *bound {
|
||||
bound_copy => {
|
||||
let kind = type_kind_ext(
|
||||
self.inference_context.tcx,
|
||||
resolved_ty,
|
||||
true);
|
||||
if !kind_can_be_copied(kind) {
|
||||
might_unify = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: We could be smarter here.
|
||||
// Check to see whether owned, send,
|
||||
// const, trait param bounds could
|
||||
// possibly unify.
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(*) => {
|
||||
// Conservatively assume it might unify.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
might_unify = false;
|
||||
}
|
||||
|
||||
result
|
||||
};
|
||||
might_unify
|
||||
}
|
||||
|
||||
fn get_self_type_for_implementation(implementation: @Impl)
|
||||
|
|
13
src/test/run-pass/coherence-copy-bound.rs
Normal file
13
src/test/run-pass/coherence-copy-bound.rs
Normal file
|
@ -0,0 +1,13 @@
|
|||
trait X {}
|
||||
|
||||
impl<A:Copy> A : X {}
|
||||
|
||||
struct S {
|
||||
x: int,
|
||||
drop {}
|
||||
}
|
||||
|
||||
impl S : X {}
|
||||
|
||||
fn main(){}
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue