typeck: disallow impl Trait
outside of return types of functions and impl methods.
This commit is contained in:
parent
ef11d4e3c7
commit
1ef7ddfda3
5 changed files with 174 additions and 43 deletions
|
@ -832,7 +832,10 @@ fn insert_late_bound_lifetimes(map: &mut NamedRegionMap,
|
||||||
constrained_by_input.visit_ty(&arg.ty);
|
constrained_by_input.visit_ty(&arg.ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut appears_in_output = AllCollector { regions: FnvHashSet() };
|
let mut appears_in_output = AllCollector {
|
||||||
|
regions: FnvHashSet(),
|
||||||
|
impl_trait: false
|
||||||
|
};
|
||||||
intravisit::walk_fn_ret_ty(&mut appears_in_output, &decl.output);
|
intravisit::walk_fn_ret_ty(&mut appears_in_output, &decl.output);
|
||||||
|
|
||||||
debug!("insert_late_bound_lifetimes: constrained_by_input={:?}",
|
debug!("insert_late_bound_lifetimes: constrained_by_input={:?}",
|
||||||
|
@ -842,7 +845,10 @@ fn insert_late_bound_lifetimes(map: &mut NamedRegionMap,
|
||||||
//
|
//
|
||||||
// Subtle point: because we disallow nested bindings, we can just
|
// Subtle point: because we disallow nested bindings, we can just
|
||||||
// ignore binders here and scrape up all names we see.
|
// ignore binders here and scrape up all names we see.
|
||||||
let mut appears_in_where_clause = AllCollector { regions: FnvHashSet() };
|
let mut appears_in_where_clause = AllCollector {
|
||||||
|
regions: FnvHashSet(),
|
||||||
|
impl_trait: false
|
||||||
|
};
|
||||||
for ty_param in generics.ty_params.iter() {
|
for ty_param in generics.ty_params.iter() {
|
||||||
walk_list!(&mut appears_in_where_clause,
|
walk_list!(&mut appears_in_where_clause,
|
||||||
visit_ty_param_bound,
|
visit_ty_param_bound,
|
||||||
|
@ -864,12 +870,16 @@ fn insert_late_bound_lifetimes(map: &mut NamedRegionMap,
|
||||||
// Late bound regions are those that:
|
// Late bound regions are those that:
|
||||||
// - appear in the inputs
|
// - appear in the inputs
|
||||||
// - do not appear in the where-clauses
|
// - do not appear in the where-clauses
|
||||||
|
// - are not implicitly captured by `impl Trait`
|
||||||
for lifetime in &generics.lifetimes {
|
for lifetime in &generics.lifetimes {
|
||||||
let name = lifetime.lifetime.name;
|
let name = lifetime.lifetime.name;
|
||||||
|
|
||||||
// appears in the where clauses? early-bound.
|
// appears in the where clauses? early-bound.
|
||||||
if appears_in_where_clause.regions.contains(&name) { continue; }
|
if appears_in_where_clause.regions.contains(&name) { continue; }
|
||||||
|
|
||||||
|
// any `impl Trait` in the return type? early-bound.
|
||||||
|
if appears_in_output.impl_trait { continue; }
|
||||||
|
|
||||||
// does not appear in the inputs, but appears in the return
|
// does not appear in the inputs, but appears in the return
|
||||||
// type? eventually this will be early-bound, but for now we
|
// type? eventually this will be early-bound, but for now we
|
||||||
// just mark it so we can issue warnings.
|
// just mark it so we can issue warnings.
|
||||||
|
@ -932,12 +942,20 @@ fn insert_late_bound_lifetimes(map: &mut NamedRegionMap,
|
||||||
|
|
||||||
struct AllCollector {
|
struct AllCollector {
|
||||||
regions: FnvHashSet<ast::Name>,
|
regions: FnvHashSet<ast::Name>,
|
||||||
|
impl_trait: bool
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'v> Visitor<'v> for AllCollector {
|
impl<'v> Visitor<'v> for AllCollector {
|
||||||
fn visit_lifetime(&mut self, lifetime_ref: &'v hir::Lifetime) {
|
fn visit_lifetime(&mut self, lifetime_ref: &'v hir::Lifetime) {
|
||||||
self.regions.insert(lifetime_ref.name);
|
self.regions.insert(lifetime_ref.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_ty(&mut self, ty: &hir::Ty) {
|
||||||
|
if let hir::TyImplTrait(_) = ty.node {
|
||||||
|
self.impl_trait = true;
|
||||||
|
}
|
||||||
|
intravisit::walk_ty(self, ty);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -65,6 +65,7 @@ use require_c_abi_if_variadic;
|
||||||
use rscope::{self, UnelidableRscope, RegionScope, ElidableRscope,
|
use rscope::{self, UnelidableRscope, RegionScope, ElidableRscope,
|
||||||
ObjectLifetimeDefaultRscope, ShiftedRscope, BindingRscope,
|
ObjectLifetimeDefaultRscope, ShiftedRscope, BindingRscope,
|
||||||
ElisionFailureInfo, ElidedLifetime};
|
ElisionFailureInfo, ElidedLifetime};
|
||||||
|
use rscope::{AnonTypeScope, MaybeWithAnonTypes};
|
||||||
use util::common::{ErrorReported, FN_OUTPUT_NAME};
|
use util::common::{ErrorReported, FN_OUTPUT_NAME};
|
||||||
use util::nodemap::{NodeMap, FnvHashSet};
|
use util::nodemap::{NodeMap, FnvHashSet};
|
||||||
|
|
||||||
|
@ -635,20 +636,21 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||||
|
|
||||||
fn convert_ty_with_lifetime_elision(&self,
|
fn convert_ty_with_lifetime_elision(&self,
|
||||||
elided_lifetime: ElidedLifetime,
|
elided_lifetime: ElidedLifetime,
|
||||||
ty: &hir::Ty)
|
ty: &hir::Ty,
|
||||||
|
anon_scope: Option<AnonTypeScope>)
|
||||||
-> Ty<'tcx>
|
-> Ty<'tcx>
|
||||||
{
|
{
|
||||||
match elided_lifetime {
|
match elided_lifetime {
|
||||||
Ok(implied_output_region) => {
|
Ok(implied_output_region) => {
|
||||||
let rb = ElidableRscope::new(implied_output_region);
|
let rb = ElidableRscope::new(implied_output_region);
|
||||||
self.ast_ty_to_ty(&rb, ty)
|
self.ast_ty_to_ty(&MaybeWithAnonTypes::new(rb, anon_scope), ty)
|
||||||
}
|
}
|
||||||
Err(param_lifetimes) => {
|
Err(param_lifetimes) => {
|
||||||
// All regions must be explicitly specified in the output
|
// All regions must be explicitly specified in the output
|
||||||
// if the lifetime elision rules do not apply. This saves
|
// if the lifetime elision rules do not apply. This saves
|
||||||
// the user from potentially-confusing errors.
|
// the user from potentially-confusing errors.
|
||||||
let rb = UnelidableRscope::new(param_lifetimes);
|
let rb = UnelidableRscope::new(param_lifetimes);
|
||||||
self.ast_ty_to_ty(&rb, ty)
|
self.ast_ty_to_ty(&MaybeWithAnonTypes::new(rb, anon_scope), ty)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -665,7 +667,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||||
let region_substs =
|
let region_substs =
|
||||||
self.create_region_substs(rscope, span, decl_generics, Vec::new());
|
self.create_region_substs(rscope, span, decl_generics, Vec::new());
|
||||||
|
|
||||||
let binding_rscope = BindingRscope::new();
|
let anon_scope = rscope.anon_type_scope();
|
||||||
|
let binding_rscope = MaybeWithAnonTypes::new(BindingRscope::new(), anon_scope);
|
||||||
let inputs =
|
let inputs =
|
||||||
data.inputs.iter()
|
data.inputs.iter()
|
||||||
.map(|a_t| self.ast_ty_arg_to_ty(&binding_rscope, decl_generics,
|
.map(|a_t| self.ast_ty_arg_to_ty(&binding_rscope, decl_generics,
|
||||||
|
@ -679,7 +682,9 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||||
|
|
||||||
let (output, output_span) = match data.output {
|
let (output, output_span) = match data.output {
|
||||||
Some(ref output_ty) => {
|
Some(ref output_ty) => {
|
||||||
(self.convert_ty_with_lifetime_elision(implied_output_region, &output_ty),
|
(self.convert_ty_with_lifetime_elision(implied_output_region,
|
||||||
|
&output_ty,
|
||||||
|
anon_scope),
|
||||||
output_ty.span)
|
output_ty.span)
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
|
@ -1703,7 +1708,14 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||||
}
|
}
|
||||||
hir::TyBareFn(ref bf) => {
|
hir::TyBareFn(ref bf) => {
|
||||||
require_c_abi_if_variadic(tcx, &bf.decl, bf.abi, ast_ty.span);
|
require_c_abi_if_variadic(tcx, &bf.decl, bf.abi, ast_ty.span);
|
||||||
let bare_fn_ty = self.ty_of_bare_fn(bf.unsafety, bf.abi, &bf.decl);
|
let anon_scope = rscope.anon_type_scope();
|
||||||
|
let (bare_fn_ty, _) =
|
||||||
|
self.ty_of_method_or_bare_fn(bf.unsafety,
|
||||||
|
bf.abi,
|
||||||
|
None,
|
||||||
|
&bf.decl,
|
||||||
|
anon_scope,
|
||||||
|
anon_scope);
|
||||||
|
|
||||||
// Find any late-bound regions declared in return type that do
|
// Find any late-bound regions declared in return type that do
|
||||||
// not appear in the arguments. These are not wellformed.
|
// not appear in the arguments. These are not wellformed.
|
||||||
|
@ -1751,10 +1763,17 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||||
|
|
||||||
// Create the anonymized type.
|
// Create the anonymized type.
|
||||||
let def_id = tcx.map.local_def_id(ast_ty.id);
|
let def_id = tcx.map.local_def_id(ast_ty.id);
|
||||||
let substs = tcx.mk_substs(Substs::empty());
|
let substs = if let Some(anon_scope) = rscope.anon_type_scope() {
|
||||||
|
anon_scope.fresh_substs(tcx)
|
||||||
|
} else {
|
||||||
|
span_err!(tcx.sess, ast_ty.span, E0562,
|
||||||
|
"`impl Trait` not allowed outside of function \
|
||||||
|
and inherent method return types");
|
||||||
|
tcx.mk_substs(Substs::empty())
|
||||||
|
};
|
||||||
let ty = tcx.mk_anon(tcx.map.local_def_id(ast_ty.id), substs);
|
let ty = tcx.mk_anon(tcx.map.local_def_id(ast_ty.id), substs);
|
||||||
|
|
||||||
// Collect the bounds, i.e. the `Trait` in `impl Trait`.
|
// Collect the bounds, i.e. the `A+B+'c` in `impl A+B+'c`.
|
||||||
let bounds = compute_bounds(self, ty, bounds, SizedByDefault::Yes, ast_ty.span);
|
let bounds = compute_bounds(self, ty, bounds, SizedByDefault::Yes, ast_ty.span);
|
||||||
let predicates = tcx.lift_to_global(&bounds.predicates(tcx, ty)).unwrap();
|
let predicates = tcx.lift_to_global(&bounds.predicates(tcx, ty)).unwrap();
|
||||||
let predicates = ty::GenericPredicates {
|
let predicates = ty::GenericPredicates {
|
||||||
|
@ -1828,36 +1847,40 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||||
|
|
||||||
pub fn ty_of_method(&self,
|
pub fn ty_of_method(&self,
|
||||||
sig: &hir::MethodSig,
|
sig: &hir::MethodSig,
|
||||||
untransformed_self_ty: Ty<'tcx>)
|
untransformed_self_ty: Ty<'tcx>,
|
||||||
|
anon_scope: Option<AnonTypeScope>)
|
||||||
-> (&'tcx ty::BareFnTy<'tcx>, ty::ExplicitSelfCategory) {
|
-> (&'tcx ty::BareFnTy<'tcx>, ty::ExplicitSelfCategory) {
|
||||||
let (bare_fn_ty, optional_explicit_self_category) =
|
self.ty_of_method_or_bare_fn(sig.unsafety,
|
||||||
self.ty_of_method_or_bare_fn(sig.unsafety,
|
sig.abi,
|
||||||
sig.abi,
|
Some(untransformed_self_ty),
|
||||||
Some(untransformed_self_ty),
|
&sig.decl,
|
||||||
&sig.decl);
|
None,
|
||||||
(bare_fn_ty, optional_explicit_self_category)
|
anon_scope)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ty_of_bare_fn(&self,
|
pub fn ty_of_bare_fn(&self,
|
||||||
unsafety: hir::Unsafety,
|
unsafety: hir::Unsafety,
|
||||||
abi: abi::Abi,
|
abi: abi::Abi,
|
||||||
decl: &hir::FnDecl)
|
decl: &hir::FnDecl,
|
||||||
|
anon_scope: Option<AnonTypeScope>)
|
||||||
-> &'tcx ty::BareFnTy<'tcx> {
|
-> &'tcx ty::BareFnTy<'tcx> {
|
||||||
self.ty_of_method_or_bare_fn(unsafety, abi, None, decl).0
|
self.ty_of_method_or_bare_fn(unsafety, abi, None, decl, None, anon_scope).0
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ty_of_method_or_bare_fn<'a>(&self,
|
fn ty_of_method_or_bare_fn(&self,
|
||||||
unsafety: hir::Unsafety,
|
unsafety: hir::Unsafety,
|
||||||
abi: abi::Abi,
|
abi: abi::Abi,
|
||||||
opt_untransformed_self_ty: Option<Ty<'tcx>>,
|
opt_untransformed_self_ty: Option<Ty<'tcx>>,
|
||||||
decl: &hir::FnDecl)
|
decl: &hir::FnDecl,
|
||||||
-> (&'tcx ty::BareFnTy<'tcx>, ty::ExplicitSelfCategory)
|
arg_anon_scope: Option<AnonTypeScope>,
|
||||||
|
ret_anon_scope: Option<AnonTypeScope>)
|
||||||
|
-> (&'tcx ty::BareFnTy<'tcx>, ty::ExplicitSelfCategory)
|
||||||
{
|
{
|
||||||
debug!("ty_of_method_or_bare_fn");
|
debug!("ty_of_method_or_bare_fn");
|
||||||
|
|
||||||
// New region names that appear inside of the arguments of the function
|
// New region names that appear inside of the arguments of the function
|
||||||
// declaration are bound to that function type.
|
// declaration are bound to that function type.
|
||||||
let rb = rscope::BindingRscope::new();
|
let rb = MaybeWithAnonTypes::new(BindingRscope::new(), arg_anon_scope);
|
||||||
|
|
||||||
// `implied_output_region` is the region that will be assumed for any
|
// `implied_output_region` is the region that will be assumed for any
|
||||||
// region parameters in the return type. In accordance with the rules for
|
// region parameters in the return type. In accordance with the rules for
|
||||||
|
@ -1895,7 +1918,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||||
let output_ty = match decl.output {
|
let output_ty = match decl.output {
|
||||||
hir::Return(ref output) =>
|
hir::Return(ref output) =>
|
||||||
ty::FnConverging(self.convert_ty_with_lifetime_elision(implied_output_region,
|
ty::FnConverging(self.convert_ty_with_lifetime_elision(implied_output_region,
|
||||||
&output)),
|
&output,
|
||||||
|
ret_anon_scope)),
|
||||||
hir::DefaultReturn(..) => ty::FnConverging(self.tcx().mk_nil()),
|
hir::DefaultReturn(..) => ty::FnConverging(self.tcx().mk_nil()),
|
||||||
hir::NoReturn(..) => ty::FnDiverging
|
hir::NoReturn(..) => ty::FnDiverging
|
||||||
};
|
};
|
||||||
|
|
|
@ -564,13 +564,17 @@ fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||||
let ty_generic_predicates =
|
let ty_generic_predicates =
|
||||||
ty_generic_predicates_for_fn(ccx, &sig.generics, rcvr_ty_predicates);
|
ty_generic_predicates_for_fn(ccx, &sig.generics, rcvr_ty_predicates);
|
||||||
|
|
||||||
let (fty, explicit_self_category) =
|
let (fty, explicit_self_category) = {
|
||||||
|
let anon_scope = match container {
|
||||||
|
ImplContainer(_) => Some(AnonTypeScope::new(&ty_generics)),
|
||||||
|
TraitContainer(_) => None
|
||||||
|
};
|
||||||
AstConv::ty_of_method(&ccx.icx(&(rcvr_ty_predicates, &sig.generics)),
|
AstConv::ty_of_method(&ccx.icx(&(rcvr_ty_predicates, &sig.generics)),
|
||||||
sig,
|
sig, untransformed_rcvr_ty, anon_scope)
|
||||||
untransformed_rcvr_ty);
|
};
|
||||||
|
|
||||||
let def_id = ccx.tcx.map.local_def_id(id);
|
let def_id = ccx.tcx.map.local_def_id(id);
|
||||||
let substs = mk_item_substs(ccx, &ty_generics);
|
let substs = mk_item_substs(ccx.tcx, &ty_generics);
|
||||||
|
|
||||||
let ty_method = ty::Method::new(name,
|
let ty_method = ty::Method::new(name,
|
||||||
ty_generics,
|
ty_generics,
|
||||||
|
@ -961,7 +965,7 @@ fn convert_variant_ctor<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||||
.map(|field| field.unsubst_ty())
|
.map(|field| field.unsubst_ty())
|
||||||
.collect();
|
.collect();
|
||||||
let def_id = tcx.map.local_def_id(ctor_id);
|
let def_id = tcx.map.local_def_id(ctor_id);
|
||||||
let substs = mk_item_substs(ccx, &scheme.generics);
|
let substs = mk_item_substs(tcx, &scheme.generics);
|
||||||
tcx.mk_fn_def(def_id, substs, tcx.mk_bare_fn(ty::BareFnTy {
|
tcx.mk_fn_def(def_id, substs, tcx.mk_bare_fn(ty::BareFnTy {
|
||||||
unsafety: hir::Unsafety::Normal,
|
unsafety: hir::Unsafety::Normal,
|
||||||
abi: abi::Abi::Rust,
|
abi: abi::Abi::Rust,
|
||||||
|
@ -1460,9 +1464,10 @@ fn compute_type_scheme_of_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
|
||||||
}
|
}
|
||||||
hir::ItemFn(ref decl, unsafety, _, abi, ref generics, _) => {
|
hir::ItemFn(ref decl, unsafety, _, abi, ref generics, _) => {
|
||||||
let ty_generics = ty_generics_for_fn(ccx, generics, &ty::Generics::empty());
|
let ty_generics = ty_generics_for_fn(ccx, generics, &ty::Generics::empty());
|
||||||
let tofd = AstConv::ty_of_bare_fn(&ccx.icx(generics), unsafety, abi, &decl);
|
let tofd = AstConv::ty_of_bare_fn(&ccx.icx(generics), unsafety, abi, &decl,
|
||||||
|
Some(AnonTypeScope::new(&ty_generics)));
|
||||||
let def_id = ccx.tcx.map.local_def_id(it.id);
|
let def_id = ccx.tcx.map.local_def_id(it.id);
|
||||||
let substs = mk_item_substs(ccx, &ty_generics);
|
let substs = mk_item_substs(tcx, &ty_generics);
|
||||||
let ty = tcx.mk_fn_def(def_id, substs, tofd);
|
let ty = tcx.mk_fn_def(def_id, substs, tofd);
|
||||||
ty::TypeScheme { ty: ty, generics: ty_generics }
|
ty::TypeScheme { ty: ty, generics: ty_generics }
|
||||||
}
|
}
|
||||||
|
@ -1474,14 +1479,14 @@ fn compute_type_scheme_of_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
|
||||||
hir::ItemEnum(ref ei, ref generics) => {
|
hir::ItemEnum(ref ei, ref generics) => {
|
||||||
let def = convert_enum_def(ccx, it, ei);
|
let def = convert_enum_def(ccx, it, ei);
|
||||||
let ty_generics = ty_generics_for_type(ccx, generics);
|
let ty_generics = ty_generics_for_type(ccx, generics);
|
||||||
let substs = mk_item_substs(ccx, &ty_generics);
|
let substs = mk_item_substs(tcx, &ty_generics);
|
||||||
let t = tcx.mk_enum(def, substs);
|
let t = tcx.mk_enum(def, substs);
|
||||||
ty::TypeScheme { ty: t, generics: ty_generics }
|
ty::TypeScheme { ty: t, generics: ty_generics }
|
||||||
}
|
}
|
||||||
hir::ItemStruct(ref si, ref generics) => {
|
hir::ItemStruct(ref si, ref generics) => {
|
||||||
let def = convert_struct_def(ccx, it, si);
|
let def = convert_struct_def(ccx, it, si);
|
||||||
let ty_generics = ty_generics_for_type(ccx, generics);
|
let ty_generics = ty_generics_for_type(ccx, generics);
|
||||||
let substs = mk_item_substs(ccx, &ty_generics);
|
let substs = mk_item_substs(tcx, &ty_generics);
|
||||||
let t = tcx.mk_struct(def, substs);
|
let t = tcx.mk_struct(def, substs);
|
||||||
ty::TypeScheme { ty: t, generics: ty_generics }
|
ty::TypeScheme { ty: t, generics: ty_generics }
|
||||||
}
|
}
|
||||||
|
@ -2194,7 +2199,7 @@ fn compute_type_scheme_of_foreign_fn_decl<'a, 'tcx>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let substs = mk_item_substs(ccx, &ty_generics);
|
let substs = mk_item_substs(ccx.tcx, &ty_generics);
|
||||||
let t_fn = ccx.tcx.mk_fn_def(id, substs, ccx.tcx.mk_bare_fn(ty::BareFnTy {
|
let t_fn = ccx.tcx.mk_fn_def(id, substs, ccx.tcx.mk_bare_fn(ty::BareFnTy {
|
||||||
abi: abi,
|
abi: abi,
|
||||||
unsafety: hir::Unsafety::Unsafe,
|
unsafety: hir::Unsafety::Unsafe,
|
||||||
|
@ -2209,19 +2214,19 @@ fn compute_type_scheme_of_foreign_fn_decl<'a, 'tcx>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mk_item_substs<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
pub fn mk_item_substs<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||||
ty_generics: &ty::Generics<'tcx>)
|
ty_generics: &ty::Generics)
|
||||||
-> &'tcx Substs<'tcx>
|
-> &'tcx Substs<'tcx>
|
||||||
{
|
{
|
||||||
let types =
|
let types =
|
||||||
ty_generics.types.map(
|
ty_generics.types.map(
|
||||||
|def| ccx.tcx.mk_param_from_def(def));
|
|def| tcx.mk_param_from_def(def));
|
||||||
|
|
||||||
let regions =
|
let regions =
|
||||||
ty_generics.regions.map(
|
ty_generics.regions.map(
|
||||||
|def| def.to_early_bound_region());
|
|def| def.to_early_bound_region());
|
||||||
|
|
||||||
ccx.tcx.mk_substs(Substs::new(types, regions))
|
tcx.mk_substs(Substs::new(types, regions))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks that all the type parameters on an impl
|
/// Checks that all the type parameters on an impl
|
||||||
|
|
|
@ -4084,4 +4084,6 @@ register_diagnostics! {
|
||||||
E0513, // no type for local variable ..
|
E0513, // no type for local variable ..
|
||||||
E0521, // redundant default implementations of trait
|
E0521, // redundant default implementations of trait
|
||||||
E0533, // `{}` does not name a unit variant, unit struct or a constant
|
E0533, // `{}` does not name a unit variant, unit struct or a constant
|
||||||
|
E0562, // `impl Trait` not allowed outside of function
|
||||||
|
// and inherent method return types
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,8 @@
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
|
|
||||||
use rustc::ty;
|
use rustc::ty::{self, TyCtxt};
|
||||||
|
use rustc::ty::subst::Substs;
|
||||||
|
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use syntax_pos::Span;
|
use syntax_pos::Span;
|
||||||
|
@ -50,6 +51,79 @@ pub trait RegionScope {
|
||||||
/// computing `object_lifetime_default` (in particular, in legacy
|
/// computing `object_lifetime_default` (in particular, in legacy
|
||||||
/// modes, it may not be relevant).
|
/// modes, it may not be relevant).
|
||||||
fn base_object_lifetime_default(&self, span: Span) -> ty::Region;
|
fn base_object_lifetime_default(&self, span: Span) -> ty::Region;
|
||||||
|
|
||||||
|
/// If this scope allows anonymized types, return the generics in
|
||||||
|
/// scope, that anonymized types will close over. For example,
|
||||||
|
/// if you have a function like:
|
||||||
|
///
|
||||||
|
/// fn foo<'a, T>() -> impl Trait { ... }
|
||||||
|
///
|
||||||
|
/// then, for the rscope that is used when handling the return type,
|
||||||
|
/// `anon_type_scope()` would return a `Some(AnonTypeScope {...})`,
|
||||||
|
/// on which `.fresh_substs(...)` can be used to obtain identity
|
||||||
|
/// Substs for `'a` and `T`, to track them in `TyAnon`. This property
|
||||||
|
/// is controlled by the region scope because it's fine-grained enough
|
||||||
|
/// to allow restriction of anonymized types to the syntactical extent
|
||||||
|
/// of a function's return type.
|
||||||
|
fn anon_type_scope(&self) -> Option<AnonTypeScope> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct AnonTypeScope<'a> {
|
||||||
|
generics: &'a ty::Generics<'a>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'b, 'gcx, 'tcx> AnonTypeScope<'a> {
|
||||||
|
pub fn new(generics: &'a ty::Generics<'a>) -> AnonTypeScope<'a> {
|
||||||
|
AnonTypeScope {
|
||||||
|
generics: generics
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fresh_substs(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> &'tcx Substs<'tcx> {
|
||||||
|
use collect::mk_item_substs;
|
||||||
|
|
||||||
|
mk_item_substs(tcx, self.generics)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A scope wrapper which optionally allows anonymized types.
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct MaybeWithAnonTypes<'a, R> {
|
||||||
|
base_scope: R,
|
||||||
|
anon_scope: Option<AnonTypeScope<'a>>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, R: RegionScope> MaybeWithAnonTypes<'a, R> {
|
||||||
|
pub fn new(base_scope: R, anon_scope: Option<AnonTypeScope<'a>>) -> Self {
|
||||||
|
MaybeWithAnonTypes {
|
||||||
|
base_scope: base_scope,
|
||||||
|
anon_scope: anon_scope
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, R: RegionScope> RegionScope for MaybeWithAnonTypes<'a, R> {
|
||||||
|
fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
|
||||||
|
self.base_scope.object_lifetime_default(span)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn anon_regions(&self,
|
||||||
|
span: Span,
|
||||||
|
count: usize)
|
||||||
|
-> Result<Vec<ty::Region>, Option<Vec<ElisionFailureInfo>>> {
|
||||||
|
self.base_scope.anon_regions(span, count)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn base_object_lifetime_default(&self, span: Span) -> ty::Region {
|
||||||
|
self.base_scope.base_object_lifetime_default(span)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn anon_type_scope(&self) -> Option<AnonTypeScope> {
|
||||||
|
self.anon_scope
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// A scope in which all regions must be explicitly named. This is used
|
// A scope in which all regions must be explicitly named. This is used
|
||||||
|
@ -221,6 +295,10 @@ impl<'r> RegionScope for ObjectLifetimeDefaultRscope<'r> {
|
||||||
{
|
{
|
||||||
self.base_scope.anon_regions(span, count)
|
self.base_scope.anon_regions(span, count)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn anon_type_scope(&self) -> Option<AnonTypeScope> {
|
||||||
|
self.base_scope.anon_type_scope()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A scope which simply shifts the Debruijn index of other scopes
|
/// A scope which simply shifts the Debruijn index of other scopes
|
||||||
|
@ -262,4 +340,8 @@ impl<'r> RegionScope for ShiftedRscope<'r> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn anon_type_scope(&self) -> Option<AnonTypeScope> {
|
||||||
|
self.base_scope.anon_type_scope()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue