Make shared kind the default only for generic functions
You almost never want a function with pinned type params. For types, objects, resources, and tags, pinned types are actually often more sane. For most of these, shared rarely makes sense. Only tricky case is objs -- you'll have to think about the kinds you want there. Issue #1076
This commit is contained in:
parent
6fe7aa4aff
commit
7dacccde94
16 changed files with 63 additions and 71 deletions
|
@ -170,12 +170,11 @@ fn encode_type_param_kinds(ebml_w: ebml::writer, tps: [ty_param]) {
|
||||||
ebml::start_tag(ebml_w, tag_items_data_item_ty_param_kinds);
|
ebml::start_tag(ebml_w, tag_items_data_item_ty_param_kinds);
|
||||||
ebml::write_vint(ebml_w.writer, vec::len::<ty_param>(tps));
|
ebml::write_vint(ebml_w.writer, vec::len::<ty_param>(tps));
|
||||||
for tp: ty_param in tps {
|
for tp: ty_param in tps {
|
||||||
let c =
|
let c = alt ast_util::ty_param_kind(tp) {
|
||||||
alt tp.kind {
|
kind_unique. { 'u' }
|
||||||
kind_unique. { 'u' }
|
kind_shared. { 's' }
|
||||||
kind_shared. { 's' }
|
kind_pinned. { 'p' }
|
||||||
kind_pinned. { 'p' }
|
};
|
||||||
};
|
|
||||||
ebml_w.writer.write([c as u8]);
|
ebml_w.writer.write([c as u8]);
|
||||||
}
|
}
|
||||||
ebml::end_tag(ebml_w);
|
ebml::end_tag(ebml_w);
|
||||||
|
|
|
@ -90,9 +90,9 @@ fn new_smallintmap_adapter<K, V>(key_idx: fn(K) -> uint,
|
||||||
idx_key: fn(uint) -> K)
|
idx_key: fn(uint) -> K)
|
||||||
-> std::map::hashmap<K, V> {
|
-> std::map::hashmap<K, V> {
|
||||||
|
|
||||||
obj adapter<K, V>(map: smallintmap::smallintmap<V>,
|
obj adapter<shar K, shar V>(map: smallintmap::smallintmap<V>,
|
||||||
key_idx: fn(K) -> uint,
|
key_idx: fn(K) -> uint,
|
||||||
idx_key: fn(uint) -> K) {
|
idx_key: fn(uint) -> K) {
|
||||||
|
|
||||||
fn size() -> uint { fail }
|
fn size() -> uint { fail }
|
||||||
|
|
||||||
|
|
|
@ -619,7 +619,7 @@ fn def_is_obj_field(d: def) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn def_is_ty_arg(d: def) -> bool {
|
fn def_is_ty_arg(d: def) -> bool {
|
||||||
ret alt d { ast::def_ty_arg(_, _) { true } _ { false } };
|
ret alt d { ast::def_ty_param(_, _) { true } _ { false } };
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lookup_in_scope(e: env, sc: scopes, sp: span, name: ident, ns: namespace)
|
fn lookup_in_scope(e: env, sc: scopes, sp: span, name: ident, ns: namespace)
|
||||||
|
@ -734,7 +734,9 @@ fn lookup_in_ty_params(name: ident, ty_params: [ast::ty_param]) ->
|
||||||
option::t<def> {
|
option::t<def> {
|
||||||
let i = 0u;
|
let i = 0u;
|
||||||
for tp: ast::ty_param in ty_params {
|
for tp: ast::ty_param in ty_params {
|
||||||
if str::eq(tp.ident, name) { ret some(ast::def_ty_arg(i, tp.kind)); }
|
if str::eq(tp.ident, name) {
|
||||||
|
ret some(ast::def_ty_param(i, ast_util::ty_param_kind(tp)));
|
||||||
|
}
|
||||||
i += 1u;
|
i += 1u;
|
||||||
}
|
}
|
||||||
ret none::<def>;
|
ret none::<def>;
|
||||||
|
|
|
@ -5227,7 +5227,8 @@ fn trans_tag_variant(cx: @local_ctxt, tag_id: ast::node_id,
|
||||||
let ty_param_substs: [ty::t] = [];
|
let ty_param_substs: [ty::t] = [];
|
||||||
i = 0u;
|
i = 0u;
|
||||||
for tp: ast::ty_param in ty_params {
|
for tp: ast::ty_param in ty_params {
|
||||||
ty_param_substs += [ty::mk_param(cx.ccx.tcx, i, tp.kind)];
|
ty_param_substs += [ty::mk_param(cx.ccx.tcx, i,
|
||||||
|
ast_util::ty_param_kind(tp))];
|
||||||
i += 1u;
|
i += 1u;
|
||||||
}
|
}
|
||||||
let arg_tys = arg_tys_of_fn(cx.ccx, variant.node.id);
|
let arg_tys = arg_tys_of_fn(cx.ccx, variant.node.id);
|
||||||
|
|
|
@ -2752,7 +2752,7 @@ fn def_has_ty_params(def: ast::def) -> bool {
|
||||||
ast::def_upvar(_, _, _) { ret false; }
|
ast::def_upvar(_, _, _) { ret false; }
|
||||||
ast::def_variant(_, _) { ret true; }
|
ast::def_variant(_, _) { ret true; }
|
||||||
ast::def_ty(_) { ret false; }
|
ast::def_ty(_) { ret false; }
|
||||||
ast::def_ty_arg(_, _) { ret false; }
|
ast::def_ty_param(_, _) { ret false; }
|
||||||
ast::def_binding(_) { ret false; }
|
ast::def_binding(_) { ret false; }
|
||||||
ast::def_use(_) { ret false; }
|
ast::def_use(_) { ret false; }
|
||||||
ast::def_native_ty(_) { ret false; }
|
ast::def_native_ty(_) { ret false; }
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import syntax::{ast, ast_util};
|
import syntax::{ast, ast_util};
|
||||||
import ast::{mutability, spanned};
|
import ast::{mutability, spanned};
|
||||||
import syntax::ast_util::{local_def, respan};
|
import syntax::ast_util::{local_def, respan, ty_param_kind};
|
||||||
import syntax::visit;
|
import syntax::visit;
|
||||||
import metadata::csearch;
|
import metadata::csearch;
|
||||||
import driver::session;
|
import driver::session;
|
||||||
|
@ -342,7 +342,7 @@ fn ast_ty_to_ty(tcx: ty::ctxt, getter: ty_getter, &&ast_ty: @ast::ty)
|
||||||
typ = instantiate(tcx, ast_ty.span, getter, id, path.node.types);
|
typ = instantiate(tcx, ast_ty.span, getter, id, path.node.types);
|
||||||
}
|
}
|
||||||
some(ast::def_native_ty(id)) { typ = getter(id).ty; }
|
some(ast::def_native_ty(id)) { typ = getter(id).ty; }
|
||||||
some(ast::def_ty_arg(id, k)) { typ = ty::mk_param(tcx, id, k); }
|
some(ast::def_ty_param(id, k)) { typ = ty::mk_param(tcx, id, k); }
|
||||||
some(_) {
|
some(_) {
|
||||||
tcx.sess.span_fatal(ast_ty.span,
|
tcx.sess.span_fatal(ast_ty.span,
|
||||||
"found type name used as a variable");
|
"found type name used as a variable");
|
||||||
|
@ -495,7 +495,7 @@ mod collect {
|
||||||
let tps = [];
|
let tps = [];
|
||||||
let i = 0u;
|
let i = 0u;
|
||||||
for atp: ast::ty_param in atps {
|
for atp: ast::ty_param in atps {
|
||||||
tps += [ty::mk_param(cx.tcx, i, atp.kind)];
|
tps += [ty::mk_param(cx.tcx, i, ty_param_kind(atp))];
|
||||||
i += 1u;
|
i += 1u;
|
||||||
}
|
}
|
||||||
ret tps;
|
ret tps;
|
||||||
|
@ -503,7 +503,7 @@ mod collect {
|
||||||
|
|
||||||
fn ty_param_kinds(tps: [ast::ty_param]) -> [ast::kind] {
|
fn ty_param_kinds(tps: [ast::ty_param]) -> [ast::kind] {
|
||||||
let k: [ast::kind] = [];
|
let k: [ast::kind] = [];
|
||||||
for p: ast::ty_param in tps { k += [p.kind]; }
|
for p: ast::ty_param in tps { k += [ty_param_kind(p)]; }
|
||||||
ret k;
|
ret k;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ type def_id = {crate: crate_num, node: node_id};
|
||||||
|
|
||||||
const local_crate: crate_num = 0;
|
const local_crate: crate_num = 0;
|
||||||
|
|
||||||
type ty_param = {ident: ident, kind: kind};
|
type ty_param = {ident: ident, kind: plicit<kind>};
|
||||||
|
|
||||||
tag def {
|
tag def {
|
||||||
def_fn(def_id, purity);
|
def_fn(def_id, purity);
|
||||||
|
@ -37,7 +37,7 @@ tag def {
|
||||||
|
|
||||||
/* variant */
|
/* variant */
|
||||||
def_ty(def_id);
|
def_ty(def_id);
|
||||||
def_ty_arg(uint, kind);
|
def_ty_param(uint, kind);
|
||||||
def_binding(def_id);
|
def_binding(def_id);
|
||||||
def_use(def_id);
|
def_use(def_id);
|
||||||
def_native_ty(def_id);
|
def_native_ty(def_id);
|
||||||
|
@ -99,7 +99,8 @@ tag pat_ {
|
||||||
|
|
||||||
tag mutability { mut; imm; maybe_mut; }
|
tag mutability { mut; imm; maybe_mut; }
|
||||||
|
|
||||||
tag kind { kind_pinned; kind_shared; kind_unique; }
|
tag plicit<T> { explicit(T); implicit(T); }
|
||||||
|
tag kind { kind_pinned; kind_shared; kind_unique; kind_auto; }
|
||||||
|
|
||||||
tag _auth { auth_unsafe; }
|
tag _auth { auth_unsafe; }
|
||||||
|
|
||||||
|
@ -489,16 +490,10 @@ tag item_ {
|
||||||
item_ty(@ty, [ty_param]);
|
item_ty(@ty, [ty_param]);
|
||||||
item_tag([variant], [ty_param]);
|
item_tag([variant], [ty_param]);
|
||||||
item_obj(_obj, [ty_param], /* constructor id */node_id);
|
item_obj(_obj, [ty_param], /* constructor id */node_id);
|
||||||
item_res(_fn,
|
item_res(_fn /* dtor */,
|
||||||
|
node_id /* dtor id */,
|
||||||
/* dtor */
|
|
||||||
node_id,
|
|
||||||
|
|
||||||
/* dtor id */
|
|
||||||
[ty_param],
|
[ty_param],
|
||||||
|
node_id /* ctor id */);
|
||||||
/* ctor id */
|
|
||||||
node_id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type native_item =
|
type native_item =
|
||||||
|
|
|
@ -33,7 +33,7 @@ fn def_id_of_def(d: def) -> def_id {
|
||||||
def_local(id, _) { ret id; }
|
def_local(id, _) { ret id; }
|
||||||
def_variant(_, id) { ret id; }
|
def_variant(_, id) { ret id; }
|
||||||
def_ty(id) { ret id; }
|
def_ty(id) { ret id; }
|
||||||
def_ty_arg(_, _) { fail; }
|
def_ty_param(_, _) { fail; }
|
||||||
def_binding(id) { ret id; }
|
def_binding(id) { ret id; }
|
||||||
def_use(id) { ret id; }
|
def_use(id) { ret id; }
|
||||||
def_native_ty(id) { ret id; }
|
def_native_ty(id) { ret id; }
|
||||||
|
@ -228,6 +228,10 @@ fn ret_by_ref(style: ret_style) -> bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ty_param_kind(tp: ty_param) -> kind {
|
||||||
|
alt tp.kind { explicit(x) | implicit(x) { x } }
|
||||||
|
}
|
||||||
|
|
||||||
// Local Variables:
|
// Local Variables:
|
||||||
// mode: rust
|
// mode: rust
|
||||||
// fill-column: 78;
|
// fill-column: 78;
|
||||||
|
|
|
@ -1735,25 +1735,21 @@ fn parse_block_tail(p: parser, lo: uint, s: ast::blk_check_mode) -> ast::blk {
|
||||||
ret spanned(lo, hi, bloc);
|
ret spanned(lo, hi, bloc);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_ty_param(p: parser) -> ast::ty_param {
|
fn parse_ty_param(default: ast::kind, p: parser) -> ast::ty_param {
|
||||||
let k = if eat_word(p, "pin") { ast::kind_pinned }
|
let k = if eat_word(p, "pin") { ast::explicit(ast::kind_pinned) }
|
||||||
else if eat_word(p, "uniq") { ast::kind_unique }
|
else if eat_word(p, "uniq") { ast::explicit(ast::kind_unique) }
|
||||||
else if eat_word(p, "shar") { ast::kind_shared }
|
else if eat_word(p, "shar") { ast::explicit(ast::kind_shared) }
|
||||||
// FIXME distinguish implied shared from explicit
|
// FIXME distinguish implied shared from explicit
|
||||||
else { ast::kind_shared };
|
else { ast::implicit(default) };
|
||||||
ret {ident: parse_ident(p), kind: k};
|
ret {ident: parse_ident(p), kind: k};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_ty_params(p: parser) -> [ast::ty_param] {
|
fn parse_ty_params(p: parser, default: ast::kind) -> [ast::ty_param] {
|
||||||
let ty_params: [ast::ty_param] = [];
|
let ty_params: [ast::ty_param] = [];
|
||||||
if p.peek() == token::LT {
|
if p.peek() == token::LT {
|
||||||
p.bump();
|
p.bump();
|
||||||
ty_params = parse_seq_to_gt(some(token::COMMA), parse_ty_param, p);
|
ty_params = parse_seq_to_gt(some(token::COMMA),
|
||||||
}
|
{|p| parse_ty_param(default, p)}, p);
|
||||||
if p.peek() == token::LT {
|
|
||||||
ty_params =
|
|
||||||
parse_seq(token::LT, token::GT, some(token::COMMA),
|
|
||||||
parse_ty_param, p).node;
|
|
||||||
}
|
}
|
||||||
ret ty_params;
|
ret ty_params;
|
||||||
}
|
}
|
||||||
|
@ -1806,7 +1802,7 @@ fn parse_fn(p: parser, proto: ast::proto, purity: ast::purity,
|
||||||
|
|
||||||
fn parse_fn_header(p: parser) -> {ident: ast::ident, tps: [ast::ty_param]} {
|
fn parse_fn_header(p: parser) -> {ident: ast::ident, tps: [ast::ty_param]} {
|
||||||
let id = parse_value_ident(p);
|
let id = parse_value_ident(p);
|
||||||
let ty_params = parse_ty_params(p);
|
let ty_params = parse_ty_params(p, ast::kind_shared);
|
||||||
ret {ident: id, tps: ty_params};
|
ret {ident: id, tps: ty_params};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1859,7 +1855,7 @@ fn parse_method(p: parser) -> @ast::method {
|
||||||
fn parse_item_obj(p: parser, attrs: [ast::attribute]) -> @ast::item {
|
fn parse_item_obj(p: parser, attrs: [ast::attribute]) -> @ast::item {
|
||||||
let lo = p.get_last_lo_pos();
|
let lo = p.get_last_lo_pos();
|
||||||
let ident = parse_value_ident(p);
|
let ident = parse_value_ident(p);
|
||||||
let ty_params = parse_ty_params(p);
|
let ty_params = parse_ty_params(p, ast::kind_pinned);
|
||||||
let fields: ast::spanned<[ast::obj_field]> =
|
let fields: ast::spanned<[ast::obj_field]> =
|
||||||
parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA),
|
parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA),
|
||||||
parse_obj_field, p);
|
parse_obj_field, p);
|
||||||
|
@ -1876,7 +1872,7 @@ fn parse_item_obj(p: parser, attrs: [ast::attribute]) -> @ast::item {
|
||||||
fn parse_item_res(p: parser, attrs: [ast::attribute]) -> @ast::item {
|
fn parse_item_res(p: parser, attrs: [ast::attribute]) -> @ast::item {
|
||||||
let lo = p.get_last_lo_pos();
|
let lo = p.get_last_lo_pos();
|
||||||
let ident = parse_value_ident(p);
|
let ident = parse_value_ident(p);
|
||||||
let ty_params = parse_ty_params(p);
|
let ty_params = parse_ty_params(p, ast::kind_pinned);
|
||||||
expect(p, token::LPAREN);
|
expect(p, token::LPAREN);
|
||||||
let arg_ident = parse_value_ident(p);
|
let arg_ident = parse_value_ident(p);
|
||||||
expect(p, token::COLON);
|
expect(p, token::COLON);
|
||||||
|
@ -2052,7 +2048,7 @@ fn parse_type_decl(p: parser) -> {lo: uint, ident: ast::ident} {
|
||||||
|
|
||||||
fn parse_item_type(p: parser, attrs: [ast::attribute]) -> @ast::item {
|
fn parse_item_type(p: parser, attrs: [ast::attribute]) -> @ast::item {
|
||||||
let t = parse_type_decl(p);
|
let t = parse_type_decl(p);
|
||||||
let tps = parse_ty_params(p);
|
let tps = parse_ty_params(p, ast::kind_pinned);
|
||||||
expect(p, token::EQ);
|
expect(p, token::EQ);
|
||||||
let ty = parse_ty(p, false);
|
let ty = parse_ty(p, false);
|
||||||
let hi = p.get_hi_pos();
|
let hi = p.get_hi_pos();
|
||||||
|
@ -2063,7 +2059,7 @@ fn parse_item_type(p: parser, attrs: [ast::attribute]) -> @ast::item {
|
||||||
fn parse_item_tag(p: parser, attrs: [ast::attribute]) -> @ast::item {
|
fn parse_item_tag(p: parser, attrs: [ast::attribute]) -> @ast::item {
|
||||||
let lo = p.get_last_lo_pos();
|
let lo = p.get_last_lo_pos();
|
||||||
let id = parse_ident(p);
|
let id = parse_ident(p);
|
||||||
let ty_params = parse_ty_params(p);
|
let ty_params = parse_ty_params(p, ast::kind_pinned);
|
||||||
let variants: [ast::variant] = [];
|
let variants: [ast::variant] = [];
|
||||||
// Newtype syntax
|
// Newtype syntax
|
||||||
if p.peek() == token::EQ {
|
if p.peek() == token::EQ {
|
||||||
|
|
|
@ -1191,11 +1191,12 @@ fn print_arg_mode(s: ps, m: ast::mode) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_kind(s: ps, kind: ast::kind) {
|
fn print_kind(s: ps, kind: ast::plicit<ast::kind>) {
|
||||||
alt kind {
|
alt kind {
|
||||||
ast::kind_unique. { word_nbsp(s, "uniq"); }
|
ast::implicit(_) {}
|
||||||
ast::kind_pinned. { word_nbsp(s, "pin"); }
|
ast::explicit(ast::kind_unique.) { word_nbsp(s, "uniq"); }
|
||||||
_ {/* fallthrough */ }
|
ast::explicit(ast::kind_pinned.) { word_nbsp(s, "pin"); }
|
||||||
|
ast::explicit(ast::kind_shared.) { word_nbsp(s, "shar"); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,12 +41,6 @@ fn create<T>() -> t<T> {
|
||||||
* Grow is only called on full elts, so nelts is also len(elts), unlike
|
* Grow is only called on full elts, so nelts is also len(elts), unlike
|
||||||
* elsewhere.
|
* elsewhere.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
fn grow<T>(nelts: uint, lo: uint, elts: [mutable cell<T>]) ->
|
fn grow<T>(nelts: uint, lo: uint, elts: [mutable cell<T>]) ->
|
||||||
[mutable cell<T>] {
|
[mutable cell<T>] {
|
||||||
assert (nelts == vec::len(elts));
|
assert (nelts == vec::len(elts));
|
||||||
|
@ -66,10 +60,10 @@ fn create<T>() -> t<T> {
|
||||||
fn get<T>(elts: [mutable cell<T>], i: uint) -> T {
|
fn get<T>(elts: [mutable cell<T>], i: uint) -> T {
|
||||||
ret alt elts[i] { option::some(t) { t } _ { fail } };
|
ret alt elts[i] { option::some(t) { t } _ { fail } };
|
||||||
}
|
}
|
||||||
obj deque<T>(mutable nelts: uint,
|
obj deque<shar T>(mutable nelts: uint,
|
||||||
mutable lo: uint,
|
mutable lo: uint,
|
||||||
mutable hi: uint,
|
mutable hi: uint,
|
||||||
mutable elts: [mutable cell<T>]) {
|
mutable elts: [mutable cell<T>]) {
|
||||||
fn size() -> uint { ret nelts; }
|
fn size() -> uint { ret nelts; }
|
||||||
fn add_front(t: T) {
|
fn add_front(t: T) {
|
||||||
let oldlo: uint = lo;
|
let oldlo: uint = lo;
|
||||||
|
|
|
@ -201,12 +201,12 @@ fn mk_hashmap<K, V>(hasher: hashfn<K>, eqer: eqfn<K>) -> hashmap<K, V> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
obj hashmap<K, V>(hasher: hashfn<K>,
|
obj hashmap<shar K, shar V>(hasher: hashfn<K>,
|
||||||
eqer: eqfn<K>,
|
eqer: eqfn<K>,
|
||||||
mutable bkts: [mutable bucket<K, V>],
|
mutable bkts: [mutable bucket<K, V>],
|
||||||
mutable nbkts: uint,
|
mutable nbkts: uint,
|
||||||
mutable nelts: uint,
|
mutable nelts: uint,
|
||||||
lf: util::rational) {
|
lf: util::rational) {
|
||||||
fn size() -> uint { ret nelts; }
|
fn size() -> uint { ret nelts; }
|
||||||
fn insert(key: K, val: V) -> bool {
|
fn insert(key: K, val: V) -> bool {
|
||||||
let load: util::rational =
|
let load: util::rational =
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
|
||||||
obj ob<K>(k: K) {
|
obj ob<shar K>(k: K) {
|
||||||
fn foo(it: block(~{a: K})) { it(~{a: k}); }
|
fn foo(it: block(~{a: K})) { it(~{a: k}); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
|
|
||||||
|
|
||||||
obj handle<T>(data: T) {
|
obj handle<shar T>(data: T) {
|
||||||
fn get() -> T { ret data; }
|
fn get() -> T { ret data; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
|
|
||||||
|
|
||||||
obj buf<T>(data: {_0: T, _1: T, _2: T}) {
|
obj buf<shar T>(data: {_0: T, _1: T, _2: T}) {
|
||||||
fn get(i: int) -> T {
|
fn get(i: int) -> T {
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
ret data._0;
|
ret data._0;
|
||||||
|
|
|
@ -6,7 +6,7 @@ tag clam<T> { signed(int); unsigned(uint); }
|
||||||
|
|
||||||
fn getclam<T>() -> clam<T> { ret signed::<T>(42); }
|
fn getclam<T>() -> clam<T> { ret signed::<T>(42); }
|
||||||
|
|
||||||
obj impatience<T>() {
|
obj impatience<shar T>() {
|
||||||
fn moreclam() -> clam<T> { be getclam::<T>(); }
|
fn moreclam() -> clam<T> { be getclam::<T>(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue