Split hir::TyImplTrait, move checks to HIR lowering

Replace hir::TyImplTrait with TyImplTraitUniversal and
TyImplTraitExistential.

Add an ImplTraitContext enum to rustc::hir::lowering to track the kind
and allowedness of an impl Trait.

Significantly alter lowering to thread ImplTraitContext and one other
boolean parameter described below throughought much of lowering.

The other parameter is for tracking if lowering a function is in a trait
impl, as there is not enough information to otherwise know this
information during lowering otherwise.

This change also removes the checks from ast_ty_to_ty for impl trait
allowedness as they are now all taking place in HIR lowering.
This commit is contained in:
Christopher Vittal 2017-11-10 12:23:59 -05:00
parent 779fc372c7
commit 8fd48e7d59
11 changed files with 211 additions and 148 deletions

View File

@ -591,7 +591,10 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
}
visitor.visit_lifetime(lifetime);
}
TyImplTrait(ref bounds) => {
TyImplTraitExistential(ref bounds) => {
walk_list!(visitor, visit_ty_param_bound, bounds);
}
TyImplTraitUniversal(_, ref bounds) => {
walk_list!(visitor, visit_ty_param_bound, bounds);
}
TyTypeof(expression) => {

View File

@ -123,6 +123,24 @@ pub trait Resolver {
fn definitions(&mut self) -> &mut Definitions;
}
#[derive(Clone, Copy, Debug)]
enum ImplTraitContext {
/// Treat `impl Trait` as shorthand for a new universal generic parameter.
/// Example: `fn foo(x: impl Debug)`, where `impl Debug` is conceptually
/// equivalent to a fresh universal parameter like `fn foo<T: Debug>(x: T)`.
///
/// We store a DefId here so we can look up necessary information later
Universal(DefId),
/// Treat `impl Trait` as shorthand for a new universal existential parameter.
/// Example: `fn foo() -> impl Debug`, where `impl Debug` is conceptually
/// equivalent to a fresh existential parameter like `abstract type T; fn foo() -> T`.
Existential,
/// `impl Trait` is not accepted in this position.
Disallowed,
}
pub fn lower_crate(sess: &Session,
cstore: &CrateStore,
dep_graph: &DepGraph,
@ -644,48 +662,48 @@ impl<'a> LoweringContext<'a> {
}
}
fn lower_ty_binding(&mut self, b: &TypeBinding) -> hir::TypeBinding {
fn lower_ty_binding(&mut self, b: &TypeBinding, itctx: ImplTraitContext) -> hir::TypeBinding {
hir::TypeBinding {
id: self.lower_node_id(b.id).node_id,
name: self.lower_ident(b.ident),
ty: self.lower_ty(&b.ty),
ty: self.lower_ty(&b.ty, itctx),
span: b.span,
}
}
fn lower_ty(&mut self, t: &Ty) -> P<hir::Ty> {
fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext) -> P<hir::Ty> {
let kind = match t.node {
TyKind::Infer => hir::TyInfer,
TyKind::Err => hir::TyErr,
TyKind::Slice(ref ty) => hir::TySlice(self.lower_ty(ty)),
TyKind::Ptr(ref mt) => hir::TyPtr(self.lower_mt(mt)),
TyKind::Slice(ref ty) => hir::TySlice(self.lower_ty(ty, itctx)),
TyKind::Ptr(ref mt) => hir::TyPtr(self.lower_mt(mt, itctx)),
TyKind::Rptr(ref region, ref mt) => {
let span = t.span.with_hi(t.span.lo());
let lifetime = match *region {
Some(ref lt) => self.lower_lifetime(lt),
None => self.elided_lifetime(span)
};
hir::TyRptr(lifetime, self.lower_mt(mt))
hir::TyRptr(lifetime, self.lower_mt(mt, itctx))
}
TyKind::BareFn(ref f) => {
hir::TyBareFn(P(hir::BareFnTy {
lifetimes: self.lower_lifetime_defs(&f.lifetimes),
unsafety: self.lower_unsafety(f.unsafety),
abi: f.abi,
decl: self.lower_fn_decl(&f.decl),
decl: self.lower_fn_decl(&f.decl, None, false),
arg_names: self.lower_fn_args_to_names(&f.decl),
}))
}
TyKind::Never => hir::TyNever,
TyKind::Tup(ref tys) => {
hir::TyTup(tys.iter().map(|ty| self.lower_ty(ty)).collect())
hir::TyTup(tys.iter().map(|ty| self.lower_ty(ty, itctx)).collect())
}
TyKind::Paren(ref ty) => {
return self.lower_ty(ty);
return self.lower_ty(ty, itctx);
}
TyKind::Path(ref qself, ref path) => {
let id = self.lower_node_id(t.id);
let qpath = self.lower_qpath(t.id, qself, path, ParamMode::Explicit);
let qpath = self.lower_qpath(t.id, qself, path, ParamMode::Explicit, itctx);
return self.ty_path(id, t.span, qpath);
}
TyKind::ImplicitSelf => {
@ -699,7 +717,7 @@ impl<'a> LoweringContext<'a> {
}
TyKind::Array(ref ty, ref length) => {
let length = self.lower_body(None, |this| this.lower_expr(length));
hir::TyArray(self.lower_ty(ty), length)
hir::TyArray(self.lower_ty(ty, itctx), length)
}
TyKind::Typeof(ref expr) => {
let expr = self.lower_body(None, |this| this.lower_expr(expr));
@ -710,7 +728,7 @@ impl<'a> LoweringContext<'a> {
let bounds = bounds.iter().filter_map(|bound| {
match *bound {
TraitTyParamBound(ref ty, TraitBoundModifier::None) => {
Some(self.lower_poly_trait_ref(ty))
Some(self.lower_poly_trait_ref(ty, itctx))
}
TraitTyParamBound(_, TraitBoundModifier::Maybe) => None,
RegionTyParamBound(ref lifetime) => {
@ -727,7 +745,21 @@ impl<'a> LoweringContext<'a> {
hir::TyTraitObject(bounds, lifetime_bound)
}
TyKind::ImplTrait(ref bounds) => {
hir::TyImplTrait(self.lower_bounds(bounds))
use syntax::feature_gate::{emit_feature_err, GateIssue};
match itctx {
ImplTraitContext::Existential => {
hir::TyImplTraitExistential(self.lower_bounds(bounds, itctx))
},
ImplTraitContext::Universal(def_id) => {
hir::TyImplTraitUniversal(def_id, self.lower_bounds(bounds, itctx))
},
ImplTraitContext::Disallowed => {
span_err!(self.sess, t.span, E0562,
"`impl Trait` not allowed outside of function \
and inherent method return types");
hir::TyErr
}
}
}
TyKind::Mac(_) => panic!("TyMac should have been expanded by now."),
};
@ -773,10 +805,11 @@ impl<'a> LoweringContext<'a> {
id: NodeId,
qself: &Option<QSelf>,
p: &Path,
param_mode: ParamMode)
param_mode: ParamMode,
itctx: ImplTraitContext)
-> hir::QPath {
let qself_position = qself.as_ref().map(|q| q.position);
let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty));
let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty, itctx));
let resolution = self.resolver.get_resolution(id)
.unwrap_or(PathResolution::new(Def::Err));
@ -846,7 +879,7 @@ impl<'a> LoweringContext<'a> {
n
});
self.lower_path_segment(p.span, segment, param_mode, num_lifetimes,
parenthesized_generic_args)
parenthesized_generic_args, itctx)
}).collect(),
span: p.span,
});
@ -882,7 +915,8 @@ impl<'a> LoweringContext<'a> {
// * final path is `<<<std::vec::Vec<T>>::IntoIter>::Item>::clone`
for (i, segment) in p.segments.iter().enumerate().skip(proj_start) {
let segment = P(self.lower_path_segment(p.span, segment, param_mode, 0,
ParenthesizedGenericArgs::Warn));
ParenthesizedGenericArgs::Warn,
itctx));
let qpath = hir::QPath::TypeRelative(ty, segment);
// It's finished, return the extension of the right node type.
@ -916,7 +950,8 @@ impl<'a> LoweringContext<'a> {
def: self.expect_full_def(id),
segments: segments.map(|segment| {
self.lower_path_segment(p.span, segment, param_mode, 0,
ParenthesizedGenericArgs::Err)
ParenthesizedGenericArgs::Err,
ImplTraitContext::Disallowed)
}).chain(name.map(|name| hir::PathSegment::from_name(name)))
.collect(),
span: p.span,
@ -937,16 +972,18 @@ impl<'a> LoweringContext<'a> {
segment: &PathSegment,
param_mode: ParamMode,
expected_lifetimes: usize,
parenthesized_generic_args: ParenthesizedGenericArgs)
parenthesized_generic_args: ParenthesizedGenericArgs,
itctx: ImplTraitContext)
-> hir::PathSegment {
let (mut parameters, infer_types) = if let Some(ref parameters) = segment.parameters {
let msg = "parenthesized parameters may only be used with a trait";
match **parameters {
PathParameters::AngleBracketed(ref data) => {
self.lower_angle_bracketed_parameter_data(data, param_mode)
self.lower_angle_bracketed_parameter_data(data, param_mode, itctx)
}
PathParameters::Parenthesized(ref data) => match parenthesized_generic_args {
ParenthesizedGenericArgs::Ok => self.lower_parenthesized_parameter_data(data),
ParenthesizedGenericArgs::Ok =>
self.lower_parenthesized_parameter_data(data, itctx),
ParenthesizedGenericArgs::Warn => {
self.sess.buffer_lint(PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES,
CRATE_NODE_ID, data.span, msg.into());
@ -960,7 +997,7 @@ impl<'a> LoweringContext<'a> {
}
}
} else {
self.lower_angle_bracketed_parameter_data(&Default::default(), param_mode)
self.lower_angle_bracketed_parameter_data(&Default::default(), param_mode, itctx)
};
if !parameters.parenthesized && parameters.lifetimes.is_empty() {
@ -978,22 +1015,25 @@ impl<'a> LoweringContext<'a> {
fn lower_angle_bracketed_parameter_data(&mut self,
data: &AngleBracketedParameterData,
param_mode: ParamMode)
param_mode: ParamMode,
itctx: ImplTraitContext)
-> (hir::PathParameters, bool) {
let &AngleBracketedParameterData { ref lifetimes, ref types, ref bindings, .. } = data;
(hir::PathParameters {
lifetimes: self.lower_lifetimes(lifetimes),
types: types.iter().map(|ty| self.lower_ty(ty)).collect(),
bindings: bindings.iter().map(|b| self.lower_ty_binding(b)).collect(),
types: types.iter().map(|ty| self.lower_ty(ty, itctx)).collect(),
bindings: bindings.iter().map(|b| self.lower_ty_binding(b, itctx)).collect(),
parenthesized: false,
}, types.is_empty() && param_mode == ParamMode::Optional)
}
fn lower_parenthesized_parameter_data(&mut self,
data: &ParenthesizedParameterData)
data: &ParenthesizedParameterData,
itctx: ImplTraitContext)
-> (hir::PathParameters, bool) {
const DISALLOWED: ImplTraitContext = ImplTraitContext::Disallowed;
let &ParenthesizedParameterData { ref inputs, ref output, span } = data;
let inputs = inputs.iter().map(|ty| self.lower_ty(ty)).collect();
let inputs = inputs.iter().map(|ty| self.lower_ty(ty, DISALLOWED)).collect();
let mk_tup = |this: &mut Self, tys, span| {
let LoweredNodeId { node_id, hir_id } = this.next_id();
P(hir::Ty { node: hir::TyTup(tys), id: node_id, hir_id, span })
@ -1005,7 +1045,7 @@ impl<'a> LoweringContext<'a> {
bindings: hir_vec![hir::TypeBinding {
id: self.next_id().node_id,
name: Symbol::intern(FN_OUTPUT_NAME),
ty: output.as_ref().map(|ty| self.lower_ty(&ty))
ty: output.as_ref().map(|ty| self.lower_ty(&ty, itctx))
.unwrap_or_else(|| mk_tup(self, hir::HirVec::new(), span)),
span: output.as_ref().map_or(span, |ty| ty.span),
}],
@ -1018,7 +1058,7 @@ impl<'a> LoweringContext<'a> {
P(hir::Local {
id: node_id,
hir_id,
ty: l.ty.as_ref().map(|t| self.lower_ty(t)),
ty: l.ty.as_ref().map(|t| self.lower_ty(t, ImplTraitContext::Disallowed)),
pat: self.lower_pat(&l.pat),
init: l.init.as_ref().map(|e| P(self.lower_expr(e))),
span: l.span,
@ -1055,11 +1095,24 @@ impl<'a> LoweringContext<'a> {
}).collect()
}
fn lower_fn_decl(&mut self, decl: &FnDecl) -> P<hir::FnDecl> {
fn lower_fn_decl(&mut self,
decl: &FnDecl,
fn_def_id: Option<DefId>,
impl_trait_return_allow: bool)
-> P<hir::FnDecl> {
P(hir::FnDecl {
inputs: decl.inputs.iter().map(|arg| self.lower_ty(&arg.ty)).collect(),
inputs: decl.inputs.iter()
.map(|arg| if let Some(def_id) = fn_def_id {
self.lower_ty(&arg.ty, ImplTraitContext::Universal(def_id))
} else {
self.lower_ty(&arg.ty, ImplTraitContext::Disallowed)
}).collect(),
output: match decl.output {
FunctionRetTy::Ty(ref ty) => hir::Return(self.lower_ty(ty)),
FunctionRetTy::Ty(ref ty) => match (impl_trait_return_allow, fn_def_id) {
(false, _) => hir::Return(self.lower_ty(ty, ImplTraitContext::Disallowed)),
(_, Some(_)) => hir::Return(self.lower_ty(ty, ImplTraitContext::Existential)),
_ => hir::Return(self.lower_ty(ty, ImplTraitContext::Disallowed)),
},
FunctionRetTy::Default(span) => hir::DefaultReturn(span),
},
variadic: decl.variadic,
@ -1073,10 +1126,11 @@ impl<'a> LoweringContext<'a> {
})
}
fn lower_ty_param_bound(&mut self, tpb: &TyParamBound) -> hir::TyParamBound {
fn lower_ty_param_bound(&mut self, tpb: &TyParamBound, itctx: ImplTraitContext)
-> hir::TyParamBound {
match *tpb {
TraitTyParamBound(ref ty, modifier) => {
hir::TraitTyParamBound(self.lower_poly_trait_ref(ty),
hir::TraitTyParamBound(self.lower_poly_trait_ref(ty, itctx),
self.lower_trait_bound_modifier(modifier))
}
RegionTyParamBound(ref lifetime) => {
@ -1095,16 +1149,19 @@ impl<'a> LoweringContext<'a> {
name = Symbol::gensym("Self");
}
let mut bounds = self.lower_bounds(&tp.bounds);
let itctx = ImplTraitContext::Universal(self.resolver.definitions().local_def_id(tp.id));
let mut bounds = self.lower_bounds(&tp.bounds, itctx);
if !add_bounds.is_empty() {
bounds = bounds.into_iter().chain(self.lower_bounds(add_bounds).into_iter()).collect();
bounds = bounds.into_iter().chain(
self.lower_bounds(add_bounds, itctx).into_iter()
).collect();
}
hir::TyParam {
id: self.lower_node_id(tp.id).node_id,
name,
bounds,
default: tp.default.as_ref().map(|x| self.lower_ty(x)),
default: tp.default.as_ref().map(|x| self.lower_ty(x, ImplTraitContext::Disallowed)),
span: tp.span,
pure_wrt_drop: tp.attrs.iter().any(|attr| attr.check_name("may_dangle")),
synthetic: tp.attrs.iter()
@ -1215,11 +1272,11 @@ impl<'a> LoweringContext<'a> {
span}) => {
hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
bound_lifetimes: self.lower_lifetime_defs(bound_lifetimes),
bounded_ty: self.lower_ty(bounded_ty),
bounded_ty: self.lower_ty(bounded_ty, ImplTraitContext::Disallowed),
bounds: bounds.iter().filter_map(|bound| match *bound {
// Ignore `?Trait` bounds, they were copied into type parameters already.
TraitTyParamBound(_, TraitBoundModifier::Maybe) => None,
_ => Some(self.lower_ty_param_bound(bound))
_ => Some(self.lower_ty_param_bound(bound, ImplTraitContext::Disallowed))
}).collect(),
span,
})
@ -1239,8 +1296,8 @@ impl<'a> LoweringContext<'a> {
span}) => {
hir::WherePredicate::EqPredicate(hir::WhereEqPredicate {
id: self.lower_node_id(id).node_id,
lhs_ty: self.lower_ty(lhs_ty),
rhs_ty: self.lower_ty(rhs_ty),
lhs_ty: self.lower_ty(lhs_ty, ImplTraitContext::Disallowed),
rhs_ty: self.lower_ty(rhs_ty, ImplTraitContext::Disallowed),
span,
})
}
@ -1267,8 +1324,8 @@ impl<'a> LoweringContext<'a> {
}
}
fn lower_trait_ref(&mut self, p: &TraitRef) -> hir::TraitRef {
let path = match self.lower_qpath(p.ref_id, &None, &p.path, ParamMode::Explicit) {
fn lower_trait_ref(&mut self, p: &TraitRef, itctx: ImplTraitContext) -> hir::TraitRef {
let path = match self.lower_qpath(p.ref_id, &None, &p.path, ParamMode::Explicit, itctx) {
hir::QPath::Resolved(None, path) => path.and_then(|path| path),
qpath => bug!("lower_trait_ref: unexpected QPath `{:?}`", qpath)
};
@ -1278,10 +1335,13 @@ impl<'a> LoweringContext<'a> {
}
}
fn lower_poly_trait_ref(&mut self, p: &PolyTraitRef) -> hir::PolyTraitRef {
fn lower_poly_trait_ref(&mut self,
p: &PolyTraitRef,
itctx: ImplTraitContext)
-> hir::PolyTraitRef {
hir::PolyTraitRef {
bound_lifetimes: self.lower_lifetime_defs(&p.bound_lifetimes),
trait_ref: self.lower_trait_ref(&p.trait_ref),
trait_ref: self.lower_trait_ref(&p.trait_ref, itctx),
span: p.span,
}
}
@ -1296,7 +1356,7 @@ impl<'a> LoweringContext<'a> {
None => Ident { name: Symbol::intern(&index.to_string()), ctxt: f.span.ctxt() },
}),
vis: self.lower_visibility(&f.vis, None),
ty: self.lower_ty(&f.ty),
ty: self.lower_ty(&f.ty, ImplTraitContext::Disallowed),
attrs: self.lower_attrs(&f.attrs),
}
}
@ -1310,15 +1370,16 @@ impl<'a> LoweringContext<'a> {
}
}
fn lower_mt(&mut self, mt: &MutTy) -> hir::MutTy {
fn lower_mt(&mut self, mt: &MutTy, itctx: ImplTraitContext) -> hir::MutTy {
hir::MutTy {
ty: self.lower_ty(&mt.ty),
ty: self.lower_ty(&mt.ty, itctx),
mutbl: self.lower_mutability(mt.mutbl),
}
}
fn lower_bounds(&mut self, bounds: &[TyParamBound]) -> hir::TyParamBounds {
bounds.iter().map(|bound| self.lower_ty_param_bound(bound)).collect()
fn lower_bounds(&mut self, bounds: &[TyParamBound], itctx: ImplTraitContext)
-> hir::TyParamBounds {
bounds.iter().map(|bound| self.lower_ty_param_bound(bound, itctx)).collect()
}
fn lower_block(&mut self, b: &Block, targeted_by_break: bool) -> P<hir::Block> {
@ -1437,33 +1498,35 @@ impl<'a> LoweringContext<'a> {
}
ItemKind::Static(ref t, m, ref e) => {
let value = self.lower_body(None, |this| this.lower_expr(e));
hir::ItemStatic(self.lower_ty(t),
hir::ItemStatic(self.lower_ty(t, ImplTraitContext::Disallowed),
self.lower_mutability(m),
value)
}
ItemKind::Const(ref t, ref e) => {
let value = self.lower_body(None, |this| this.lower_expr(e));
hir::ItemConst(self.lower_ty(t), value)
hir::ItemConst(self.lower_ty(t, ImplTraitContext::Disallowed), value)
}
ItemKind::Fn(ref decl, unsafety, constness, abi, ref generics, ref body) => {
let fn_def_id = self.resolver.definitions().opt_local_def_id(id);
self.with_new_scopes(|this| {
let body_id = this.lower_body(Some(decl), |this| {
let body = this.lower_block(body, false);
this.expr_block(body, ThinVec::new())
});
hir::ItemFn(this.lower_fn_decl(decl),
this.lower_unsafety(unsafety),
this.lower_constness(constness),
abi,
this.lower_generics(generics),
body_id)
hir::ItemFn(this.lower_fn_decl(decl, fn_def_id, true),
this.lower_unsafety(unsafety),
this.lower_constness(constness),
abi,
this.lower_generics(generics),
body_id)
})
}
ItemKind::Mod(ref m) => hir::ItemMod(self.lower_mod(m)),
ItemKind::ForeignMod(ref nm) => hir::ItemForeignMod(self.lower_foreign_mod(nm)),
ItemKind::GlobalAsm(ref ga) => hir::ItemGlobalAsm(self.lower_global_asm(ga)),
ItemKind::Ty(ref t, ref generics) => {
hir::ItemTy(self.lower_ty(t), self.lower_generics(generics))
hir::ItemTy(self.lower_ty(t, ImplTraitContext::Disallowed),
self.lower_generics(generics))
}
ItemKind::Enum(ref enum_definition, ref generics) => {
hir::ItemEnum(hir::EnumDef {
@ -1483,7 +1546,7 @@ impl<'a> LoweringContext<'a> {
hir::ItemUnion(vdata, self.lower_generics(generics))
}
ItemKind::AutoImpl(unsafety, ref trait_ref) => {
let trait_ref = self.lower_trait_ref(trait_ref);
let trait_ref = self.lower_trait_ref(trait_ref, ImplTraitContext::Disallowed);
if let Def::Trait(def_id) = trait_ref.path.def {
self.trait_auto_impl.insert(def_id, id);
@ -1502,7 +1565,9 @@ impl<'a> LoweringContext<'a> {
let new_impl_items = impl_items.iter()
.map(|item| self.lower_impl_item_ref(item))
.collect();
let ifce = ifce.as_ref().map(|trait_ref| self.lower_trait_ref(trait_ref));
let ifce = ifce.as_ref().map(|trait_ref| {
self.lower_trait_ref(trait_ref, ImplTraitContext::Disallowed)
});
if let Some(ref trait_ref) = ifce {
if let Def::Trait(def_id) = trait_ref.path.def {
@ -1515,11 +1580,11 @@ impl<'a> LoweringContext<'a> {
self.lower_defaultness(defaultness, true /* [1] */),
self.lower_generics(generics),
ifce,
self.lower_ty(ty),
self.lower_ty(ty, ImplTraitContext::Disallowed),
new_impl_items)
}
ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, ref items) => {
let bounds = self.lower_bounds(bounds);
let bounds = self.lower_bounds(bounds, ImplTraitContext::Disallowed);
let items = items.iter().map(|item| self.lower_trait_item_ref(item)).collect();
hir::ItemTrait(self.lower_is_auto(is_auto),
self.lower_unsafety(unsafety),
@ -1537,6 +1602,7 @@ impl<'a> LoweringContext<'a> {
fn lower_trait_item(&mut self, i: &TraitItem) -> hir::TraitItem {
self.with_parent_def(i.id, |this| {
let LoweredNodeId { node_id, hir_id } = this.lower_node_id(i.id);
let fn_def_id = this.resolver.definitions().opt_local_def_id(node_id);
hir::TraitItem {
id: node_id,
@ -1546,14 +1612,14 @@ impl<'a> LoweringContext<'a> {
generics: this.lower_generics(&i.generics),
node: match i.node {
TraitItemKind::Const(ref ty, ref default) => {
hir::TraitItemKind::Const(this.lower_ty(ty),
hir::TraitItemKind::Const(this.lower_ty(ty, ImplTraitContext::Disallowed),
default.as_ref().map(|x| {
this.lower_body(None, |this| this.lower_expr(x))
}))
}
TraitItemKind::Method(ref sig, None) => {
let names = this.lower_fn_args_to_names(&sig.decl);
hir::TraitItemKind::Method(this.lower_method_sig(sig),
hir::TraitItemKind::Method(this.lower_method_sig(sig, fn_def_id, false),
hir::TraitMethod::Required(names))
}
TraitItemKind::Method(ref sig, Some(ref body)) => {
@ -1561,12 +1627,15 @@ impl<'a> LoweringContext<'a> {
let body = this.lower_block(body, false);
this.expr_block(body, ThinVec::new())
});
hir::TraitItemKind::Method(this.lower_method_sig(sig),
hir::TraitItemKind::Method(this.lower_method_sig(sig, fn_def_id, false),
hir::TraitMethod::Provided(body_id))
}
TraitItemKind::Type(ref bounds, ref default) => {
hir::TraitItemKind::Type(this.lower_bounds(bounds),
default.as_ref().map(|x| this.lower_ty(x)))
hir::TraitItemKind::Type(this.lower_bounds(bounds,
ImplTraitContext::Disallowed),
default.as_ref().map(|x| {
this.lower_ty(x, ImplTraitContext::Disallowed)
}))
}
TraitItemKind::Macro(..) => panic!("Shouldn't exist any more"),
},
@ -1602,6 +1671,7 @@ impl<'a> LoweringContext<'a> {
fn lower_impl_item(&mut self, i: &ImplItem) -> hir::ImplItem {
self.with_parent_def(i.id, |this| {
let LoweredNodeId { node_id, hir_id } = this.lower_node_id(i.id);
let fn_def_id = this.resolver.definitions().opt_local_def_id(node_id);
hir::ImplItem {
id: node_id,
@ -1614,16 +1684,23 @@ impl<'a> LoweringContext<'a> {
node: match i.node {
ImplItemKind::Const(ref ty, ref expr) => {
let body_id = this.lower_body(None, |this| this.lower_expr(expr));
hir::ImplItemKind::Const(this.lower_ty(ty), body_id)
hir::ImplItemKind::Const(
this.lower_ty(ty, ImplTraitContext::Disallowed),
body_id
)
}
ImplItemKind::Method(ref sig, ref body) => {
let body_id = this.lower_body(Some(&sig.decl), |this| {
let body = this.lower_block(body, false);
this.expr_block(body, ThinVec::new())
});
hir::ImplItemKind::Method(this.lower_method_sig(sig), body_id)
let impl_trait_return_allow = !this.is_in_trait_impl;
hir::ImplItemKind::Method(this.lower_method_sig(sig, fn_def_id,
impl_trait_return_allow),
body_id)
}
ImplItemKind::Type(ref ty) => hir::ImplItemKind::Type(this.lower_ty(ty)),
ImplItemKind::Type(ref ty) =>
hir::ImplItemKind::Type(this.lower_ty(ty, ImplTraitContext::Disallowed)),
ImplItemKind::Macro(..) => panic!("Shouldn't exist any more"),
},
span: i.span,
@ -1643,8 +1720,10 @@ impl<'a> LoweringContext<'a> {
kind: match i.node {
ImplItemKind::Const(..) => hir::AssociatedItemKind::Const,
ImplItemKind::Type(..) => hir::AssociatedItemKind::Type,
ImplItemKind::Method(ref sig, _) => hir::AssociatedItemKind::Method {
has_self: sig.decl.has_self(),
ImplItemKind::Method(ref sig, _) => {
hir::AssociatedItemKind::Method {
has_self: sig.decl.has_self(),
}
},
ImplItemKind::Macro(..) => unimplemented!(),
},
@ -1719,12 +1798,13 @@ impl<'a> LoweringContext<'a> {
attrs: this.lower_attrs(&i.attrs),
node: match i.node {
ForeignItemKind::Fn(ref fdec, ref generics) => {
hir::ForeignItemFn(this.lower_fn_decl(fdec),
let fn_def_id = this.resolver.definitions().opt_local_def_id(i.id);
hir::ForeignItemFn(this.lower_fn_decl(fdec, fn_def_id, true),
this.lower_fn_args_to_names(fdec),
this.lower_generics(generics))
}
ForeignItemKind::Static(ref t, m) => {
hir::ForeignItemStatic(this.lower_ty(t), m)
hir::ForeignItemStatic(this.lower_ty(t, ImplTraitContext::Disallowed), m)
}
ForeignItemKind::Ty => {
hir::ForeignItemType
@ -1736,12 +1816,16 @@ impl<'a> LoweringContext<'a> {
})
}
fn lower_method_sig(&mut self, sig: &MethodSig) -> hir::MethodSig {
fn lower_method_sig(&mut self,
sig: &MethodSig,
fn_def_id: Option<DefId>,
impl_trait_return_allow: bool)
-> hir::MethodSig {
hir::MethodSig {
abi: sig.abi,
unsafety: self.lower_unsafety(sig.unsafety),
constness: self.lower_constness(sig.constness),
decl: self.lower_fn_decl(&sig.decl),
decl: self.lower_fn_decl(&sig.decl, fn_def_id, impl_trait_return_allow),
}
}
@ -1834,16 +1918,19 @@ impl<'a> LoweringContext<'a> {
}
PatKind::Lit(ref e) => hir::PatKind::Lit(P(self.lower_expr(e))),
PatKind::TupleStruct(ref path, ref pats, ddpos) => {
let qpath = self.lower_qpath(p.id, &None, path, ParamMode::Optional);
let qpath = self.lower_qpath(p.id, &None, path, ParamMode::Optional,
ImplTraitContext::Disallowed);
hir::PatKind::TupleStruct(qpath,
pats.iter().map(|x| self.lower_pat(x)).collect(),
ddpos)
}
PatKind::Path(ref qself, ref path) => {
hir::PatKind::Path(self.lower_qpath(p.id, qself, path, ParamMode::Optional))
hir::PatKind::Path(self.lower_qpath(p.id, qself, path, ParamMode::Optional,
ImplTraitContext::Disallowed))
}
PatKind::Struct(ref path, ref fields, etc) => {
let qpath = self.lower_qpath(p.id, &None, path, ParamMode::Optional);
let qpath = self.lower_qpath(p.id, &None, path, ParamMode::Optional,
ImplTraitContext::Disallowed);
let fs = fields.iter()
.map(|f| {
@ -2020,7 +2107,8 @@ impl<'a> LoweringContext<'a> {
}
ExprKind::MethodCall(ref seg, ref args) => {
let hir_seg = self.lower_path_segment(e.span, seg, ParamMode::Optional, 0,
ParenthesizedGenericArgs::Err);
ParenthesizedGenericArgs::Err,
ImplTraitContext::Disallowed);
let args = args.iter().map(|x| self.lower_expr(x)).collect();
hir::ExprMethodCall(hir_seg, seg.span, args)
}
@ -2038,11 +2126,11 @@ impl<'a> LoweringContext<'a> {
ExprKind::Lit(ref l) => hir::ExprLit(P((**l).clone())),
ExprKind::Cast(ref expr, ref ty) => {
let expr = P(self.lower_expr(expr));
hir::ExprCast(expr, self.lower_ty(ty))
hir::ExprCast(expr, self.lower_ty(ty, ImplTraitContext::Disallowed))
}
ExprKind::Type(ref expr, ref ty) => {
let expr = P(self.lower_expr(expr));
hir::ExprType(expr, self.lower_ty(ty))
hir::ExprType(expr, self.lower_ty(ty, ImplTraitContext::Disallowed))
}
ExprKind::AddrOf(m, ref ohs) => {
let m = self.lower_mutability(m);
@ -2119,7 +2207,7 @@ impl<'a> LoweringContext<'a> {
this.sess.abort_if_errors();
}
hir::ExprClosure(this.lower_capture_clause(capture_clause),
this.lower_fn_decl(decl),
this.lower_fn_decl(decl, None, false),
body_id,
fn_decl_span,
is_generator)
@ -2193,7 +2281,8 @@ impl<'a> LoweringContext<'a> {
};
}
ExprKind::Path(ref qself, ref path) => {
hir::ExprPath(self.lower_qpath(e.id, qself, path, ParamMode::Optional))
hir::ExprPath(self.lower_qpath(e.id, qself, path, ParamMode::Optional,
ImplTraitContext::Disallowed))
}
ExprKind::Break(opt_ident, ref opt_expr) => {
let label_result = if self.is_in_loop_condition && opt_ident.is_none() {
@ -2246,7 +2335,8 @@ impl<'a> LoweringContext<'a> {
hir::ExprInlineAsm(P(hir_asm), outputs, inputs)
}
ExprKind::Struct(ref path, ref fields, ref maybe_expr) => {
hir::ExprStruct(self.lower_qpath(e.id, &None, path, ParamMode::Optional),
hir::ExprStruct(self.lower_qpath(e.id, &None, path, ParamMode::Optional,
ImplTraitContext::Disallowed),
fields.iter().map(|x| self.lower_field(x)).collect(),
maybe_expr.as_ref().map(|x| P(self.lower_expr(x))))
}

View File

@ -1461,9 +1461,12 @@ pub enum Ty_ {
/// A trait object type `Bound1 + Bound2 + Bound3`
/// where `Bound` is a trait or a lifetime.
TyTraitObject(HirVec<PolyTraitRef>, Lifetime),
/// An `impl Bound1 + Bound2 + Bound3` type
/// where `Bound` is a trait or a lifetime.
TyImplTrait(TyParamBounds),
/// An exsitentially quantified (there exists a type satisfying) `impl
/// Bound1 + Bound2 + Bound3` type where `Bound` is a trait or a lifetime.
TyImplTraitExistential(TyParamBounds),
/// An universally quantified (for all types satisfying) `impl
/// Bound1 + Bound2 + Bound3` type where `Bound` is a trait or a lifetime.
TyImplTraitUniversal(DefId, TyParamBounds),
/// Unused for now
TyTypeof(BodyId),
/// TyInfer means the type should be inferred instead of it having been

View File

@ -421,7 +421,8 @@ impl<'a> State<'a> {
self.print_lifetime(lifetime)?;
}
}
hir::TyImplTrait(ref bounds) => {
hir::TyImplTraitExistential(ref bounds) |
hir::TyImplTraitUniversal(_, ref bounds) => {
self.print_bounds("impl ", &bounds[..])?;
}
hir::TyArray(ref ty, v) => {

View File

@ -287,7 +287,8 @@ impl_stable_hash_for!(enum hir::Ty_ {
TyTup(ts),
TyPath(qpath),
TyTraitObject(trait_refs, lifetime),
TyImplTrait(bounds),
TyImplTraitExistential(bounds),
TyImplTraitUniversal(def_id, bounds),
TyTypeof(body_id),
TyErr,
TyInfer

View File

@ -1698,7 +1698,7 @@ fn insert_late_bound_lifetimes(map: &mut NamedRegionMap,
}
fn visit_ty(&mut self, ty: &hir::Ty) {
if let hir::TyImplTrait(_) = ty.node {
if let hir::TyImplTraitExistential(_) = ty.node {
self.impl_trait = true;
}
intravisit::walk_ty(self, ty);

View File

@ -1487,7 +1487,7 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
fn encode_info_for_ty(&mut self, ty: &hir::Ty) {
match ty.node {
hir::TyImplTrait(_) => {
hir::TyImplTraitExistential(_) => {
let def_id = self.tcx.hir.local_def_id(ty.id);
self.record(def_id, IsolatedEncoder::encode_info_for_anon_ty, def_id);
}

View File

@ -373,7 +373,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> {
}
fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
if let hir::TyImplTrait(..) = ty.node {
if let hir::TyImplTraitExistential(..) = ty.node {
if self.get(ty.id).is_some() {
// Reach the (potentially private) type and the API being exposed.
self.reach(ty.id).ty().predicates();
@ -1557,7 +1557,7 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx>
}
fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
if let hir::TyImplTrait(..) = ty.node {
if let hir::TyImplTraitExistential(..) = ty.node {
// Check the traits being exposed, as they're separate,
// e.g. `impl Iterator<Item=T>` has two predicates,
// `X: Iterator` and `<X as Iterator>::Item == T`,

View File

@ -30,6 +30,7 @@ use util::nodemap::FxHashSet;
use std::iter;
use syntax::{abi, ast};
use syntax::symbol::keywords;
use syntax::feature_gate::{GateIssue, emit_feature_err};
use syntax_pos::Span;
@ -1033,53 +1034,15 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
hir::TyTraitObject(ref bounds, ref lifetime) => {
self.conv_object_ty_poly_trait_ref(ast_ty.span, bounds, lifetime)
}
hir::TyImplTrait(_) => {
// 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.
if allow {
let def_id = tcx.hir.local_def_id(ast_ty.id);
tcx.mk_anon(def_id, Substs::identity_for_item(tcx, def_id))
} else {
span_err!(tcx.sess, ast_ty.span, E0562,
"`impl Trait` not allowed outside of function \
and inherent method return types");
tcx.types.err
}
hir::TyImplTraitExistential(_) => {
let def_id = tcx.hir.local_def_id(ast_ty.id);
tcx.mk_anon(def_id, Substs::identity_for_item(tcx, def_id))
}
hir::TyImplTraitUniversal(fn_def_id, _) => {
let impl_trait_def_id = tcx.hir.local_def_id(ast_ty.id);
let generics = tcx.generics_of(fn_def_id);
let index = generics.type_param_to_index[&impl_trait_def_id.index];
tcx.mk_param(index, keywords::Invalid.name() /* FIXME(chrisvittal) invalid? */)
}
hir::TyPath(hir::QPath::Resolved(ref maybe_qself, ref path)) => {
debug!("ast_ty_to_ty: maybe_qself={:?} path={:?}", maybe_qself, path);

View File

@ -130,7 +130,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'a, 'tcx> {
}
fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
if let hir::TyImplTrait(..) = ty.node {
if let hir::TyImplTraitExistential(..) = ty.node {
let def_id = self.tcx.hir.local_def_id(ty.id);
self.tcx.generics_of(def_id);
self.tcx.predicates_of(def_id);
@ -854,7 +854,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
NodeExpr(&hir::Expr { node: hir::ExprClosure(..), .. }) => {
Some(tcx.closure_base_def_id(def_id))
}
NodeTy(&hir::Ty { node: hir::TyImplTrait(..), .. }) => {
NodeTy(&hir::Ty { node: hir::TyImplTraitExistential(..), .. }) => {
let mut parent_id = node_id;
loop {
match tcx.hir.get(parent_id) {
@ -1155,7 +1155,7 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
icx.to_ty(ty)
}
NodeTy(&hir::Ty { node: TyImplTrait(..), .. }) => {
NodeTy(&hir::Ty { node: TyImplTraitExistential(..), .. }) => {
let owner = tcx.hir.get_parent_did(node_id);
let hir_id = tcx.hir.node_to_hir_id(node_id);
tcx.typeck_tables_of(owner).node_id_to_type(hir_id)
@ -1373,7 +1373,7 @@ fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
}
}
NodeTy(&Ty { node: TyImplTrait(ref bounds), span, .. }) => {
NodeTy(&Ty { node: TyImplTraitExistential(ref bounds), span, .. }) => {
let substs = Substs::identity_for_item(tcx, def_id);
let anon_ty = tcx.mk_anon(def_id, substs);

View File

@ -1960,7 +1960,9 @@ impl Clean<Type> for hir::Ty {
}
}
TyBareFn(ref barefn) => BareFunction(box barefn.clean(cx)),
TyImplTrait(ref bounds) => ImplTrait(bounds.clean(cx)),
TyImplTraitExistential(ref bounds) |
TyImplTraitUniversal(_, ref bounds) =>
ImplTrait(bounds.clean(cx)),
TyInfer | TyErr => Infer,
TyTypeof(..) => panic!("Unimplemented type {:?}", self.node),
}