Skip to content

Commit 732c39c

Browse files
committed
librustc: Have coherence check Copy kind bounds when determining whether parameter substitutions could possibly unify. r=nmatsakis
1 parent d809e89 commit 732c39c

File tree

3 files changed

+120
-22
lines changed

3 files changed

+120
-22
lines changed

src/librustc/middle/ty.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ export kind_can_be_copied, kind_can_be_sent, kind_can_be_implicitly_copied;
141141
export type_implicitly_moves;
142142
export kind_is_safe_for_default_mode;
143143
export kind_is_durable;
144-
export meta_kind, kind_lteq, type_kind;
144+
export meta_kind, kind_lteq, type_kind, type_kind_ext;
145145
export operators;
146146
export type_err, terr_vstore_kind;
147147
export terr_mismatch, terr_onceness_mismatch;
@@ -2101,6 +2101,12 @@ fn mutable_type_kind(cx: ctxt, ty: mt) -> Kind {
21012101
}
21022102
21032103
fn type_kind(cx: ctxt, ty: t) -> Kind {
2104+
type_kind_ext(cx, ty, false)
2105+
}
2106+
2107+
// If `allow_ty_var` is true, then this is a conservative assumption; we
2108+
// assume that type variables *do* have all kinds.
2109+
fn type_kind_ext(cx: ctxt, ty: t, allow_ty_var: bool) -> Kind {
21042110
match cx.kind_cache.find(ty) {
21052111
Some(result) => return result,
21062112
None => {/* fall through */ }
@@ -2135,7 +2141,12 @@ fn type_kind(cx: ctxt, ty: t) -> Kind {
21352141
}
21362142
21372143
// Trait instances are (for now) like shared boxes, basically
2144+
<<<<<<< HEAD
21382145
ty_trait(_, _, _) => kind_safe_for_default_mode() | kind_durable(),
2146+
=======
2147+
// XXX: This is wrong for ~Trait and &Trait!
2148+
ty_trait(_, _, _) => kind_safe_for_default_mode() | kind_owned(),
2149+
>>>>>>> librustc: Have coherence check Copy kind bounds when determining whether parameter substitutions could possibly unify. r=nmatsakis
21392150
21402151
// Static region pointers are copyable and sendable, but not owned
21412152
ty_rptr(re_static, mt) =>
@@ -2249,8 +2260,13 @@ fn type_kind(cx: ctxt, ty: t) -> Kind {
22492260
ty_self => kind_noncopyable(),
22502261
22512262
ty_infer(_) => {
2252-
cx.sess.bug(~"Asked to compute kind of a type variable");
2263+
if allow_ty_var {
2264+
kind_top()
2265+
} else {
2266+
cx.sess.bug(~"Asked to compute kind of a type variable")
2267+
}
22532268
}
2269+
22542270
ty_type | ty_opaque_closure_ptr(_)
22552271
| ty_opaque_box | ty_unboxed_vec(_) | ty_err => {
22562272
cx.sess.bug(~"Asked to compute kind of fictitious type");

src/librustc/middle/typeck/coherence.rs

Lines changed: 89 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,17 @@ use metadata::csearch::{get_impls_for_mod};
1919
use metadata::cstore::{CStore, iter_crate_data};
2020
use metadata::decoder::{dl_def, dl_field, dl_impl};
2121
use middle::resolve::{Impl, MethodInfo};
22-
use middle::ty::{ProvidedMethodSource,
23-
ProvidedMethodInfo, get};
24-
use middle::ty::{lookup_item_type, subst, t, ty_bot, ty_box, ty_struct};
25-
use middle::ty::{ty_bool, ty_enum, ty_int, ty_nil, ty_ptr, ty_rptr, ty_uint};
26-
use middle::ty::{ty_float, ty_estr, ty_evec, ty_rec, ty_uniq};
27-
use middle::ty::{ty_err, ty_fn, ty_trait, ty_tup, ty_infer};
28-
use middle::ty::{ty_param, ty_self, ty_type, ty_opaque_box};
29-
use middle::ty::{ty_opaque_closure_ptr, ty_unboxed_vec, type_is_ty_var};
22+
use middle::ty::{ProvidedMethodSource, ProvidedMethodInfo, bound_copy, get};
23+
use middle::ty::{kind_can_be_copied, lookup_item_type, param_bounds, subst};
24+
use middle::ty::{t, ty_bool, ty_bot, ty_box, ty_enum, ty_err, ty_estr};
25+
use middle::ty::{ty_evec, ty_float, ty_fn, ty_infer, ty_int, ty_nil, ty_ptr};
26+
use middle::ty::{ty_rec, ty_rptr, ty_struct, ty_trait, ty_tup, ty_uint};
27+
use middle::ty::{ty_param, ty_self, ty_type, ty_opaque_box, ty_uniq};
28+
use middle::ty::{ty_opaque_closure_ptr, ty_unboxed_vec, type_kind_ext};
29+
use middle::ty::{type_is_ty_var};
3030
use middle::typeck::infer::{infer_ctxt, can_mk_subty};
31-
use middle::typeck::infer::{new_infer_ctxt, resolve_ivar, resolve_type};
31+
use middle::typeck::infer::{new_infer_ctxt, resolve_ivar};
32+
use middle::typeck::infer::{resolve_nested_tvar, resolve_type};
3233
use syntax::ast::{crate, def_id, def_mod, def_ty};
3334
use syntax::ast::{item, item_struct, item_const, item_enum, item_fn};
3435
use syntax::ast::{item_foreign_mod, item_impl, item_mac, item_mod};
@@ -49,6 +50,12 @@ use std::map::HashMap;
4950
use core::uint::range;
5051
use core::vec::{len, push};
5152

53+
struct UniversalQuantificationResult {
54+
monotype: t,
55+
type_variables: ~[ty::t],
56+
bounds: @~[param_bounds]
57+
}
58+
5259
fn get_base_type(inference_context: infer_ctxt, span: span, original_type: t)
5360
-> Option<t> {
5461

@@ -465,19 +472,21 @@ impl CoherenceChecker {
465472
fn polytypes_unify(polytype_a: ty_param_bounds_and_ty,
466473
polytype_b: ty_param_bounds_and_ty)
467474
-> bool {
468-
469-
let monotype_a = self.universally_quantify_polytype(polytype_a);
470-
let monotype_b = self.universally_quantify_polytype(polytype_b);
471-
return can_mk_subty(self.inference_context,
472-
monotype_a, monotype_b).is_ok()
473-
|| can_mk_subty(self.inference_context,
474-
monotype_b, monotype_a).is_ok();
475+
let universally_quantified_a =
476+
self.universally_quantify_polytype(polytype_a);
477+
let universally_quantified_b =
478+
self.universally_quantify_polytype(polytype_b);
479+
480+
return self.can_unify_universally_quantified(
481+
&universally_quantified_a, &universally_quantified_b) ||
482+
self.can_unify_universally_quantified(
483+
&universally_quantified_b, &universally_quantified_a);
475484
}
476485

477486
// Converts a polytype to a monotype by replacing all parameters with
478-
// type variables.
479-
480-
fn universally_quantify_polytype(polytype: ty_param_bounds_and_ty) -> t {
487+
// type variables. Returns the monotype and the type variables created.
488+
fn universally_quantify_polytype(polytype: ty_param_bounds_and_ty)
489+
-> UniversalQuantificationResult {
481490
// NDM--this span is bogus.
482491
let self_region =
483492
polytype.region_param.map(
@@ -493,7 +502,67 @@ impl CoherenceChecker {
493502
tps: type_parameters
494503
};
495504

496-
return subst(self.crate_context.tcx, &substitutions, polytype.ty);
505+
let monotype = subst(self.crate_context.tcx,
506+
&substitutions,
507+
polytype.ty);
508+
UniversalQuantificationResult {
509+
monotype: monotype,
510+
type_variables: move type_parameters,
511+
bounds: polytype.bounds
512+
}
513+
}
514+
515+
fn can_unify_universally_quantified(a: &a/UniversalQuantificationResult,
516+
b: &a/UniversalQuantificationResult)
517+
-> bool {
518+
let mut might_unify = true;
519+
let _ = do self.inference_context.probe {
520+
let result = self.inference_context.sub(true, dummy_sp())
521+
.tys(a.monotype, b.monotype);
522+
if result.is_ok() {
523+
// Check to ensure that each parameter binding respected its
524+
// kind bounds.
525+
for [ a, b ].each |result| {
526+
for vec::each2(result.type_variables, *result.bounds)
527+
|ty_var, bounds| {
528+
match resolve_type(self.inference_context,
529+
*ty_var,
530+
resolve_nested_tvar) {
531+
Ok(resolved_ty) => {
532+
for bounds.each |bound| {
533+
match *bound {
534+
bound_copy => {
535+
let kind = type_kind_ext(
536+
self.inference_context.tcx,
537+
resolved_ty,
538+
true);
539+
if !kind_can_be_copied(kind) {
540+
might_unify = false;
541+
break;
542+
}
543+
}
544+
545+
// XXX: We could be smarter here.
546+
// Check to see whether owned, send,
547+
// const, trait param bounds could
548+
// possibly unify.
549+
_ => {}
550+
}
551+
}
552+
}
553+
Err(*) => {
554+
// Conservatively assume it might unify.
555+
}
556+
}
557+
}
558+
}
559+
} else {
560+
might_unify = false;
561+
}
562+
563+
result
564+
};
565+
might_unify
497566
}
498567

499568
fn get_self_type_for_implementation(implementation: @Impl)
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
trait X {}
2+
3+
impl<A:Copy> A : X {}
4+
5+
struct S {
6+
x: int,
7+
drop {}
8+
}
9+
10+
impl S : X {}
11+
12+
fn main(){}
13+

0 commit comments

Comments
 (0)