Consistently normalize fn types after erasing lifetimes.
Fixes #23406. Fixes #23958. Fixes #29832.
This commit is contained in:
parent
4f5edf9e38
commit
82ab7079dd
13 changed files with 114 additions and 56 deletions
|
@ -142,6 +142,7 @@ pub fn from_fn_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_type: ty::Ty<'tcx
|
|||
};
|
||||
|
||||
let fn_sig = ccx.tcx().erase_late_bound_regions(fn_sig);
|
||||
let fn_sig = infer::normalize_associated_type(ccx.tcx(), &fn_sig);
|
||||
|
||||
let mut attrs = llvm::AttrBuilder::new();
|
||||
let ret_ty = fn_sig.output;
|
||||
|
|
|
@ -38,6 +38,7 @@ use metadata::{csearch, encoder, loader};
|
|||
use middle::astencode;
|
||||
use middle::cfg;
|
||||
use middle::def_id::DefId;
|
||||
use middle::infer;
|
||||
use middle::lang_items::{LangItem, ExchangeMallocFnLangItem, StartFnLangItem};
|
||||
use middle::weak_lang_items;
|
||||
use middle::pat_util::simple_name;
|
||||
|
@ -1905,7 +1906,11 @@ pub fn trans_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
|||
debug!("trans_fn(param_substs={:?})", param_substs);
|
||||
let _icx = push_ctxt("trans_fn");
|
||||
let fn_ty = ccx.tcx().node_id_to_type(id);
|
||||
let output_type = ccx.tcx().erase_late_bound_regions(&fn_ty.fn_ret());
|
||||
let fn_ty = monomorphize::apply_param_substs(ccx.tcx(), param_substs, &fn_ty);
|
||||
let sig = fn_ty.fn_sig();
|
||||
let sig = ccx.tcx().erase_late_bound_regions(&sig);
|
||||
let sig = infer::normalize_associated_type(ccx.tcx(), &sig);
|
||||
let output_type = sig.output;
|
||||
let abi = fn_ty.fn_abi();
|
||||
trans_closure(ccx, decl, body, llfndecl, param_substs, id, attrs, output_type, abi,
|
||||
closure::ClosureEnv::NotClosure);
|
||||
|
@ -1936,15 +1941,9 @@ pub fn trans_named_tuple_constructor<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
|
|||
|
||||
let ccx = bcx.fcx.ccx;
|
||||
|
||||
let result_ty = match ctor_ty.sty {
|
||||
ty::TyBareFn(_, ref bft) => {
|
||||
bcx.tcx().erase_late_bound_regions(&bft.sig.output()).unwrap()
|
||||
}
|
||||
_ => ccx.sess().bug(
|
||||
&format!("trans_enum_variant_constructor: \
|
||||
unexpected ctor return type {}",
|
||||
ctor_ty))
|
||||
};
|
||||
let sig = ccx.tcx().erase_late_bound_regions(&ctor_ty.fn_sig());
|
||||
let sig = infer::normalize_associated_type(ccx.tcx(), &sig);
|
||||
let result_ty = sig.output.unwrap();
|
||||
|
||||
// Get location to store the result. If the user does not care about
|
||||
// the result, just make a stack slot
|
||||
|
@ -2026,15 +2025,10 @@ fn trans_enum_variant_or_tuple_like_struct<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx
|
|||
let ctor_ty = ccx.tcx().node_id_to_type(ctor_id);
|
||||
let ctor_ty = monomorphize::apply_param_substs(ccx.tcx(), param_substs, &ctor_ty);
|
||||
|
||||
let result_ty = match ctor_ty.sty {
|
||||
ty::TyBareFn(_, ref bft) => {
|
||||
ccx.tcx().erase_late_bound_regions(&bft.sig.output())
|
||||
}
|
||||
_ => ccx.sess().bug(
|
||||
&format!("trans_enum_variant_or_tuple_like_struct: \
|
||||
unexpected ctor return type {}",
|
||||
ctor_ty))
|
||||
};
|
||||
let sig = ccx.tcx().erase_late_bound_regions(&ctor_ty.fn_sig());
|
||||
let sig = infer::normalize_associated_type(ccx.tcx(), &sig);
|
||||
let arg_tys = sig.inputs;
|
||||
let result_ty = sig.output;
|
||||
|
||||
let (arena, fcx): (TypedArena<_>, FunctionContext);
|
||||
arena = TypedArena::new();
|
||||
|
@ -2044,8 +2038,6 @@ fn trans_enum_variant_or_tuple_like_struct<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx
|
|||
|
||||
assert!(!fcx.needs_ret_allocas);
|
||||
|
||||
let arg_tys = ccx.tcx().erase_late_bound_regions(&ctor_ty.fn_args());
|
||||
|
||||
if !type_is_zero_size(fcx.ccx, result_ty.unwrap()) {
|
||||
let dest = fcx.get_ret_slot(bcx, result_ty, "eret_slot");
|
||||
let repr = adt::represent_type(ccx, result_ty.unwrap());
|
||||
|
|
|
@ -25,7 +25,7 @@ use llvm::{self, ValueRef, get_params};
|
|||
use metadata::cstore::LOCAL_CRATE;
|
||||
use middle::def;
|
||||
use middle::def_id::DefId;
|
||||
use middle::infer::normalize_associated_type;
|
||||
use middle::infer;
|
||||
use middle::subst;
|
||||
use middle::subst::{Substs};
|
||||
use rustc::front::map as hir_map;
|
||||
|
@ -304,6 +304,7 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>(
|
|||
}
|
||||
};
|
||||
let sig = tcx.erase_late_bound_regions(sig);
|
||||
let sig = infer::normalize_associated_type(ccx.tcx(), &sig);
|
||||
let tuple_input_ty = tcx.mk_tup(sig.inputs.to_vec());
|
||||
let tuple_fn_ty = tcx.mk_fn(opt_def_id,
|
||||
tcx.mk_bare_fn(ty::BareFnTy {
|
||||
|
@ -466,7 +467,7 @@ pub fn trans_fn_ref_with_substs<'a, 'tcx>(
|
|||
|
||||
// Type scheme of the function item (may have type params)
|
||||
let fn_type_scheme = tcx.lookup_item_type(def_id);
|
||||
let fn_type = normalize_associated_type(tcx, &fn_type_scheme.ty);
|
||||
let fn_type = infer::normalize_associated_type(tcx, &fn_type_scheme.ty);
|
||||
|
||||
// Find the actual function pointer.
|
||||
let mut val = {
|
||||
|
@ -605,8 +606,9 @@ pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
|
|||
|
||||
let (abi, ret_ty) = match callee.ty.sty {
|
||||
ty::TyBareFn(_, ref f) => {
|
||||
let output = bcx.tcx().erase_late_bound_regions(&f.sig.output());
|
||||
(f.abi, output)
|
||||
let sig = bcx.tcx().erase_late_bound_regions(&f.sig);
|
||||
let sig = infer::normalize_associated_type(bcx.tcx(), &sig);
|
||||
(f.abi, sig.output)
|
||||
}
|
||||
_ => panic!("expected bare rust fn or closure in trans_call_inner")
|
||||
};
|
||||
|
@ -826,7 +828,9 @@ fn trans_args_under_call_abi<'blk, 'tcx>(
|
|||
ignore_self: bool)
|
||||
-> Block<'blk, 'tcx>
|
||||
{
|
||||
let args = bcx.tcx().erase_late_bound_regions(&fn_ty.fn_args());
|
||||
let sig = bcx.tcx().erase_late_bound_regions(&fn_ty.fn_sig());
|
||||
let sig = infer::normalize_associated_type(bcx.tcx(), &sig);
|
||||
let args = sig.inputs;
|
||||
|
||||
// Translate the `self` argument first.
|
||||
if !ignore_self {
|
||||
|
@ -887,7 +891,10 @@ fn trans_overloaded_call_args<'blk, 'tcx>(
|
|||
ignore_self: bool)
|
||||
-> Block<'blk, 'tcx> {
|
||||
// Translate the `self` argument first.
|
||||
let arg_tys = bcx.tcx().erase_late_bound_regions( &fn_ty.fn_args());
|
||||
let sig = bcx.tcx().erase_late_bound_regions(&fn_ty.fn_sig());
|
||||
let sig = infer::normalize_associated_type(bcx.tcx(), &sig);
|
||||
let arg_tys = sig.inputs;
|
||||
|
||||
if !ignore_self {
|
||||
let arg_datum = unpack_datum!(bcx, expr::trans(bcx, arg_exprs[0]));
|
||||
bcx = trans_arg_datum(bcx,
|
||||
|
@ -933,8 +940,10 @@ pub fn trans_args<'a, 'blk, 'tcx>(cx: Block<'blk, 'tcx>,
|
|||
debug!("trans_args(abi={})", abi);
|
||||
|
||||
let _icx = push_ctxt("trans_args");
|
||||
let arg_tys = cx.tcx().erase_late_bound_regions(&fn_ty.fn_args());
|
||||
let variadic = fn_ty.fn_sig().0.variadic;
|
||||
let sig = cx.tcx().erase_late_bound_regions(&fn_ty.fn_sig());
|
||||
let sig = infer::normalize_associated_type(cx.tcx(), &sig);
|
||||
let arg_tys = sig.inputs;
|
||||
let variadic = sig.variadic;
|
||||
|
||||
let mut bcx = cx;
|
||||
|
||||
|
|
|
@ -210,6 +210,7 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>,
|
|||
tcx.with_freevars(id, |fv| fv.iter().cloned().collect());
|
||||
|
||||
let sig = tcx.erase_late_bound_regions(&function_type.sig);
|
||||
let sig = infer::normalize_associated_type(ccx.tcx(), &sig);
|
||||
|
||||
trans_closure(ccx,
|
||||
decl,
|
||||
|
@ -371,6 +372,8 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>(
|
|||
let lloncefn = declare::define_internal_rust_fn(ccx, &function_name,
|
||||
llonce_fn_ty);
|
||||
let sig = tcx.erase_late_bound_regions(&llonce_bare_fn_ty.sig);
|
||||
let sig = infer::normalize_associated_type(ccx.tcx(), &sig);
|
||||
|
||||
let (block_arena, fcx): (TypedArena<_>, FunctionContext);
|
||||
block_arena = TypedArena::new();
|
||||
fcx = new_fn_ctxt(ccx,
|
||||
|
|
|
@ -24,6 +24,7 @@ use llvm::{self, ValueRef};
|
|||
use llvm::debuginfo::{DIType, DIFile, DIScope, DIDescriptor, DICompositeType};
|
||||
|
||||
use middle::def_id::DefId;
|
||||
use middle::infer;
|
||||
use middle::pat_util;
|
||||
use middle::subst::{self, Substs};
|
||||
use rustc::front::map as hir_map;
|
||||
|
@ -262,6 +263,7 @@ impl<'tcx> TypeMap<'tcx> {
|
|||
unique_type_id.push_str(" fn(");
|
||||
|
||||
let sig = cx.tcx().erase_late_bound_regions(sig);
|
||||
let sig = infer::normalize_associated_type(cx.tcx(), &sig);
|
||||
|
||||
for ¶meter_type in &sig.inputs {
|
||||
let parameter_type_id =
|
||||
|
|
|
@ -35,6 +35,7 @@ use rustc_front::hir;
|
|||
use trans::common::{NodeIdAndSpan, CrateContext, FunctionContext, Block};
|
||||
use trans;
|
||||
use trans::{monomorphize, type_of};
|
||||
use middle::infer;
|
||||
use middle::ty::{self, Ty};
|
||||
use session::config::{self, FullDebugInfo, LimitedDebugInfo, NoDebugInfo};
|
||||
use util::nodemap::{NodeMap, FnvHashMap, FnvHashSet};
|
||||
|
@ -418,19 +419,23 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|||
// Return type -- llvm::DIBuilder wants this at index 0
|
||||
assert_type_for_node_id(cx, fn_ast_id, error_reporting_span);
|
||||
let fn_type = cx.tcx().node_id_to_type(fn_ast_id);
|
||||
let fn_type = monomorphize::apply_param_substs(cx.tcx(), param_substs, &fn_type);
|
||||
|
||||
let (sig, abi) = match fn_type.sty {
|
||||
ty::TyBareFn(_, ref barefnty) => {
|
||||
(cx.tcx().erase_late_bound_regions(&barefnty.sig), barefnty.abi)
|
||||
let sig = cx.tcx().erase_late_bound_regions(&barefnty.sig);
|
||||
let sig = infer::normalize_associated_type(cx.tcx(), &sig);
|
||||
(sig, barefnty.abi)
|
||||
}
|
||||
ty::TyClosure(def_id, ref substs) => {
|
||||
let closure_type = cx.tcx().closure_type(def_id, substs);
|
||||
(cx.tcx().erase_late_bound_regions(&closure_type.sig), closure_type.abi)
|
||||
let sig = cx.tcx().erase_late_bound_regions(&closure_type.sig);
|
||||
let sig = infer::normalize_associated_type(cx.tcx(), &sig);
|
||||
(sig, closure_type.abi)
|
||||
}
|
||||
|
||||
_ => cx.sess().bug("get_function_metdata: Expected a function type!")
|
||||
};
|
||||
let sig = monomorphize::apply_param_substs(cx.tcx(), param_substs, &sig);
|
||||
|
||||
let mut signature = Vec::with_capacity(sig.inputs.len() + 1);
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ use super::namespace::crate_root_namespace;
|
|||
|
||||
use trans::common::CrateContext;
|
||||
use middle::def_id::DefId;
|
||||
use middle::infer;
|
||||
use middle::subst::{self, Substs};
|
||||
use middle::ty::{self, Ty};
|
||||
|
||||
|
@ -124,6 +125,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|||
output.push_str("fn(");
|
||||
|
||||
let sig = cx.tcx().erase_late_bound_regions(sig);
|
||||
let sig = infer::normalize_associated_type(cx.tcx(), &sig);
|
||||
if !sig.inputs.is_empty() {
|
||||
for ¶meter_type in &sig.inputs {
|
||||
push_debuginfo_type_name(cx, parameter_type, true, output);
|
||||
|
|
|
@ -103,9 +103,6 @@ pub fn declare_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, name: &str,
|
|||
fn_type: ty::Ty<'tcx>) -> ValueRef {
|
||||
debug!("declare_rust_fn(name={:?}, fn_type={:?})", name,
|
||||
fn_type);
|
||||
let fn_type = infer::normalize_associated_type(ccx.tcx(), &fn_type);
|
||||
debug!("declare_rust_fn (after normalised associated types) fn_type={:?}",
|
||||
fn_type);
|
||||
|
||||
let function_type; // placeholder so that the memory ownership works out ok
|
||||
let (sig, abi, env) = match fn_type.sty {
|
||||
|
@ -124,14 +121,15 @@ pub fn declare_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, name: &str,
|
|||
_ => ccx.sess().bug("expected closure or fn")
|
||||
};
|
||||
|
||||
let sig = ty::Binder(ccx.tcx().erase_late_bound_regions(sig));
|
||||
let sig = ccx.tcx().erase_late_bound_regions(sig);
|
||||
let sig = infer::normalize_associated_type(ccx.tcx(), &sig);
|
||||
debug!("declare_rust_fn (after region erasure) sig={:?}", sig);
|
||||
let llfty = type_of::type_of_rust_fn(ccx, env, &sig, abi);
|
||||
debug!("declare_rust_fn llfty={}", ccx.tn().type_to_string(llfty));
|
||||
|
||||
// it is ok to directly access sig.0.output because we erased all
|
||||
// late-bound-regions above
|
||||
let llfn = declare_fn(ccx, name, llvm::CCallConv, llfty, sig.0.output);
|
||||
let llfn = declare_fn(ccx, name, llvm::CCallConv, llfty, sig.output);
|
||||
attributes::from_fn_type(ccx, fn_type).apply_llfn(llfn);
|
||||
llfn
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ use intrinsics::{self, Intrinsic};
|
|||
use libc;
|
||||
use llvm;
|
||||
use llvm::{SequentiallyConsistent, Acquire, Release, AtomicXchg, ValueRef, TypeKind};
|
||||
use middle::infer;
|
||||
use middle::subst;
|
||||
use middle::subst::FnSpace;
|
||||
use trans::adt;
|
||||
|
@ -170,13 +171,10 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
|
|||
|
||||
let _icx = push_ctxt("trans_intrinsic_call");
|
||||
|
||||
let (arg_tys, ret_ty) = match callee_ty.sty {
|
||||
ty::TyBareFn(_, ref f) => {
|
||||
(bcx.tcx().erase_late_bound_regions(&f.sig.inputs()),
|
||||
bcx.tcx().erase_late_bound_regions(&f.sig.output()))
|
||||
}
|
||||
_ => panic!("expected bare_fn in trans_intrinsic_call")
|
||||
};
|
||||
let sig = ccx.tcx().erase_late_bound_regions(callee_ty.fn_sig());
|
||||
let sig = infer::normalize_associated_type(ccx.tcx(), &sig);
|
||||
let arg_tys = sig.inputs;
|
||||
let ret_ty = sig.output;
|
||||
let foreign_item = tcx.map.expect_foreign_item(node);
|
||||
let name = foreign_item.name.as_str();
|
||||
|
||||
|
@ -1330,12 +1328,9 @@ fn generic_simd_intrinsic<'blk, 'tcx, 'a>
|
|||
|
||||
|
||||
let tcx = bcx.tcx();
|
||||
let arg_tys = match callee_ty.sty {
|
||||
ty::TyBareFn(_, ref f) => {
|
||||
bcx.tcx().erase_late_bound_regions(&f.sig.inputs())
|
||||
}
|
||||
_ => unreachable!()
|
||||
};
|
||||
let sig = tcx.erase_late_bound_regions(callee_ty.fn_sig());
|
||||
let sig = infer::normalize_associated_type(tcx, &sig);
|
||||
let arg_tys = sig.inputs;
|
||||
|
||||
// every intrinsic takes a SIMD vector as its first argument
|
||||
require_simd!(arg_tys[0], "input");
|
||||
|
|
|
@ -12,6 +12,7 @@ use arena::TypedArena;
|
|||
use back::link;
|
||||
use llvm::{ValueRef, get_params};
|
||||
use middle::def_id::DefId;
|
||||
use middle::infer;
|
||||
use middle::subst::{Subst, Substs};
|
||||
use middle::subst::VecPerParamSpace;
|
||||
use middle::subst;
|
||||
|
@ -522,6 +523,7 @@ fn trans_object_shim<'a, 'tcx>(
|
|||
let llfn = declare::define_internal_rust_fn(ccx, &function_name, shim_fn_ty);
|
||||
|
||||
let sig = ccx.tcx().erase_late_bound_regions(&fty.sig);
|
||||
let sig = infer::normalize_associated_type(ccx.tcx(), &sig);
|
||||
|
||||
let empty_substs = tcx.mk_substs(Substs::trans_empty());
|
||||
let (block_arena, fcx): (TypedArena<_>, FunctionContext);
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#![allow(non_camel_case_types)]
|
||||
|
||||
use middle::def_id::DefId;
|
||||
use middle::infer;
|
||||
use middle::subst;
|
||||
use trans::adt;
|
||||
use trans::common::*;
|
||||
|
@ -89,7 +90,7 @@ pub fn untuple_arguments<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
|||
|
||||
pub fn type_of_rust_fn<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||
llenvironment_type: Option<Type>,
|
||||
sig: &ty::Binder<ty::FnSig<'tcx>>,
|
||||
sig: &ty::FnSig<'tcx>,
|
||||
abi: abi::Abi)
|
||||
-> Type
|
||||
{
|
||||
|
@ -97,16 +98,17 @@ pub fn type_of_rust_fn<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|||
sig,
|
||||
abi);
|
||||
|
||||
let sig = cx.tcx().erase_late_bound_regions(sig);
|
||||
assert!(!sig.variadic); // rust fns are never variadic
|
||||
|
||||
let mut atys: Vec<Type> = Vec::new();
|
||||
|
||||
// First, munge the inputs, if this has the `rust-call` ABI.
|
||||
let inputs = &if abi == abi::RustCall {
|
||||
untuple_arguments(cx, &sig.inputs)
|
||||
let inputs_temp;
|
||||
let inputs = if abi == abi::RustCall {
|
||||
inputs_temp = untuple_arguments(cx, &sig.inputs);
|
||||
&inputs_temp
|
||||
} else {
|
||||
sig.inputs
|
||||
&sig.inputs
|
||||
};
|
||||
|
||||
// Arg 0: Output pointer.
|
||||
|
@ -155,7 +157,9 @@ pub fn type_of_fn_from_ty<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, fty: Ty<'tcx>)
|
|||
// FIXME(#19925) once fn item types are
|
||||
// zero-sized, we'll need to do something here
|
||||
if f.abi == abi::Rust || f.abi == abi::RustCall {
|
||||
type_of_rust_fn(cx, None, &f.sig, f.abi)
|
||||
let sig = cx.tcx().erase_late_bound_regions(&f.sig);
|
||||
let sig = infer::normalize_associated_type(cx.tcx(), &sig);
|
||||
type_of_rust_fn(cx, None, &sig, f.abi)
|
||||
} else {
|
||||
foreign::lltype_for_foreign_fn(cx, fty)
|
||||
}
|
||||
|
|
23
src/test/run-pass/issue-23406.rs
Normal file
23
src/test/run-pass/issue-23406.rs
Normal file
|
@ -0,0 +1,23 @@
|
|||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
trait Inner {
|
||||
type T;
|
||||
}
|
||||
|
||||
impl<'a> Inner for &'a i32 {
|
||||
type T = i32;
|
||||
}
|
||||
|
||||
fn f<'a>(x: &'a i32) -> <&'a i32 as Inner>::T {
|
||||
*x
|
||||
}
|
||||
|
||||
fn main() {}
|
22
src/test/run-pass/issue-23598.rs
Normal file
22
src/test/run-pass/issue-23598.rs
Normal file
|
@ -0,0 +1,22 @@
|
|||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
trait Collection where for<'a> &'a Self: IntoIterator {
|
||||
fn my_iter(&self) -> <&Self as IntoIterator>::IntoIter {
|
||||
self.into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Collection for [T] { }
|
||||
|
||||
fn main() {
|
||||
let v = [0usize];
|
||||
let _ = v.my_iter();
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue