提交 9783947c 编写于 作者: E Eduard-Mihai Burtescu

rustc_typeck: move impl Trait checks out of RegionScope.

上级 ba1849da
......@@ -62,7 +62,7 @@
use rustc_back::slice;
use require_c_abi_if_variadic;
use rscope::{RegionScope, ObjectLifetimeDefaultRscope, ShiftedRscope};
use rscope::{AnonTypeScope, MaybeWithAnonTypes, ExplicitRscope};
use rscope::ExplicitRscope;
use util::common::{ErrorReported, FN_OUTPUT_NAME};
use util::nodemap::{NodeMap, FxHashSet};
......@@ -361,8 +361,7 @@ fn create_substs_for_ast_path(&self,
}
hir::ParenthesizedParameters(ref data) => {
assert_eq!(i, 0);
let (ty, assoc) =
self.convert_parenthesized_parameters(rscope, substs, data);
let (ty, assoc) = self.convert_parenthesized_parameters(substs, data);
output_assoc_binding = Some(assoc);
ty
}
......@@ -416,7 +415,7 @@ fn create_substs_for_ast_path(&self,
vec![output_assoc_binding.unwrap_or_else(|| {
// This is an error condition, but we should
// get the associated type binding anyway.
self.convert_parenthesized_parameters(rscope, substs, data).1
self.convert_parenthesized_parameters(substs, data).1
})]
}
};
......@@ -428,20 +427,17 @@ fn create_substs_for_ast_path(&self,
}
fn convert_parenthesized_parameters(&self,
rscope: &RegionScope,
region_substs: &[Kind<'tcx>],
data: &hir::ParenthesizedParameterData)
-> (Ty<'tcx>, ConvertedBinding<'tcx>)
{
let anon_scope = rscope.anon_type_scope();
let rscope = MaybeWithAnonTypes::new(ExplicitRscope, anon_scope);
let inputs = self.tcx().mk_type_list(data.inputs.iter().map(|a_t| {
self.ast_ty_arg_to_ty(&rscope, None, region_substs, a_t)
self.ast_ty_arg_to_ty(&ExplicitRscope, None, region_substs, a_t)
}));
let (output, output_span) = match data.output {
Some(ref output_ty) => {
(self.ast_ty_to_ty(&rscope, output_ty), output_ty.span)
(self.ast_ty_to_ty(&ExplicitRscope, output_ty), output_ty.span)
}
None => {
(self.tcx().mk_nil(), data.span)
......@@ -1309,12 +1305,7 @@ pub fn ast_ty_to_ty(&self, rscope: &RegionScope, ast_ty: &hir::Ty) -> Ty<'tcx> {
}
hir::TyBareFn(ref bf) => {
require_c_abi_if_variadic(tcx, &bf.decl, bf.abi, ast_ty.span);
let anon_scope = rscope.anon_type_scope();
let bare_fn_ty = self.ty_of_method_or_bare_fn(bf.unsafety,
bf.abi,
&bf.decl,
anon_scope,
anon_scope);
let bare_fn_ty = self.ty_of_fn(bf.unsafety, bf.abi, &bf.decl);
// Find any late-bound regions declared in return type that do
// not appear in the arguments. These are not wellformed.
......@@ -1361,16 +1352,54 @@ pub fn ast_ty_to_ty(&self, rscope: &RegionScope, ast_ty: &hir::Ty) -> Ty<'tcx> {
hir::TyImplTrait(ref bounds) => {
use collect::{compute_bounds, SizedByDefault};
// Figure out if we can allow an `impl Trait` here, by walking up
// to a `fn` or inherent `impl` method, going only through `Ty`
// or `TraitRef` nodes (as nothing else should be in types) and
// ensuring that we reach the `fn`/method signature's return type.
let mut node_id = ast_ty.id;
let fn_decl = loop {
let parent = tcx.hir.get_parent_node(node_id);
match tcx.hir.get(parent) {
hir::map::NodeItem(&hir::Item {
node: hir::ItemFn(ref fn_decl, ..), ..
}) => break Some(fn_decl),
hir::map::NodeImplItem(&hir::ImplItem {
node: hir::ImplItemKind::Method(ref sig, _), ..
}) => {
match tcx.hir.expect_item(tcx.hir.get_parent(parent)).node {
hir::ItemImpl(.., None, _, _) => {
break Some(&sig.decl)
}
_ => break None
}
}
hir::map::NodeTy(_) | hir::map::NodeTraitRef(_) => {}
_ => break None
}
node_id = parent;
};
let allow = fn_decl.map_or(false, |fd| {
match fd.output {
hir::DefaultReturn(_) => false,
hir::Return(ref ty) => ty.id == node_id
}
});
// Create the anonymized type.
let def_id = tcx.hir.local_def_id(ast_ty.id);
if let Some(anon_scope) = rscope.anon_type_scope() {
let substs = anon_scope.fresh_substs(self, ast_ty.span);
if allow {
let def_id = tcx.hir.local_def_id(ast_ty.id);
if let Err(ErrorReported) = self.get_generics(ast_ty.span, def_id) {
return tcx.types.err;
}
let substs = Substs::identity_for_item(tcx, def_id);
let ty = tcx.mk_anon(tcx.hir.local_def_id(ast_ty.id), substs);
// Collect the bounds, i.e. the `A+B+'c` in `impl A+B+'c`.
let bounds = compute_bounds(self, ty, bounds,
SizedByDefault::Yes,
Some(anon_scope),
ast_ty.span);
let predicates = bounds.predicates(tcx, ty);
let predicates = tcx.lift_to_global(&predicates).unwrap();
......@@ -1450,36 +1479,19 @@ pub fn ty_of_arg(&self,
pub fn ty_of_fn(&self,
unsafety: hir::Unsafety,
abi: abi::Abi,
decl: &hir::FnDecl,
anon_scope: Option<AnonTypeScope>)
decl: &hir::FnDecl)
-> &'tcx ty::BareFnTy<'tcx> {
self.ty_of_method_or_bare_fn(unsafety, abi, decl, None, anon_scope)
}
fn ty_of_method_or_bare_fn(&self,
unsafety: hir::Unsafety,
abi: abi::Abi,
decl: &hir::FnDecl,
arg_anon_scope: Option<AnonTypeScope>,
ret_anon_scope: Option<AnonTypeScope>)
-> &'tcx ty::BareFnTy<'tcx>
{
debug!("ty_of_method_or_bare_fn");
// New region names that appear inside of the arguments of the function
// declaration are bound to that function type.
let rb = MaybeWithAnonTypes::new(ExplicitRscope, arg_anon_scope);
debug!("ty_of_fn");
let input_tys: Vec<Ty> =
decl.inputs.iter().map(|a| self.ty_of_arg(&rb, a, None)).collect();
decl.inputs.iter().map(|a| self.ty_of_arg(&ExplicitRscope, a, None)).collect();
let output_ty = match decl.output {
hir::Return(ref output) =>
self.ast_ty_to_ty(&MaybeWithAnonTypes::new(ExplicitRscope, ret_anon_scope), output),
hir::Return(ref output) => self.ast_ty_to_ty(&ExplicitRscope, output),
hir::DefaultReturn(..) => self.tcx().mk_nil(),
};
debug!("ty_of_method_or_bare_fn: output_ty={:?}", output_ty);
debug!("ty_of_fn: output_ty={:?}", output_ty);
self.tcx().mk_bare_fn(ty::BareFnTy {
unsafety: unsafety,
......
......@@ -641,7 +641,6 @@ fn convert_field<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
}
fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
container: AssociatedItemContainer,
id: ast::NodeId,
sig: &hir::MethodSig,
rcvr_ty_predicates: &ty::GenericPredicates<'tcx>,) {
......@@ -651,12 +650,8 @@ fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
let ty_generic_predicates =
ty_generic_predicates(ccx, &sig.generics, ty_generics.parent, vec![], false);
let anon_scope = match container {
ImplContainer(_) => Some(AnonTypeScope::new(def_id)),
TraitContainer(_) => None
};
let fty = AstConv::ty_of_fn(&ccx.icx(&(rcvr_ty_predicates, &sig.generics)),
sig.unsafety, sig.abi, &sig.decl, anon_scope);
sig.unsafety, sig.abi, &sig.decl);
let substs = mk_item_substs(&ccx.icx(&(rcvr_ty_predicates, &sig.generics)),
ccx.tcx.hir.span(id), def_id);
......@@ -874,8 +869,7 @@ fn convert_trait_item(ccx: &CrateCtxt, trait_item: &hir::TraitItem) {
}
hir::TraitItemKind::Method(ref sig, _) => {
convert_method(ccx, TraitContainer(trait_def_id),
trait_item.id, sig, &trait_predicates);
convert_method(ccx, trait_item.id, sig, &trait_predicates);
}
}
}
......@@ -915,7 +909,7 @@ fn convert_impl_item(ccx: &CrateCtxt, impl_item: &hir::ImplItem) {
}
hir::ImplItemKind::Method(ref sig, _) => {
convert_method(ccx, ImplContainer(impl_def_id), impl_item.id, sig, &impl_predicates);
convert_method(ccx, impl_item.id, sig, &impl_predicates);
}
}
}
......@@ -1186,7 +1180,6 @@ fn ensure_super_predicates_step(ccx: &CrateCtxt,
self_param_ty,
bounds,
SizedByDefault::No,
None,
item.span);
let superbounds1 = superbounds1.predicates(tcx, self_param_ty);
......@@ -1323,7 +1316,6 @@ fn predicates_for_associated_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
assoc_ty,
bounds,
SizedByDefault::Yes,
None,
trait_item.span);
bounds.predicates(ccx.tcx, assoc_ty).into_iter()
......@@ -1537,8 +1529,7 @@ fn type_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
ccx.icx(&()).to_ty(&ExplicitRscope, &t)
}
ItemFn(ref decl, unsafety, _, abi, ref generics, _) => {
let tofd = AstConv::ty_of_fn(&ccx.icx(generics), unsafety, abi, &decl,
Some(AnonTypeScope::new(def_id)));
let tofd = AstConv::ty_of_fn(&ccx.icx(generics), unsafety, abi, &decl);
let substs = mk_item_substs(&ccx.icx(generics), item.span, def_id);
ccx.tcx.mk_fn_def(def_id, substs, tofd)
}
......@@ -1770,7 +1761,6 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
param_ty,
&param.bounds,
SizedByDefault::Yes,
None,
param.span);
predicates.extend(bounds.predicates(ccx.tcx, param_ty));
}
......@@ -1968,7 +1958,6 @@ pub fn compute_bounds<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
param_ty: ty::Ty<'tcx>,
ast_bounds: &[hir::TyParamBound],
sized_by_default: SizedByDefault,
anon_scope: Option<AnonTypeScope>,
span: Span)
-> Bounds<'tcx>
{
......@@ -1979,9 +1968,8 @@ pub fn compute_bounds<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
let mut projection_bounds = vec![];
let rscope = MaybeWithAnonTypes::new(ExplicitRscope, anon_scope);
let mut trait_bounds: Vec<_> = trait_bounds.iter().map(|&bound| {
astconv.instantiate_poly_trait_ref(&rscope,
astconv.instantiate_poly_trait_ref(&ExplicitRscope,
bound,
param_ty,
&mut projection_bounds)
......@@ -2048,7 +2036,7 @@ fn compute_type_of_foreign_fn_decl<'a, 'tcx>(
abi: abi::Abi)
-> Ty<'tcx>
{
let fty = AstConv::ty_of_fn(&ccx.icx(ast_generics), hir::Unsafety::Unsafe, abi, decl, None);
let fty = AstConv::ty_of_fn(&ccx.icx(ast_generics), hir::Unsafety::Unsafe, abi, decl);
// feature gate SIMD types in FFI, since I (huonw) am not sure the
// ABIs are handled at all correctly.
......@@ -2077,10 +2065,10 @@ fn compute_type_of_foreign_fn_decl<'a, 'tcx>(
ccx.tcx.mk_fn_def(def_id, substs, fty)
}
pub fn mk_item_substs<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
span: Span,
def_id: DefId)
-> &'tcx Substs<'tcx> {
fn mk_item_substs<'tcx>(astconv: &AstConv<'tcx, 'tcx>,
span: Span,
def_id: DefId)
-> &'tcx Substs<'tcx> {
let tcx = astconv.tcx();
// FIXME(eddyb) Do this request from Substs::for_item in librustc.
if let Err(ErrorReported) = astconv.get_generics(span, def_id) {
......
......@@ -77,6 +77,7 @@
#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(conservative_impl_trait)]
#![feature(loop_break_value)]
#![feature(quote)]
#![feature(rustc_diagnostic_macros)]
#![feature(rustc_private)]
......
......@@ -8,11 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use rustc::hir::def_id::DefId;
use rustc::ty;
use rustc::ty::subst::Substs;
use astconv::AstConv;
use syntax_pos::Span;
......@@ -38,73 +34,6 @@ pub trait RegionScope {
/// computing `object_lifetime_default` (in particular, in legacy
/// modes, it may not be relevant).
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 {
enclosing_item: DefId
}
impl<'gcx: 'tcx, 'tcx> AnonTypeScope {
pub fn new(enclosing_item: DefId) -> AnonTypeScope {
AnonTypeScope {
enclosing_item: enclosing_item
}
}
pub fn fresh_substs(&self, astconv: &AstConv<'gcx, 'tcx>, span: Span)
-> &'tcx Substs<'tcx> {
use collect::mk_item_substs;
mk_item_substs(astconv, span, self.enclosing_item)
}
}
/// A scope wrapper which optionally allows anonymized types.
#[derive(Copy, Clone)]
pub struct MaybeWithAnonTypes<R> {
base_scope: R,
anon_scope: Option<AnonTypeScope>
}
impl<R: RegionScope> MaybeWithAnonTypes<R> {
pub fn new(base_scope: R, anon_scope: Option<AnonTypeScope>) -> Self {
MaybeWithAnonTypes {
base_scope: base_scope,
anon_scope: anon_scope
}
}
}
impl<R: RegionScope> RegionScope for MaybeWithAnonTypes<R> {
fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
self.base_scope.object_lifetime_default(span)
}
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
......@@ -158,10 +87,6 @@ fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
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.base_scope.anon_type_scope()
}
}
/// A scope which simply shifts the Debruijn index of other scopes
......@@ -185,8 +110,4 @@ fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
fn base_object_lifetime_default(&self, span: Span) -> ty::Region {
ty::fold::shift_region(self.base_scope.base_object_lifetime_default(span), 1)
}
fn anon_type_scope(&self) -> Option<AnonTypeScope> {
self.base_scope.anon_type_scope()
}
}
......@@ -26,9 +26,9 @@ trait LazyToString {
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
}
// Note that the following impl doesn't error, because the trait is invalid.
impl LazyToString for String {
fn lazy_to_string<'a>(&'a self) -> impl Fn() -> String {
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
|| self.clone()
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册