Skip to content

Commit f827561

Browse files
committed
auto merge of #7314 : bblum/rust/trait-bounds2, r=nikomatsakis
Fixed a merge conflict, some tests, some bitrotting, etc., from #7248.
2 parents cb58b19 + ba3f43e commit f827561

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+583
-180
lines changed

src/etc/vim/syntax/rust.vim

+18-6
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
" Language: Rust
33
" Maintainer: Patrick Walton <[email protected]>
44
" Maintainer: Ben Blum <[email protected]>
5-
" Last Change: 2012 Dec 25
5+
" Last Change: 2012 Jun 14
66

77
if version < 600
88
syntax clear
@@ -13,13 +13,16 @@ endif
1313
syn keyword rustConditional match if else
1414
syn keyword rustOperator as
1515

16+
syn match rustAssert "\<assert\(\w\)*!"
17+
syn match rustFail "\<fail\(\w\)*!"
1618
syn keyword rustKeyword break copy do drop extern
1719
syn keyword rustKeyword for if impl let log
1820
syn keyword rustKeyword copy do extern
1921
syn keyword rustKeyword for impl let log
2022
syn keyword rustKeyword loop mod once priv pub
2123
syn keyword rustKeyword return
22-
syn keyword rustKeyword unsafe use while
24+
syn keyword rustKeyword unsafe while
25+
syn keyword rustKeyword use nextgroup=rustModPath skipwhite
2326
" FIXME: Scoped impl's name is also fallen in this category
2427
syn keyword rustKeyword mod trait struct enum type nextgroup=rustIdentifier skipwhite
2528
syn keyword rustKeyword fn nextgroup=rustFuncName skipwhite
@@ -45,7 +48,8 @@ syn keyword rustType c_longlong c_ulonglong intptr_t uintptr_t
4548
syn keyword rustType off_t dev_t ino_t pid_t mode_t ssize_t
4649

4750
syn keyword rustTrait Const Copy Send Owned Sized " inherent traits
48-
syn keyword rustTrait Eq Ord Num Ptr
51+
syn keyword rustTrait Clone Decodable Encodable IterBytes Rand ToStr
52+
syn keyword rustTrait Eq Ord TotalEq TotalOrd Num Ptr
4953
syn keyword rustTrait Drop Add Sub Mul Quot Rem Neg BitAnd BitOr
5054
syn keyword rustTrait BitXor Shl Shr Index
5155

@@ -72,19 +76,21 @@ syn keyword rustConstant STDIN_FILENO STDOUT_FILENO STDERR_FILENO
7276
" If foo::bar changes to foo.bar, change this ("::" to "\.").
7377
" If foo::bar changes to Foo::bar, change this (first "\w" to "\u").
7478
syn match rustModPath "\w\(\w\)*::[^<]"he=e-3,me=e-3
79+
syn match rustModPath "\w\(\w\)*" contained " only for 'use path;'
7580
syn match rustModPathSep "::"
7681

7782
syn match rustFuncCall "\w\(\w\)*("he=e-1,me=e-1
7883
syn match rustFuncCall "\w\(\w\)*::<"he=e-3,me=e-3 " foo::<T>();
7984

80-
syn match rustMacro '\w\(\w\)*!'
81-
syn match rustMacro '#\w\(\w\)*'
85+
syn match rustMacro '\w\(\w\)*!' contains=rustAssert,rustFail
86+
syn match rustMacro '#\w\(\w\)*' contains=rustAssert,rustFail
8287

8388
syn match rustFormat display "%\(\d\+\$\)\=[-+' #0*]*\(\d*\|\*\|\*\d\+\$\)\(\.\(\d*\|\*\|\*\d\+\$\)\)\=\([hlLjzt]\|ll\|hh\)\=\([aAbdiuoxXDOUfFeEgGcCsSpn?]\|\[\^\=.[^]]*\]\)" contained
8489
syn match rustFormat display "%%" contained
8590
syn region rustString start=+L\="+ skip=+\\\\\|\\"+ end=+"+ contains=rustTodo,rustFormat
8691

87-
syn region rustAttribute start="#\[" end="\]" contains=rustString
92+
syn region rustAttribute start="#\[" end="\]" contains=rustString,rustDeriving
93+
syn region rustDeriving start="deriving(" end=")" contains=rustTrait
8894

8995
" Number literals
9096
syn match rustNumber display "\<[0-9][0-9_]*\>"
@@ -143,11 +149,17 @@ hi def link rustMacro Macro
143149
hi def link rustType Type
144150
hi def link rustTodo Todo
145151
hi def link rustAttribute PreProc
152+
hi def link rustDeriving PreProc
146153
hi def link rustStorage StorageClass
147154
hi def link rustLifetime Special
148155

149156
" Other Suggestions:
157+
" hi rustAttribute ctermfg=cyan
158+
" hi rustDeriving ctermfg=cyan
159+
" hi rustAssert ctermfg=yellow
160+
" hi rustFail ctermfg=red
150161
" hi rustMacro ctermfg=magenta
162+
" hi rustModPathSep ctermfg=grey
151163

152164
syn sync minlines=200
153165
syn sync maxlines=500

src/librustc/metadata/encoder.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -954,7 +954,8 @@ fn encode_info_for_item(ecx: &EncodeContext,
954954
encode_name(ecx, ebml_w, item.ident);
955955
encode_attributes(ebml_w, item.attrs);
956956
match ty.node {
957-
ast::ty_path(path, _) if path.idents.len() == 1 => {
957+
ast::ty_path(path, bounds, _) if path.idents.len() == 1 => {
958+
assert!(bounds.is_empty());
958959
encode_impl_type_basename(ecx, ebml_w,
959960
ast_util::path_to_ident(path));
960961
}

src/librustc/metadata/tydecode.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -311,8 +311,9 @@ fn parse_ty(st: &mut PState, conv: conv_did) -> ty::t {
311311
let substs = parse_substs(st, conv);
312312
let store = parse_trait_store(st);
313313
let mt = parse_mutability(st);
314+
let bounds = parse_bounds(st, conv);
314315
assert_eq!(next(st), ']');
315-
return ty::mk_trait(st.tcx, def, substs, store, mt);
316+
return ty::mk_trait(st.tcx, def, substs, store, mt, bounds.builtin_bounds);
316317
}
317318
'p' => {
318319
let did = parse_def(st, TypeParameter, conv);

src/librustc/metadata/tyencode.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -261,13 +261,16 @@ fn enc_sty(w: @io::Writer, cx: @ctxt, st: ty::sty) {
261261
enc_substs(w, cx, substs);
262262
w.write_char(']');
263263
}
264-
ty::ty_trait(def, ref substs, store, mt) => {
264+
ty::ty_trait(def, ref substs, store, mt, bounds) => {
265265
w.write_str(&"x[");
266266
w.write_str((cx.ds)(def));
267267
w.write_char('|');
268268
enc_substs(w, cx, substs);
269269
enc_trait_store(w, cx, store);
270270
enc_mutability(w, mt);
271+
let bounds = ty::ParamBounds {builtin_bounds: bounds,
272+
trait_bounds: ~[]};
273+
enc_bounds(w, cx, &bounds);
271274
w.write_char(']');
272275
}
273276
ty::ty_tup(ts) => {

src/librustc/middle/kind.rs

+83-40
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,6 @@ pub fn check_crate(tcx: ty::ctxt,
8181
tcx.sess.abort_if_errors();
8282
}
8383

84-
type check_fn = @fn(Context, @freevar_entry);
85-
8684
fn check_struct_safe_for_destructor(cx: Context,
8785
span: span,
8886
struct_did: def_id) {
@@ -129,7 +127,8 @@ fn check_item(item: @item, (cx, visitor): (Context, visit::vt<Context>)) {
129127
if cx.tcx.lang_items.drop_trait() == trait_def_id {
130128
// Yes, it's a destructor.
131129
match self_type.node {
132-
ty_path(_, path_node_id) => {
130+
ty_path(_, bounds, path_node_id) => {
131+
assert!(bounds.is_empty());
133132
let struct_def = cx.tcx.def_map.get_copy(
134133
&path_node_id);
135134
let struct_did =
@@ -162,30 +161,43 @@ fn check_item(item: @item, (cx, visitor): (Context, visit::vt<Context>)) {
162161
// Yields the appropriate function to check the kind of closed over
163162
// variables. `id` is the node_id for some expression that creates the
164163
// closure.
165-
fn with_appropriate_checker(cx: Context, id: node_id, b: &fn(check_fn)) {
166-
fn check_for_uniq(cx: Context, fv: @freevar_entry) {
164+
fn with_appropriate_checker(cx: Context, id: node_id,
165+
b: &fn(checker: &fn(Context, @freevar_entry))) {
166+
fn check_for_uniq(cx: Context, fv: @freevar_entry, bounds: ty::BuiltinBounds) {
167167
// all captured data must be owned, regardless of whether it is
168168
// moved in or copied in.
169169
let id = ast_util::def_id_of_def(fv.def).node;
170170
let var_t = ty::node_id_to_type(cx.tcx, id);
171+
172+
// FIXME(#3569): Once closure capabilities are restricted based on their
173+
// incoming bounds, make this check conditional based on the bounds.
171174
if !check_owned(cx, var_t, fv.span) { return; }
172175

173176
// check that only immutable variables are implicitly copied in
174177
check_imm_free_var(cx, fv.def, fv.span);
178+
179+
check_freevar_bounds(cx, fv.span, var_t, bounds);
175180
}
176181

177-
fn check_for_box(cx: Context, fv: @freevar_entry) {
182+
fn check_for_box(cx: Context, fv: @freevar_entry, bounds: ty::BuiltinBounds) {
178183
// all captured data must be owned
179184
let id = ast_util::def_id_of_def(fv.def).node;
180185
let var_t = ty::node_id_to_type(cx.tcx, id);
186+
187+
// FIXME(#3569): Once closure capabilities are restricted based on their
188+
// incoming bounds, make this check conditional based on the bounds.
181189
if !check_durable(cx.tcx, var_t, fv.span) { return; }
182190

183191
// check that only immutable variables are implicitly copied in
184192
check_imm_free_var(cx, fv.def, fv.span);
193+
194+
check_freevar_bounds(cx, fv.span, var_t, bounds);
185195
}
186196

187-
fn check_for_block(_cx: Context, _fv: @freevar_entry) {
188-
// no restrictions
197+
fn check_for_block(cx: Context, fv: @freevar_entry, bounds: ty::BuiltinBounds) {
198+
let id = ast_util::def_id_of_def(fv.def).node;
199+
let var_t = ty::node_id_to_type(cx.tcx, id);
200+
check_freevar_bounds(cx, fv.span, var_t, bounds);
189201
}
190202

191203
fn check_for_bare(cx: Context, fv: @freevar_entry) {
@@ -196,14 +208,14 @@ fn with_appropriate_checker(cx: Context, id: node_id, b: &fn(check_fn)) {
196208

197209
let fty = ty::node_id_to_type(cx.tcx, id);
198210
match ty::get(fty).sty {
199-
ty::ty_closure(ty::ClosureTy {sigil: OwnedSigil, _}) => {
200-
b(check_for_uniq)
211+
ty::ty_closure(ty::ClosureTy {sigil: OwnedSigil, bounds: bounds, _}) => {
212+
b(|cx, fv| check_for_uniq(cx, fv, bounds))
201213
}
202-
ty::ty_closure(ty::ClosureTy {sigil: ManagedSigil, _}) => {
203-
b(check_for_box)
214+
ty::ty_closure(ty::ClosureTy {sigil: ManagedSigil, bounds: bounds, _}) => {
215+
b(|cx, fv| check_for_box(cx, fv, bounds))
204216
}
205-
ty::ty_closure(ty::ClosureTy {sigil: BorrowedSigil, _}) => {
206-
b(check_for_block)
217+
ty::ty_closure(ty::ClosureTy {sigil: BorrowedSigil, bounds: bounds, _}) => {
218+
b(|cx, fv| check_for_block(cx, fv, bounds))
207219
}
208220
ty::ty_bare_fn(_) => {
209221
b(check_for_bare)
@@ -271,15 +283,21 @@ pub fn check_expr(e: @expr, (cx, v): (Context, visit::vt<Context>)) {
271283
type_param_defs.repr(cx.tcx));
272284
}
273285
for ts.iter().zip(type_param_defs.iter()).advance |(&ty, type_param_def)| {
274-
check_bounds(cx, type_parameter_id, e.span, ty, type_param_def)
286+
check_typaram_bounds(cx, type_parameter_id, e.span, ty, type_param_def)
275287
}
276288
}
277289
}
278290

279291
match e.node {
280292
expr_cast(source, _) => {
281293
check_cast_for_escaping_regions(cx, source, e);
282-
check_kind_bounds_of_cast(cx, source, e);
294+
match ty::get(ty::expr_ty(cx.tcx, e)).sty {
295+
ty::ty_trait(_, _, store, _, bounds) => {
296+
let source_ty = ty::expr_ty(cx.tcx, source);
297+
check_trait_cast_bounds(cx, e.span, source_ty, bounds, store)
298+
}
299+
_ => { }
300+
}
283301
}
284302
expr_copy(expr) => {
285303
// Note: This is the only place where we must check whether the
@@ -307,14 +325,14 @@ pub fn check_expr(e: @expr, (cx, v): (Context, visit::vt<Context>)) {
307325

308326
fn check_ty(aty: @Ty, (cx, v): (Context, visit::vt<Context>)) {
309327
match aty.node {
310-
ty_path(_, id) => {
328+
ty_path(_, _, id) => {
311329
let r = cx.tcx.node_type_substs.find(&id);
312330
for r.iter().advance |ts| {
313331
let did = ast_util::def_id_of_def(cx.tcx.def_map.get_copy(&id));
314332
let type_param_defs =
315333
ty::lookup_item_type(cx.tcx, did).generics.type_param_defs;
316334
for ts.iter().zip(type_param_defs.iter()).advance |(&ty, type_param_def)| {
317-
check_bounds(cx, aty.id, aty.span, ty, type_param_def)
335+
check_typaram_bounds(cx, aty.id, aty.span, ty, type_param_def)
318336
}
319337
}
320338
}
@@ -323,20 +341,29 @@ fn check_ty(aty: @Ty, (cx, v): (Context, visit::vt<Context>)) {
323341
visit::visit_ty(aty, (cx, v));
324342
}
325343

326-
pub fn check_bounds(cx: Context,
327-
_type_parameter_id: node_id,
328-
sp: span,
329-
ty: ty::t,
330-
type_param_def: &ty::TypeParameterDef)
344+
// Calls "any_missing" if any bounds were missing.
345+
pub fn check_builtin_bounds(cx: Context, ty: ty::t, bounds: ty::BuiltinBounds,
346+
any_missing: &fn(ty::BuiltinBounds))
331347
{
332348
let kind = ty::type_contents(cx.tcx, ty);
333349
let mut missing = ty::EmptyBuiltinBounds();
334-
for type_param_def.bounds.builtin_bounds.each |bound| {
350+
for bounds.each |bound| {
335351
if !kind.meets_bound(cx.tcx, bound) {
336352
missing.add(bound);
337353
}
338354
}
339355
if !missing.is_empty() {
356+
any_missing(missing);
357+
}
358+
}
359+
360+
pub fn check_typaram_bounds(cx: Context,
361+
_type_parameter_id: node_id,
362+
sp: span,
363+
ty: ty::t,
364+
type_param_def: &ty::TypeParameterDef)
365+
{
366+
do check_builtin_bounds(cx, ty, type_param_def.bounds.builtin_bounds) |missing| {
340367
cx.tcx.sess.span_err(
341368
sp,
342369
fmt!("instantiating a type parameter with an incompatible type \
@@ -346,6 +373,38 @@ pub fn check_bounds(cx: Context,
346373
}
347374
}
348375

376+
pub fn check_freevar_bounds(cx: Context, sp: span, ty: ty::t,
377+
bounds: ty::BuiltinBounds)
378+
{
379+
do check_builtin_bounds(cx, ty, bounds) |missing| {
380+
cx.tcx.sess.span_err(
381+
sp,
382+
fmt!("cannot capture variable of type `%s`, which does not fulfill \
383+
`%s`, in a bounded closure",
384+
ty_to_str(cx.tcx, ty), missing.user_string(cx.tcx)));
385+
cx.tcx.sess.span_note(
386+
sp,
387+
fmt!("this closure's environment must satisfy `%s`",
388+
bounds.user_string(cx.tcx)));
389+
}
390+
}
391+
392+
pub fn check_trait_cast_bounds(cx: Context, sp: span, ty: ty::t,
393+
bounds: ty::BuiltinBounds, store: ty::TraitStore) {
394+
do check_builtin_bounds(cx, ty, bounds) |missing| {
395+
cx.tcx.sess.span_err(sp,
396+
fmt!("cannot pack type `%s`, which does not fulfill \
397+
`%s`, as a trait bounded by %s",
398+
ty_to_str(cx.tcx, ty), missing.user_string(cx.tcx),
399+
bounds.user_string(cx.tcx)));
400+
}
401+
// FIXME(#3569): Remove this check when the corresponding restriction
402+
// is made with type contents.
403+
if store == ty::UniqTraitStore && !ty::type_is_owned(cx.tcx, ty) {
404+
cx.tcx.sess.span_err(sp, "uniquely-owned trait objects must be sendable");
405+
}
406+
}
407+
349408
fn is_nullary_variant(cx: Context, ex: @expr) -> bool {
350409
match ex.node {
351410
expr_path(_) => {
@@ -528,19 +587,3 @@ pub fn check_cast_for_escaping_regions(
528587
cx.tcx.region_maps.is_subregion_of(r_sub, r_sup)
529588
}
530589
}
531-
532-
/// Ensures that values placed into a ~Trait are copyable and sendable.
533-
pub fn check_kind_bounds_of_cast(cx: Context, source: @expr, target: @expr) {
534-
let target_ty = ty::expr_ty(cx.tcx, target);
535-
match ty::get(target_ty).sty {
536-
ty::ty_trait(_, _, ty::UniqTraitStore, _) => {
537-
let source_ty = ty::expr_ty(cx.tcx, source);
538-
if !ty::type_is_owned(cx.tcx, source_ty) {
539-
cx.tcx.sess.span_err(
540-
target.span,
541-
"uniquely-owned trait objects must be sendable");
542-
}
543-
}
544-
_ => {} // Nothing to do.
545-
}
546-
}

src/librustc/middle/lint.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -714,7 +714,7 @@ fn check_item_ctypes(cx: &Context, it: @ast::item) {
714714
let tys = vec::map(decl.inputs, |a| a.ty );
715715
for vec::each(vec::append_one(tys, decl.output)) |ty| {
716716
match ty.node {
717-
ast::ty_path(_, id) => {
717+
ast::ty_path(_, _, id) => {
718718
match cx.tcx.def_map.get_copy(&id) {
719719
ast::def_prim_ty(ast::ty_int(ast::ty_i)) => {
720720
cx.span_lint(ctypes, ty.span,

src/librustc/middle/region.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -804,7 +804,7 @@ pub fn determine_rp_in_ty(ty: @ast::Ty,
804804
// then check whether it is region-parameterized and consider
805805
// that as a direct dependency.
806806
match ty.node {
807-
ast::ty_path(path, id) => {
807+
ast::ty_path(path, _bounds, id) => {
808808
match cx.def_map.find(&id) {
809809
Some(&ast::def_ty(did)) |
810810
Some(&ast::def_trait(did)) |
@@ -840,7 +840,7 @@ pub fn determine_rp_in_ty(ty: @ast::Ty,
840840
visit_mt(mt, (cx, visitor));
841841
}
842842

843-
ast::ty_path(path, _) => {
843+
ast::ty_path(path, _bounds, _) => {
844844
// type parameters are---for now, anyway---always invariant
845845
do cx.with_ambient_variance(rv_invariant) {
846846
for path.types.iter().advance |tp| {

src/librustc/middle/resolve.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -1250,7 +1250,7 @@ impl Resolver {
12501250
// If there are static methods, then create the module
12511251
// and add them.
12521252
match (trait_ref_opt, ty) {
1253-
(None, @Ty { node: ty_path(path, _), _ }) if
1253+
(None, @Ty { node: ty_path(path, _, _), _ }) if
12541254
has_static_methods && path.idents.len() == 1 => {
12551255
let name = path_to_ident(path);
12561256

@@ -4120,7 +4120,7 @@ impl Resolver {
41204120
// Like path expressions, the interpretation of path types depends
41214121
// on whether the path has multiple elements in it or not.
41224122

4123-
ty_path(path, path_id) => {
4123+
ty_path(path, bounds, path_id) => {
41244124
// This is a path in the type namespace. Walk through scopes
41254125
// scopes looking for it.
41264126
let mut result_def = None;
@@ -4179,6 +4179,10 @@ impl Resolver {
41794179
self.idents_to_str(path.idents)));
41804180
}
41814181
}
4182+
4183+
for bounds.each |bound| {
4184+
self.resolve_type_parameter_bound(bound, visitor);
4185+
}
41824186
}
41834187

41844188
ty_closure(c) => {

0 commit comments

Comments
 (0)