Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rustc: Implement ~Trait #3894

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/rustc/middle/borrowck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -594,7 +594,7 @@ impl borrowck_ctxt {
// mutable structure.
fn inherent_mutability(ck: comp_kind) -> mutability {
match ck {
comp_tuple | comp_variant(_) => m_imm,
comp_field(_, m) | comp_index(_, m) => m
comp_tuple | comp_anon_field | comp_variant(_) => m_imm,
comp_field(_, m) | comp_index(_, m) => m
}
}
7 changes: 4 additions & 3 deletions src/rustc/middle/borrowck/gather_loans.rs
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,8 @@ impl gather_loan_ctxt {
alt_id: ast::node_id) {
do self.bccx.cat_pattern(discr_cmt, root_pat) |cmt, pat| {
match pat.node {
ast::pat_ident(bm, _, _) if !self.pat_is_variant(pat) => {
ast::pat_ident(bm, _, _)
if !self.pat_is_variant_or_struct(pat) => {
match bm {
ast::bind_by_value | ast::bind_by_move => {
// copying does not borrow anything, so no check
Expand Down Expand Up @@ -492,8 +493,8 @@ impl gather_loan_ctxt {
}
}

fn pat_is_variant(&self, pat: @ast::pat) -> bool {
pat_util::pat_is_variant(self.bccx.tcx.def_map, pat)
fn pat_is_variant_or_struct(&self, pat: @ast::pat) -> bool {
pat_util::pat_is_variant_or_struct(self.bccx.tcx.def_map, pat)
}
}

3 changes: 2 additions & 1 deletion src/rustc/middle/borrowck/loan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,8 @@ impl LoanContext {
// overwritten and the component along with it.
self.loan_stable_comp(cmt, cmt_base, req_mutbl, m)
}
cat_comp(cmt_base, comp_tuple) => {
cat_comp(cmt_base, comp_tuple) |
cat_comp(cmt_base, comp_anon_field) => {
// As above.
self.loan_stable_comp(cmt, cmt_base, req_mutbl, m_imm)
}
Expand Down
3 changes: 2 additions & 1 deletion src/rustc/middle/borrowck/preserve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,8 @@ priv impl &preserve_ctxt {
}
cat_comp(cmt_base, comp_field(*)) |
cat_comp(cmt_base, comp_index(*)) |
cat_comp(cmt_base, comp_tuple) => {
cat_comp(cmt_base, comp_tuple) |
cat_comp(cmt_base, comp_anon_field) => {
// Most embedded components: if the base is stable, the
// type never changes.
self.preserve(cmt_base)
Expand Down
9 changes: 9 additions & 0 deletions src/rustc/middle/check_alt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,15 @@ fn specialize(tcx: ty::ctxt, r: ~[@pat], ctor_id: ctor, arity: uint,
Some(vec::append(args, vec::tail(r)))
}
def_variant(_, _) => None,
def_class(*) => {
// XXX: Is this right? --pcw
let new_args;
match args {
Some(args) => new_args = args,
None => new_args = vec::from_elem(arity, wild())
}
Some(vec::append(new_args, vec::tail(r)))
}
_ => None
}
}
Expand Down
21 changes: 21 additions & 0 deletions src/rustc/middle/kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,7 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) {
maybe_copy(cx, source, Some(("casted values must be copyable",
try_adding)));
check_cast_for_escaping_regions(cx, source, e);
check_kind_bounds_of_cast(cx, source, e);
}
expr_copy(expr) => check_copy_ex(cx, expr, false,
Some(("explicit copy requires a copyable argument", ""))),
Expand Down Expand Up @@ -607,6 +608,26 @@ fn check_cast_for_escaping_regions(
}
}

/// Ensures that values placed into a ~Trait are copyable and sendable.
fn check_kind_bounds_of_cast(cx: ctx, source: @expr, target: @expr) {
let target_ty = ty::expr_ty(cx.tcx, target);
match ty::get(target_ty).sty {
ty::ty_trait(_, _, ty::vstore_uniq) => {
let source_ty = ty::expr_ty(cx.tcx, source);
let source_kind = ty::type_kind(cx.tcx, source_ty);
if !ty::kind_can_be_copied(source_kind) {
cx.tcx.sess.span_err(target.span,
~"uniquely-owned trait objects must be copyable");
}
if !ty::kind_can_be_sent(source_kind) {
cx.tcx.sess.span_err(target.span,
~"uniquely-owned trait objects must be sendable");
}
}
_ => {} // Nothing to do.
}
}

//
// Local Variables:
// mode: rust
Expand Down
48 changes: 38 additions & 10 deletions src/rustc/middle/mem_categorization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,8 @@ impl ptr_kind : cmp::Eq {
// structure accessible without a dereference":
enum comp_kind {
comp_tuple, // elt in a tuple
comp_anon_field, // anonymous field (in e.g.
// struct Foo(int, int);
comp_variant(ast::def_id), // internals to a variant of given enum
comp_field(ast::ident, // name of field
ast::mutability), // declared mutability of field
Expand All @@ -178,6 +180,12 @@ impl comp_kind : cmp::Eq {
_ => false
}
}
comp_anon_field => {
match (*other) {
comp_anon_field => true,
_ => false
}
}
comp_variant(e0a) => {
match (*other) {
comp_variant(e0b) => e0a == e0b,
Expand Down Expand Up @@ -773,6 +781,14 @@ impl &mem_categorization_ctxt {
ty: self.tcx.ty(elt)}
}

fn cat_anon_struct_field<N: ast_node>(elt: N, cmt: cmt) -> cmt {
@{id: elt.id(), span: elt.span(),
cat: cat_comp(cmt, comp_anon_field),
lp: cmt.lp.map(|l| @lp_comp(*l, comp_anon_field)),
mutbl: cmt.mutbl, // imm iff in an immutable context
ty: self.tcx.ty(elt)}
}

fn cat_method_ref(expr: @ast::expr, expr_ty: ty::t) -> cmt {
@{id:expr.id, span:expr.span,
cat:cat_special(sk_method), lp:None,
Expand Down Expand Up @@ -832,16 +848,26 @@ impl &mem_categorization_ctxt {
// variant(*)
}
ast::pat_enum(_, Some(subpats)) => {
// variant(x, y, z)
let enum_did = match self.tcx.def_map.find(pat.id) {
Some(ast::def_variant(enum_did, _)) => enum_did,
e => tcx.sess.span_bug(pat.span,
fmt!("resolved to %?, not variant", e))
};

for subpats.each |subpat| {
let subcmt = self.cat_variant(*subpat, enum_did, cmt);
self.cat_pattern(subcmt, *subpat, op);
match self.tcx.def_map.find(pat.id) {
Some(ast::def_variant(enum_did, _)) => {
// variant(x, y, z)
for subpats.each |subpat| {
let subcmt = self.cat_variant(*subpat, enum_did, cmt);
self.cat_pattern(subcmt, *subpat, op);
}
}
Some(ast::def_class(*)) => {
for subpats.each |subpat| {
let cmt_field = self.cat_anon_struct_field(*subpat,
cmt);
self.cat_pattern(cmt_field, *subpat, op);
}
}
_ => {
self.tcx.sess.span_bug(
pat.span,
~"enum pattern didn't resolve to enum or struct");
}
}
}

Expand Down Expand Up @@ -932,6 +958,7 @@ impl &mem_categorization_ctxt {
comp_field(fld, _) => self.tcx.sess.str_of(fld),
comp_index(*) => ~"[]",
comp_tuple => ~"()",
comp_anon_field => ~"<anonymous field>",
comp_variant(_) => ~"<enum>"
}
}
Expand Down Expand Up @@ -984,6 +1011,7 @@ impl &mem_categorization_ctxt {
}
cat_comp(_, comp_field(*)) => mut_str + ~" field",
cat_comp(_, comp_tuple) => ~"tuple content",
cat_comp(_, comp_anon_field) => ~"anonymous field",
cat_comp(_, comp_variant(_)) => ~"enum content",
cat_comp(_, comp_index(t, _)) => {
match ty::get(t).sty {
Expand Down
20 changes: 11 additions & 9 deletions src/rustc/middle/pat_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use syntax::codemap::span;
use std::map::HashMap;

export pat_binding_ids, pat_bindings, pat_id_map, PatIdMap;
export pat_is_variant, pat_is_binding_or_wild;
export pat_is_variant_or_struct, pat_is_binding_or_wild;

type PatIdMap = std::map::HashMap<ident, node_id>;

Expand All @@ -21,20 +21,21 @@ fn pat_id_map(dm: resolve::DefMap, pat: @pat) -> PatIdMap {
return map;
}

fn pat_is_variant(dm: resolve::DefMap, pat: @pat) -> bool {
fn pat_is_variant_or_struct(dm: resolve::DefMap, pat: @pat) -> bool {
match pat.node {
pat_enum(_, _) => true,
pat_ident(_, _, None) | pat_struct(*) => match dm.find(pat.id) {
Some(def_variant(_, _)) => true,
pat_enum(_, _) | pat_ident(_, _, None) | pat_struct(*) => {
match dm.find(pat.id) {
Some(def_variant(*)) | Some(def_class(*)) => true,
_ => false
}
}
_ => false
},
_ => false
}
}

fn pat_is_binding_or_wild(dm: resolve::DefMap, pat: @pat) -> bool {
match pat.node {
pat_ident(*) => !pat_is_variant(dm, pat),
pat_ident(*) => !pat_is_variant_or_struct(dm, pat),
pat_wild => true,
_ => false
}
Expand All @@ -44,7 +45,8 @@ fn pat_bindings(dm: resolve::DefMap, pat: @pat,
it: fn(binding_mode, node_id, span, @path)) {
do walk_pat(pat) |p| {
match p.node {
pat_ident(binding_mode, pth, _) if !pat_is_variant(dm, p) => {
pat_ident(binding_mode, pth, _)
if !pat_is_variant_or_struct(dm, p) => {
it(binding_mode, p.id, p.span, pth);
}
_ => {}
Expand Down
56 changes: 29 additions & 27 deletions src/rustc/middle/resolve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -288,10 +288,10 @@ impl AllowCapturingSelfFlag : cmp::Eq {
pure fn ne(other: &AllowCapturingSelfFlag) -> bool { !self.eq(other) }
}

enum EnumVariantOrConstResolution {
FoundEnumVariant(def),
enum BareIdentifierPatternResolution {
FoundStructOrEnumVariant(def),
FoundConst,
EnumVariantOrConstNotFound
BareIdentifierPatternUnresolved
}

// Specifies how duplicates should be handled when adding a child item if
Expand Down Expand Up @@ -4187,28 +4187,31 @@ impl Resolver {
if !path.global && path.idents.len() == 1u => {

// The meaning of pat_ident with no type parameters
// depends on whether an enum variant with that name is in
// scope. The probing lookup has to be careful not to emit
// spurious errors. Only matching patterns (match) can
// match nullary variants. For binding patterns (let),
// matching such a variant is simply disallowed (since
// it's rarely what you want).
// depends on whether an enum variant or unit-like struct
// with that name is in scope. The probing lookup has to
// be careful not to emit spurious errors. Only matching
// patterns (match) can match nullary variants or
// unit-like structs. For binding patterns (let), matching
// such a value is simply disallowed (since it's rarely
// what you want).

let ident = path.idents[0];

match self.resolve_enum_variant_or_const(ident) {
FoundEnumVariant(def) if mode == RefutableMode => {
match self.resolve_bare_identifier_pattern(ident) {
FoundStructOrEnumVariant(def)
if mode == RefutableMode => {
debug!("(resolving pattern) resolving `%s` to \
enum variant",
struct or enum variant",
self.session.str_of(ident));

self.record_def(pattern.id, def);
}
FoundEnumVariant(_) => {
FoundStructOrEnumVariant(_) => {
self.session.span_err(pattern.span,
fmt!("declaration of `%s` \
shadows an enum \
that's in scope",
variant or unit-like \
struct in scope",
self.session
.str_of(ident)));
}
Expand All @@ -4218,7 +4221,7 @@ impl Resolver {
conflicts with a constant \
in scope");
}
EnumVariantOrConstNotFound => {
BareIdentifierPatternUnresolved => {
debug!("(resolving pattern) binding `%s`",
self.session.str_of(ident));

Expand Down Expand Up @@ -4286,9 +4289,10 @@ impl Resolver {
}

pat_ident(_, path, _) | pat_enum(path, _) => {
// These two must be enum variants.
// These two must be enum variants or structs.
match self.resolve_path(path, ValueNS, false, visitor) {
Some(def @ def_variant(*)) => {
Some(def @ def_variant(*)) |
Some(def @ def_class(*)) => {
self.record_def(pattern.id, def);
}
Some(_) => {
Expand Down Expand Up @@ -4348,13 +4352,11 @@ impl Resolver {
}
}

fn resolve_enum_variant_or_const(name: ident)
-> EnumVariantOrConstResolution {

fn resolve_bare_identifier_pattern(name: ident)
-> BareIdentifierPatternResolution {
match self.resolve_item_in_lexical_scope(self.current_module,
name,
ValueNS) {

name,
ValueNS) {
Success(target) => {
match target.bindings.value_def {
None => {
Expand All @@ -4363,14 +4365,14 @@ impl Resolver {
}
Some(def) => {
match def.def {
def @ def_variant(*) => {
return FoundEnumVariant(def);
def @ def_variant(*) | def @ def_class(*) => {
return FoundStructOrEnumVariant(def);
}
def_const(*) => {
return FoundConst;
}
_ => {
return EnumVariantOrConstNotFound;
return BareIdentifierPatternUnresolved;
}
}
}
Expand All @@ -4382,7 +4384,7 @@ impl Resolver {
}

Failed => {
return EnumVariantOrConstNotFound;
return BareIdentifierPatternUnresolved;
}
}
}
Expand Down
Loading