use middle::cstore::CrateStore;
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::indexed_vec::IndexVec;
-use rustc_data_structures::small_vec::OneVector;
use rustc_data_structures::thin_vec::ThinVec;
use session::Session;
use util::common::FN_OUTPUT_NAME;
use std::fmt::Debug;
use std::iter;
use std::mem;
+use smallvec::SmallVec;
use syntax::attr;
use syntax::ast;
use syntax::ast::*;
use syntax::errors;
use syntax::ext::hygiene::{Mark, SyntaxContext};
+use syntax::feature_gate::{emit_feature_err, GateIssue};
use syntax::print::pprust;
use syntax::ptr::P;
use syntax::source_map::{self, respan, CompilerDesugaringKind, Spanned};
/// Example: `fn foo(x: impl Debug)`, where `impl Debug` is conceptually
/// equivalent to a fresh universal parameter like `fn foo<T: Debug>(x: T)`.
///
- /// Newly generated parameters should be inserted into the given `Vec`
+ /// Newly generated parameters should be inserted into the given `Vec`.
Universal(&'a mut Vec<hir::GenericParam>),
- /// Treat `impl Trait` as shorthand for a new universal existential parameter.
+ /// Treat `impl Trait` as shorthand for a new 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`.
+ /// equivalent to a fresh existential parameter like `existential type T; fn foo() -> T`.
///
- /// We store a DefId here so we can look up necessary information later
- Existential(DefId),
+ /// We optionally store a `DefId` for the parent item here so we can look up necessary
+ /// information later. It is `None` when no information about the context should be stored,
+ /// e.g. for consts and statics.
+ Existential(Option<DefId>),
/// `impl Trait` is not accepted in this position.
Disallowed,
PassThrough,
}
+struct ImplTraitTypeIdVisitor<'a> { ids: &'a mut SmallVec<[hir::ItemId; 1]> }
+
+impl<'a, 'b> Visitor<'a> for ImplTraitTypeIdVisitor<'b> {
+ fn visit_ty(&mut self, ty: &'a Ty) {
+ match ty.node {
+ | TyKind::Typeof(_)
+ | TyKind::BareFn(_)
+ => return,
+
+ TyKind::ImplTrait(id, _) => self.ids.push(hir::ItemId { id }),
+ _ => {},
+ }
+ visit::walk_ty(self, ty);
+ }
+
+ fn visit_path_segment(
+ &mut self,
+ path_span: Span,
+ path_segment: &'v PathSegment,
+ ) {
+ if let Some(ref p) = path_segment.args {
+ if let GenericArgs::Parenthesized(_) = **p {
+ return;
+ }
+ }
+ visit::walk_path_segment(self, path_span, path_segment)
+ }
+}
+
impl<'a> LoweringContext<'a> {
fn lower_crate(mut self, c: &Crate) -> hir::Crate {
/// Full-crate AST visitor that inserts into a fresh
self.lctx.with_parent_impl_lifetime_defs(&item_generics, |this| {
let this = &mut ItemLowerer { lctx: this };
- if let ItemKind::Impl(_, _, _, _, ref opt_trait_ref, _, _) = item.node {
+ if let ItemKind::Impl(.., ref opt_trait_ref, _, _) = item.node {
this.with_trait_impl_ref(opt_trait_ref, |this| {
visit::walk_item(this, item)
});
})
}
- fn expect_full_def_from_use(&mut self, id: NodeId) -> impl Iterator<Item=Def> {
+ fn expect_full_def_from_use(&mut self, id: NodeId) -> impl Iterator<Item = Def> {
self.resolver.get_import(id).present_items().map(|pr| {
if pr.unresolved_segments() != 0 {
bug!("path not fully resolved: {:?}", pr);
f: F,
) -> (Vec<hir::GenericParam>, T)
where
- F: FnOnce(&mut LoweringContext) -> (Vec<hir::GenericParam>, T),
+ F: FnOnce(&mut LoweringContext<'_>) -> (Vec<hir::GenericParam>, T),
{
assert!(!self.is_collecting_in_band_lifetimes);
assert!(self.lifetimes_to_define.is_empty());
// for them.
fn with_in_scope_lifetime_defs<T, F>(&mut self, params: &[GenericParam], f: F) -> T
where
- F: FnOnce(&mut LoweringContext) -> T,
+ F: FnOnce(&mut LoweringContext<'_>) -> T,
{
let old_len = self.in_scope_lifetimes.len();
let lt_def_names = params.iter().filter_map(|param| match param.kind {
params: &HirVec<hir::GenericParam>,
f: F
) -> T where
- F: FnOnce(&mut LoweringContext) -> T,
+ F: FnOnce(&mut LoweringContext<'_>) -> T,
{
let old_len = self.in_scope_lifetimes.len();
let lt_def_names = params.iter().filter_map(|param| match param.kind {
f: F,
) -> (hir::Generics, T)
where
- F: FnOnce(&mut LoweringContext, &mut Vec<hir::GenericParam>) -> T,
+ F: FnOnce(&mut LoweringContext<'_>, &mut Vec<hir::GenericParam>) -> T,
{
let (in_band_defs, (mut lowered_generics, res)) = self.with_in_scope_lifetime_defs(
&generics.params,
fn with_catch_scope<T, F>(&mut self, catch_id: NodeId, f: F) -> T
where
- F: FnOnce(&mut LoweringContext) -> T,
+ F: FnOnce(&mut LoweringContext<'_>) -> T,
{
let len = self.catch_scopes.len();
self.catch_scopes.push(catch_id);
capture_clause: CaptureBy,
closure_node_id: NodeId,
ret_ty: Option<&Ty>,
- body: impl FnOnce(&mut LoweringContext) -> hir::Expr,
+ body: impl FnOnce(&mut LoweringContext<'_>) -> hir::Expr,
) -> hir::ExprKind {
let prev_is_generator = mem::replace(&mut self.is_generator, true);
let body_expr = body(self);
fn lower_body<F>(&mut self, decl: Option<&FnDecl>, f: F) -> hir::BodyId
where
- F: FnOnce(&mut LoweringContext) -> hir::Expr,
+ F: FnOnce(&mut LoweringContext<'_>) -> hir::Expr,
{
let prev = mem::replace(&mut self.is_generator, false);
let result = f(self);
fn with_loop_scope<T, F>(&mut self, loop_id: NodeId, f: F) -> T
where
- F: FnOnce(&mut LoweringContext) -> T,
+ F: FnOnce(&mut LoweringContext<'_>) -> T,
{
// We're no longer in the base loop's condition; we're in another loop.
let was_in_loop_condition = self.is_in_loop_condition;
fn with_loop_condition_scope<T, F>(&mut self, f: F) -> T
where
- F: FnOnce(&mut LoweringContext) -> T,
+ F: FnOnce(&mut LoweringContext<'_>) -> T,
{
let was_in_loop_condition = self.is_in_loop_condition;
self.is_in_loop_condition = true;
fn with_new_scopes<T, F>(&mut self, f: F) -> T
where
- F: FnOnce(&mut LoweringContext) -> T,
+ F: FnOnce(&mut LoweringContext<'_>) -> T,
{
let was_in_loop_condition = self.is_in_loop_condition;
self.is_in_loop_condition = false;
let catch_scopes = mem::replace(&mut self.catch_scopes, Vec::new());
let loop_scopes = mem::replace(&mut self.loop_scopes, Vec::new());
- let result = f(self);
+ let ret = f(self);
self.catch_scopes = catch_scopes;
self.loop_scopes = loop_scopes;
self.is_in_loop_condition = was_in_loop_condition;
- result
+ ret
}
fn def_key(&mut self, id: DefId) -> DefKey {
None => {
self.loop_scopes
.last()
- .map(|innermost_loop_id| *innermost_loop_id)
+ .cloned()
.map(|id| Ok(self.lower_node_id(id).node_id))
.unwrap_or(Err(hir::LoopIdError::OutsideLoopScope))
.into()
}
}
- fn lower_ty_binding(&mut self, b: &TypeBinding, itctx: ImplTraitContext) -> 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,
ident: b.ident,
fn lower_generic_arg(&mut self,
arg: &ast::GenericArg,
- itctx: ImplTraitContext)
+ itctx: ImplTraitContext<'_>)
-> hir::GenericArg {
match arg {
ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(<)),
}
}
- fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext) -> P<hir::Ty> {
+ fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext<'_>) -> P<hir::Ty> {
P(self.lower_ty_direct(t, itctx))
}
- fn lower_ty_direct(&mut self, t: &Ty, mut itctx: ImplTraitContext) -> hir::Ty {
+ fn lower_ty_direct(&mut self, t: &Ty, mut itctx: ImplTraitContext<'_>) -> hir::Ty {
let kind = match t.node {
TyKind::Infer => hir::TyKind::Infer,
TyKind::Err => hir::TyKind::Err,
))
}
ImplTraitContext::Disallowed => {
+ let allowed_in = if self.sess.features_untracked()
+ .impl_trait_in_bindings {
+ "bindings or function and inherent method return types"
+ } else {
+ "function and inherent method return types"
+ };
span_err!(
self.sess,
t.span,
E0562,
- "`impl Trait` not allowed outside of function \
- and inherent method return types"
+ "`impl Trait` not allowed outside of {}",
+ allowed_in,
);
hir::TyKind::Err
}
fn lower_existential_impl_trait(
&mut self,
span: Span,
- fn_def_id: DefId,
+ fn_def_id: Option<DefId>,
exist_ty_node_id: NodeId,
- lower_bounds: impl FnOnce(&mut LoweringContext) -> hir::GenericBounds,
+ lower_bounds: impl FnOnce(&mut LoweringContext<'_>) -> hir::GenericBounds,
) -> hir::TyKind {
// Make sure we know that some funky desugaring has been going on here.
// This is a first: there is code in other places like for loop
.opt_def_index(exist_ty_node_id)
.unwrap();
-
self.allocate_hir_id_counter(exist_ty_node_id, &"existential impl trait");
let hir_bounds = self.with_hir_id_owner(exist_ty_node_id, lower_bounds);
span,
},
bounds: hir_bounds,
- impl_trait_fn: Some(fn_def_id),
+ impl_trait_fn: fn_def_id,
});
let exist_ty_id = lctx.lower_node_id(exist_ty_node_id);
// Generate an `existential type Foo: Trait;` declaration
lctx.items.insert(exist_ty_id.node_id, exist_ty_item);
// `impl Trait` now just becomes `Foo<'a, 'b, ..>`
- let path = P(hir::Path {
- span: exist_ty_span,
- def: Def::Existential(DefId::local(exist_ty_def_index)),
- segments: hir_vec![hir::PathSegment {
- infer_types: false,
- ident: Ident::new(keywords::Invalid.name(), exist_ty_span),
- args: Some(P(hir::GenericArgs {
- parenthesized: false,
- bindings: HirVec::new(),
- args: lifetimes,
- }))
- }],
- });
- hir::TyKind::Path(hir::QPath::Resolved(None, path))
+ hir::TyKind::Def(hir::ItemId { id: exist_ty_id.node_id }, lifetimes)
})
}
qself: &Option<QSelf>,
p: &Path,
param_mode: ParamMode,
- mut itctx: ImplTraitContext,
+ mut 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, itctx.reborrow()));
param_mode: ParamMode,
expected_lifetimes: usize,
parenthesized_generic_args: ParenthesizedGenericArgs,
- itctx: ImplTraitContext,
+ itctx: ImplTraitContext<'_>,
) -> hir::PathSegment {
let (mut generic_args, infer_types) = if let Some(ref generic_args) = segment.args {
let msg = "parenthesized parameters may only be used with a trait";
&mut self,
data: &AngleBracketedArgs,
param_mode: ParamMode,
- mut itctx: ImplTraitContext,
+ mut itctx: ImplTraitContext<'_>,
) -> (hir::GenericArgs, bool) {
let &AngleBracketedArgs { ref args, ref bindings, .. } = data;
let has_types = args.iter().any(|arg| match arg {
self.with_anonymous_lifetime_mode(
AnonymousLifetimeMode::PassThrough,
|this| {
- const DISALLOWED: ImplTraitContext = ImplTraitContext::Disallowed;
+ const DISALLOWED: ImplTraitContext<'_> = ImplTraitContext::Disallowed;
let &ParenthesisedArgs { ref inputs, ref output, span } = data;
let inputs = inputs.iter().map(|ty| this.lower_ty_direct(ty, DISALLOWED)).collect();
let mk_tup = |this: &mut Self, tys, span| {
)
}
- fn lower_local(&mut self, l: &Local) -> P<hir::Local> {
+ fn lower_local(&mut self, l: &Local) -> (P<hir::Local>, SmallVec<[hir::ItemId; 1]>) {
let LoweredNodeId { node_id, hir_id } = self.lower_node_id(l.id);
- P(hir::Local {
+ let mut ids = SmallVec::<[hir::ItemId; 1]>::new();
+ if self.sess.features_untracked().impl_trait_in_bindings {
+ if let Some(ref ty) = l.ty {
+ let mut visitor = ImplTraitTypeIdVisitor { ids: &mut ids };
+ visitor.visit_ty(ty);
+ }
+ }
+ let parent_def_id = DefId::local(self.current_hir_id_owner.last().unwrap().0);
+ (P(hir::Local {
id: node_id,
hir_id,
ty: l.ty
.as_ref()
- .map(|t| self.lower_ty(t, ImplTraitContext::Disallowed)),
+ .map(|t| self.lower_ty(t,
+ if self.sess.features_untracked().impl_trait_in_bindings {
+ ImplTraitContext::Existential(Some(parent_def_id))
+ } else {
+ ImplTraitContext::Disallowed
+ }
+ )),
pat: self.lower_pat(&l.pat),
init: l.init.as_ref().map(|e| P(self.lower_expr(e))),
span: l.span,
attrs: l.attrs.clone(),
source: hir::LocalSource::Normal,
- })
+ }), ids)
}
fn lower_mutability(&mut self, m: Mutability) -> hir::Mutability {
match decl.output {
FunctionRetTy::Ty(ref ty) => match in_band_ty_params {
Some((def_id, _)) if impl_trait_return_allow => {
- hir::Return(self.lower_ty(ty, ImplTraitContext::Existential(def_id)))
+ hir::Return(self.lower_ty(ty, ImplTraitContext::Existential(Some(def_id))))
}
_ => hir::Return(self.lower_ty(ty, ImplTraitContext::Disallowed)),
},
};
let impl_trait_ty = self.lower_existential_impl_trait(
- span, fn_def_id, return_impl_trait_id, |this| {
+ span, Some(fn_def_id), return_impl_trait_id, |this| {
let output_ty = match output {
- FunctionRetTy::Ty(ty) =>
- this.lower_ty(ty, ImplTraitContext::Existential(fn_def_id)),
+ FunctionRetTy::Ty(ty) => {
+ this.lower_ty(ty, ImplTraitContext::Existential(Some(fn_def_id)))
+ }
FunctionRetTy::Default(span) => {
let LoweredNodeId { node_id, hir_id } = this.next_id();
P(hir::Ty {
fn lower_param_bound(
&mut self,
tpb: &GenericBound,
- itctx: ImplTraitContext,
+ itctx: ImplTraitContext<'_>,
) -> hir::GenericBound {
match *tpb {
GenericBound::Trait(ref ty, modifier) => hir::GenericBound::Trait(
&mut self,
params: &[GenericParam],
add_bounds: &NodeMap<Vec<GenericBound>>,
- mut itctx: ImplTraitContext,
+ mut itctx: ImplTraitContext<'_>,
) -> hir::HirVec<hir::GenericParam> {
params.iter().map(|param| {
self.lower_generic_param(param, add_bounds, itctx.reborrow())
fn lower_generic_param(&mut self,
param: &GenericParam,
add_bounds: &NodeMap<Vec<GenericBound>>,
- mut itctx: ImplTraitContext)
+ mut itctx: ImplTraitContext<'_>)
-> hir::GenericParam {
let mut bounds = self.lower_param_bounds(¶m.bounds, itctx.reborrow());
match param.kind {
fn lower_generics(
&mut self,
generics: &Generics,
- itctx: ImplTraitContext)
+ itctx: ImplTraitContext<'_>)
-> hir::Generics
{
// Collect `?Trait` bounds in where clause and move them to parameter definitions.
}
}
- fn lower_trait_ref(&mut self, p: &TraitRef, itctx: ImplTraitContext) -> hir::TraitRef {
+ 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),
fn lower_poly_trait_ref(
&mut self,
p: &PolyTraitRef,
- mut itctx: ImplTraitContext,
+ mut itctx: ImplTraitContext<'_>,
) -> hir::PolyTraitRef {
let bound_generic_params =
self.lower_generic_params(&p.bound_generic_params, &NodeMap(), itctx.reborrow());
}
}
- fn lower_mt(&mut self, mt: &MutTy, itctx: ImplTraitContext) -> hir::MutTy {
+ fn lower_mt(&mut self, mt: &MutTy, itctx: ImplTraitContext<'_>) -> hir::MutTy {
hir::MutTy {
ty: self.lower_ty(&mt.ty, itctx),
mutbl: self.lower_mutability(mt.mutbl),
}
}
- fn lower_param_bounds(&mut self, bounds: &[GenericBound], mut itctx: ImplTraitContext)
+ fn lower_param_bounds(&mut self, bounds: &[GenericBound], mut itctx: ImplTraitContext<'_>)
-> hir::GenericBounds {
bounds.iter().map(|bound| self.lower_param_bound(bound, itctx.reborrow())).collect()
}
ItemKind::Static(ref t, m, ref e) => {
let value = self.lower_body(None, |this| this.lower_expr(e));
hir::ItemKind::Static(
- self.lower_ty(t, ImplTraitContext::Disallowed),
+ self.lower_ty(
+ t,
+ if self.sess.features_untracked().impl_trait_in_bindings {
+ ImplTraitContext::Existential(None)
+ } else {
+ 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::ItemKind::Const(self.lower_ty(t, ImplTraitContext::Disallowed), value)
+ hir::ItemKind::Const(
+ self.lower_ty(
+ t,
+ if self.sess.features_untracked().impl_trait_in_bindings {
+ ImplTraitContext::Existential(None)
+ } else {
+ ImplTraitContext::Disallowed
+ }
+ ),
+ value
+ )
}
ItemKind::Fn(ref decl, header, ref generics, ref body) => {
let fn_def_id = self.resolver.definitions().local_def_id(id);
-
self.with_new_scopes(|this| {
// Note: we don't need to change the return type from `T` to
// `impl Future<Output = T>` here because lower_body
fn_def_id,
AnonymousLifetimeMode::PassThrough,
|this, idty| this.lower_fn_decl(
- decl, Some((fn_def_id, idty)), true, header.asyncness.opt_return_id()),
+ decl,
+ Some((fn_def_id, idty)),
+ true,
+ header.asyncness.opt_return_id()
+ ),
);
hir::ItemKind::Fn(
let body = this.lower_block(body, false);
this.expr_block(body, ThinVec::new())
});
-
let (generics, sig) = self.lower_method_sig(
&i.generics,
sig,
false,
None,
);
-
(generics, hir::TraitItemKind::Method(sig, hir::TraitMethod::Provided(body_id)))
}
TraitItemKind::Type(ref bounds, ref default) => (
}
}
- /// Lowers `impl Trait` items and appends them to the list
- fn lower_impl_trait_ids(
- &mut self,
- decl: &FnDecl,
- header: &FnHeader,
- ids: &mut OneVector<hir::ItemId>,
- ) {
- if let Some(id) = header.asyncness.opt_return_id() {
- ids.push(hir::ItemId { id });
- }
- struct IdVisitor<'a> { ids: &'a mut OneVector<hir::ItemId> }
- impl<'a, 'b> Visitor<'a> for IdVisitor<'b> {
- fn visit_ty(&mut self, ty: &'a Ty) {
- match ty.node {
- | TyKind::Typeof(_)
- | TyKind::BareFn(_)
- => return,
-
- TyKind::ImplTrait(id, _) => self.ids.push(hir::ItemId { id }),
- _ => {},
- }
- visit::walk_ty(self, ty);
- }
- fn visit_path_segment(
- &mut self,
- path_span: Span,
- path_segment: &'v PathSegment,
- ) {
- if let Some(ref p) = path_segment.args {
- if let GenericArgs::Parenthesized(_) = **p {
- return;
- }
- }
- visit::walk_path_segment(self, path_span, path_segment)
- }
- }
- let mut visitor = IdVisitor { ids };
- match decl.output {
- FunctionRetTy::Default(_) => {},
- FunctionRetTy::Ty(ref ty) => visitor.visit_ty(ty),
- }
- }
-
- fn lower_item_id(&mut self, i: &Item) -> OneVector<hir::ItemId> {
+ fn lower_item_id(&mut self, i: &Item) -> SmallVec<[hir::ItemId; 1]> {
match i.node {
ItemKind::Use(ref use_tree) => {
let mut vec = smallvec![hir::ItemId { id: i.id }];
self.lower_item_id_use_tree(use_tree, i.id, &mut vec);
vec
}
- ItemKind::MacroDef(..) => OneVector::new(),
- ItemKind::Fn(ref decl, ref header, ..) => {
+ ItemKind::MacroDef(..) => SmallVec::new(),
+ ItemKind::Fn(..) |
+ ItemKind::Impl(.., None, _, _) => smallvec![hir::ItemId { id: i.id }],
+ ItemKind::Static(ref ty, ..) => {
let mut ids = smallvec![hir::ItemId { id: i.id }];
- self.lower_impl_trait_ids(decl, header, &mut ids);
+ if self.sess.features_untracked().impl_trait_in_bindings {
+ let mut visitor = ImplTraitTypeIdVisitor { ids: &mut ids };
+ visitor.visit_ty(ty);
+ }
ids
},
- ItemKind::Impl(.., None, _, ref items) => {
+ ItemKind::Const(ref ty, ..) => {
let mut ids = smallvec![hir::ItemId { id: i.id }];
- for item in items {
- if let ImplItemKind::Method(ref sig, _) = item.node {
- self.lower_impl_trait_ids(&sig.decl, &sig.header, &mut ids);
- }
+ if self.sess.features_untracked().impl_trait_in_bindings {
+ let mut visitor = ImplTraitTypeIdVisitor { ids: &mut ids };
+ visitor.visit_ty(ty);
}
ids
},
fn lower_item_id_use_tree(&mut self,
tree: &UseTree,
base_id: NodeId,
- vec: &mut OneVector<hir::ItemId>)
+ vec: &mut SmallVec<[hir::ItemId; 1]>)
{
match tree.kind {
UseTreeKind::Nested(ref nested_vec) => for &(ref nested, id) in nested_vec {
ParamMode::Optional,
ImplTraitContext::Disallowed,
);
+ self.check_self_struct_ctor_feature(&qpath);
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,
- ImplTraitContext::Disallowed,
- )),
+ PatKind::Path(ref qself, ref path) => {
+ let qpath = self.lower_qpath(
+ p.id,
+ qself,
+ path,
+ ParamMode::Optional,
+ ImplTraitContext::Disallowed,
+ );
+ self.check_self_struct_ctor_feature(&qpath);
+ hir::PatKind::Path(qpath)
+ }
PatKind::Struct(ref path, ref fields, etc) => {
let qpath = self.lower_qpath(
p.id,
}
ExprKind::Block(ref blk, opt_label) => {
hir::ExprKind::Block(self.lower_block(blk,
- opt_label.is_some()),
- self.lower_label(opt_label))
+ opt_label.is_some()),
+ self.lower_label(opt_label))
}
ExprKind::Assign(ref el, ref er) => {
hir::ExprKind::Assign(P(self.lower_expr(el)), P(self.lower_expr(er)))
attrs: e.attrs.clone(),
};
}
- ExprKind::Path(ref qself, ref path) => hir::ExprKind::Path(self.lower_qpath(
- e.id,
- qself,
- path,
- ParamMode::Optional,
- ImplTraitContext::Disallowed,
- )),
+ ExprKind::Path(ref qself, ref path) => {
+ let qpath = self.lower_qpath(
+ e.id,
+ qself,
+ path,
+ ParamMode::Optional,
+ ImplTraitContext::Disallowed,
+ );
+ self.check_self_struct_ctor_feature(&qpath);
+ hir::ExprKind::Path(qpath)
+ }
ExprKind::Break(opt_label, ref opt_expr) => {
let destination = if self.is_in_loop_condition && opt_label.is_none() {
hir::Destination {
}
}
- fn lower_stmt(&mut self, s: &Stmt) -> OneVector<hir::Stmt> {
+ fn lower_stmt(&mut self, s: &Stmt) -> SmallVec<[hir::Stmt; 1]> {
smallvec![match s.node {
- StmtKind::Local(ref l) => Spanned {
- node: hir::StmtKind::Decl(
- P(Spanned {
- node: hir::DeclKind::Local(self.lower_local(l)),
+ StmtKind::Local(ref l) => {
+ let (l, item_ids) = self.lower_local(l);
+ let mut ids: SmallVec<[hir::Stmt; 1]> = item_ids
+ .into_iter()
+ .map(|item_id| Spanned {
+ node: hir::StmtKind::Decl(
+ P(Spanned {
+ node: hir::DeclKind::Item(item_id),
+ span: s.span,
+ }),
+ self.next_id().node_id,
+ ),
span: s.span,
- }),
- self.lower_node_id(s.id).node_id,
- ),
- span: s.span,
+ })
+ .collect();
+ ids.push(Spanned {
+ node: hir::StmtKind::Decl(
+ P(Spanned {
+ node: hir::DeclKind::Local(l),
+ span: s.span,
+ }),
+ self.lower_node_id(s.id).node_id,
+ ),
+ span: s.span,
+ });
+ return ids;
},
StmtKind::Item(ref it) => {
// Can only use the ID once.
span: s.span,
}),
id.take()
- .map(|id| self.lower_node_id(id).node_id)
- .unwrap_or_else(|| self.next_id().node_id),
+ .map(|id| self.lower_node_id(id).node_id)
+ .unwrap_or_else(|| self.next_id().node_id),
),
span: s.span,
})
ThinVec::new()));
P(self.expr_call(e.span, from_err, hir_vec![e]))
}
+
+ fn check_self_struct_ctor_feature(&self, qp: &hir::QPath) {
+ if let hir::QPath::Resolved(_, ref p) = qp {
+ if p.segments.len() == 1 &&
+ p.segments[0].ident.name == keywords::SelfType.name() &&
+ !self.sess.features_untracked().self_struct_ctor {
+ emit_feature_err(&self.sess.parse_sess, "self_struct_ctor",
+ p.span, GateIssue::Language,
+ "`Self` struct constructors are unstable");
+ }
+ }
+ }
}
fn body_ids(bodies: &BTreeMap<hir::BodyId, hir::Body>) -> Vec<hir::BodyId> {