1 //! Lowers the AST to the HIR.
3 //! Since the AST and HIR are fairly similar, this is mostly a simple procedure,
4 //! much like a fold. Where lowering involves a bit more work things get more
5 //! interesting and there are some invariants you should know about. These mostly
6 //! concern spans and IDs.
8 //! Spans are assigned to AST nodes during parsing and then are modified during
9 //! expansion to indicate the origin of a node and the process it went through
10 //! being expanded. IDs are assigned to AST nodes just before lowering.
12 //! For the simpler lowering steps, IDs and spans should be preserved. Unlike
13 //! expansion we do not preserve the process of lowering in the spans, so spans
14 //! should not be modified here. When creating a new node (as opposed to
15 //! 'folding' an existing one), then you create a new ID using `next_id()`.
17 //! You must ensure that IDs are unique. That means that you should only use the
18 //! ID from an AST node in a single HIR node (you can assume that AST node IDs
19 //! are unique). Every new node must have a unique ID. Avoid cloning HIR nodes.
20 //! If you do, you must then set the new node's ID to a fresh one.
22 //! Spans are used for error messages and for tools to map semantics back to
23 //! source code. It is therefore not as important with spans as IDs to be strict
24 //! about use (you can't break the compiler by screwing up a span). Obviously, a
25 //! HIR node can only have a single span. But multiple nodes can have the same
26 //! span and spans don't need to be kept in order, etc. Where code is preserved
27 //! by lowering, it should have the same span as in the AST. Where HIR nodes are
28 //! new it is probably best to give a span for the whole AST node being lowered.
29 //! All nodes should have real spans, don't use dummy spans. Tools are likely to
30 //! get confused if the spans from leaf AST nodes occur in multiple places
31 //! in the HIR, especially for multiple identifiers.
33 use crate::dep_graph
::DepGraph
;
34 use crate::hir
::{self, ParamName}
;
35 use crate::hir
::HirVec
;
36 use crate::hir
::map
::{DefKey, DefPathData, Definitions}
;
37 use crate::hir
::def_id
::{DefId, DefIndex, DefIndexAddressSpace, CRATE_DEF_INDEX}
;
38 use crate::hir
::def
::{Def, PathResolution, PerNS}
;
39 use crate::hir
::{GenericArg, ConstArg}
;
40 use crate::lint
::builtin
::{self, PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES
,
41 ELIDED_LIFETIMES_IN_PATHS
};
42 use crate::middle
::cstore
::CrateStore
;
43 use crate::session
::Session
;
44 use crate::session
::config
::nightly_options
;
45 use crate::util
::common
::FN_OUTPUT_NAME
;
46 use crate::util
::nodemap
::{DefIdMap, NodeMap}
;
47 use errors
::Applicability
;
48 use rustc_data_structures
::fx
::FxHashSet
;
49 use rustc_data_structures
::indexed_vec
::IndexVec
;
50 use rustc_data_structures
::thin_vec
::ThinVec
;
51 use rustc_data_structures
::sync
::Lrc
;
53 use std
::collections
::{BTreeSet, BTreeMap}
;
56 use smallvec
::SmallVec
;
61 use syntax
::ext
::hygiene
::{Mark, SyntaxContext}
;
62 use syntax
::print
::pprust
;
64 use syntax
::source_map
::{self, respan, CompilerDesugaringKind, Spanned}
;
65 use syntax
::std_inject
;
66 use syntax
::symbol
::{keywords, Symbol}
;
67 use syntax
::tokenstream
::{TokenStream, TokenTree}
;
68 use syntax
::parse
::token
::Token
;
69 use syntax
::visit
::{self, Visitor}
;
70 use syntax_pos
::{Span, MultiSpan}
;
72 const HIR_ID_COUNTER_LOCKED
: u32 = 0xFFFFFFFF;
74 pub struct LoweringContext
<'a
> {
75 crate_root
: Option
<&'
static str>,
77 // Used to assign ids to HIR nodes that do not directly correspond to an AST node.
80 cstore
: &'a
dyn CrateStore
,
82 resolver
: &'a
mut dyn Resolver
,
84 /// The items being lowered are collected here.
85 items
: BTreeMap
<NodeId
, hir
::Item
>,
87 trait_items
: BTreeMap
<hir
::TraitItemId
, hir
::TraitItem
>,
88 impl_items
: BTreeMap
<hir
::ImplItemId
, hir
::ImplItem
>,
89 bodies
: BTreeMap
<hir
::BodyId
, hir
::Body
>,
90 exported_macros
: Vec
<hir
::MacroDef
>,
92 trait_impls
: BTreeMap
<DefId
, Vec
<NodeId
>>,
93 trait_auto_impl
: BTreeMap
<DefId
, NodeId
>,
95 modules
: BTreeMap
<NodeId
, hir
::ModuleItems
>,
99 catch_scopes
: Vec
<NodeId
>,
100 loop_scopes
: Vec
<NodeId
>,
101 is_in_loop_condition
: bool
,
102 is_in_trait_impl
: bool
,
104 /// What to do when we encounter either an "anonymous lifetime
105 /// reference". The term "anonymous" is meant to encompass both
106 /// `'_` lifetimes as well as fully elided cases where nothing is
107 /// written at all (e.g., `&T` or `std::cell::Ref<T>`).
108 anonymous_lifetime_mode
: AnonymousLifetimeMode
,
110 // Used to create lifetime definitions from in-band lifetime usages.
111 // e.g., `fn foo(x: &'x u8) -> &'x u8` to `fn foo<'x>(x: &'x u8) -> &'x u8`
112 // When a named lifetime is encountered in a function or impl header and
113 // has not been defined
114 // (i.e., it doesn't appear in the in_scope_lifetimes list), it is added
115 // to this list. The results of this list are then added to the list of
116 // lifetime definitions in the corresponding impl or function generics.
117 lifetimes_to_define
: Vec
<(Span
, ParamName
)>,
119 // Whether or not in-band lifetimes are being collected. This is used to
120 // indicate whether or not we're in a place where new lifetimes will result
121 // in in-band lifetime definitions, such a function or an impl header,
122 // including implicit lifetimes from `impl_header_lifetime_elision`.
123 is_collecting_in_band_lifetimes
: bool
,
125 // Currently in-scope lifetimes defined in impl headers, fn headers, or HRTB.
126 // When `is_collectin_in_band_lifetimes` is true, each lifetime is checked
127 // against this list to see if it is already in-scope, or if a definition
128 // needs to be created for it.
129 in_scope_lifetimes
: Vec
<Ident
>,
131 current_module
: NodeId
,
133 type_def_lifetime_params
: DefIdMap
<usize>,
135 current_hir_id_owner
: Vec
<(DefIndex
, u32)>,
136 item_local_id_counters
: NodeMap
<u32>,
137 node_id_to_hir_id
: IndexVec
<NodeId
, hir
::HirId
>,
141 /// Resolve a path generated by the lowerer when expanding `for`, `if let`, etc.
148 /// Obtain the resolution for a `NodeId`.
149 fn get_resolution(&mut self, id
: NodeId
) -> Option
<PathResolution
>;
151 /// Obtain the possible resolutions for the given `use` statement.
152 fn get_import(&mut self, id
: NodeId
) -> PerNS
<Option
<PathResolution
>>;
154 /// We must keep the set of definitions up to date as we add nodes that weren't in the AST.
155 /// This should only return `None` during testing.
156 fn definitions(&mut self) -> &mut Definitions
;
158 /// Given suffix `["b", "c", "d"]`, creates a HIR path for `[::crate_root]::b::c::d` and
159 /// resolves it based on `is_value`.
163 crate_root
: Option
<&str>,
170 enum ImplTraitContext
<'a
> {
171 /// Treat `impl Trait` as shorthand for a new universal generic parameter.
172 /// Example: `fn foo(x: impl Debug)`, where `impl Debug` is conceptually
173 /// equivalent to a fresh universal parameter like `fn foo<T: Debug>(x: T)`.
175 /// Newly generated parameters should be inserted into the given `Vec`.
176 Universal(&'a
mut Vec
<hir
::GenericParam
>),
178 /// Treat `impl Trait` as shorthand for a new existential parameter.
179 /// Example: `fn foo() -> impl Debug`, where `impl Debug` is conceptually
180 /// equivalent to a fresh existential parameter like `existential type T; fn foo() -> T`.
182 /// We optionally store a `DefId` for the parent item here so we can look up necessary
183 /// information later. It is `None` when no information about the context should be stored,
184 /// e.g., for consts and statics.
185 Existential(Option
<DefId
>),
187 /// `impl Trait` is not accepted in this position.
188 Disallowed(ImplTraitPosition
),
191 /// Position in which `impl Trait` is disallowed. Used for error reporting.
192 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
193 enum ImplTraitPosition
{
198 impl<'a
> ImplTraitContext
<'a
> {
200 fn disallowed() -> Self {
201 ImplTraitContext
::Disallowed(ImplTraitPosition
::Other
)
204 fn reborrow(&'b
mut self) -> ImplTraitContext
<'b
> {
205 use self::ImplTraitContext
::*;
207 Universal(params
) => Universal(params
),
208 Existential(did
) => Existential(*did
),
209 Disallowed(pos
) => Disallowed(*pos
),
216 cstore
: &dyn CrateStore
,
217 dep_graph
: &DepGraph
,
219 resolver
: &mut dyn Resolver
,
221 // We're constructing the HIR here; we don't care what we will
222 // read, since we haven't even constructed the *input* to
224 dep_graph
.assert_ignored();
227 crate_root
: std_inject
::injected_crate_name(),
231 items
: BTreeMap
::new(),
232 trait_items
: BTreeMap
::new(),
233 impl_items
: BTreeMap
::new(),
234 bodies
: BTreeMap
::new(),
235 trait_impls
: BTreeMap
::new(),
236 trait_auto_impl
: BTreeMap
::new(),
237 modules
: BTreeMap
::new(),
238 exported_macros
: Vec
::new(),
239 catch_scopes
: Vec
::new(),
240 loop_scopes
: Vec
::new(),
241 is_in_loop_condition
: false,
242 anonymous_lifetime_mode
: AnonymousLifetimeMode
::PassThrough
,
243 type_def_lifetime_params
: Default
::default(),
244 current_module
: CRATE_NODE_ID
,
245 current_hir_id_owner
: vec
![(CRATE_DEF_INDEX
, 0)],
246 item_local_id_counters
: Default
::default(),
247 node_id_to_hir_id
: IndexVec
::new(),
249 is_in_trait_impl
: false,
250 lifetimes_to_define
: Vec
::new(),
251 is_collecting_in_band_lifetimes
: false,
252 in_scope_lifetimes
: Vec
::new(),
256 #[derive(Copy, Clone, PartialEq)]
258 /// Any path in a type context.
260 /// The `module::Type` in `module::Type::method` in an expression.
265 struct LoweredNodeId
{
270 enum ParenthesizedGenericArgs
{
276 /// What to do when we encounter an **anonymous** lifetime
277 /// reference. Anonymous lifetime references come in two flavors. You
278 /// have implicit, or fully elided, references to lifetimes, like the
279 /// one in `&T` or `Ref<T>`, and you have `'_` lifetimes, like `&'_ T`
280 /// or `Ref<'_, T>`. These often behave the same, but not always:
282 /// - certain usages of implicit references are deprecated, like
283 /// `Ref<T>`, and we sometimes just give hard errors in those cases
285 /// - for object bounds there is a difference: `Box<dyn Foo>` is not
286 /// the same as `Box<dyn Foo + '_>`.
288 /// We describe the effects of the various modes in terms of three cases:
290 /// - **Modern** -- includes all uses of `'_`, but also the lifetime arg
291 /// of a `&` (e.g., the missing lifetime in something like `&T`)
292 /// - **Dyn Bound** -- if you have something like `Box<dyn Foo>`,
293 /// there is an elided lifetime bound (`Box<dyn Foo + 'X>`). These
294 /// elided bounds follow special rules. Note that this only covers
295 /// cases where *nothing* is written; the `'_` in `Box<dyn Foo +
296 /// '_>` is a case of "modern" elision.
297 /// - **Deprecated** -- this coverse cases like `Ref<T>`, where the lifetime
298 /// parameter to ref is completely elided. `Ref<'_, T>` would be the modern,
299 /// non-deprecated equivalent.
301 /// Currently, the handling of lifetime elision is somewhat spread out
302 /// between HIR lowering and -- as described below -- the
303 /// `resolve_lifetime` module. Often we "fallthrough" to that code by generating
304 /// an "elided" or "underscore" lifetime name. In the future, we probably want to move
305 /// everything into HIR lowering.
306 #[derive(Copy, Clone)]
307 enum AnonymousLifetimeMode
{
308 /// For **Modern** cases, create a new anonymous region parameter
309 /// and reference that.
311 /// For **Dyn Bound** cases, pass responsibility to
312 /// `resolve_lifetime` code.
314 /// For **Deprecated** cases, report an error.
317 /// Give a hard error when either `&` or `'_` is written. Used to
318 /// rule out things like `where T: Foo<'_>`. Does not imply an
319 /// error on default object bounds (e.g., `Box<dyn Foo>`).
322 /// Pass responsibility to `resolve_lifetime` code for all cases.
326 struct ImplTraitTypeIdVisitor
<'a
> { ids: &'a mut SmallVec<[hir::ItemId; 1]> }
328 impl<'a
, 'b
> Visitor
<'a
> for ImplTraitTypeIdVisitor
<'b
> {
329 fn visit_ty(&mut self, ty
: &'a Ty
) {
335 TyKind
::ImplTrait(id
, _
) => self.ids
.push(hir
::ItemId { id }
),
338 visit
::walk_ty(self, ty
);
341 fn visit_path_segment(
344 path_segment
: &'v PathSegment
,
346 if let Some(ref p
) = path_segment
.args
{
347 if let GenericArgs
::Parenthesized(_
) = **p
{
351 visit
::walk_path_segment(self, path_span
, path_segment
)
355 impl<'a
> LoweringContext
<'a
> {
356 fn lower_crate(mut self, c
: &Crate
) -> hir
::Crate
{
357 /// Full-crate AST visitor that inserts into a fresh
358 /// `LoweringContext` any information that may be
359 /// needed from arbitrary locations in the crate,
360 /// e.g., the number of lifetime generic parameters
361 /// declared for every type and trait definition.
362 struct MiscCollector
<'lcx
, 'interner
: 'lcx
> {
363 lctx
: &'lcx
mut LoweringContext
<'interner
>,
366 impl<'lcx
, 'interner
> Visitor
<'lcx
> for MiscCollector
<'lcx
, 'interner
> {
367 fn visit_item(&mut self, item
: &'lcx Item
) {
368 self.lctx
.allocate_hir_id_counter(item
.id
, item
);
371 ItemKind
::Struct(_
, ref generics
)
372 | ItemKind
::Union(_
, ref generics
)
373 | ItemKind
::Enum(_
, ref generics
)
374 | ItemKind
::Ty(_
, ref generics
)
375 | ItemKind
::Existential(_
, ref generics
)
376 | ItemKind
::Trait(_
, _
, ref generics
, ..) => {
377 let def_id
= self.lctx
.resolver
.definitions().local_def_id(item
.id
);
381 .filter(|param
| match param
.kind
{
382 ast
::GenericParamKind
::Lifetime { .. }
=> true,
386 self.lctx
.type_def_lifetime_params
.insert(def_id
, count
);
390 visit
::walk_item(self, item
);
393 fn visit_trait_item(&mut self, item
: &'lcx TraitItem
) {
394 self.lctx
.allocate_hir_id_counter(item
.id
, item
);
395 visit
::walk_trait_item(self, item
);
398 fn visit_impl_item(&mut self, item
: &'lcx ImplItem
) {
399 self.lctx
.allocate_hir_id_counter(item
.id
, item
);
400 visit
::walk_impl_item(self, item
);
404 struct ItemLowerer
<'lcx
, 'interner
: 'lcx
> {
405 lctx
: &'lcx
mut LoweringContext
<'interner
>,
408 impl<'lcx
, 'interner
> ItemLowerer
<'lcx
, 'interner
> {
409 fn with_trait_impl_ref
<F
>(&mut self, trait_impl_ref
: &Option
<TraitRef
>, f
: F
)
411 F
: FnOnce(&mut Self),
413 let old
= self.lctx
.is_in_trait_impl
;
414 self.lctx
.is_in_trait_impl
= if let &None
= trait_impl_ref
{
420 self.lctx
.is_in_trait_impl
= old
;
424 impl<'lcx
, 'interner
> Visitor
<'lcx
> for ItemLowerer
<'lcx
, 'interner
> {
425 fn visit_mod(&mut self, m
: &'lcx Mod
, _s
: Span
, _attrs
: &[Attribute
], n
: NodeId
) {
426 self.lctx
.modules
.insert(n
, hir
::ModuleItems
{
427 items
: BTreeSet
::new(),
428 trait_items
: BTreeSet
::new(),
429 impl_items
: BTreeSet
::new(),
432 let old
= self.lctx
.current_module
;
433 self.lctx
.current_module
= n
;
434 visit
::walk_mod(self, m
);
435 self.lctx
.current_module
= old
;
438 fn visit_item(&mut self, item
: &'lcx Item
) {
439 let mut item_lowered
= true;
440 self.lctx
.with_hir_id_owner(item
.id
, |lctx
| {
441 if let Some(hir_item
) = lctx
.lower_item(item
) {
442 lctx
.insert_item(item
.id
, hir_item
);
444 item_lowered
= false;
449 let item_generics
= match self.lctx
.items
.get(&item
.id
).unwrap().node
{
450 hir
::ItemKind
::Impl(_
, _
, _
, ref generics
, ..)
451 | hir
::ItemKind
::Trait(_
, _
, ref generics
, ..) => {
452 generics
.params
.clone()
457 self.lctx
.with_parent_impl_lifetime_defs(&item_generics
, |this
| {
458 let this
= &mut ItemLowerer { lctx: this }
;
459 if let ItemKind
::Impl(.., ref opt_trait_ref
, _
, _
) = item
.node
{
460 this
.with_trait_impl_ref(opt_trait_ref
, |this
| {
461 visit
::walk_item(this
, item
)
464 visit
::walk_item(this
, item
);
470 fn visit_trait_item(&mut self, item
: &'lcx TraitItem
) {
471 self.lctx
.with_hir_id_owner(item
.id
, |lctx
| {
472 let id
= hir
::TraitItemId { node_id: item.id }
;
473 let hir_item
= lctx
.lower_trait_item(item
);
474 lctx
.trait_items
.insert(id
, hir_item
);
475 lctx
.modules
.get_mut(&lctx
.current_module
).unwrap().trait_items
.insert(id
);
478 visit
::walk_trait_item(self, item
);
481 fn visit_impl_item(&mut self, item
: &'lcx ImplItem
) {
482 self.lctx
.with_hir_id_owner(item
.id
, |lctx
| {
483 let id
= hir
::ImplItemId { node_id: item.id }
;
484 let hir_item
= lctx
.lower_impl_item(item
);
485 lctx
.impl_items
.insert(id
, hir_item
);
486 lctx
.modules
.get_mut(&lctx
.current_module
).unwrap().impl_items
.insert(id
);
488 visit
::walk_impl_item(self, item
);
492 self.lower_node_id(CRATE_NODE_ID
);
493 debug_assert
!(self.node_id_to_hir_id
[CRATE_NODE_ID
] == hir
::CRATE_HIR_ID
);
495 visit
::walk_crate(&mut MiscCollector { lctx: &mut self }
, c
);
496 visit
::walk_crate(&mut ItemLowerer { lctx: &mut self }
, c
);
498 let module
= self.lower_mod(&c
.module
);
499 let attrs
= self.lower_attrs(&c
.attrs
);
500 let body_ids
= body_ids(&self.bodies
);
504 .init_node_id_to_hir_id_mapping(self.node_id_to_hir_id
);
510 exported_macros
: hir
::HirVec
::from(self.exported_macros
),
512 trait_items
: self.trait_items
,
513 impl_items
: self.impl_items
,
516 trait_impls
: self.trait_impls
,
517 trait_auto_impl
: self.trait_auto_impl
,
518 modules
: self.modules
,
522 fn insert_item(&mut self, id
: NodeId
, item
: hir
::Item
) {
523 self.items
.insert(id
, item
);
524 self.modules
.get_mut(&self.current_module
).unwrap().items
.insert(id
);
527 fn allocate_hir_id_counter
<T
: Debug
>(&mut self, owner
: NodeId
, debug
: &T
) -> LoweredNodeId
{
528 if self.item_local_id_counters
.insert(owner
, 0).is_some() {
530 "Tried to allocate item_local_id_counter for {:?} twice",
534 // Always allocate the first `HirId` for the owner itself.
535 self.lower_node_id_with_owner(owner
, owner
)
538 fn lower_node_id_generic
<F
>(&mut self, ast_node_id
: NodeId
, alloc_hir_id
: F
) -> LoweredNodeId
540 F
: FnOnce(&mut Self) -> hir
::HirId
,
542 if ast_node_id
== DUMMY_NODE_ID
{
543 return LoweredNodeId
{
544 node_id
: DUMMY_NODE_ID
,
545 hir_id
: hir
::DUMMY_HIR_ID
,
549 let min_size
= ast_node_id
.as_usize() + 1;
551 if min_size
> self.node_id_to_hir_id
.len() {
552 self.node_id_to_hir_id
.resize(min_size
, hir
::DUMMY_HIR_ID
);
555 let existing_hir_id
= self.node_id_to_hir_id
[ast_node_id
];
557 if existing_hir_id
== hir
::DUMMY_HIR_ID
{
558 // Generate a new `HirId`.
559 let hir_id
= alloc_hir_id(self);
560 self.node_id_to_hir_id
[ast_node_id
] = hir_id
;
562 node_id
: ast_node_id
,
567 node_id
: ast_node_id
,
568 hir_id
: existing_hir_id
,
573 fn with_hir_id_owner
<F
, T
>(&mut self, owner
: NodeId
, f
: F
) -> T
575 F
: FnOnce(&mut Self) -> T
,
577 let counter
= self.item_local_id_counters
578 .insert(owner
, HIR_ID_COUNTER_LOCKED
)
579 .unwrap_or_else(|| panic
!("No item_local_id_counters entry for {:?}", owner
));
580 let def_index
= self.resolver
.definitions().opt_def_index(owner
).unwrap();
581 self.current_hir_id_owner
.push((def_index
, counter
));
583 let (new_def_index
, new_counter
) = self.current_hir_id_owner
.pop().unwrap();
585 debug_assert
!(def_index
== new_def_index
);
586 debug_assert
!(new_counter
>= counter
);
588 let prev
= self.item_local_id_counters
589 .insert(owner
, new_counter
)
591 debug_assert
!(prev
== HIR_ID_COUNTER_LOCKED
);
595 /// This method allocates a new `HirId` for the given `NodeId` and stores it in
596 /// the `LoweringContext`'s `NodeId => HirId` map.
597 /// Take care not to call this method if the resulting `HirId` is then not
598 /// actually used in the HIR, as that would trigger an assertion in the
599 /// `HirIdValidator` later on, which makes sure that all `NodeId`s got mapped
600 /// properly. Calling the method twice with the same `NodeId` is fine though.
601 fn lower_node_id(&mut self, ast_node_id
: NodeId
) -> LoweredNodeId
{
602 self.lower_node_id_generic(ast_node_id
, |this
| {
603 let &mut (def_index
, ref mut local_id_counter
) =
604 this
.current_hir_id_owner
.last_mut().unwrap();
605 let local_id
= *local_id_counter
;
606 *local_id_counter
+= 1;
609 local_id
: hir
::ItemLocalId
::from_u32(local_id
),
614 fn lower_node_id_with_owner(&mut self, ast_node_id
: NodeId
, owner
: NodeId
) -> LoweredNodeId
{
615 self.lower_node_id_generic(ast_node_id
, |this
| {
616 let local_id_counter
= this
617 .item_local_id_counters
619 .expect("called lower_node_id_with_owner before allocate_hir_id_counter");
620 let local_id
= *local_id_counter
;
622 // We want to be sure not to modify the counter in the map while it
623 // is also on the stack. Otherwise we'll get lost updates when writing
624 // back from the stack to the map.
625 debug_assert
!(local_id
!= HIR_ID_COUNTER_LOCKED
);
627 *local_id_counter
+= 1;
631 .opt_def_index(owner
)
632 .expect("You forgot to call `create_def_with_parent` or are lowering node ids \
633 that do not belong to the current owner");
637 local_id
: hir
::ItemLocalId
::from_u32(local_id
),
642 fn record_body(&mut self, value
: hir
::Expr
, decl
: Option
<&FnDecl
>) -> hir
::BodyId
{
643 let body
= hir
::Body
{
644 arguments
: decl
.map_or(hir_vec
![], |decl
| {
645 decl
.inputs
.iter().map(|x
| self.lower_arg(x
)).collect()
647 is_generator
: self.is_generator
,
651 self.bodies
.insert(id
, body
);
655 fn next_id(&mut self) -> LoweredNodeId
{
656 self.lower_node_id(self.sess
.next_node_id())
659 fn expect_full_def(&mut self, id
: NodeId
) -> Def
{
660 self.resolver
.get_resolution(id
).map_or(Def
::Err
, |pr
| {
661 if pr
.unresolved_segments() != 0 {
662 bug
!("path not fully resolved: {:?}", pr
);
668 fn expect_full_def_from_use(&mut self, id
: NodeId
) -> impl Iterator
<Item
= Def
> {
669 self.resolver
.get_import(id
).present_items().map(|pr
| {
670 if pr
.unresolved_segments() != 0 {
671 bug
!("path not fully resolved: {:?}", pr
);
677 fn diagnostic(&self) -> &errors
::Handler
{
678 self.sess
.diagnostic()
681 fn str_to_ident(&self, s
: &'
static str) -> Ident
{
682 Ident
::with_empty_ctxt(Symbol
::gensym(s
))
685 /// Reuses the span but adds information like the kind of the desugaring and features that are
686 /// allowed inside this span.
687 fn mark_span_with_reason(
689 reason
: CompilerDesugaringKind
,
691 allow_internal_unstable
: Option
<Lrc
<[Symbol
]>>,
693 let mark
= Mark
::fresh(Mark
::root());
694 mark
.set_expn_info(source_map
::ExpnInfo
{
696 def_site
: Some(span
),
697 format
: source_map
::CompilerDesugaring(reason
),
698 allow_internal_unstable
,
699 allow_internal_unsafe
: false,
700 local_inner_macros
: false,
701 edition
: source_map
::hygiene
::default_edition(),
703 span
.with_ctxt(SyntaxContext
::empty().apply_mark(mark
))
706 fn with_anonymous_lifetime_mode
<R
>(
708 anonymous_lifetime_mode
: AnonymousLifetimeMode
,
709 op
: impl FnOnce(&mut Self) -> R
,
711 let old_anonymous_lifetime_mode
= self.anonymous_lifetime_mode
;
712 self.anonymous_lifetime_mode
= anonymous_lifetime_mode
;
713 let result
= op(self);
714 self.anonymous_lifetime_mode
= old_anonymous_lifetime_mode
;
718 /// Creates a new hir::GenericParam for every new lifetime and
719 /// type parameter encountered while evaluating `f`. Definitions
720 /// are created with the parent provided. If no `parent_id` is
721 /// provided, no definitions will be returned.
723 /// Presuming that in-band lifetimes are enabled, then
724 /// `self.anonymous_lifetime_mode` will be updated to match the
725 /// argument while `f` is running (and restored afterwards).
726 fn collect_in_band_defs
<T
, F
>(
729 anonymous_lifetime_mode
: AnonymousLifetimeMode
,
731 ) -> (Vec
<hir
::GenericParam
>, T
)
733 F
: FnOnce(&mut LoweringContext
<'_
>) -> (Vec
<hir
::GenericParam
>, T
),
735 assert
!(!self.is_collecting_in_band_lifetimes
);
736 assert
!(self.lifetimes_to_define
.is_empty());
737 let old_anonymous_lifetime_mode
= self.anonymous_lifetime_mode
;
739 self.anonymous_lifetime_mode
= anonymous_lifetime_mode
;
740 self.is_collecting_in_band_lifetimes
= true;
742 let (in_band_ty_params
, res
) = f(self);
744 self.is_collecting_in_band_lifetimes
= false;
745 self.anonymous_lifetime_mode
= old_anonymous_lifetime_mode
;
747 let lifetimes_to_define
= self.lifetimes_to_define
.split_off(0);
749 let params
= lifetimes_to_define
751 .map(|(span
, hir_name
)| {
752 let LoweredNodeId { node_id, hir_id }
= self.next_id();
754 // Get the name we'll use to make the def-path. Note
755 // that collisions are ok here and this shouldn't
756 // really show up for end-user.
757 let (str_name
, kind
) = match hir_name
{
758 ParamName
::Plain(ident
) => (
759 ident
.as_interned_str(),
760 hir
::LifetimeParamKind
::InBand
,
762 ParamName
::Fresh(_
) => (
763 keywords
::UnderscoreLifetime
.name().as_interned_str(),
764 hir
::LifetimeParamKind
::Elided
,
766 ParamName
::Error
=> (
767 keywords
::UnderscoreLifetime
.name().as_interned_str(),
768 hir
::LifetimeParamKind
::Error
,
772 // Add a definition for the in-band lifetime def.
773 self.resolver
.definitions().create_def_with_parent(
776 DefPathData
::LifetimeParam(str_name
),
777 DefIndexAddressSpace
::High
,
789 pure_wrt_drop
: false,
790 kind
: hir
::GenericParamKind
::Lifetime { kind }
793 .chain(in_band_ty_params
.into_iter())
799 /// When there is a reference to some lifetime `'a`, and in-band
800 /// lifetimes are enabled, then we want to push that lifetime into
801 /// the vector of names to define later. In that case, it will get
802 /// added to the appropriate generics.
803 fn maybe_collect_in_band_lifetime(&mut self, ident
: Ident
) {
804 if !self.is_collecting_in_band_lifetimes
{
808 if !self.sess
.features_untracked().in_band_lifetimes
{
812 if self.in_scope_lifetimes
.contains(&ident
.modern()) {
816 let hir_name
= ParamName
::Plain(ident
);
818 if self.lifetimes_to_define
.iter()
819 .any(|(_
, lt_name
)| lt_name
.modern() == hir_name
.modern()) {
823 self.lifetimes_to_define
.push((ident
.span
, hir_name
));
826 /// When we have either an elided or `'_` lifetime in an impl
827 /// header, we convert it to an in-band lifetime.
828 fn collect_fresh_in_band_lifetime(&mut self, span
: Span
) -> ParamName
{
829 assert
!(self.is_collecting_in_band_lifetimes
);
830 let index
= self.lifetimes_to_define
.len();
831 let hir_name
= ParamName
::Fresh(index
);
832 self.lifetimes_to_define
.push((span
, hir_name
));
836 // Evaluates `f` with the lifetimes in `params` in-scope.
837 // This is used to track which lifetimes have already been defined, and
838 // which are new in-band lifetimes that need to have a definition created
840 fn with_in_scope_lifetime_defs
<T
, F
>(&mut self, params
: &[GenericParam
], f
: F
) -> T
842 F
: FnOnce(&mut LoweringContext
<'_
>) -> T
,
844 let old_len
= self.in_scope_lifetimes
.len();
845 let lt_def_names
= params
.iter().filter_map(|param
| match param
.kind
{
846 GenericParamKind
::Lifetime { .. }
=> Some(param
.ident
.modern()),
849 self.in_scope_lifetimes
.extend(lt_def_names
);
853 self.in_scope_lifetimes
.truncate(old_len
);
857 // Same as the method above, but accepts `hir::GenericParam`s
858 // instead of `ast::GenericParam`s.
859 // This should only be used with generics that have already had their
860 // in-band lifetimes added. In practice, this means that this function is
861 // only used when lowering a child item of a trait or impl.
862 fn with_parent_impl_lifetime_defs
<T
, F
>(&mut self,
863 params
: &HirVec
<hir
::GenericParam
>,
866 F
: FnOnce(&mut LoweringContext
<'_
>) -> T
,
868 let old_len
= self.in_scope_lifetimes
.len();
869 let lt_def_names
= params
.iter().filter_map(|param
| match param
.kind
{
870 hir
::GenericParamKind
::Lifetime { .. }
=> Some(param
.name
.ident().modern()),
873 self.in_scope_lifetimes
.extend(lt_def_names
);
877 self.in_scope_lifetimes
.truncate(old_len
);
881 /// Appends in-band lifetime defs and argument-position `impl
882 /// Trait` defs to the existing set of generics.
884 /// Presuming that in-band lifetimes are enabled, then
885 /// `self.anonymous_lifetime_mode` will be updated to match the
886 /// argument while `f` is running (and restored afterwards).
887 fn add_in_band_defs
<F
, T
>(
891 anonymous_lifetime_mode
: AnonymousLifetimeMode
,
893 ) -> (hir
::Generics
, T
)
895 F
: FnOnce(&mut LoweringContext
<'_
>, &mut Vec
<hir
::GenericParam
>) -> T
,
897 let (in_band_defs
, (mut lowered_generics
, res
)) = self.with_in_scope_lifetime_defs(
900 this
.collect_in_band_defs(parent_id
, anonymous_lifetime_mode
, |this
| {
901 let mut params
= Vec
::new();
902 let generics
= this
.lower_generics(
904 ImplTraitContext
::Universal(&mut params
),
906 let res
= f(this
, &mut params
);
907 (params
, (generics
, res
))
912 lowered_generics
.params
= lowered_generics
919 (lowered_generics
, res
)
922 fn with_catch_scope
<T
, F
>(&mut self, catch_id
: NodeId
, f
: F
) -> T
924 F
: FnOnce(&mut LoweringContext
<'_
>) -> T
,
926 let len
= self.catch_scopes
.len();
927 self.catch_scopes
.push(catch_id
);
929 let result
= f(self);
932 self.catch_scopes
.len(),
933 "catch scopes should be added and removed in stack order"
936 self.catch_scopes
.pop().unwrap();
943 capture_clause
: CaptureBy
,
944 closure_node_id
: NodeId
,
946 body
: impl FnOnce(&mut LoweringContext
<'_
>) -> hir
::Expr
,
948 let prev_is_generator
= mem
::replace(&mut self.is_generator
, true);
949 let body_expr
= body(self);
950 let span
= body_expr
.span
;
951 let output
= match ret_ty
{
952 Some(ty
) => FunctionRetTy
::Ty(P(ty
.clone())),
953 None
=> FunctionRetTy
::Default(span
),
960 let body_id
= self.record_body(body_expr
, Some(&decl
));
961 self.is_generator
= prev_is_generator
;
963 let capture_clause
= self.lower_capture_clause(capture_clause
);
964 let closure_hir_id
= self.lower_node_id(closure_node_id
).hir_id
;
965 let decl
= self.lower_fn_decl(&decl
, None
, /* impl trait allowed */ false, None
);
966 let generator
= hir
::Expr
{
968 hir_id
: closure_hir_id
,
969 node
: hir
::ExprKind
::Closure(capture_clause
, decl
, body_id
, span
,
970 Some(hir
::GeneratorMovability
::Static
)),
972 attrs
: ThinVec
::new(),
975 let unstable_span
= self.mark_span_with_reason(
976 CompilerDesugaringKind
::Async
,
979 Symbol
::intern("gen_future"),
982 let gen_future
= self.expr_std_path(
983 unstable_span
, &["future", "from_generator"], None
, ThinVec
::new());
984 hir
::ExprKind
::Call(P(gen_future
), hir_vec
![generator
])
987 fn lower_body
<F
>(&mut self, decl
: Option
<&FnDecl
>, f
: F
) -> hir
::BodyId
989 F
: FnOnce(&mut LoweringContext
<'_
>) -> hir
::Expr
,
991 let prev
= mem
::replace(&mut self.is_generator
, false);
992 let result
= f(self);
993 let r
= self.record_body(result
, decl
);
994 self.is_generator
= prev
;
998 fn with_loop_scope
<T
, F
>(&mut self, loop_id
: NodeId
, f
: F
) -> T
1000 F
: FnOnce(&mut LoweringContext
<'_
>) -> T
,
1002 // We're no longer in the base loop's condition; we're in another loop.
1003 let was_in_loop_condition
= self.is_in_loop_condition
;
1004 self.is_in_loop_condition
= false;
1006 let len
= self.loop_scopes
.len();
1007 self.loop_scopes
.push(loop_id
);
1009 let result
= f(self);
1012 self.loop_scopes
.len(),
1013 "Loop scopes should be added and removed in stack order"
1016 self.loop_scopes
.pop().unwrap();
1018 self.is_in_loop_condition
= was_in_loop_condition
;
1023 fn with_loop_condition_scope
<T
, F
>(&mut self, f
: F
) -> T
1025 F
: FnOnce(&mut LoweringContext
<'_
>) -> T
,
1027 let was_in_loop_condition
= self.is_in_loop_condition
;
1028 self.is_in_loop_condition
= true;
1030 let result
= f(self);
1032 self.is_in_loop_condition
= was_in_loop_condition
;
1037 fn with_new_scopes
<T
, F
>(&mut self, f
: F
) -> T
1039 F
: FnOnce(&mut LoweringContext
<'_
>) -> T
,
1041 let was_in_loop_condition
= self.is_in_loop_condition
;
1042 self.is_in_loop_condition
= false;
1044 let catch_scopes
= mem
::replace(&mut self.catch_scopes
, Vec
::new());
1045 let loop_scopes
= mem
::replace(&mut self.loop_scopes
, Vec
::new());
1047 self.catch_scopes
= catch_scopes
;
1048 self.loop_scopes
= loop_scopes
;
1050 self.is_in_loop_condition
= was_in_loop_condition
;
1055 fn def_key(&mut self, id
: DefId
) -> DefKey
{
1057 self.resolver
.definitions().def_key(id
.index
)
1059 self.cstore
.def_key(id
)
1063 fn lower_label(&mut self, label
: Option
<Label
>) -> Option
<hir
::Label
> {
1064 label
.map(|label
| hir
::Label
{
1069 fn lower_loop_destination(&mut self, destination
: Option
<(NodeId
, Label
)>) -> hir
::Destination
{
1070 let target_id
= match destination
{
1072 if let Def
::Label(loop_id
) = self.expect_full_def(id
) {
1073 Ok(self.lower_node_id(loop_id
).node_id
)
1075 Err(hir
::LoopIdError
::UnresolvedLabel
)
1082 .map(|id
| Ok(self.lower_node_id(id
).node_id
))
1083 .unwrap_or(Err(hir
::LoopIdError
::OutsideLoopScope
))
1088 label
: self.lower_label(destination
.map(|(_
, label
)| label
)),
1093 fn lower_attrs(&mut self, attrs
: &[Attribute
]) -> hir
::HirVec
<Attribute
> {
1096 .map(|a
| self.lower_attr(a
))
1100 fn lower_attr(&mut self, attr
: &Attribute
) -> Attribute
{
1101 // Note that we explicitly do not walk the path. Since we don't really
1102 // lower attributes (we use the AST version) there is nowhere to keep
1103 // the `HirId`s. We don't actually need HIR version of attributes anyway.
1107 path
: attr
.path
.clone(),
1108 tokens
: self.lower_token_stream(attr
.tokens
.clone()),
1109 is_sugared_doc
: attr
.is_sugared_doc
,
1114 fn lower_token_stream(&mut self, tokens
: TokenStream
) -> TokenStream
{
1117 .flat_map(|tree
| self.lower_token_tree(tree
).into_trees())
1121 fn lower_token_tree(&mut self, tree
: TokenTree
) -> TokenStream
{
1123 TokenTree
::Token(span
, token
) => self.lower_token(token
, span
),
1124 TokenTree
::Delimited(span
, delim
, tts
) => TokenTree
::Delimited(
1127 self.lower_token_stream(tts
),
1132 fn lower_token(&mut self, token
: Token
, span
: Span
) -> TokenStream
{
1134 Token
::Interpolated(nt
) => {
1135 let tts
= nt
.to_tokenstream(&self.sess
.parse_sess
, span
);
1136 self.lower_token_stream(tts
)
1138 other
=> TokenTree
::Token(span
, other
).into(),
1142 fn lower_arm(&mut self, arm
: &Arm
) -> hir
::Arm
{
1144 attrs
: self.lower_attrs(&arm
.attrs
),
1145 pats
: arm
.pats
.iter().map(|x
| self.lower_pat(x
)).collect(),
1146 guard
: match arm
.guard
{
1147 Some(Guard
::If(ref x
)) => Some(hir
::Guard
::If(P(self.lower_expr(x
)))),
1150 body
: P(self.lower_expr(&arm
.body
)),
1154 fn lower_ty_binding(&mut self, b
: &TypeBinding
,
1155 itctx
: ImplTraitContext
<'_
>) -> hir
::TypeBinding
{
1156 let LoweredNodeId { node_id, hir_id }
= self.lower_node_id(b
.id
);
1162 ty
: self.lower_ty(&b
.ty
, itctx
),
1167 fn lower_generic_arg(&mut self,
1168 arg
: &ast
::GenericArg
,
1169 itctx
: ImplTraitContext
<'_
>)
1170 -> hir
::GenericArg
{
1172 ast
::GenericArg
::Lifetime(lt
) => GenericArg
::Lifetime(self.lower_lifetime(<
)),
1173 ast
::GenericArg
::Type(ty
) => GenericArg
::Type(self.lower_ty_direct(&ty
, itctx
)),
1174 ast
::GenericArg
::Const(ct
) => {
1175 GenericArg
::Const(ConstArg
{
1176 value
: self.lower_anon_const(&ct
),
1177 span
: ct
.value
.span
,
1183 fn lower_ty(&mut self, t
: &Ty
, itctx
: ImplTraitContext
<'_
>) -> P
<hir
::Ty
> {
1184 P(self.lower_ty_direct(t
, itctx
))
1187 fn lower_ty_direct(&mut self, t
: &Ty
, mut itctx
: ImplTraitContext
<'_
>) -> hir
::Ty
{
1188 let kind
= match t
.node
{
1189 TyKind
::Infer
=> hir
::TyKind
::Infer
,
1190 TyKind
::Err
=> hir
::TyKind
::Err
,
1191 TyKind
::Slice(ref ty
) => hir
::TyKind
::Slice(self.lower_ty(ty
, itctx
)),
1192 TyKind
::Ptr(ref mt
) => hir
::TyKind
::Ptr(self.lower_mt(mt
, itctx
)),
1193 TyKind
::Rptr(ref region
, ref mt
) => {
1194 let span
= self.sess
.source_map().next_point(t
.span
.shrink_to_lo());
1195 let lifetime
= match *region
{
1196 Some(ref lt
) => self.lower_lifetime(lt
),
1197 None
=> self.elided_ref_lifetime(span
),
1199 hir
::TyKind
::Rptr(lifetime
, self.lower_mt(mt
, itctx
))
1201 TyKind
::BareFn(ref f
) => self.with_in_scope_lifetime_defs(
1204 this
.with_anonymous_lifetime_mode(
1205 AnonymousLifetimeMode
::PassThrough
,
1207 hir
::TyKind
::BareFn(P(hir
::BareFnTy
{
1208 generic_params
: this
.lower_generic_params(
1210 &NodeMap
::default(),
1211 ImplTraitContext
::disallowed(),
1213 unsafety
: this
.lower_unsafety(f
.unsafety
),
1215 decl
: this
.lower_fn_decl(&f
.decl
, None
, false, None
),
1216 arg_names
: this
.lower_fn_args_to_names(&f
.decl
),
1222 TyKind
::Never
=> hir
::TyKind
::Never
,
1223 TyKind
::Tup(ref tys
) => {
1224 hir
::TyKind
::Tup(tys
.iter().map(|ty
| {
1225 self.lower_ty_direct(ty
, itctx
.reborrow())
1228 TyKind
::Paren(ref ty
) => {
1229 return self.lower_ty_direct(ty
, itctx
);
1231 TyKind
::Path(ref qself
, ref path
) => {
1232 let id
= self.lower_node_id(t
.id
);
1233 let qpath
= self.lower_qpath(t
.id
, qself
, path
, ParamMode
::Explicit
, itctx
);
1234 let ty
= self.ty_path(id
, t
.span
, qpath
);
1235 if let hir
::TyKind
::TraitObject(..) = ty
.node
{
1236 self.maybe_lint_bare_trait(t
.span
, t
.id
, qself
.is_none() && path
.is_global());
1240 TyKind
::ImplicitSelf
=> hir
::TyKind
::Path(hir
::QPath
::Resolved(
1243 def
: self.expect_full_def(t
.id
),
1244 segments
: hir_vec
![hir
::PathSegment
::from_ident(keywords
::SelfUpper
.ident())],
1248 TyKind
::Array(ref ty
, ref length
) => {
1249 hir
::TyKind
::Array(self.lower_ty(ty
, itctx
), self.lower_anon_const(length
))
1251 TyKind
::Typeof(ref expr
) => {
1252 hir
::TyKind
::Typeof(self.lower_anon_const(expr
))
1254 TyKind
::TraitObject(ref bounds
, kind
) => {
1255 let mut lifetime_bound
= None
;
1258 .filter_map(|bound
| match *bound
{
1259 GenericBound
::Trait(ref ty
, TraitBoundModifier
::None
) => {
1260 Some(self.lower_poly_trait_ref(ty
, itctx
.reborrow()))
1262 GenericBound
::Trait(_
, TraitBoundModifier
::Maybe
) => None
,
1263 GenericBound
::Outlives(ref lifetime
) => {
1264 if lifetime_bound
.is_none() {
1265 lifetime_bound
= Some(self.lower_lifetime(lifetime
));
1271 let lifetime_bound
=
1272 lifetime_bound
.unwrap_or_else(|| self.elided_dyn_bound(t
.span
));
1273 if kind
!= TraitObjectSyntax
::Dyn
{
1274 self.maybe_lint_bare_trait(t
.span
, t
.id
, false);
1276 hir
::TyKind
::TraitObject(bounds
, lifetime_bound
)
1278 TyKind
::ImplTrait(def_node_id
, ref bounds
) => {
1281 ImplTraitContext
::Existential(fn_def_id
) => {
1282 self.lower_existential_impl_trait(
1283 span
, fn_def_id
, def_node_id
,
1284 |this
| this
.lower_param_bounds(bounds
, itctx
),
1287 ImplTraitContext
::Universal(in_band_ty_params
) => {
1288 let LoweredNodeId { node_id: _, hir_id }
= self.lower_node_id(def_node_id
);
1289 // Add a definition for the in-band `Param`.
1290 let def_index
= self
1293 .opt_def_index(def_node_id
)
1296 let hir_bounds
= self.lower_param_bounds(
1298 ImplTraitContext
::Universal(in_band_ty_params
),
1300 // Set the name to `impl Bound1 + Bound2`.
1301 let ident
= Ident
::from_str(&pprust
::ty_to_string(t
)).with_span_pos(span
);
1302 in_band_ty_params
.push(hir
::GenericParam
{
1305 name
: ParamName
::Plain(ident
),
1306 pure_wrt_drop
: false,
1310 kind
: hir
::GenericParamKind
::Type
{
1312 synthetic
: Some(hir
::SyntheticTyParamKind
::ImplTrait
),
1316 hir
::TyKind
::Path(hir
::QPath
::Resolved(
1320 def
: Def
::TyParam(DefId
::local(def_index
)),
1321 segments
: hir_vec
![hir
::PathSegment
::from_ident(ident
)],
1325 ImplTraitContext
::Disallowed(pos
) => {
1326 let allowed_in
= if self.sess
.features_untracked()
1327 .impl_trait_in_bindings
{
1328 "bindings or function and inherent method return types"
1330 "function and inherent method return types"
1332 let mut err
= struct_span_err
!(
1336 "`impl Trait` not allowed outside of {}",
1339 if pos
== ImplTraitPosition
::Binding
&&
1340 nightly_options
::is_nightly_build() {
1342 "add #![feature(impl_trait_in_bindings)] to the crate attributes \
1350 TyKind
::Mac(_
) => panic
!("TyMac should have been expanded by now."),
1353 let LoweredNodeId { node_id, hir_id }
= self.lower_node_id(t
.id
);
1362 fn lower_existential_impl_trait(
1365 fn_def_id
: Option
<DefId
>,
1366 exist_ty_node_id
: NodeId
,
1367 lower_bounds
: impl FnOnce(&mut LoweringContext
<'_
>) -> hir
::GenericBounds
,
1369 // Make sure we know that some funky desugaring has been going on here.
1370 // This is a first: there is code in other places like for loop
1371 // desugaring that explicitly states that we don't want to track that.
1372 // Not tracking it makes lints in rustc and clippy very fragile as
1373 // frequently opened issues show.
1374 let exist_ty_span
= self.mark_span_with_reason(
1375 CompilerDesugaringKind
::ExistentialReturnType
,
1380 let exist_ty_def_index
= self
1383 .opt_def_index(exist_ty_node_id
)
1386 self.allocate_hir_id_counter(exist_ty_node_id
, &"existential impl trait");
1388 let hir_bounds
= self.with_hir_id_owner(exist_ty_node_id
, lower_bounds
);
1390 let (lifetimes
, lifetime_defs
) = self.lifetimes_from_impl_trait_bounds(
1396 self.with_hir_id_owner(exist_ty_node_id
, |lctx
| {
1397 let LoweredNodeId { node_id, hir_id }
= lctx
.next_id();
1398 let exist_ty_item_kind
= hir
::ItemKind
::Existential(hir
::ExistTy
{
1399 generics
: hir
::Generics
{
1400 params
: lifetime_defs
,
1401 where_clause
: hir
::WhereClause
{
1404 predicates
: Vec
::new().into(),
1409 impl_trait_fn
: fn_def_id
,
1411 let exist_ty_id
= lctx
.lower_node_id(exist_ty_node_id
);
1412 // Generate an `existential type Foo: Trait;` declaration.
1413 trace
!("creating existential type with id {:#?}", exist_ty_id
);
1415 trace
!("exist ty def index: {:#?}", exist_ty_def_index
);
1416 let exist_ty_item
= hir
::Item
{
1417 id
: exist_ty_id
.node_id
,
1418 hir_id
: exist_ty_id
.hir_id
,
1419 ident
: keywords
::Invalid
.ident(),
1420 attrs
: Default
::default(),
1421 node
: exist_ty_item_kind
,
1422 vis
: respan(span
.shrink_to_lo(), hir
::VisibilityKind
::Inherited
),
1423 span
: exist_ty_span
,
1426 // Insert the item into the global list. This usually happens
1427 // automatically for all AST items. But this existential type item
1428 // does not actually exist in the AST.
1429 lctx
.insert_item(exist_ty_id
.node_id
, exist_ty_item
);
1431 // `impl Trait` now just becomes `Foo<'a, 'b, ..>`.
1432 hir
::TyKind
::Def(hir
::ItemId { id: exist_ty_id.node_id }
, lifetimes
)
1436 fn lifetimes_from_impl_trait_bounds(
1438 exist_ty_id
: NodeId
,
1439 parent_index
: DefIndex
,
1440 bounds
: &hir
::GenericBounds
,
1441 ) -> (HirVec
<hir
::GenericArg
>, HirVec
<hir
::GenericParam
>) {
1442 // This visitor walks over impl trait bounds and creates defs for all lifetimes which
1443 // appear in the bounds, excluding lifetimes that are created within the bounds.
1444 // E.g., `'a`, `'b`, but not `'c` in `impl for<'c> SomeTrait<'a, 'b, 'c>`.
1445 struct ImplTraitLifetimeCollector
<'r
, 'a
: 'r
> {
1446 context
: &'r
mut LoweringContext
<'a
>,
1448 exist_ty_id
: NodeId
,
1449 collect_elided_lifetimes
: bool
,
1450 currently_bound_lifetimes
: Vec
<hir
::LifetimeName
>,
1451 already_defined_lifetimes
: FxHashSet
<hir
::LifetimeName
>,
1452 output_lifetimes
: Vec
<hir
::GenericArg
>,
1453 output_lifetime_params
: Vec
<hir
::GenericParam
>,
1456 impl<'r
, 'a
: 'r
, 'v
> hir
::intravisit
::Visitor
<'v
> for ImplTraitLifetimeCollector
<'r
, 'a
> {
1457 fn nested_visit_map
<'this
>(
1459 ) -> hir
::intravisit
::NestedVisitorMap
<'this
, 'v
> {
1460 hir
::intravisit
::NestedVisitorMap
::None
1463 fn visit_generic_args(&mut self, span
: Span
, parameters
: &'v hir
::GenericArgs
) {
1464 // Don't collect elided lifetimes used inside of `Fn()` syntax.
1465 if parameters
.parenthesized
{
1466 let old_collect_elided_lifetimes
= self.collect_elided_lifetimes
;
1467 self.collect_elided_lifetimes
= false;
1468 hir
::intravisit
::walk_generic_args(self, span
, parameters
);
1469 self.collect_elided_lifetimes
= old_collect_elided_lifetimes
;
1471 hir
::intravisit
::walk_generic_args(self, span
, parameters
);
1475 fn visit_ty(&mut self, t
: &'v hir
::Ty
) {
1476 // Don't collect elided lifetimes used inside of `fn()` syntax.
1477 if let hir
::TyKind
::BareFn(_
) = t
.node
{
1478 let old_collect_elided_lifetimes
= self.collect_elided_lifetimes
;
1479 self.collect_elided_lifetimes
= false;
1481 // Record the "stack height" of `for<'a>` lifetime bindings
1482 // to be able to later fully undo their introduction.
1483 let old_len
= self.currently_bound_lifetimes
.len();
1484 hir
::intravisit
::walk_ty(self, t
);
1485 self.currently_bound_lifetimes
.truncate(old_len
);
1487 self.collect_elided_lifetimes
= old_collect_elided_lifetimes
;
1489 hir
::intravisit
::walk_ty(self, t
)
1493 fn visit_poly_trait_ref(
1495 trait_ref
: &'v hir
::PolyTraitRef
,
1496 modifier
: hir
::TraitBoundModifier
,
1498 // Record the "stack height" of `for<'a>` lifetime bindings
1499 // to be able to later fully undo their introduction.
1500 let old_len
= self.currently_bound_lifetimes
.len();
1501 hir
::intravisit
::walk_poly_trait_ref(self, trait_ref
, modifier
);
1502 self.currently_bound_lifetimes
.truncate(old_len
);
1505 fn visit_generic_param(&mut self, param
: &'v hir
::GenericParam
) {
1506 // Record the introduction of 'a in `for<'a> ...`.
1507 if let hir
::GenericParamKind
::Lifetime { .. }
= param
.kind
{
1508 // Introduce lifetimes one at a time so that we can handle
1509 // cases like `fn foo<'d>() -> impl for<'a, 'b: 'a, 'c: 'b + 'd>`.
1510 let lt_name
= hir
::LifetimeName
::Param(param
.name
);
1511 self.currently_bound_lifetimes
.push(lt_name
);
1514 hir
::intravisit
::walk_generic_param(self, param
);
1517 fn visit_lifetime(&mut self, lifetime
: &'v hir
::Lifetime
) {
1518 let name
= match lifetime
.name
{
1519 hir
::LifetimeName
::Implicit
| hir
::LifetimeName
::Underscore
=> {
1520 if self.collect_elided_lifetimes
{
1521 // Use `'_` for both implicit and underscore lifetimes in
1522 // `abstract type Foo<'_>: SomeTrait<'_>;`.
1523 hir
::LifetimeName
::Underscore
1528 hir
::LifetimeName
::Param(_
) => lifetime
.name
,
1529 hir
::LifetimeName
::Error
| hir
::LifetimeName
::Static
=> return,
1532 if !self.currently_bound_lifetimes
.contains(&name
)
1533 && !self.already_defined_lifetimes
.contains(&name
) {
1534 self.already_defined_lifetimes
.insert(name
);
1536 let LoweredNodeId { node_id, hir_id }
= self.context
.next_id();
1537 self.output_lifetimes
.push(hir
::GenericArg
::Lifetime(hir
::Lifetime
{
1540 span
: lifetime
.span
,
1544 // We need to manually create the ids here, because the
1545 // definitions will go into the explicit `existential type`
1546 // declaration and thus need to have their owner set to that item
1547 let def_node_id
= self.context
.sess
.next_node_id();
1548 let LoweredNodeId { node_id: _, hir_id }
=
1549 self.context
.lower_node_id_with_owner(def_node_id
, self.exist_ty_id
);
1550 self.context
.resolver
.definitions().create_def_with_parent(
1553 DefPathData
::LifetimeParam(name
.ident().as_interned_str()),
1554 DefIndexAddressSpace
::High
,
1559 let (name
, kind
) = match name
{
1560 hir
::LifetimeName
::Underscore
=> (
1561 hir
::ParamName
::Plain(keywords
::UnderscoreLifetime
.ident()),
1562 hir
::LifetimeParamKind
::Elided
,
1564 hir
::LifetimeName
::Param(param_name
) => (
1566 hir
::LifetimeParamKind
::Explicit
,
1568 _
=> bug
!("expected LifetimeName::Param or ParamName::Plain"),
1571 self.output_lifetime_params
.push(hir
::GenericParam
{
1575 span
: lifetime
.span
,
1576 pure_wrt_drop
: false,
1579 kind
: hir
::GenericParamKind
::Lifetime { kind }
1585 let mut lifetime_collector
= ImplTraitLifetimeCollector
{
1587 parent
: parent_index
,
1589 collect_elided_lifetimes
: true,
1590 currently_bound_lifetimes
: Vec
::new(),
1591 already_defined_lifetimes
: FxHashSet
::default(),
1592 output_lifetimes
: Vec
::new(),
1593 output_lifetime_params
: Vec
::new(),
1596 for bound
in bounds
{
1597 hir
::intravisit
::walk_param_bound(&mut lifetime_collector
, &bound
);
1601 lifetime_collector
.output_lifetimes
.into(),
1602 lifetime_collector
.output_lifetime_params
.into(),
1606 fn lower_foreign_mod(&mut self, fm
: &ForeignMod
) -> hir
::ForeignMod
{
1611 .map(|x
| self.lower_foreign_item(x
))
1616 fn lower_global_asm(&mut self, ga
: &GlobalAsm
) -> P
<hir
::GlobalAsm
> {
1623 fn lower_variant(&mut self, v
: &Variant
) -> hir
::Variant
{
1625 node
: hir
::VariantKind
{
1626 ident
: v
.node
.ident
,
1627 attrs
: self.lower_attrs(&v
.node
.attrs
),
1628 data
: self.lower_variant_data(&v
.node
.data
),
1629 disr_expr
: v
.node
.disr_expr
.as_ref().map(|e
| self.lower_anon_const(e
)),
1638 qself
: &Option
<QSelf
>,
1640 param_mode
: ParamMode
,
1641 mut itctx
: ImplTraitContext
<'_
>,
1643 let qself_position
= qself
.as_ref().map(|q
| q
.position
);
1644 let qself
= qself
.as_ref().map(|q
| self.lower_ty(&q
.ty
, itctx
.reborrow()));
1646 let resolution
= self.resolver
1648 .unwrap_or_else(|| PathResolution
::new(Def
::Err
));
1650 let proj_start
= p
.segments
.len() - resolution
.unresolved_segments();
1651 let path
= P(hir
::Path
{
1652 def
: resolution
.base_def(),
1653 segments
: p
.segments
[..proj_start
]
1656 .map(|(i
, segment
)| {
1657 let param_mode
= match (qself_position
, param_mode
) {
1658 (Some(j
), ParamMode
::Optional
) if i
< j
=> {
1659 // This segment is part of the trait path in a
1660 // qualified path - one of `a`, `b` or `Trait`
1661 // in `<X as a::b::Trait>::T::U::method`.
1667 // Figure out if this is a type/trait segment,
1668 // which may need lifetime elision performed.
1669 let parent_def_id
= |this
: &mut Self, def_id
: DefId
| DefId
{
1670 krate
: def_id
.krate
,
1671 index
: this
.def_key(def_id
).parent
.expect("missing parent"),
1673 let type_def_id
= match resolution
.base_def() {
1674 Def
::AssociatedTy(def_id
) if i
+ 2 == proj_start
=> {
1675 Some(parent_def_id(self, def_id
))
1677 Def
::Variant(def_id
) if i
+ 1 == proj_start
=> {
1678 Some(parent_def_id(self, def_id
))
1681 | Def
::Union(def_id
)
1683 | Def
::TyAlias(def_id
)
1684 | Def
::Trait(def_id
) if i
+ 1 == proj_start
=>
1690 let parenthesized_generic_args
= match resolution
.base_def() {
1691 // `a::b::Trait(Args)`
1692 Def
::Trait(..) if i
+ 1 == proj_start
=> ParenthesizedGenericArgs
::Ok
,
1693 // `a::b::Trait(Args)::TraitItem`
1694 Def
::Method(..) | Def
::AssociatedConst(..) | Def
::AssociatedTy(..)
1695 if i
+ 2 == proj_start
=>
1697 ParenthesizedGenericArgs
::Ok
1699 // Avoid duplicated errors.
1700 Def
::Err
=> ParenthesizedGenericArgs
::Ok
,
1706 | Def
::Variant(..) if i
+ 1 == proj_start
=>
1708 ParenthesizedGenericArgs
::Err
1710 // A warning for now, for compatibility reasons
1711 _
=> ParenthesizedGenericArgs
::Warn
,
1714 let num_lifetimes
= type_def_id
.map_or(0, |def_id
| {
1715 if let Some(&n
) = self.type_def_lifetime_params
.get(&def_id
) {
1718 assert
!(!def_id
.is_local());
1720 self.cstore
.item_generics_cloned_untracked(def_id
, self.sess
);
1721 let n
= item_generics
.own_counts().lifetimes
;
1722 self.type_def_lifetime_params
.insert(def_id
, n
);
1725 self.lower_path_segment(
1730 parenthesized_generic_args
,
1739 // Simple case, either no projections, or only fully-qualified.
1740 // E.g., `std::mem::size_of` or `<I as Iterator>::Item`.
1741 if resolution
.unresolved_segments() == 0 {
1742 return hir
::QPath
::Resolved(qself
, path
);
1745 // Create the innermost type that we're projecting from.
1746 let mut ty
= if path
.segments
.is_empty() {
1747 // If the base path is empty that means there exists a
1748 // syntactical `Self`, e.g., `&i32` in `<&i32>::clone`.
1749 qself
.expect("missing QSelf for <T>::...")
1751 // Otherwise, the base path is an implicit `Self` type path,
1752 // e.g., `Vec` in `Vec::new` or `<I as Iterator>::Item` in
1753 // `<I as Iterator>::Item::default`.
1754 let new_id
= self.next_id();
1755 P(self.ty_path(new_id
, p
.span
, hir
::QPath
::Resolved(qself
, path
)))
1758 // Anything after the base path are associated "extensions",
1759 // out of which all but the last one are associated types,
1760 // e.g., for `std::vec::Vec::<T>::IntoIter::Item::clone`:
1761 // * base path is `std::vec::Vec<T>`
1762 // * "extensions" are `IntoIter`, `Item` and `clone`
1763 // * type nodes are:
1764 // 1. `std::vec::Vec<T>` (created above)
1765 // 2. `<std::vec::Vec<T>>::IntoIter`
1766 // 3. `<<std::vec::Vec<T>>::IntoIter>::Item`
1767 // * final path is `<<<std::vec::Vec<T>>::IntoIter>::Item>::clone`
1768 for (i
, segment
) in p
.segments
.iter().enumerate().skip(proj_start
) {
1769 let segment
= P(self.lower_path_segment(
1774 ParenthesizedGenericArgs
::Warn
,
1778 let qpath
= hir
::QPath
::TypeRelative(ty
, segment
);
1780 // It's finished, return the extension of the right node type.
1781 if i
== p
.segments
.len() - 1 {
1785 // Wrap the associated extension in another type node.
1786 let new_id
= self.next_id();
1787 ty
= P(self.ty_path(new_id
, p
.span
, qpath
));
1790 // We should've returned in the for loop above.
1793 "lower_qpath: no final extension segment in {}..{}",
1799 fn lower_path_extra(
1803 param_mode
: ParamMode
,
1804 explicit_owner
: Option
<NodeId
>,
1808 segments
: p
.segments
1811 self.lower_path_segment(
1816 ParenthesizedGenericArgs
::Err
,
1817 ImplTraitContext
::disallowed(),
1826 fn lower_path(&mut self, id
: NodeId
, p
: &Path
, param_mode
: ParamMode
) -> hir
::Path
{
1827 let def
= self.expect_full_def(id
);
1828 self.lower_path_extra(def
, p
, param_mode
, None
)
1831 fn lower_path_segment(
1834 segment
: &PathSegment
,
1835 param_mode
: ParamMode
,
1836 expected_lifetimes
: usize,
1837 parenthesized_generic_args
: ParenthesizedGenericArgs
,
1838 itctx
: ImplTraitContext
<'_
>,
1839 explicit_owner
: Option
<NodeId
>,
1840 ) -> hir
::PathSegment
{
1841 let (mut generic_args
, infer_types
) = if let Some(ref generic_args
) = segment
.args
{
1842 let msg
= "parenthesized type parameters may only be used with a `Fn` trait";
1843 match **generic_args
{
1844 GenericArgs
::AngleBracketed(ref data
) => {
1845 self.lower_angle_bracketed_parameter_data(data
, param_mode
, itctx
)
1847 GenericArgs
::Parenthesized(ref data
) => match parenthesized_generic_args
{
1848 ParenthesizedGenericArgs
::Ok
=> self.lower_parenthesized_parameter_data(data
),
1849 ParenthesizedGenericArgs
::Warn
=> {
1850 self.sess
.buffer_lint(
1851 PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES
,
1856 (hir
::GenericArgs
::none(), true)
1858 ParenthesizedGenericArgs
::Err
=> {
1859 let mut err
= struct_span_err
!(self.sess
, data
.span
, E0214
, "{}", msg
);
1860 err
.span_label(data
.span
, "only `Fn` traits may use parentheses");
1861 if let Ok(snippet
) = self.sess
.source_map().span_to_snippet(data
.span
) {
1862 // Do not suggest going from `Trait()` to `Trait<>`
1863 if data
.inputs
.len() > 0 {
1864 err
.span_suggestion(
1866 "use angle brackets instead",
1867 format
!("<{}>", &snippet
[1..snippet
.len() - 1]),
1868 Applicability
::MaybeIncorrect
,
1873 (self.lower_angle_bracketed_parameter_data(
1874 &data
.as_angle_bracketed_args(),
1882 self.lower_angle_bracketed_parameter_data(&Default
::default(), param_mode
, itctx
)
1885 let has_lifetimes
= generic_args
.args
.iter().any(|arg
| match arg
{
1886 GenericArg
::Lifetime(_
) => true,
1889 let first_generic_span
= generic_args
.args
.iter().map(|a
| a
.span())
1890 .chain(generic_args
.bindings
.iter().map(|b
| b
.span
)).next();
1891 if !generic_args
.parenthesized
&& !has_lifetimes
{
1893 self.elided_path_lifetimes(path_span
, expected_lifetimes
)
1895 .map(|lt
| GenericArg
::Lifetime(lt
))
1896 .chain(generic_args
.args
.into_iter())
1898 if expected_lifetimes
> 0 && param_mode
== ParamMode
::Explicit
{
1899 let anon_lt_suggestion
= vec
!["'_"; expected_lifetimes
].join(", ");
1900 let no_ty_args
= generic_args
.args
.len() == expected_lifetimes
;
1901 let no_bindings
= generic_args
.bindings
.is_empty();
1902 let (incl_angl_brckt
, insertion_span
, suggestion
) = if no_ty_args
&& no_bindings
{
1903 // If there are no (non-implicit) generic args or associated-type
1904 // bindings, our suggestion includes the angle brackets.
1905 (true, path_span
.shrink_to_hi(), format
!("<{}>", anon_lt_suggestion
))
1907 // Otherwise—sorry, this is kind of gross—we need to infer the
1908 // place to splice in the `'_, ` from the generics that do exist.
1909 let first_generic_span
= first_generic_span
1910 .expect("already checked that type args or bindings exist");
1911 (false, first_generic_span
.shrink_to_lo(), format
!("{}, ", anon_lt_suggestion
))
1913 self.sess
.buffer_lint_with_diagnostic(
1914 ELIDED_LIFETIMES_IN_PATHS
,
1917 "hidden lifetime parameters in types are deprecated",
1918 builtin
::BuiltinLintDiagnostics
::ElidedLifetimesInPaths(
1919 expected_lifetimes
, path_span
, incl_angl_brckt
, insertion_span
, suggestion
1925 let def
= self.expect_full_def(segment
.id
);
1926 let id
= if let Some(owner
) = explicit_owner
{
1927 self.lower_node_id_with_owner(segment
.id
, owner
)
1929 self.lower_node_id(segment
.id
)
1932 "lower_path_segment: ident={:?} original-id={:?} new-id={:?}",
1933 segment
.ident
, segment
.id
, id
,
1936 hir
::PathSegment
::new(
1946 fn lower_angle_bracketed_parameter_data(
1948 data
: &AngleBracketedArgs
,
1949 param_mode
: ParamMode
,
1950 mut itctx
: ImplTraitContext
<'_
>,
1951 ) -> (hir
::GenericArgs
, bool
) {
1952 let &AngleBracketedArgs { ref args, ref bindings, .. }
= data
;
1953 let has_types
= args
.iter().any(|arg
| match arg
{
1954 ast
::GenericArg
::Type(_
) => true,
1958 args
: args
.iter().map(|a
| self.lower_generic_arg(a
, itctx
.reborrow())).collect(),
1959 bindings
: bindings
.iter().map(|b
| self.lower_ty_binding(b
, itctx
.reborrow())).collect(),
1960 parenthesized
: false,
1962 !has_types
&& param_mode
== ParamMode
::Optional
)
1965 fn lower_parenthesized_parameter_data(
1967 data
: &ParenthesizedArgs
,
1968 ) -> (hir
::GenericArgs
, bool
) {
1969 // Switch to `PassThrough` mode for anonymous lifetimes: this
1970 // means that we permit things like `&Ref<T>`, where `Ref` has
1971 // a hidden lifetime parameter. This is needed for backwards
1972 // compatibility, even in contexts like an impl header where
1973 // we generally don't permit such things (see #51008).
1974 self.with_anonymous_lifetime_mode(
1975 AnonymousLifetimeMode
::PassThrough
,
1977 let &ParenthesizedArgs { ref inputs, ref output, span }
= data
;
1980 .map(|ty
| this
.lower_ty_direct(ty
, ImplTraitContext
::disallowed()))
1982 let mk_tup
= |this
: &mut Self, tys
, span
| {
1983 let LoweredNodeId { node_id, hir_id }
= this
.next_id();
1984 hir
::Ty { node: hir::TyKind::Tup(tys), id: node_id, hir_id, span }
1986 let LoweredNodeId { node_id, hir_id }
= this
.next_id();
1990 args
: hir_vec
![GenericArg
::Type(mk_tup(this
, inputs
, span
))],
1995 ident
: Ident
::from_str(FN_OUTPUT_NAME
),
1998 .map(|ty
| this
.lower_ty(&ty
, ImplTraitContext
::disallowed()))
1999 .unwrap_or_else(|| P(mk_tup(this
, hir
::HirVec
::new(), span
))),
2000 span
: output
.as_ref().map_or(span
, |ty
| ty
.span
),
2003 parenthesized
: true,
2011 fn lower_local(&mut self, l
: &Local
) -> (hir
::Local
, SmallVec
<[hir
::ItemId
; 1]>) {
2012 let LoweredNodeId { node_id, hir_id }
= self.lower_node_id(l
.id
);
2013 let mut ids
= SmallVec
::<[hir
::ItemId
; 1]>::new();
2014 if self.sess
.features_untracked().impl_trait_in_bindings
{
2015 if let Some(ref ty
) = l
.ty
{
2016 let mut visitor
= ImplTraitTypeIdVisitor { ids: &mut ids }
;
2017 visitor
.visit_ty(ty
);
2020 let parent_def_id
= DefId
::local(self.current_hir_id_owner
.last().unwrap().0);
2026 .map(|t
| self.lower_ty(t
,
2027 if self.sess
.features_untracked().impl_trait_in_bindings
{
2028 ImplTraitContext
::Existential(Some(parent_def_id
))
2030 ImplTraitContext
::Disallowed(ImplTraitPosition
::Binding
)
2033 pat
: self.lower_pat(&l
.pat
),
2034 init
: l
.init
.as_ref().map(|e
| P(self.lower_expr(e
))),
2036 attrs
: l
.attrs
.clone(),
2037 source
: hir
::LocalSource
::Normal
,
2041 fn lower_mutability(&mut self, m
: Mutability
) -> hir
::Mutability
{
2043 Mutability
::Mutable
=> hir
::MutMutable
,
2044 Mutability
::Immutable
=> hir
::MutImmutable
,
2048 fn lower_arg(&mut self, arg
: &Arg
) -> hir
::Arg
{
2049 let LoweredNodeId { node_id, hir_id }
= self.lower_node_id(arg
.id
);
2053 pat
: self.lower_pat(&arg
.pat
),
2057 fn lower_fn_args_to_names(&mut self, decl
: &FnDecl
) -> hir
::HirVec
<Ident
> {
2060 .map(|arg
| match arg
.pat
.node
{
2061 PatKind
::Ident(_
, ident
, _
) => ident
,
2062 _
=> Ident
::new(keywords
::Invalid
.name(), arg
.pat
.span
),
2067 // Lowers a function declaration.
2069 // decl: the unlowered (ast) function declaration.
2070 // fn_def_id: if `Some`, impl Trait arguments are lowered into generic parameters on the
2071 // given DefId, otherwise impl Trait is disallowed. Must be `Some` if
2072 // make_ret_async is also `Some`.
2073 // impl_trait_return_allow: determines whether impl Trait can be used in return position.
2074 // This guards against trait declarations and implementations where impl Trait is
2076 // make_ret_async: if `Some`, converts `-> T` into `-> impl Future<Output = T>` in the
2077 // return type. This is used for `async fn` declarations. The `NodeId` is the id of the
2078 // return type impl Trait item.
2082 mut in_band_ty_params
: Option
<(DefId
, &mut Vec
<hir
::GenericParam
>)>,
2083 impl_trait_return_allow
: bool
,
2084 make_ret_async
: Option
<NodeId
>,
2085 ) -> P
<hir
::FnDecl
> {
2086 let inputs
= decl
.inputs
2089 if let Some((_
, ref mut ibty
)) = in_band_ty_params
{
2090 self.lower_ty_direct(&arg
.ty
, ImplTraitContext
::Universal(ibty
))
2092 self.lower_ty_direct(&arg
.ty
, ImplTraitContext
::disallowed())
2095 .collect
::<HirVec
<_
>>();
2097 let output
= if let Some(ret_id
) = make_ret_async
{
2098 self.lower_async_fn_ret_ty(
2101 in_band_ty_params
.expect("make_ret_async but no fn_def_id").0,
2106 FunctionRetTy
::Ty(ref ty
) => match in_band_ty_params
{
2107 Some((def_id
, _
)) if impl_trait_return_allow
=> {
2108 hir
::Return(self.lower_ty(ty
,
2109 ImplTraitContext
::Existential(Some(def_id
))))
2112 hir
::Return(self.lower_ty(ty
, ImplTraitContext
::disallowed()))
2115 FunctionRetTy
::Default(span
) => hir
::DefaultReturn(span
),
2122 variadic
: decl
.variadic
,
2123 implicit_self
: decl
.inputs
.get(0).map_or(
2124 hir
::ImplicitSelfKind
::None
,
2126 let is_mutable_pat
= match arg
.pat
.node
{
2127 PatKind
::Ident(BindingMode
::ByValue(mt
), _
, _
) |
2128 PatKind
::Ident(BindingMode
::ByRef(mt
), _
, _
) =>
2129 mt
== Mutability
::Mutable
,
2134 TyKind
::ImplicitSelf
if is_mutable_pat
=> hir
::ImplicitSelfKind
::Mut
,
2135 TyKind
::ImplicitSelf
=> hir
::ImplicitSelfKind
::Imm
,
2136 // Given we are only considering `ImplicitSelf` types, we needn't consider
2137 // the case where we have a mutable pattern to a reference as that would
2138 // no longer be an `ImplicitSelf`.
2139 TyKind
::Rptr(_
, ref mt
) if mt
.ty
.node
.is_implicit_self() &&
2140 mt
.mutbl
== ast
::Mutability
::Mutable
=>
2141 hir
::ImplicitSelfKind
::MutRef
,
2142 TyKind
::Rptr(_
, ref mt
) if mt
.ty
.node
.is_implicit_self() =>
2143 hir
::ImplicitSelfKind
::ImmRef
,
2144 _
=> hir
::ImplicitSelfKind
::None
,
2151 // Transform `-> T` into `-> impl Future<Output = T>` for `async fn`
2153 // fn_span: the span of the async function declaration. Used for error reporting.
2154 // inputs: lowered types of arguments to the function. Used to collect lifetimes.
2155 // output: unlowered output type (`T` in `-> T`)
2156 // fn_def_id: DefId of the parent function. Used to create child impl trait definition.
2157 fn lower_async_fn_ret_ty(
2160 output
: &FunctionRetTy
,
2162 return_impl_trait_id
: NodeId
,
2163 ) -> hir
::FunctionRetTy
{
2164 // Get lifetimes used in the input arguments to the function. Our output type must also
2165 // have the same lifetime.
2166 // FIXME(cramertj): multiple different lifetimes are not allowed because
2167 // `impl Trait + 'a + 'b` doesn't allow for capture `'a` and `'b` where neither is a subset
2168 // of the other. We really want some new lifetime that is a subset of all input lifetimes,
2169 // but that doesn't exist at the moment.
2171 struct AsyncFnLifetimeCollector
<'r
, 'a
: 'r
> {
2172 context
: &'r
mut LoweringContext
<'a
>,
2173 // Lifetimes bound by HRTB.
2174 currently_bound_lifetimes
: Vec
<hir
::LifetimeName
>,
2175 // Whether to count elided lifetimes.
2176 // Disabled inside of `Fn` or `fn` syntax.
2177 collect_elided_lifetimes
: bool
,
2178 // The lifetime found.
2179 // Multiple different or elided lifetimes cannot appear in async fn for now.
2180 output_lifetime
: Option
<(hir
::LifetimeName
, Span
)>,
2183 impl<'r
, 'a
: 'r
, 'v
> hir
::intravisit
::Visitor
<'v
> for AsyncFnLifetimeCollector
<'r
, 'a
> {
2184 fn nested_visit_map
<'this
>(
2186 ) -> hir
::intravisit
::NestedVisitorMap
<'this
, 'v
> {
2187 hir
::intravisit
::NestedVisitorMap
::None
2190 fn visit_generic_args(&mut self, span
: Span
, parameters
: &'v hir
::GenericArgs
) {
2191 // Don't collect elided lifetimes used inside of `Fn()` syntax.
2192 if parameters
.parenthesized
{
2193 let old_collect_elided_lifetimes
= self.collect_elided_lifetimes
;
2194 self.collect_elided_lifetimes
= false;
2195 hir
::intravisit
::walk_generic_args(self, span
, parameters
);
2196 self.collect_elided_lifetimes
= old_collect_elided_lifetimes
;
2198 hir
::intravisit
::walk_generic_args(self, span
, parameters
);
2202 fn visit_ty(&mut self, t
: &'v hir
::Ty
) {
2203 // Don't collect elided lifetimes used inside of `fn()` syntax.
2204 if let &hir
::TyKind
::BareFn(_
) = &t
.node
{
2205 let old_collect_elided_lifetimes
= self.collect_elided_lifetimes
;
2206 self.collect_elided_lifetimes
= false;
2208 // Record the "stack height" of `for<'a>` lifetime bindings
2209 // to be able to later fully undo their introduction.
2210 let old_len
= self.currently_bound_lifetimes
.len();
2211 hir
::intravisit
::walk_ty(self, t
);
2212 self.currently_bound_lifetimes
.truncate(old_len
);
2214 self.collect_elided_lifetimes
= old_collect_elided_lifetimes
;
2216 hir
::intravisit
::walk_ty(self, t
);
2220 fn visit_poly_trait_ref(
2222 trait_ref
: &'v hir
::PolyTraitRef
,
2223 modifier
: hir
::TraitBoundModifier
,
2225 // Record the "stack height" of `for<'a>` lifetime bindings
2226 // to be able to later fully undo their introduction.
2227 let old_len
= self.currently_bound_lifetimes
.len();
2228 hir
::intravisit
::walk_poly_trait_ref(self, trait_ref
, modifier
);
2229 self.currently_bound_lifetimes
.truncate(old_len
);
2232 fn visit_generic_param(&mut self, param
: &'v hir
::GenericParam
) {
2233 // Record the introduction of 'a in `for<'a> ...`
2234 if let hir
::GenericParamKind
::Lifetime { .. }
= param
.kind
{
2235 // Introduce lifetimes one at a time so that we can handle
2236 // cases like `fn foo<'d>() -> impl for<'a, 'b: 'a, 'c: 'b + 'd>`
2237 let lt_name
= hir
::LifetimeName
::Param(param
.name
);
2238 self.currently_bound_lifetimes
.push(lt_name
);
2241 hir
::intravisit
::walk_generic_param(self, param
);
2244 fn visit_lifetime(&mut self, lifetime
: &'v hir
::Lifetime
) {
2245 let name
= match lifetime
.name
{
2246 hir
::LifetimeName
::Implicit
| hir
::LifetimeName
::Underscore
=> {
2247 if self.collect_elided_lifetimes
{
2248 // Use `'_` for both implicit and underscore lifetimes in
2249 // `abstract type Foo<'_>: SomeTrait<'_>;`
2250 hir
::LifetimeName
::Underscore
2255 hir
::LifetimeName
::Param(_
) => lifetime
.name
,
2256 hir
::LifetimeName
::Error
| hir
::LifetimeName
::Static
=> return,
2259 if !self.currently_bound_lifetimes
.contains(&name
) {
2260 if let Some((current_lt_name
, current_lt_span
)) = self.output_lifetime
{
2261 // We don't currently have a reliable way to desugar `async fn` with
2262 // multiple potentially unrelated input lifetimes into
2263 // `-> impl Trait + 'lt`, so we report an error in this case.
2264 if current_lt_name
!= name
{
2267 MultiSpan
::from_spans(vec
![current_lt_span
, lifetime
.span
]),
2269 "multiple different lifetimes used in arguments of `async fn`",
2271 .span_label(current_lt_span
, "first lifetime here")
2272 .span_label(lifetime
.span
, "different lifetime here")
2273 .help("`async fn` can only accept borrowed values \
2274 with identical lifetimes")
2276 } else if current_lt_name
.is_elided() && name
.is_elided() {
2279 MultiSpan
::from_spans(vec
![current_lt_span
, lifetime
.span
]),
2281 "multiple elided lifetimes used in arguments of `async fn`",
2283 .span_label(current_lt_span
, "first lifetime here")
2284 .span_label(lifetime
.span
, "different lifetime here")
2285 .help("consider giving these arguments named lifetimes")
2289 self.output_lifetime
= Some((name
, lifetime
.span
));
2295 let bound_lifetime
= {
2296 let mut lifetime_collector
= AsyncFnLifetimeCollector
{
2298 currently_bound_lifetimes
: Vec
::new(),
2299 collect_elided_lifetimes
: true,
2300 output_lifetime
: None
,
2304 hir
::intravisit
::walk_ty(&mut lifetime_collector
, arg
);
2306 lifetime_collector
.output_lifetime
2309 let span
= match output
{
2310 FunctionRetTy
::Ty(ty
) => ty
.span
,
2311 FunctionRetTy
::Default(span
) => *span
,
2314 let impl_trait_ty
= self.lower_existential_impl_trait(
2315 span
, Some(fn_def_id
), return_impl_trait_id
, |this
| {
2316 let output_ty
= match output
{
2317 FunctionRetTy
::Ty(ty
) => {
2318 this
.lower_ty(ty
, ImplTraitContext
::Existential(Some(fn_def_id
)))
2320 FunctionRetTy
::Default(span
) => {
2321 let LoweredNodeId { node_id, hir_id }
= this
.next_id();
2325 node
: hir
::TyKind
::Tup(hir_vec
![]),
2332 let LoweredNodeId { node_id, hir_id }
= this
.next_id();
2333 let future_params
= P(hir
::GenericArgs
{
2335 bindings
: hir_vec
![hir
::TypeBinding
{
2336 ident
: Ident
::from_str(FN_OUTPUT_NAME
),
2342 parenthesized
: false,
2346 this
.std_path(span
, &["future", "Future"], Some(future_params
), false);
2348 let LoweredNodeId { node_id, hir_id }
= this
.next_id();
2349 let mut bounds
= vec
![
2350 hir
::GenericBound
::Trait(
2352 trait_ref
: hir
::TraitRef
{
2357 bound_generic_params
: hir_vec
![],
2360 hir
::TraitBoundModifier
::None
2364 if let Some((name
, span
)) = bound_lifetime
{
2365 let LoweredNodeId { node_id, hir_id }
= this
.next_id();
2366 bounds
.push(hir
::GenericBound
::Outlives(
2367 hir
::Lifetime { id: node_id, hir_id, name, span }
));
2370 hir
::HirVec
::from(bounds
)
2373 let LoweredNodeId { node_id, hir_id }
= self.next_id();
2374 let impl_trait_ty
= P(hir
::Ty
{
2376 node
: impl_trait_ty
,
2381 hir
::FunctionRetTy
::Return(impl_trait_ty
)
2384 fn lower_param_bound(
2387 itctx
: ImplTraitContext
<'_
>,
2388 ) -> hir
::GenericBound
{
2390 GenericBound
::Trait(ref ty
, modifier
) => {
2391 hir
::GenericBound
::Trait(
2392 self.lower_poly_trait_ref(ty
, itctx
),
2393 self.lower_trait_bound_modifier(modifier
),
2396 GenericBound
::Outlives(ref lifetime
) => {
2397 hir
::GenericBound
::Outlives(self.lower_lifetime(lifetime
))
2402 fn lower_lifetime(&mut self, l
: &Lifetime
) -> hir
::Lifetime
{
2403 let span
= l
.ident
.span
;
2405 ident
if ident
.name
== keywords
::StaticLifetime
.name() =>
2406 self.new_named_lifetime(l
.id
, span
, hir
::LifetimeName
::Static
),
2407 ident
if ident
.name
== keywords
::UnderscoreLifetime
.name() =>
2408 match self.anonymous_lifetime_mode
{
2409 AnonymousLifetimeMode
::CreateParameter
=> {
2410 let fresh_name
= self.collect_fresh_in_band_lifetime(span
);
2411 self.new_named_lifetime(l
.id
, span
, hir
::LifetimeName
::Param(fresh_name
))
2414 AnonymousLifetimeMode
::PassThrough
=> {
2415 self.new_named_lifetime(l
.id
, span
, hir
::LifetimeName
::Underscore
)
2418 AnonymousLifetimeMode
::ReportError
=> self.new_error_lifetime(Some(l
.id
), span
),
2421 self.maybe_collect_in_band_lifetime(ident
);
2422 let param_name
= ParamName
::Plain(ident
);
2423 self.new_named_lifetime(l
.id
, span
, hir
::LifetimeName
::Param(param_name
))
2428 fn new_named_lifetime(
2432 name
: hir
::LifetimeName
,
2433 ) -> hir
::Lifetime
{
2434 let LoweredNodeId { node_id, hir_id }
= self.lower_node_id(id
);
2444 fn lower_generic_params(
2446 params
: &[GenericParam
],
2447 add_bounds
: &NodeMap
<Vec
<GenericBound
>>,
2448 mut itctx
: ImplTraitContext
<'_
>,
2449 ) -> hir
::HirVec
<hir
::GenericParam
> {
2450 params
.iter().map(|param
| {
2451 self.lower_generic_param(param
, add_bounds
, itctx
.reborrow())
2455 fn lower_generic_param(&mut self,
2456 param
: &GenericParam
,
2457 add_bounds
: &NodeMap
<Vec
<GenericBound
>>,
2458 mut itctx
: ImplTraitContext
<'_
>)
2459 -> hir
::GenericParam
{
2460 let mut bounds
= self.with_anonymous_lifetime_mode(
2461 AnonymousLifetimeMode
::ReportError
,
2462 |this
| this
.lower_param_bounds(¶m
.bounds
, itctx
.reborrow()),
2465 let (name
, kind
) = match param
.kind
{
2466 GenericParamKind
::Lifetime
=> {
2467 let was_collecting_in_band
= self.is_collecting_in_band_lifetimes
;
2468 self.is_collecting_in_band_lifetimes
= false;
2470 let lt
= self.with_anonymous_lifetime_mode(
2471 AnonymousLifetimeMode
::ReportError
,
2472 |this
| this
.lower_lifetime(&Lifetime { id: param.id, ident: param.ident }
),
2474 let param_name
= match lt
.name
{
2475 hir
::LifetimeName
::Param(param_name
) => param_name
,
2476 hir
::LifetimeName
::Implicit
2477 | hir
::LifetimeName
::Underscore
2478 | hir
::LifetimeName
::Static
=> hir
::ParamName
::Plain(lt
.name
.ident()),
2479 hir
::LifetimeName
::Error
=> ParamName
::Error
,
2482 let kind
= hir
::GenericParamKind
::Lifetime
{
2483 kind
: hir
::LifetimeParamKind
::Explicit
2486 self.is_collecting_in_band_lifetimes
= was_collecting_in_band
;
2490 GenericParamKind
::Type { ref default, .. }
=> {
2491 // Don't expose `Self` (recovered "keyword used as ident" parse error).
2492 // `rustc::ty` expects `Self` to be only used for a trait's `Self`.
2493 // Instead, use `gensym("Self")` to create a distinct name that looks the same.
2494 let ident
= if param
.ident
.name
== keywords
::SelfUpper
.name() {
2495 param
.ident
.gensym()
2500 let add_bounds
= add_bounds
.get(¶m
.id
).map_or(&[][..], |x
| &x
);
2501 if !add_bounds
.is_empty() {
2502 let params
= self.lower_param_bounds(add_bounds
, itctx
.reborrow()).into_iter();
2503 bounds
= bounds
.into_iter()
2508 let kind
= hir
::GenericParamKind
::Type
{
2509 default: default.as_ref().map(|x
| {
2510 self.lower_ty(x
, ImplTraitContext
::disallowed())
2512 synthetic
: param
.attrs
.iter()
2513 .filter(|attr
| attr
.check_name("rustc_synthetic"))
2514 .map(|_
| hir
::SyntheticTyParamKind
::ImplTrait
)
2518 (hir
::ParamName
::Plain(ident
), kind
)
2520 GenericParamKind
::Const { ref ty }
=> {
2521 (hir
::ParamName
::Plain(param
.ident
), hir
::GenericParamKind
::Const
{
2522 ty
: self.lower_ty(&ty
, ImplTraitContext
::disallowed()),
2527 let LoweredNodeId { node_id, hir_id }
= self.lower_node_id(param
.id
);
2533 span
: param
.ident
.span
,
2534 pure_wrt_drop
: attr
::contains_name(¶m
.attrs
, "may_dangle"),
2535 attrs
: self.lower_attrs(¶m
.attrs
),
2543 generics
: &Generics
,
2544 itctx
: ImplTraitContext
<'_
>)
2547 // Collect `?Trait` bounds in where clause and move them to parameter definitions.
2548 // FIXME: this could probably be done with less rightward drift. Also looks like two control
2549 // paths where report_error is called are also the only paths that advance to after
2550 // the match statement, so the error reporting could probably just be moved there.
2551 let mut add_bounds
: NodeMap
<Vec
<_
>> = Default
::default();
2552 for pred
in &generics
.where_clause
.predicates
{
2553 if let WherePredicate
::BoundPredicate(ref bound_pred
) = *pred
{
2554 'next_bound
: for bound
in &bound_pred
.bounds
{
2555 if let GenericBound
::Trait(_
, TraitBoundModifier
::Maybe
) = *bound
{
2556 let report_error
= |this
: &mut Self| {
2557 this
.diagnostic().span_err(
2558 bound_pred
.bounded_ty
.span
,
2559 "`?Trait` bounds are only permitted at the \
2560 point where a type parameter is declared",
2563 // Check if the where clause type is a plain type parameter.
2564 match bound_pred
.bounded_ty
.node
{
2565 TyKind
::Path(None
, ref path
)
2566 if path
.segments
.len() == 1
2567 && bound_pred
.bound_generic_params
.is_empty() =>
2569 if let Some(Def
::TyParam(def_id
)) = self.resolver
2570 .get_resolution(bound_pred
.bounded_ty
.id
)
2571 .map(|d
| d
.base_def())
2573 if let Some(node_id
) =
2574 self.resolver
.definitions().as_local_node_id(def_id
)
2576 for param
in &generics
.params
{
2578 GenericParamKind
::Type { .. }
=> {
2579 if node_id
== param
.id
{
2580 add_bounds
.entry(param
.id
)
2582 .push(bound
.clone());
2583 continue 'next_bound
;
2593 _
=> report_error(self),
2601 params
: self.lower_generic_params(&generics
.params
, &add_bounds
, itctx
),
2602 where_clause
: self.lower_where_clause(&generics
.where_clause
),
2603 span
: generics
.span
,
2607 fn lower_where_clause(&mut self, wc
: &WhereClause
) -> hir
::WhereClause
{
2608 self.with_anonymous_lifetime_mode(
2609 AnonymousLifetimeMode
::ReportError
,
2611 let LoweredNodeId { node_id, hir_id }
= this
.lower_node_id(wc
.id
);
2616 predicates
: wc
.predicates
2618 .map(|predicate
| this
.lower_where_predicate(predicate
))
2625 fn lower_where_predicate(&mut self, pred
: &WherePredicate
) -> hir
::WherePredicate
{
2627 WherePredicate
::BoundPredicate(WhereBoundPredicate
{
2628 ref bound_generic_params
,
2633 self.with_in_scope_lifetime_defs(
2634 &bound_generic_params
,
2636 hir
::WherePredicate
::BoundPredicate(hir
::WhereBoundPredicate
{
2637 bound_generic_params
: this
.lower_generic_params(
2638 bound_generic_params
,
2639 &NodeMap
::default(),
2640 ImplTraitContext
::disallowed(),
2642 bounded_ty
: this
.lower_ty(bounded_ty
, ImplTraitContext
::disallowed()),
2645 .filter_map(|bound
| match *bound
{
2646 // Ignore `?Trait` bounds.
2647 // They were copied into type parameters already.
2648 GenericBound
::Trait(_
, TraitBoundModifier
::Maybe
) => None
,
2649 _
=> Some(this
.lower_param_bound(
2651 ImplTraitContext
::disallowed(),
2660 WherePredicate
::RegionPredicate(WhereRegionPredicate
{
2664 }) => hir
::WherePredicate
::RegionPredicate(hir
::WhereRegionPredicate
{
2666 lifetime
: self.lower_lifetime(lifetime
),
2667 bounds
: self.lower_param_bounds(bounds
, ImplTraitContext
::disallowed()),
2669 WherePredicate
::EqPredicate(WhereEqPredicate
{
2675 let LoweredNodeId { node_id, hir_id }
= self.lower_node_id(id
);
2677 hir
::WherePredicate
::EqPredicate(hir
::WhereEqPredicate
{
2680 lhs_ty
: self.lower_ty(lhs_ty
, ImplTraitContext
::disallowed()),
2681 rhs_ty
: self.lower_ty(rhs_ty
, ImplTraitContext
::disallowed()),
2688 fn lower_variant_data(&mut self, vdata
: &VariantData
) -> hir
::VariantData
{
2690 VariantData
::Struct(ref fields
, id
) => {
2691 let LoweredNodeId { node_id, hir_id }
= self.lower_node_id(id
);
2693 hir
::VariantData
::Struct(
2697 .map(|f
| self.lower_struct_field(f
))
2703 VariantData
::Tuple(ref fields
, id
) => {
2704 let LoweredNodeId { node_id, hir_id }
= self.lower_node_id(id
);
2706 hir
::VariantData
::Tuple(
2710 .map(|f
| self.lower_struct_field(f
))
2716 VariantData
::Unit(id
) => {
2717 let LoweredNodeId { node_id, hir_id }
= self.lower_node_id(id
);
2719 hir
::VariantData
::Unit(node_id
, hir_id
)
2724 fn lower_trait_ref(&mut self, p
: &TraitRef
, itctx
: ImplTraitContext
<'_
>) -> hir
::TraitRef
{
2725 let path
= match self.lower_qpath(p
.ref_id
, &None
, &p
.path
, ParamMode
::Explicit
, itctx
) {
2726 hir
::QPath
::Resolved(None
, path
) => path
.and_then(|path
| path
),
2727 qpath
=> bug
!("lower_trait_ref: unexpected QPath `{:?}`", qpath
),
2729 let LoweredNodeId { node_id, hir_id }
= self.lower_node_id(p
.ref_id
);
2737 fn lower_poly_trait_ref(
2740 mut itctx
: ImplTraitContext
<'_
>,
2741 ) -> hir
::PolyTraitRef
{
2742 let bound_generic_params
= self.lower_generic_params(
2743 &p
.bound_generic_params
,
2744 &NodeMap
::default(),
2747 let trait_ref
= self.with_parent_impl_lifetime_defs(
2748 &bound_generic_params
,
2749 |this
| this
.lower_trait_ref(&p
.trait_ref
, itctx
),
2753 bound_generic_params
,
2759 fn lower_struct_field(&mut self, (index
, f
): (usize, &StructField
)) -> hir
::StructField
{
2760 let LoweredNodeId { node_id, hir_id }
= self.lower_node_id(f
.id
);
2766 ident
: match f
.ident
{
2767 Some(ident
) => ident
,
2768 // FIXME(jseyfried): positional field hygiene
2769 None
=> Ident
::new(Symbol
::intern(&index
.to_string()), f
.span
),
2771 vis
: self.lower_visibility(&f
.vis
, None
),
2772 ty
: self.lower_ty(&f
.ty
, ImplTraitContext
::disallowed()),
2773 attrs
: self.lower_attrs(&f
.attrs
),
2777 fn lower_field(&mut self, f
: &Field
) -> hir
::Field
{
2778 let LoweredNodeId { node_id, hir_id }
= self.next_id();
2784 expr
: P(self.lower_expr(&f
.expr
)),
2786 is_shorthand
: f
.is_shorthand
,
2790 fn lower_mt(&mut self, mt
: &MutTy
, itctx
: ImplTraitContext
<'_
>) -> hir
::MutTy
{
2792 ty
: self.lower_ty(&mt
.ty
, itctx
),
2793 mutbl
: self.lower_mutability(mt
.mutbl
),
2797 fn lower_param_bounds(&mut self, bounds
: &[GenericBound
], mut itctx
: ImplTraitContext
<'_
>)
2798 -> hir
::GenericBounds
{
2799 bounds
.iter().map(|bound
| self.lower_param_bound(bound
, itctx
.reborrow())).collect()
2802 fn lower_block(&mut self, b
: &Block
, targeted_by_break
: bool
) -> P
<hir
::Block
> {
2803 let mut expr
= None
;
2805 let mut stmts
= vec
![];
2807 for (index
, stmt
) in b
.stmts
.iter().enumerate() {
2808 if index
== b
.stmts
.len() - 1 {
2809 if let StmtKind
::Expr(ref e
) = stmt
.node
{
2810 expr
= Some(P(self.lower_expr(e
)));
2812 stmts
.extend(self.lower_stmt(stmt
));
2815 stmts
.extend(self.lower_stmt(stmt
));
2819 let LoweredNodeId { node_id, hir_id }
= self.lower_node_id(b
.id
);
2824 stmts
: stmts
.into(),
2826 rules
: self.lower_block_check_mode(&b
.rules
),
2832 fn lower_async_body(
2838 self.lower_body(Some(decl
), |this
| {
2839 if let IsAsync
::Async { closure_id, .. }
= asyncness
{
2840 let async_expr
= this
.make_async_expr(
2841 CaptureBy
::Value
, closure_id
, None
,
2843 let body
= this
.lower_block(body
, false);
2844 this
.expr_block(body
, ThinVec
::new())
2846 this
.expr(body
.span
, async_expr
, ThinVec
::new())
2848 let body
= this
.lower_block(body
, false);
2849 this
.expr_block(body
, ThinVec
::new())
2858 attrs
: &hir
::HirVec
<Attribute
>,
2859 vis
: &mut hir
::Visibility
,
2861 ) -> hir
::ItemKind
{
2863 ItemKind
::ExternCrate(orig_name
) => hir
::ItemKind
::ExternCrate(orig_name
),
2864 ItemKind
::Use(ref use_tree
) => {
2865 // Start with an empty prefix
2868 span
: use_tree
.span
,
2871 self.lower_use_tree(use_tree
, &prefix
, id
, vis
, ident
, attrs
)
2873 ItemKind
::Static(ref t
, m
, ref e
) => {
2874 let value
= self.lower_body(None
, |this
| this
.lower_expr(e
));
2875 hir
::ItemKind
::Static(
2878 if self.sess
.features_untracked().impl_trait_in_bindings
{
2879 ImplTraitContext
::Existential(None
)
2881 ImplTraitContext
::Disallowed(ImplTraitPosition
::Binding
)
2884 self.lower_mutability(m
),
2888 ItemKind
::Const(ref t
, ref e
) => {
2889 let value
= self.lower_body(None
, |this
| this
.lower_expr(e
));
2890 hir
::ItemKind
::Const(
2893 if self.sess
.features_untracked().impl_trait_in_bindings
{
2894 ImplTraitContext
::Existential(None
)
2896 ImplTraitContext
::Disallowed(ImplTraitPosition
::Binding
)
2902 ItemKind
::Fn(ref decl
, header
, ref generics
, ref body
) => {
2903 let fn_def_id
= self.resolver
.definitions().local_def_id(id
);
2904 self.with_new_scopes(|this
| {
2905 // Note: we don't need to change the return type from `T` to
2906 // `impl Future<Output = T>` here because lower_body
2907 // only cares about the input argument patterns in the function
2908 // declaration (decl), not the return types.
2909 let body_id
= this
.lower_async_body(decl
, header
.asyncness
, body
);
2911 let (generics
, fn_decl
) = this
.add_in_band_defs(
2914 AnonymousLifetimeMode
::PassThrough
,
2915 |this
, idty
| this
.lower_fn_decl(
2917 Some((fn_def_id
, idty
)),
2919 header
.asyncness
.opt_return_id()
2925 this
.lower_fn_header(header
),
2931 ItemKind
::Mod(ref m
) => hir
::ItemKind
::Mod(self.lower_mod(m
)),
2932 ItemKind
::ForeignMod(ref nm
) => hir
::ItemKind
::ForeignMod(self.lower_foreign_mod(nm
)),
2933 ItemKind
::GlobalAsm(ref ga
) => hir
::ItemKind
::GlobalAsm(self.lower_global_asm(ga
)),
2934 ItemKind
::Ty(ref t
, ref generics
) => hir
::ItemKind
::Ty(
2935 self.lower_ty(t
, ImplTraitContext
::disallowed()),
2936 self.lower_generics(generics
, ImplTraitContext
::disallowed()),
2938 ItemKind
::Existential(ref b
, ref generics
) => hir
::ItemKind
::Existential(hir
::ExistTy
{
2939 generics
: self.lower_generics(generics
, ImplTraitContext
::disallowed()),
2940 bounds
: self.lower_param_bounds(b
, ImplTraitContext
::disallowed()),
2941 impl_trait_fn
: None
,
2943 ItemKind
::Enum(ref enum_definition
, ref generics
) => hir
::ItemKind
::Enum(
2945 variants
: enum_definition
2948 .map(|x
| self.lower_variant(x
))
2951 self.lower_generics(generics
, ImplTraitContext
::disallowed()),
2953 ItemKind
::Struct(ref struct_def
, ref generics
) => {
2954 let struct_def
= self.lower_variant_data(struct_def
);
2955 hir
::ItemKind
::Struct(
2957 self.lower_generics(generics
, ImplTraitContext
::disallowed()),
2960 ItemKind
::Union(ref vdata
, ref generics
) => {
2961 let vdata
= self.lower_variant_data(vdata
);
2962 hir
::ItemKind
::Union(
2964 self.lower_generics(generics
, ImplTraitContext
::disallowed()),
2976 let def_id
= self.resolver
.definitions().local_def_id(id
);
2978 // Lower the "impl header" first. This ordering is important
2979 // for in-band lifetimes! Consider `'a` here:
2981 // impl Foo<'a> for u32 {
2982 // fn method(&'a self) { .. }
2985 // Because we start by lowering the `Foo<'a> for u32`
2986 // part, we will add `'a` to the list of generics on
2987 // the impl. When we then encounter it later in the
2988 // method, it will not be considered an in-band
2989 // lifetime to be added, but rather a reference to a
2991 let (generics
, (trait_ref
, lowered_ty
)) = self.add_in_band_defs(
2994 AnonymousLifetimeMode
::CreateParameter
,
2996 let trait_ref
= trait_ref
.as_ref().map(|trait_ref
| {
2997 this
.lower_trait_ref(trait_ref
, ImplTraitContext
::disallowed())
3000 if let Some(ref trait_ref
) = trait_ref
{
3001 if let Def
::Trait(def_id
) = trait_ref
.path
.def
{
3002 this
.trait_impls
.entry(def_id
).or_default().push(id
);
3006 let lowered_ty
= this
.lower_ty(ty
, ImplTraitContext
::disallowed());
3008 (trait_ref
, lowered_ty
)
3012 let new_impl_items
= self.with_in_scope_lifetime_defs(
3013 &ast_generics
.params
,
3017 .map(|item
| this
.lower_impl_item_ref(item
))
3022 hir
::ItemKind
::Impl(
3023 self.lower_unsafety(unsafety
),
3024 self.lower_impl_polarity(polarity
),
3025 self.lower_defaultness(defaultness
, true /* [1] */),
3032 ItemKind
::Trait(is_auto
, unsafety
, ref generics
, ref bounds
, ref items
) => {
3033 let bounds
= self.lower_param_bounds(bounds
, ImplTraitContext
::disallowed());
3036 .map(|item
| self.lower_trait_item_ref(item
))
3038 hir
::ItemKind
::Trait(
3039 self.lower_is_auto(is_auto
),
3040 self.lower_unsafety(unsafety
),
3041 self.lower_generics(generics
, ImplTraitContext
::disallowed()),
3046 ItemKind
::TraitAlias(ref generics
, ref bounds
) => hir
::ItemKind
::TraitAlias(
3047 self.lower_generics(generics
, ImplTraitContext
::disallowed()),
3048 self.lower_param_bounds(bounds
, ImplTraitContext
::disallowed()),
3050 ItemKind
::MacroDef(..) | ItemKind
::Mac(..) => panic
!("Shouldn't still be around"),
3053 // [1] `defaultness.has_value()` is never called for an `impl`, always `true` in order to
3054 // not cause an assertion failure inside the `lower_defaultness` function.
3062 vis
: &mut hir
::Visibility
,
3064 attrs
: &hir
::HirVec
<Attribute
>,
3065 ) -> hir
::ItemKind
{
3066 debug
!("lower_use_tree(tree={:?})", tree
);
3067 debug
!("lower_use_tree: vis = {:?}", vis
);
3069 let path
= &tree
.prefix
;
3070 let segments
= prefix
3073 .chain(path
.segments
.iter())
3078 UseTreeKind
::Simple(rename
, id1
, id2
) => {
3079 *ident
= tree
.ident();
3081 // First, apply the prefix to the path.
3082 let mut path
= Path
{
3087 // Correctly resolve `self` imports.
3088 if path
.segments
.len() > 1
3089 && path
.segments
.last().unwrap().ident
.name
== keywords
::SelfLower
.name()
3091 let _
= path
.segments
.pop();
3092 if rename
.is_none() {
3093 *ident
= path
.segments
.last().unwrap().ident
;
3097 let parent_def_index
= self.current_hir_id_owner
.last().unwrap().0;
3098 let mut defs
= self.expect_full_def_from_use(id
);
3099 // We want to return *something* from this function, so hold onto the first item
3101 let ret_def
= defs
.next().unwrap_or(Def
::Err
);
3103 // Here, we are looping over namespaces, if they exist for the definition
3104 // being imported. We only handle type and value namespaces because we
3105 // won't be dealing with macros in the rest of the compiler.
3106 // Essentially a single `use` which imports two names is desugared into
3108 for (def
, &new_node_id
) in defs
.zip([id1
, id2
].iter()) {
3109 let vis
= vis
.clone();
3110 let ident
= ident
.clone();
3111 let mut path
= path
.clone();
3112 for seg
in &mut path
.segments
{
3113 seg
.id
= self.sess
.next_node_id();
3115 let span
= path
.span
;
3116 self.resolver
.definitions().create_def_with_parent(
3120 DefIndexAddressSpace
::High
,
3123 self.allocate_hir_id_counter(new_node_id
, &path
);
3125 self.with_hir_id_owner(new_node_id
, |this
| {
3126 let new_id
= this
.lower_node_id(new_node_id
);
3128 this
.lower_path_extra(def
, &path
, ParamMode
::Explicit
, None
);
3129 let item
= hir
::ItemKind
::Use(P(path
), hir
::UseKind
::Single
);
3130 let vis_kind
= match vis
.node
{
3131 hir
::VisibilityKind
::Public
=> hir
::VisibilityKind
::Public
,
3132 hir
::VisibilityKind
::Crate(sugar
) => hir
::VisibilityKind
::Crate(sugar
),
3133 hir
::VisibilityKind
::Inherited
=> hir
::VisibilityKind
::Inherited
,
3134 hir
::VisibilityKind
::Restricted { ref path, id: _, hir_id: _ }
=> {
3135 let id
= this
.next_id();
3136 let path
= this
.renumber_segment_ids(path
);
3137 hir
::VisibilityKind
::Restricted
{
3144 let vis
= respan(vis
.span
, vis_kind
);
3150 hir_id
: new_id
.hir_id
,
3152 attrs
: attrs
.clone(),
3162 P(self.lower_path_extra(ret_def
, &path
, ParamMode
::Explicit
, None
));
3163 hir
::ItemKind
::Use(path
, hir
::UseKind
::Single
)
3165 UseTreeKind
::Glob
=> {
3166 let path
= P(self.lower_path(
3172 ParamMode
::Explicit
,
3174 hir
::ItemKind
::Use(path
, hir
::UseKind
::Glob
)
3176 UseTreeKind
::Nested(ref trees
) => {
3177 // Nested imports are desugared into simple imports.
3178 // So, if we start with
3181 // pub(x) use foo::{a, b};
3184 // we will create three items:
3187 // pub(x) use foo::a;
3188 // pub(x) use foo::b;
3189 // pub(x) use foo::{}; // <-- this is called the `ListStem`
3192 // The first two are produced by recursively invoking
3193 // `lower_use_tree` (and indeed there may be things
3194 // like `use foo::{a::{b, c}}` and so forth). They
3195 // wind up being directly added to
3196 // `self.items`. However, the structure of this
3197 // function also requires us to return one item, and
3198 // for that we return the `{}` import (called the
3203 span
: prefix
.span
.to(path
.span
),
3206 // Add all the nested `PathListItem`s to the HIR.
3207 for &(ref use_tree
, id
) in trees
{
3208 self.allocate_hir_id_counter(id
, &use_tree
);
3213 } = self.lower_node_id(id
);
3215 let mut vis
= vis
.clone();
3216 let mut ident
= ident
.clone();
3217 let mut prefix
= prefix
.clone();
3219 // Give the segments new node-ids since they are being cloned.
3220 for seg
in &mut prefix
.segments
{
3221 seg
.id
= self.sess
.next_node_id();
3224 // Each `use` import is an item and thus are owners of the
3225 // names in the path. Up to this point the nested import is
3226 // the current owner, since we want each desugared import to
3227 // own its own names, we have to adjust the owner before
3228 // lowering the rest of the import.
3229 self.with_hir_id_owner(new_id
, |this
| {
3230 let item
= this
.lower_use_tree(use_tree
,
3237 let vis_kind
= match vis
.node
{
3238 hir
::VisibilityKind
::Public
=> hir
::VisibilityKind
::Public
,
3239 hir
::VisibilityKind
::Crate(sugar
) => hir
::VisibilityKind
::Crate(sugar
),
3240 hir
::VisibilityKind
::Inherited
=> hir
::VisibilityKind
::Inherited
,
3241 hir
::VisibilityKind
::Restricted { ref path, id: _, hir_id: _ }
=> {
3242 let id
= this
.next_id();
3243 let path
= this
.renumber_segment_ids(path
);
3244 hir
::VisibilityKind
::Restricted
{
3251 let vis
= respan(vis
.span
, vis_kind
);
3259 attrs
: attrs
.clone(),
3262 span
: use_tree
.span
,
3268 // Subtle and a bit hacky: we lower the privacy level
3269 // of the list stem to "private" most of the time, but
3270 // not for "restricted" paths. The key thing is that
3271 // we don't want it to stay as `pub` (with no caveats)
3272 // because that affects rustdoc and also the lints
3273 // about `pub` items. But we can't *always* make it
3274 // private -- particularly not for restricted paths --
3275 // because it contains node-ids that would then be
3276 // unused, failing the check that HirIds are "densely
3279 hir
::VisibilityKind
::Public
|
3280 hir
::VisibilityKind
::Crate(_
) |
3281 hir
::VisibilityKind
::Inherited
=> {
3282 *vis
= respan(prefix
.span
.shrink_to_lo(), hir
::VisibilityKind
::Inherited
);
3284 hir
::VisibilityKind
::Restricted { .. }
=> {
3285 // Do nothing here, as described in the comment on the match.
3289 let def
= self.expect_full_def_from_use(id
).next().unwrap_or(Def
::Err
);
3290 let path
= P(self.lower_path_extra(def
, &prefix
, ParamMode
::Explicit
, None
));
3291 hir
::ItemKind
::Use(path
, hir
::UseKind
::ListStem
)
3296 /// Paths like the visibility path in `pub(super) use foo::{bar, baz}` are repeated
3297 /// many times in the HIR tree; for each occurrence, we need to assign distinct
3298 /// `NodeId`s. (See, e.g., #56128.)
3299 fn renumber_segment_ids(&mut self, path
: &P
<hir
::Path
>) -> P
<hir
::Path
> {
3300 debug
!("renumber_segment_ids(path = {:?})", path
);
3301 let mut path
= path
.clone();
3302 for seg
in path
.segments
.iter_mut() {
3303 if seg
.id
.is_some() {
3304 let next_id
= self.next_id();
3305 seg
.id
= Some(next_id
.node_id
);
3306 seg
.hir_id
= Some(next_id
.hir_id
);
3312 fn lower_trait_item(&mut self, i
: &TraitItem
) -> hir
::TraitItem
{
3313 let LoweredNodeId { node_id, hir_id }
= self.lower_node_id(i
.id
);
3314 let trait_item_def_id
= self.resolver
.definitions().local_def_id(node_id
);
3316 let (generics
, node
) = match i
.node
{
3317 TraitItemKind
::Const(ref ty
, ref default) => (
3318 self.lower_generics(&i
.generics
, ImplTraitContext
::disallowed()),
3319 hir
::TraitItemKind
::Const(
3320 self.lower_ty(ty
, ImplTraitContext
::disallowed()),
3323 .map(|x
| self.lower_body(None
, |this
| this
.lower_expr(x
))),
3326 TraitItemKind
::Method(ref sig
, None
) => {
3327 let names
= self.lower_fn_args_to_names(&sig
.decl
);
3328 let (generics
, sig
) = self.lower_method_sig(
3335 (generics
, hir
::TraitItemKind
::Method(sig
, hir
::TraitMethod
::Required(names
)))
3337 TraitItemKind
::Method(ref sig
, Some(ref body
)) => {
3338 let body_id
= self.lower_body(Some(&sig
.decl
), |this
| {
3339 let body
= this
.lower_block(body
, false);
3340 this
.expr_block(body
, ThinVec
::new())
3342 let (generics
, sig
) = self.lower_method_sig(
3349 (generics
, hir
::TraitItemKind
::Method(sig
, hir
::TraitMethod
::Provided(body_id
)))
3351 TraitItemKind
::Type(ref bounds
, ref default) => (
3352 self.lower_generics(&i
.generics
, ImplTraitContext
::disallowed()),
3353 hir
::TraitItemKind
::Type(
3354 self.lower_param_bounds(bounds
, ImplTraitContext
::disallowed()),
3357 .map(|x
| self.lower_ty(x
, ImplTraitContext
::disallowed())),
3360 TraitItemKind
::Macro(..) => panic
!("Shouldn't exist any more"),
3367 attrs
: self.lower_attrs(&i
.attrs
),
3374 fn lower_trait_item_ref(&mut self, i
: &TraitItem
) -> hir
::TraitItemRef
{
3375 let (kind
, has_default
) = match i
.node
{
3376 TraitItemKind
::Const(_
, ref default) => {
3377 (hir
::AssociatedItemKind
::Const
, default.is_some())
3379 TraitItemKind
::Type(_
, ref default) => {
3380 (hir
::AssociatedItemKind
::Type
, default.is_some())
3382 TraitItemKind
::Method(ref sig
, ref default) => (
3383 hir
::AssociatedItemKind
::Method
{
3384 has_self
: sig
.decl
.has_self(),
3388 TraitItemKind
::Macro(..) => unimplemented
!(),
3391 id
: hir
::TraitItemId { node_id: i.id }
,
3394 defaultness
: self.lower_defaultness(Defaultness
::Default
, has_default
),
3399 fn lower_impl_item(&mut self, i
: &ImplItem
) -> hir
::ImplItem
{
3400 let LoweredNodeId { node_id, hir_id }
= self.lower_node_id(i
.id
);
3401 let impl_item_def_id
= self.resolver
.definitions().local_def_id(node_id
);
3403 let (generics
, node
) = match i
.node
{
3404 ImplItemKind
::Const(ref ty
, ref expr
) => {
3405 let body_id
= self.lower_body(None
, |this
| this
.lower_expr(expr
));
3407 self.lower_generics(&i
.generics
, ImplTraitContext
::disallowed()),
3408 hir
::ImplItemKind
::Const(
3409 self.lower_ty(ty
, ImplTraitContext
::disallowed()),
3414 ImplItemKind
::Method(ref sig
, ref body
) => {
3415 let body_id
= self.lower_async_body(&sig
.decl
, sig
.header
.asyncness
, body
);
3416 let impl_trait_return_allow
= !self.is_in_trait_impl
;
3417 let (generics
, sig
) = self.lower_method_sig(
3421 impl_trait_return_allow
,
3422 sig
.header
.asyncness
.opt_return_id(),
3424 (generics
, hir
::ImplItemKind
::Method(sig
, body_id
))
3426 ImplItemKind
::Type(ref ty
) => (
3427 self.lower_generics(&i
.generics
, ImplTraitContext
::disallowed()),
3428 hir
::ImplItemKind
::Type(self.lower_ty(ty
, ImplTraitContext
::disallowed())),
3430 ImplItemKind
::Existential(ref bounds
) => (
3431 self.lower_generics(&i
.generics
, ImplTraitContext
::disallowed()),
3432 hir
::ImplItemKind
::Existential(
3433 self.lower_param_bounds(bounds
, ImplTraitContext
::disallowed()),
3436 ImplItemKind
::Macro(..) => panic
!("Shouldn't exist any more"),
3443 attrs
: self.lower_attrs(&i
.attrs
),
3445 vis
: self.lower_visibility(&i
.vis
, None
),
3446 defaultness
: self.lower_defaultness(i
.defaultness
, true /* [1] */),
3451 // [1] since `default impl` is not yet implemented, this is always true in impls
3454 fn lower_impl_item_ref(&mut self, i
: &ImplItem
) -> hir
::ImplItemRef
{
3456 id
: hir
::ImplItemId { node_id: i.id }
,
3459 vis
: self.lower_visibility(&i
.vis
, Some(i
.id
)),
3460 defaultness
: self.lower_defaultness(i
.defaultness
, true /* [1] */),
3461 kind
: match i
.node
{
3462 ImplItemKind
::Const(..) => hir
::AssociatedItemKind
::Const
,
3463 ImplItemKind
::Type(..) => hir
::AssociatedItemKind
::Type
,
3464 ImplItemKind
::Existential(..) => hir
::AssociatedItemKind
::Existential
,
3465 ImplItemKind
::Method(ref sig
, _
) => hir
::AssociatedItemKind
::Method
{
3466 has_self
: sig
.decl
.has_self(),
3468 ImplItemKind
::Macro(..) => unimplemented
!(),
3472 // [1] since `default impl` is not yet implemented, this is always true in impls
3475 fn lower_mod(&mut self, m
: &Mod
) -> hir
::Mod
{
3478 item_ids
: m
.items
.iter().flat_map(|x
| self.lower_item_id(x
)).collect(),
3482 fn lower_item_id(&mut self, i
: &Item
) -> SmallVec
<[hir
::ItemId
; 1]> {
3484 ItemKind
::Use(ref use_tree
) => {
3485 let mut vec
= smallvec
![hir
::ItemId { id: i.id }
];
3486 self.lower_item_id_use_tree(use_tree
, i
.id
, &mut vec
);
3489 ItemKind
::MacroDef(..) => SmallVec
::new(),
3491 ItemKind
::Impl(.., None
, _
, _
) => smallvec
![hir
::ItemId { id: i.id }
],
3492 ItemKind
::Static(ref ty
, ..) => {
3493 let mut ids
= smallvec
![hir
::ItemId { id: i.id }
];
3494 if self.sess
.features_untracked().impl_trait_in_bindings
{
3495 let mut visitor
= ImplTraitTypeIdVisitor { ids: &mut ids }
;
3496 visitor
.visit_ty(ty
);
3500 ItemKind
::Const(ref ty
, ..) => {
3501 let mut ids
= smallvec
![hir
::ItemId { id: i.id }
];
3502 if self.sess
.features_untracked().impl_trait_in_bindings
{
3503 let mut visitor
= ImplTraitTypeIdVisitor { ids: &mut ids }
;
3504 visitor
.visit_ty(ty
);
3508 _
=> smallvec
![hir
::ItemId { id: i.id }
],
3512 fn lower_item_id_use_tree(&mut self,
3515 vec
: &mut SmallVec
<[hir
::ItemId
; 1]>)
3518 UseTreeKind
::Nested(ref nested_vec
) => for &(ref nested
, id
) in nested_vec
{
3519 vec
.push(hir
::ItemId { id }
);
3520 self.lower_item_id_use_tree(nested
, id
, vec
);
3522 UseTreeKind
::Glob
=> {}
3523 UseTreeKind
::Simple(_
, id1
, id2
) => {
3524 for (_
, &id
) in self.expect_full_def_from_use(base_id
)
3526 .zip([id1
, id2
].iter())
3528 vec
.push(hir
::ItemId { id }
);
3534 pub fn lower_item(&mut self, i
: &Item
) -> Option
<hir
::Item
> {
3535 let mut ident
= i
.ident
;
3536 let mut vis
= self.lower_visibility(&i
.vis
, None
);
3537 let attrs
= self.lower_attrs(&i
.attrs
);
3538 if let ItemKind
::MacroDef(ref def
) = i
.node
{
3539 if !def
.legacy
|| attr
::contains_name(&i
.attrs
, "macro_export") ||
3540 attr
::contains_name(&i
.attrs
, "rustc_doc_only_macro") {
3541 let body
= self.lower_token_stream(def
.stream());
3542 let hir_id
= self.lower_node_id(i
.id
).hir_id
;
3543 self.exported_macros
.push(hir
::MacroDef
{
3557 let node
= self.lower_item_kind(i
.id
, &mut ident
, &attrs
, &mut vis
, &i
.node
);
3559 let LoweredNodeId { node_id, hir_id }
= self.lower_node_id(i
.id
);
3572 fn lower_foreign_item(&mut self, i
: &ForeignItem
) -> hir
::ForeignItem
{
3573 let LoweredNodeId { node_id, hir_id }
= self.lower_node_id(i
.id
);
3574 let def_id
= self.resolver
.definitions().local_def_id(node_id
);
3579 attrs
: self.lower_attrs(&i
.attrs
),
3580 node
: match i
.node
{
3581 ForeignItemKind
::Fn(ref fdec
, ref generics
) => {
3582 let (generics
, (fn_dec
, fn_args
)) = self.add_in_band_defs(
3585 AnonymousLifetimeMode
::PassThrough
,
3588 // Disallow impl Trait in foreign items
3589 this
.lower_fn_decl(fdec
, None
, false, None
),
3590 this
.lower_fn_args_to_names(fdec
),
3595 hir
::ForeignItemKind
::Fn(fn_dec
, fn_args
, generics
)
3597 ForeignItemKind
::Static(ref t
, m
) => {
3598 hir
::ForeignItemKind
::Static(
3599 self.lower_ty(t
, ImplTraitContext
::disallowed()), m
)
3601 ForeignItemKind
::Ty
=> hir
::ForeignItemKind
::Type
,
3602 ForeignItemKind
::Macro(_
) => panic
!("shouldn't exist here"),
3604 vis
: self.lower_visibility(&i
.vis
, None
),
3609 fn lower_method_sig(
3611 generics
: &Generics
,
3614 impl_trait_return_allow
: bool
,
3615 is_async
: Option
<NodeId
>,
3616 ) -> (hir
::Generics
, hir
::MethodSig
) {
3617 let header
= self.lower_fn_header(sig
.header
);
3618 let (generics
, decl
) = self.add_in_band_defs(
3621 AnonymousLifetimeMode
::PassThrough
,
3622 |this
, idty
| this
.lower_fn_decl(
3624 Some((fn_def_id
, idty
)),
3625 impl_trait_return_allow
,
3629 (generics
, hir
::MethodSig { header, decl }
)
3632 fn lower_is_auto(&mut self, a
: IsAuto
) -> hir
::IsAuto
{
3634 IsAuto
::Yes
=> hir
::IsAuto
::Yes
,
3635 IsAuto
::No
=> hir
::IsAuto
::No
,
3639 fn lower_fn_header(&mut self, h
: FnHeader
) -> hir
::FnHeader
{
3641 unsafety
: self.lower_unsafety(h
.unsafety
),
3642 asyncness
: self.lower_asyncness(h
.asyncness
),
3643 constness
: self.lower_constness(h
.constness
),
3648 fn lower_unsafety(&mut self, u
: Unsafety
) -> hir
::Unsafety
{
3650 Unsafety
::Unsafe
=> hir
::Unsafety
::Unsafe
,
3651 Unsafety
::Normal
=> hir
::Unsafety
::Normal
,
3655 fn lower_constness(&mut self, c
: Spanned
<Constness
>) -> hir
::Constness
{
3657 Constness
::Const
=> hir
::Constness
::Const
,
3658 Constness
::NotConst
=> hir
::Constness
::NotConst
,
3662 fn lower_asyncness(&mut self, a
: IsAsync
) -> hir
::IsAsync
{
3664 IsAsync
::Async { .. }
=> hir
::IsAsync
::Async
,
3665 IsAsync
::NotAsync
=> hir
::IsAsync
::NotAsync
,
3669 fn lower_unop(&mut self, u
: UnOp
) -> hir
::UnOp
{
3671 UnOp
::Deref
=> hir
::UnDeref
,
3672 UnOp
::Not
=> hir
::UnNot
,
3673 UnOp
::Neg
=> hir
::UnNeg
,
3677 fn lower_binop(&mut self, b
: BinOp
) -> hir
::BinOp
{
3679 node
: match b
.node
{
3680 BinOpKind
::Add
=> hir
::BinOpKind
::Add
,
3681 BinOpKind
::Sub
=> hir
::BinOpKind
::Sub
,
3682 BinOpKind
::Mul
=> hir
::BinOpKind
::Mul
,
3683 BinOpKind
::Div
=> hir
::BinOpKind
::Div
,
3684 BinOpKind
::Rem
=> hir
::BinOpKind
::Rem
,
3685 BinOpKind
::And
=> hir
::BinOpKind
::And
,
3686 BinOpKind
::Or
=> hir
::BinOpKind
::Or
,
3687 BinOpKind
::BitXor
=> hir
::BinOpKind
::BitXor
,
3688 BinOpKind
::BitAnd
=> hir
::BinOpKind
::BitAnd
,
3689 BinOpKind
::BitOr
=> hir
::BinOpKind
::BitOr
,
3690 BinOpKind
::Shl
=> hir
::BinOpKind
::Shl
,
3691 BinOpKind
::Shr
=> hir
::BinOpKind
::Shr
,
3692 BinOpKind
::Eq
=> hir
::BinOpKind
::Eq
,
3693 BinOpKind
::Lt
=> hir
::BinOpKind
::Lt
,
3694 BinOpKind
::Le
=> hir
::BinOpKind
::Le
,
3695 BinOpKind
::Ne
=> hir
::BinOpKind
::Ne
,
3696 BinOpKind
::Ge
=> hir
::BinOpKind
::Ge
,
3697 BinOpKind
::Gt
=> hir
::BinOpKind
::Gt
,
3703 fn lower_pat(&mut self, p
: &Pat
) -> P
<hir
::Pat
> {
3704 let node
= match p
.node
{
3705 PatKind
::Wild
=> hir
::PatKind
::Wild
,
3706 PatKind
::Ident(ref binding_mode
, ident
, ref sub
) => {
3707 match self.resolver
.get_resolution(p
.id
).map(|d
| d
.base_def()) {
3708 // `None` can occur in body-less function signatures
3709 def @ None
| def @
Some(Def
::Local(_
)) => {
3710 let canonical_id
= match def
{
3711 Some(Def
::Local(id
)) => id
,
3714 let hir_id
= self.lower_node_id(canonical_id
).hir_id
;
3715 hir
::PatKind
::Binding(
3716 self.lower_binding_mode(binding_mode
),
3720 sub
.as_ref().map(|x
| self.lower_pat(x
)),
3723 Some(def
) => hir
::PatKind
::Path(hir
::QPath
::Resolved(
3728 segments
: hir_vec
![hir
::PathSegment
::from_ident(ident
)],
3733 PatKind
::Lit(ref e
) => hir
::PatKind
::Lit(P(self.lower_expr(e
))),
3734 PatKind
::TupleStruct(ref path
, ref pats
, ddpos
) => {
3735 let qpath
= self.lower_qpath(
3739 ParamMode
::Optional
,
3740 ImplTraitContext
::disallowed(),
3742 hir
::PatKind
::TupleStruct(
3744 pats
.iter().map(|x
| self.lower_pat(x
)).collect(),
3748 PatKind
::Path(ref qself
, ref path
) => {
3749 let qpath
= self.lower_qpath(
3753 ParamMode
::Optional
,
3754 ImplTraitContext
::disallowed(),
3756 hir
::PatKind
::Path(qpath
)
3758 PatKind
::Struct(ref path
, ref fields
, etc
) => {
3759 let qpath
= self.lower_qpath(
3763 ParamMode
::Optional
,
3764 ImplTraitContext
::disallowed(),
3770 let LoweredNodeId { node_id, hir_id }
= self.next_id();
3774 node
: hir
::FieldPat
{
3777 ident
: f
.node
.ident
,
3778 pat
: self.lower_pat(&f
.node
.pat
),
3779 is_shorthand
: f
.node
.is_shorthand
,
3784 hir
::PatKind
::Struct(qpath
, fs
, etc
)
3786 PatKind
::Tuple(ref elts
, ddpos
) => {
3787 hir
::PatKind
::Tuple(elts
.iter().map(|x
| self.lower_pat(x
)).collect(), ddpos
)
3789 PatKind
::Box(ref inner
) => hir
::PatKind
::Box(self.lower_pat(inner
)),
3790 PatKind
::Ref(ref inner
, mutbl
) => {
3791 hir
::PatKind
::Ref(self.lower_pat(inner
), self.lower_mutability(mutbl
))
3793 PatKind
::Range(ref e1
, ref e2
, Spanned { node: ref end, .. }
) => hir
::PatKind
::Range(
3794 P(self.lower_expr(e1
)),
3795 P(self.lower_expr(e2
)),
3796 self.lower_range_end(end
),
3798 PatKind
::Slice(ref before
, ref slice
, ref after
) => hir
::PatKind
::Slice(
3799 before
.iter().map(|x
| self.lower_pat(x
)).collect(),
3800 slice
.as_ref().map(|x
| self.lower_pat(x
)),
3801 after
.iter().map(|x
| self.lower_pat(x
)).collect(),
3803 PatKind
::Paren(ref inner
) => return self.lower_pat(inner
),
3804 PatKind
::Mac(_
) => panic
!("Shouldn't exist here"),
3807 let LoweredNodeId { node_id, hir_id }
= self.lower_node_id(p
.id
);
3816 fn lower_range_end(&mut self, e
: &RangeEnd
) -> hir
::RangeEnd
{
3818 RangeEnd
::Included(_
) => hir
::RangeEnd
::Included
,
3819 RangeEnd
::Excluded
=> hir
::RangeEnd
::Excluded
,
3823 fn lower_anon_const(&mut self, c
: &AnonConst
) -> hir
::AnonConst
{
3824 self.with_new_scopes(|this
| {
3825 let LoweredNodeId { node_id, hir_id }
= this
.lower_node_id(c
.id
);
3829 body
: this
.lower_body(None
, |this
| this
.lower_expr(&c
.value
)),
3834 fn lower_expr(&mut self, e
: &Expr
) -> hir
::Expr
{
3835 let kind
= match e
.node
{
3836 ExprKind
::Box(ref inner
) => hir
::ExprKind
::Box(P(self.lower_expr(inner
))),
3837 ExprKind
::ObsoleteInPlace(..) => {
3838 self.sess
.abort_if_errors();
3839 span_bug
!(e
.span
, "encountered ObsoleteInPlace expr during lowering");
3841 ExprKind
::Array(ref exprs
) => {
3842 hir
::ExprKind
::Array(exprs
.iter().map(|x
| self.lower_expr(x
)).collect())
3844 ExprKind
::Repeat(ref expr
, ref count
) => {
3845 let expr
= P(self.lower_expr(expr
));
3846 let count
= self.lower_anon_const(count
);
3847 hir
::ExprKind
::Repeat(expr
, count
)
3849 ExprKind
::Tup(ref elts
) => {
3850 hir
::ExprKind
::Tup(elts
.iter().map(|x
| self.lower_expr(x
)).collect())
3852 ExprKind
::Call(ref f
, ref args
) => {
3853 let f
= P(self.lower_expr(f
));
3854 hir
::ExprKind
::Call(f
, args
.iter().map(|x
| self.lower_expr(x
)).collect())
3856 ExprKind
::MethodCall(ref seg
, ref args
) => {
3857 let hir_seg
= P(self.lower_path_segment(
3860 ParamMode
::Optional
,
3862 ParenthesizedGenericArgs
::Err
,
3863 ImplTraitContext
::disallowed(),
3866 let args
= args
.iter().map(|x
| self.lower_expr(x
)).collect();
3867 hir
::ExprKind
::MethodCall(hir_seg
, seg
.ident
.span
, args
)
3869 ExprKind
::Binary(binop
, ref lhs
, ref rhs
) => {
3870 let binop
= self.lower_binop(binop
);
3871 let lhs
= P(self.lower_expr(lhs
));
3872 let rhs
= P(self.lower_expr(rhs
));
3873 hir
::ExprKind
::Binary(binop
, lhs
, rhs
)
3875 ExprKind
::Unary(op
, ref ohs
) => {
3876 let op
= self.lower_unop(op
);
3877 let ohs
= P(self.lower_expr(ohs
));
3878 hir
::ExprKind
::Unary(op
, ohs
)
3880 ExprKind
::Lit(ref l
) => hir
::ExprKind
::Lit((*l
).clone()),
3881 ExprKind
::Cast(ref expr
, ref ty
) => {
3882 let expr
= P(self.lower_expr(expr
));
3883 hir
::ExprKind
::Cast(expr
, self.lower_ty(ty
, ImplTraitContext
::disallowed()))
3885 ExprKind
::Type(ref expr
, ref ty
) => {
3886 let expr
= P(self.lower_expr(expr
));
3887 hir
::ExprKind
::Type(expr
, self.lower_ty(ty
, ImplTraitContext
::disallowed()))
3889 ExprKind
::AddrOf(m
, ref ohs
) => {
3890 let m
= self.lower_mutability(m
);
3891 let ohs
= P(self.lower_expr(ohs
));
3892 hir
::ExprKind
::AddrOf(m
, ohs
)
3894 // More complicated than you might expect because the else branch
3895 // might be `if let`.
3896 ExprKind
::If(ref cond
, ref blk
, ref else_opt
) => {
3897 let else_opt
= else_opt
.as_ref().map(|els
| {
3899 ExprKind
::IfLet(..) => {
3900 // Wrap the `if let` expr in a block.
3901 let span
= els
.span
;
3902 let els
= P(self.lower_expr(els
));
3903 let LoweredNodeId { node_id, hir_id }
= self.next_id();
3904 let blk
= P(hir
::Block
{
3909 rules
: hir
::DefaultBlock
,
3911 targeted_by_break
: false,
3913 P(self.expr_block(blk
, ThinVec
::new()))
3915 _
=> P(self.lower_expr(els
)),
3919 let then_blk
= self.lower_block(blk
, false);
3920 let then_expr
= self.expr_block(then_blk
, ThinVec
::new());
3922 hir
::ExprKind
::If(P(self.lower_expr(cond
)), P(then_expr
), else_opt
)
3924 ExprKind
::While(ref cond
, ref body
, opt_label
) => self.with_loop_scope(e
.id
, |this
| {
3925 hir
::ExprKind
::While(
3926 this
.with_loop_condition_scope(|this
| P(this
.lower_expr(cond
))),
3927 this
.lower_block(body
, false),
3928 this
.lower_label(opt_label
),
3931 ExprKind
::Loop(ref body
, opt_label
) => self.with_loop_scope(e
.id
, |this
| {
3932 hir
::ExprKind
::Loop(
3933 this
.lower_block(body
, false),
3934 this
.lower_label(opt_label
),
3935 hir
::LoopSource
::Loop
,
3938 ExprKind
::TryBlock(ref body
) => {
3939 self.with_catch_scope(body
.id
, |this
| {
3940 let unstable_span
= this
.mark_span_with_reason(
3941 CompilerDesugaringKind
::TryBlock
,
3944 Symbol
::intern("try_trait"),
3947 let mut block
= this
.lower_block(body
, true).into_inner();
3948 let tail
= block
.expr
.take().map_or_else(
3950 let LoweredNodeId { node_id, hir_id }
= this
.next_id();
3951 let span
= this
.sess
.source_map().end_point(unstable_span
);
3955 node
: hir
::ExprKind
::Tup(hir_vec
![]),
3956 attrs
: ThinVec
::new(),
3960 |x
: P
<hir
::Expr
>| x
.into_inner(),
3962 block
.expr
= Some(this
.wrap_in_try_constructor(
3963 "from_ok", tail
, unstable_span
));
3964 hir
::ExprKind
::Block(P(block
), None
)
3967 ExprKind
::Match(ref expr
, ref arms
) => hir
::ExprKind
::Match(
3968 P(self.lower_expr(expr
)),
3969 arms
.iter().map(|x
| self.lower_arm(x
)).collect(),
3970 hir
::MatchSource
::Normal
,
3972 ExprKind
::Async(capture_clause
, closure_node_id
, ref block
) => {
3973 self.make_async_expr(capture_clause
, closure_node_id
, None
, |this
| {
3974 this
.with_new_scopes(|this
| {
3975 let block
= this
.lower_block(block
, false);
3976 this
.expr_block(block
, ThinVec
::new())
3981 capture_clause
, asyncness
, movability
, ref decl
, ref body
, fn_decl_span
3983 if let IsAsync
::Async { closure_id, .. }
= asyncness
{
3984 let outer_decl
= FnDecl
{
3985 inputs
: decl
.inputs
.clone(),
3986 output
: FunctionRetTy
::Default(fn_decl_span
),
3989 // We need to lower the declaration outside the new scope, because we
3990 // have to conserve the state of being inside a loop condition for the
3991 // closure argument types.
3992 let fn_decl
= self.lower_fn_decl(&outer_decl
, None
, false, None
);
3994 self.with_new_scopes(|this
| {
3995 // FIXME(cramertj): allow `async` non-`move` closures with arguments.
3996 if capture_clause
== CaptureBy
::Ref
&&
3997 !decl
.inputs
.is_empty()
4003 "`async` non-`move` closures with arguments \
4004 are not currently supported",
4006 .help("consider using `let` statements to manually capture \
4007 variables by reference before entering an \
4008 `async move` closure")
4012 // Transform `async |x: u8| -> X { ... }` into
4013 // `|x: u8| future_from_generator(|| -> X { ... })`.
4014 let body_id
= this
.lower_body(Some(&outer_decl
), |this
| {
4015 let async_ret_ty
= if let FunctionRetTy
::Ty(ty
) = &decl
.output
{
4018 let async_body
= this
.make_async_expr(
4019 capture_clause
, closure_id
, async_ret_ty
,
4021 this
.with_new_scopes(|this
| this
.lower_expr(body
))
4023 this
.expr(fn_decl_span
, async_body
, ThinVec
::new())
4025 hir
::ExprKind
::Closure(
4026 this
.lower_capture_clause(capture_clause
),
4034 // Lower outside new scope to preserve `is_in_loop_condition`.
4035 let fn_decl
= self.lower_fn_decl(decl
, None
, false, None
);
4037 self.with_new_scopes(|this
| {
4038 let mut is_generator
= false;
4039 let body_id
= this
.lower_body(Some(decl
), |this
| {
4040 let e
= this
.lower_expr(body
);
4041 is_generator
= this
.is_generator
;
4044 let generator_option
= if is_generator
{
4045 if !decl
.inputs
.is_empty() {
4050 "generators cannot have explicit arguments"
4052 this
.sess
.abort_if_errors();
4054 Some(match movability
{
4055 Movability
::Movable
=> hir
::GeneratorMovability
::Movable
,
4056 Movability
::Static
=> hir
::GeneratorMovability
::Static
,
4059 if movability
== Movability
::Static
{
4064 "closures cannot be static"
4069 hir
::ExprKind
::Closure(
4070 this
.lower_capture_clause(capture_clause
),
4079 ExprKind
::Block(ref blk
, opt_label
) => {
4080 hir
::ExprKind
::Block(self.lower_block(blk
,
4081 opt_label
.is_some()),
4082 self.lower_label(opt_label
))
4084 ExprKind
::Assign(ref el
, ref er
) => {
4085 hir
::ExprKind
::Assign(P(self.lower_expr(el
)), P(self.lower_expr(er
)))
4087 ExprKind
::AssignOp(op
, ref el
, ref er
) => hir
::ExprKind
::AssignOp(
4088 self.lower_binop(op
),
4089 P(self.lower_expr(el
)),
4090 P(self.lower_expr(er
)),
4092 ExprKind
::Field(ref el
, ident
) => hir
::ExprKind
::Field(P(self.lower_expr(el
)), ident
),
4093 ExprKind
::Index(ref el
, ref er
) => {
4094 hir
::ExprKind
::Index(P(self.lower_expr(el
)), P(self.lower_expr(er
)))
4096 // Desugar `<start>..=<end>` into `std::ops::RangeInclusive::new(<start>, <end>)`.
4097 ExprKind
::Range(Some(ref e1
), Some(ref e2
), RangeLimits
::Closed
) => {
4098 let id
= self.next_id();
4099 let e1
= self.lower_expr(e1
);
4100 let e2
= self.lower_expr(e2
);
4101 let ty_path
= P(self.std_path(e
.span
, &["ops", "RangeInclusive"], None
, false));
4102 let ty
= P(self.ty_path(id
, e
.span
, hir
::QPath
::Resolved(None
, ty_path
)));
4103 let new_seg
= P(hir
::PathSegment
::from_ident(Ident
::from_str("new")));
4104 let new_path
= hir
::QPath
::TypeRelative(ty
, new_seg
);
4105 let new
= P(self.expr(e
.span
, hir
::ExprKind
::Path(new_path
), ThinVec
::new()));
4106 hir
::ExprKind
::Call(new
, hir_vec
![e1
, e2
])
4108 ExprKind
::Range(ref e1
, ref e2
, lims
) => {
4109 use syntax
::ast
::RangeLimits
::*;
4111 let path
= match (e1
, e2
, lims
) {
4112 (&None
, &None
, HalfOpen
) => "RangeFull",
4113 (&Some(..), &None
, HalfOpen
) => "RangeFrom",
4114 (&None
, &Some(..), HalfOpen
) => "RangeTo",
4115 (&Some(..), &Some(..), HalfOpen
) => "Range",
4116 (&None
, &Some(..), Closed
) => "RangeToInclusive",
4117 (&Some(..), &Some(..), Closed
) => unreachable
!(),
4118 (_
, &None
, Closed
) => self.diagnostic()
4119 .span_fatal(e
.span
, "inclusive range with no end")
4123 let fields
= e1
.iter()
4124 .map(|e
| ("start", e
))
4125 .chain(e2
.iter().map(|e
| ("end", e
)))
4127 let expr
= P(self.lower_expr(&e
));
4128 let ident
= Ident
::new(Symbol
::intern(s
), e
.span
);
4129 self.field(ident
, expr
, e
.span
)
4131 .collect
::<P
<[hir
::Field
]>>();
4133 let is_unit
= fields
.is_empty();
4134 let struct_path
= ["ops", path
];
4135 let struct_path
= self.std_path(e
.span
, &struct_path
, None
, is_unit
);
4136 let struct_path
= hir
::QPath
::Resolved(None
, P(struct_path
));
4138 let LoweredNodeId { node_id, hir_id }
= self.lower_node_id(e
.id
);
4144 hir
::ExprKind
::Path(struct_path
)
4146 hir
::ExprKind
::Struct(P(struct_path
), fields
, None
)
4149 attrs
: e
.attrs
.clone(),
4152 ExprKind
::Path(ref qself
, ref path
) => {
4153 let qpath
= self.lower_qpath(
4157 ParamMode
::Optional
,
4158 ImplTraitContext
::disallowed(),
4160 hir
::ExprKind
::Path(qpath
)
4162 ExprKind
::Break(opt_label
, ref opt_expr
) => {
4163 let destination
= if self.is_in_loop_condition
&& opt_label
.is_none() {
4166 target_id
: Err(hir
::LoopIdError
::UnlabeledCfInWhileCondition
).into(),
4169 self.lower_loop_destination(opt_label
.map(|label
| (e
.id
, label
)))
4171 hir
::ExprKind
::Break(
4173 opt_expr
.as_ref().map(|x
| P(self.lower_expr(x
))),
4176 ExprKind
::Continue(opt_label
) => {
4177 hir
::ExprKind
::Continue(if self.is_in_loop_condition
&& opt_label
.is_none() {
4180 target_id
: Err(hir
::LoopIdError
::UnlabeledCfInWhileCondition
).into(),
4183 self.lower_loop_destination(opt_label
.map(|label
| (e
.id
, label
)))
4186 ExprKind
::Ret(ref e
) => hir
::ExprKind
::Ret(e
.as_ref().map(|x
| P(self.lower_expr(x
)))),
4187 ExprKind
::InlineAsm(ref asm
) => {
4188 let hir_asm
= hir
::InlineAsm
{
4189 inputs
: asm
.inputs
.iter().map(|&(ref c
, _
)| c
.clone()).collect(),
4190 outputs
: asm
.outputs
4192 .map(|out
| hir
::InlineAsmOutput
{
4193 constraint
: out
.constraint
.clone(),
4195 is_indirect
: out
.is_indirect
,
4196 span
: out
.expr
.span
,
4199 asm
: asm
.asm
.clone(),
4200 asm_str_style
: asm
.asm_str_style
,
4201 clobbers
: asm
.clobbers
.clone().into(),
4202 volatile
: asm
.volatile
,
4203 alignstack
: asm
.alignstack
,
4204 dialect
: asm
.dialect
,
4207 let outputs
= asm
.outputs
4209 .map(|out
| self.lower_expr(&out
.expr
))
4211 let inputs
= asm
.inputs
4213 .map(|&(_
, ref input
)| self.lower_expr(input
))
4215 hir
::ExprKind
::InlineAsm(P(hir_asm
), outputs
, inputs
)
4217 ExprKind
::Struct(ref path
, ref fields
, ref maybe_expr
) => hir
::ExprKind
::Struct(
4222 ParamMode
::Optional
,
4223 ImplTraitContext
::disallowed(),
4225 fields
.iter().map(|x
| self.lower_field(x
)).collect(),
4226 maybe_expr
.as_ref().map(|x
| P(self.lower_expr(x
))),
4228 ExprKind
::Paren(ref ex
) => {
4229 let mut ex
= self.lower_expr(ex
);
4230 // Include parens in span, but only if it is a super-span.
4231 if e
.span
.contains(ex
.span
) {
4234 // Merge attributes into the inner expression.
4235 let mut attrs
= e
.attrs
.clone();
4236 attrs
.extend
::<Vec
<_
>>(ex
.attrs
.into());
4241 ExprKind
::Yield(ref opt_expr
) => {
4242 self.is_generator
= true;
4245 .map(|x
| self.lower_expr(x
))
4247 self.expr(e
.span
, hir
::ExprKind
::Tup(hir_vec
![]), ThinVec
::new())
4249 hir
::ExprKind
::Yield(P(expr
))
4252 ExprKind
::Err
=> hir
::ExprKind
::Err
,
4254 // Desugar `ExprIfLet`
4255 // from: `if let <pat> = <sub_expr> <body> [<else_opt>]`
4256 ExprKind
::IfLet(ref pats
, ref sub_expr
, ref body
, ref else_opt
) => {
4259 // match <sub_expr> {
4261 // _ => [<else_opt> | ()]
4264 let mut arms
= vec
![];
4266 // `<pat> => <body>`
4268 let body
= self.lower_block(body
, false);
4269 let body_expr
= P(self.expr_block(body
, ThinVec
::new()));
4270 let pats
= pats
.iter().map(|pat
| self.lower_pat(pat
)).collect();
4271 arms
.push(self.arm(pats
, body_expr
));
4274 // _ => [<else_opt>|()]
4276 let wildcard_arm
: Option
<&Expr
> = else_opt
.as_ref().map(|p
| &**p
);
4277 let wildcard_pattern
= self.pat_wild(e
.span
);
4278 let body
= if let Some(else_expr
) = wildcard_arm
{
4279 P(self.lower_expr(else_expr
))
4281 self.expr_tuple(e
.span
, hir_vec
![])
4283 arms
.push(self.arm(hir_vec
![wildcard_pattern
], body
));
4286 let contains_else_clause
= else_opt
.is_some();
4288 let sub_expr
= P(self.lower_expr(sub_expr
));
4290 hir
::ExprKind
::Match(
4293 hir
::MatchSource
::IfLetDesugar
{
4294 contains_else_clause
,
4299 // Desugar `ExprWhileLet`
4300 // from: `[opt_ident]: while let <pat> = <sub_expr> <body>`
4301 ExprKind
::WhileLet(ref pats
, ref sub_expr
, ref body
, opt_label
) => {
4304 // [opt_ident]: loop {
4305 // match <sub_expr> {
4311 // Note that the block AND the condition are evaluated in the loop scope.
4312 // This is done to allow `break` from inside the condition of the loop.
4313 let (body
, break_expr
, sub_expr
) = self.with_loop_scope(e
.id
, |this
| {
4315 this
.lower_block(body
, false),
4316 this
.expr_break(e
.span
, ThinVec
::new()),
4317 this
.with_loop_condition_scope(|this
| P(this
.lower_expr(sub_expr
))),
4321 // `<pat> => <body>`
4323 let body_expr
= P(self.expr_block(body
, ThinVec
::new()));
4324 let pats
= pats
.iter().map(|pat
| self.lower_pat(pat
)).collect();
4325 self.arm(pats
, body_expr
)
4330 let pat_under
= self.pat_wild(e
.span
);
4331 self.arm(hir_vec
![pat_under
], break_expr
)
4334 // `match <sub_expr> { ... }`
4335 let arms
= hir_vec
![pat_arm
, break_arm
];
4336 let match_expr
= self.expr(
4338 hir
::ExprKind
::Match(sub_expr
, arms
, hir
::MatchSource
::WhileLetDesugar
),
4342 // `[opt_ident]: loop { ... }`
4343 let loop_block
= P(self.block_expr(P(match_expr
)));
4344 let loop_expr
= hir
::ExprKind
::Loop(
4346 self.lower_label(opt_label
),
4347 hir
::LoopSource
::WhileLet
,
4349 // Add attributes to the outer returned expr node.
4353 // Desugar `ExprForLoop`
4354 // from: `[opt_ident]: for <pat> in <head> <body>`
4355 ExprKind
::ForLoop(ref pat
, ref head
, ref body
, opt_label
) => {
4359 // let result = match ::std::iter::IntoIterator::into_iter(<head>) {
4361 // [opt_ident]: loop {
4363 // match ::std::iter::Iterator::next(&mut iter) {
4364 // ::std::option::Option::Some(val) => __next = val,
4365 // ::std::option::Option::None => break
4367 // let <pat> = __next;
4368 // StmtKind::Expr(<body>);
4376 let head
= self.lower_expr(head
);
4377 let head_sp
= head
.span
;
4378 let desugared_span
= self.mark_span_with_reason(
4379 CompilerDesugaringKind
::ForLoop
,
4384 let iter
= self.str_to_ident("iter");
4386 let next_ident
= self.str_to_ident("__next");
4387 let next_pat
= self.pat_ident_binding_mode(
4390 hir
::BindingAnnotation
::Mutable
,
4393 // `::std::option::Option::Some(val) => next = val`
4395 let val_ident
= self.str_to_ident("val");
4396 let val_pat
= self.pat_ident(pat
.span
, val_ident
);
4397 let val_expr
= P(self.expr_ident(pat
.span
, val_ident
, val_pat
.id
));
4398 let next_expr
= P(self.expr_ident(pat
.span
, next_ident
, next_pat
.id
));
4399 let assign
= P(self.expr(
4401 hir
::ExprKind
::Assign(next_expr
, val_expr
),
4404 let some_pat
= self.pat_some(pat
.span
, val_pat
);
4405 self.arm(hir_vec
![some_pat
], assign
)
4408 // `::std::option::Option::None => break`
4411 self.with_loop_scope(e
.id
, |this
| this
.expr_break(e
.span
, ThinVec
::new()));
4412 let pat
= self.pat_none(e
.span
);
4413 self.arm(hir_vec
![pat
], break_expr
)
4417 let iter_pat
= self.pat_ident_binding_mode(
4420 hir
::BindingAnnotation
::Mutable
4423 // `match ::std::iter::Iterator::next(&mut iter) { ... }`
4425 let iter
= P(self.expr_ident(head_sp
, iter
, iter_pat
.id
));
4426 let ref_mut_iter
= self.expr_mut_addr_of(head_sp
, iter
);
4427 let next_path
= &["iter", "Iterator", "next"];
4428 let next_path
= P(self.expr_std_path(head_sp
, next_path
, None
, ThinVec
::new()));
4429 let next_expr
= P(self.expr_call(head_sp
, next_path
, hir_vec
![ref_mut_iter
]));
4430 let arms
= hir_vec
![pat_arm
, break_arm
];
4434 hir
::ExprKind
::Match(
4437 hir
::MatchSource
::ForLoopDesugar
4442 let LoweredNodeId { node_id, hir_id }
= self.next_id();
4443 let match_stmt
= hir
::Stmt
{
4446 node
: hir
::StmtKind
::Expr(match_expr
),
4450 let next_expr
= P(self.expr_ident(head_sp
, next_ident
, next_pat
.id
));
4453 let next_let
= self.stmt_let_pat(
4457 hir
::LocalSource
::ForLoopDesugar
,
4460 // `let <pat> = __next`
4461 let pat
= self.lower_pat(pat
);
4462 let pat_let
= self.stmt_let_pat(
4466 hir
::LocalSource
::ForLoopDesugar
,
4469 let body_block
= self.with_loop_scope(e
.id
, |this
| this
.lower_block(body
, false));
4470 let body_expr
= P(self.expr_block(body_block
, ThinVec
::new()));
4471 let LoweredNodeId { node_id, hir_id }
= self.next_id();
4472 let body_stmt
= hir
::Stmt
{
4475 node
: hir
::StmtKind
::Expr(body_expr
),
4479 let loop_block
= P(self.block_all(
4481 hir_vec
![next_let
, match_stmt
, pat_let
, body_stmt
],
4485 // `[opt_ident]: loop { ... }`
4486 let loop_expr
= hir
::ExprKind
::Loop(
4488 self.lower_label(opt_label
),
4489 hir
::LoopSource
::ForLoop
,
4491 let LoweredNodeId { node_id, hir_id }
= self.lower_node_id(e
.id
);
4492 let loop_expr
= P(hir
::Expr
{
4497 attrs
: ThinVec
::new(),
4500 // `mut iter => { ... }`
4501 let iter_arm
= self.arm(hir_vec
![iter_pat
], loop_expr
);
4503 // `match ::std::iter::IntoIterator::into_iter(<head>) { ... }`
4504 let into_iter_expr
= {
4505 let into_iter_path
= &["iter", "IntoIterator", "into_iter"];
4506 let into_iter
= P(self.expr_std_path(
4507 head_sp
, into_iter_path
, None
, ThinVec
::new()));
4508 P(self.expr_call(head_sp
, into_iter
, hir_vec
![head
]))
4511 let match_expr
= P(self.expr_match(
4515 hir
::MatchSource
::ForLoopDesugar
,
4518 // `{ let _result = ...; _result }`
4519 // Underscore prevents an `unused_variables` lint if the head diverges.
4520 let result_ident
= self.str_to_ident("_result");
4521 let (let_stmt
, let_stmt_binding
) =
4522 self.stmt_let(e
.span
, false, result_ident
, match_expr
);
4524 let result
= P(self.expr_ident(e
.span
, result_ident
, let_stmt_binding
));
4525 let block
= P(self.block_all(e
.span
, hir_vec
![let_stmt
], Some(result
)));
4526 // Add the attributes to the outer returned expr node.
4527 return self.expr_block(block
, e
.attrs
.clone());
4530 // Desugar `ExprKind::Try`
4532 ExprKind
::Try(ref sub_expr
) => {
4535 // match Try::into_result(<expr>) {
4536 // Ok(val) => #[allow(unreachable_code)] val,
4537 // Err(err) => #[allow(unreachable_code)]
4538 // // If there is an enclosing `catch {...}`
4539 // break 'catch_target Try::from_error(From::from(err)),
4541 // return Try::from_error(From::from(err)),
4544 let unstable_span
= self.mark_span_with_reason(
4545 CompilerDesugaringKind
::QuestionMark
,
4548 Symbol
::intern("try_trait")
4552 // `Try::into_result(<expr>)`
4555 let sub_expr
= self.lower_expr(sub_expr
);
4557 let path
= &["ops", "Try", "into_result"];
4558 let path
= P(self.expr_std_path(
4559 unstable_span
, path
, None
, ThinVec
::new()));
4560 P(self.expr_call(e
.span
, path
, hir_vec
![sub_expr
]))
4563 // `#[allow(unreachable_code)]`
4565 // `allow(unreachable_code)`
4567 let allow_ident
= Ident
::from_str("allow").with_span_pos(e
.span
);
4568 let uc_ident
= Ident
::from_str("unreachable_code").with_span_pos(e
.span
);
4569 let uc_nested
= attr
::mk_nested_word_item(uc_ident
);
4570 attr
::mk_list_item(e
.span
, allow_ident
, vec
![uc_nested
])
4572 attr
::mk_spanned_attr_outer(e
.span
, attr
::mk_attr_id(), allow
)
4574 let attrs
= vec
![attr
];
4576 // `Ok(val) => #[allow(unreachable_code)] val,`
4578 let val_ident
= self.str_to_ident("val");
4579 let val_pat
= self.pat_ident(e
.span
, val_ident
);
4580 let val_expr
= P(self.expr_ident_with_attrs(
4584 ThinVec
::from(attrs
.clone()),
4586 let ok_pat
= self.pat_ok(e
.span
, val_pat
);
4588 self.arm(hir_vec
![ok_pat
], val_expr
)
4591 // `Err(err) => #[allow(unreachable_code)]
4592 // return Try::from_error(From::from(err)),`
4594 let err_ident
= self.str_to_ident("err");
4595 let err_local
= self.pat_ident(e
.span
, err_ident
);
4597 let path
= &["convert", "From", "from"];
4598 let from
= P(self.expr_std_path(
4599 e
.span
, path
, None
, ThinVec
::new()));
4600 let err_expr
= self.expr_ident(e
.span
, err_ident
, err_local
.id
);
4602 self.expr_call(e
.span
, from
, hir_vec
![err_expr
])
4605 self.wrap_in_try_constructor("from_error", from_expr
, unstable_span
);
4606 let thin_attrs
= ThinVec
::from(attrs
);
4607 let catch_scope
= self.catch_scopes
.last().map(|x
| *x
);
4608 let ret_expr
= if let Some(catch_node
) = catch_scope
{
4611 hir
::ExprKind
::Break(
4614 target_id
: Ok(catch_node
),
4616 Some(from_err_expr
),
4621 P(self.expr(e
.span
, hir
::ExprKind
::Ret(Some(from_err_expr
)), thin_attrs
))
4624 let err_pat
= self.pat_err(e
.span
, err_local
);
4625 self.arm(hir_vec
![err_pat
], ret_expr
)
4628 hir
::ExprKind
::Match(
4630 hir_vec
![err_arm
, ok_arm
],
4631 hir
::MatchSource
::TryDesugar
,
4635 ExprKind
::Mac(_
) => panic
!("Shouldn't exist here"),
4638 let LoweredNodeId { node_id, hir_id }
= self.lower_node_id(e
.id
);
4645 attrs
: e
.attrs
.clone(),
4649 fn lower_stmt(&mut self, s
: &Stmt
) -> SmallVec
<[hir
::Stmt
; 1]> {
4650 smallvec
![match s
.node
{
4651 StmtKind
::Local(ref l
) => {
4652 let (l
, item_ids
) = self.lower_local(l
);
4653 let mut ids
: SmallVec
<[hir
::Stmt
; 1]> = item_ids
4656 let LoweredNodeId { node_id, hir_id }
= self.next_id();
4661 node
: hir
::StmtKind
::Item(item_id
),
4667 let LoweredNodeId { node_id, hir_id }
= self.lower_node_id(s
.id
);
4672 node
: hir
::StmtKind
::Local(P(l
)),
4678 StmtKind
::Item(ref it
) => {
4679 // Can only use the ID once.
4680 let mut id
= Some(s
.id
);
4681 return self.lower_item_id(it
)
4684 let LoweredNodeId { node_id, hir_id }
= id
.take()
4685 .map(|id
| self.lower_node_id(id
))
4686 .unwrap_or_else(|| self.next_id());
4691 node
: hir
::StmtKind
::Item(item_id
),
4697 StmtKind
::Expr(ref e
) => {
4698 let LoweredNodeId { node_id, hir_id }
= self.lower_node_id(s
.id
);
4703 node
: hir
::StmtKind
::Expr(P(self.lower_expr(e
))),
4707 StmtKind
::Semi(ref e
) => {
4708 let LoweredNodeId { node_id, hir_id }
= self.lower_node_id(s
.id
);
4713 node
: hir
::StmtKind
::Semi(P(self.lower_expr(e
))),
4717 StmtKind
::Mac(..) => panic
!("Shouldn't exist here"),
4721 fn lower_capture_clause(&mut self, c
: CaptureBy
) -> hir
::CaptureClause
{
4723 CaptureBy
::Value
=> hir
::CaptureByValue
,
4724 CaptureBy
::Ref
=> hir
::CaptureByRef
,
4728 /// If an `explicit_owner` is given, this method allocates the `HirId` in
4729 /// the address space of that item instead of the item currently being
4730 /// lowered. This can happen during `lower_impl_item_ref()` where we need to
4731 /// lower a `Visibility` value although we haven't lowered the owning
4732 /// `ImplItem` in question yet.
4733 fn lower_visibility(
4736 explicit_owner
: Option
<NodeId
>,
4737 ) -> hir
::Visibility
{
4738 let node
= match v
.node
{
4739 VisibilityKind
::Public
=> hir
::VisibilityKind
::Public
,
4740 VisibilityKind
::Crate(sugar
) => hir
::VisibilityKind
::Crate(sugar
),
4741 VisibilityKind
::Restricted { ref path, id }
=> {
4742 debug
!("lower_visibility: restricted path id = {:?}", id
);
4743 let lowered_id
= if let Some(owner
) = explicit_owner
{
4744 self.lower_node_id_with_owner(id
, owner
)
4746 self.lower_node_id(id
)
4748 let def
= self.expect_full_def(id
);
4749 hir
::VisibilityKind
::Restricted
{
4750 path
: P(self.lower_path_extra(
4753 ParamMode
::Explicit
,
4756 id
: lowered_id
.node_id
,
4757 hir_id
: lowered_id
.hir_id
,
4760 VisibilityKind
::Inherited
=> hir
::VisibilityKind
::Inherited
,
4762 respan(v
.span
, node
)
4765 fn lower_defaultness(&self, d
: Defaultness
, has_value
: bool
) -> hir
::Defaultness
{
4767 Defaultness
::Default
=> hir
::Defaultness
::Default
{
4768 has_value
: has_value
,
4770 Defaultness
::Final
=> {
4772 hir
::Defaultness
::Final
4777 fn lower_block_check_mode(&mut self, b
: &BlockCheckMode
) -> hir
::BlockCheckMode
{
4779 BlockCheckMode
::Default
=> hir
::DefaultBlock
,
4780 BlockCheckMode
::Unsafe(u
) => hir
::UnsafeBlock(self.lower_unsafe_source(u
)),
4784 fn lower_binding_mode(&mut self, b
: &BindingMode
) -> hir
::BindingAnnotation
{
4786 BindingMode
::ByValue(Mutability
::Immutable
) => hir
::BindingAnnotation
::Unannotated
,
4787 BindingMode
::ByRef(Mutability
::Immutable
) => hir
::BindingAnnotation
::Ref
,
4788 BindingMode
::ByValue(Mutability
::Mutable
) => hir
::BindingAnnotation
::Mutable
,
4789 BindingMode
::ByRef(Mutability
::Mutable
) => hir
::BindingAnnotation
::RefMut
,
4793 fn lower_unsafe_source(&mut self, u
: UnsafeSource
) -> hir
::UnsafeSource
{
4795 CompilerGenerated
=> hir
::CompilerGenerated
,
4796 UserProvided
=> hir
::UserProvided
,
4800 fn lower_impl_polarity(&mut self, i
: ImplPolarity
) -> hir
::ImplPolarity
{
4802 ImplPolarity
::Positive
=> hir
::ImplPolarity
::Positive
,
4803 ImplPolarity
::Negative
=> hir
::ImplPolarity
::Negative
,
4807 fn lower_trait_bound_modifier(&mut self, f
: TraitBoundModifier
) -> hir
::TraitBoundModifier
{
4809 TraitBoundModifier
::None
=> hir
::TraitBoundModifier
::None
,
4810 TraitBoundModifier
::Maybe
=> hir
::TraitBoundModifier
::Maybe
,
4814 // Helper methods for building HIR.
4816 fn arm(&mut self, pats
: hir
::HirVec
<P
<hir
::Pat
>>, expr
: P
<hir
::Expr
>) -> hir
::Arm
{
4825 fn field(&mut self, ident
: Ident
, expr
: P
<hir
::Expr
>, span
: Span
) -> hir
::Field
{
4826 let LoweredNodeId { node_id, hir_id }
= self.next_id();
4834 is_shorthand
: false,
4838 fn expr_break(&mut self, span
: Span
, attrs
: ThinVec
<Attribute
>) -> P
<hir
::Expr
> {
4839 let expr_break
= hir
::ExprKind
::Break(self.lower_loop_destination(None
), None
);
4840 P(self.expr(span
, expr_break
, attrs
))
4847 args
: hir
::HirVec
<hir
::Expr
>,
4849 self.expr(span
, hir
::ExprKind
::Call(e
, args
), ThinVec
::new())
4852 fn expr_ident(&mut self, span
: Span
, ident
: Ident
, binding
: NodeId
) -> hir
::Expr
{
4853 self.expr_ident_with_attrs(span
, ident
, binding
, ThinVec
::new())
4856 fn expr_ident_with_attrs(
4861 attrs
: ThinVec
<Attribute
>,
4863 let expr_path
= hir
::ExprKind
::Path(hir
::QPath
::Resolved(
4867 def
: Def
::Local(binding
),
4868 segments
: hir_vec
![hir
::PathSegment
::from_ident(ident
)],
4872 self.expr(span
, expr_path
, attrs
)
4875 fn expr_mut_addr_of(&mut self, span
: Span
, e
: P
<hir
::Expr
>) -> hir
::Expr
{
4876 self.expr(span
, hir
::ExprKind
::AddrOf(hir
::MutMutable
, e
), ThinVec
::new())
4882 components
: &[&str],
4883 params
: Option
<P
<hir
::GenericArgs
>>,
4884 attrs
: ThinVec
<Attribute
>,
4886 let path
= self.std_path(span
, components
, params
, true);
4889 hir
::ExprKind
::Path(hir
::QPath
::Resolved(None
, P(path
))),
4898 arms
: hir
::HirVec
<hir
::Arm
>,
4899 source
: hir
::MatchSource
,
4901 self.expr(span
, hir
::ExprKind
::Match(arg
, arms
, source
), ThinVec
::new())
4904 fn expr_block(&mut self, b
: P
<hir
::Block
>, attrs
: ThinVec
<Attribute
>) -> hir
::Expr
{
4905 self.expr(b
.span
, hir
::ExprKind
::Block(b
, None
), attrs
)
4908 fn expr_tuple(&mut self, sp
: Span
, exprs
: hir
::HirVec
<hir
::Expr
>) -> P
<hir
::Expr
> {
4909 P(self.expr(sp
, hir
::ExprKind
::Tup(exprs
), ThinVec
::new()))
4912 fn expr(&mut self, span
: Span
, node
: hir
::ExprKind
, attrs
: ThinVec
<Attribute
>) -> hir
::Expr
{
4913 let LoweredNodeId { node_id, hir_id }
= self.next_id();
4926 ex
: Option
<P
<hir
::Expr
>>,
4928 source
: hir
::LocalSource
,
4930 let LoweredNodeId { node_id, hir_id }
= self.next_id();
4932 let local
= hir
::Local
{
4939 attrs
: ThinVec
::new(),
4943 let LoweredNodeId { node_id, hir_id }
= self.next_id();
4947 node
: hir
::StmtKind
::Local(P(local
)),
4958 ) -> (hir
::Stmt
, NodeId
) {
4959 let pat
= if mutbl
{
4960 self.pat_ident_binding_mode(sp
, ident
, hir
::BindingAnnotation
::Mutable
)
4962 self.pat_ident(sp
, ident
)
4964 let pat_id
= pat
.id
;
4966 self.stmt_let_pat(sp
, Some(ex
), pat
, hir
::LocalSource
::Normal
),
4971 fn block_expr(&mut self, expr
: P
<hir
::Expr
>) -> hir
::Block
{
4972 self.block_all(expr
.span
, hir
::HirVec
::new(), Some(expr
))
4978 stmts
: hir
::HirVec
<hir
::Stmt
>,
4979 expr
: Option
<P
<hir
::Expr
>>,
4981 let LoweredNodeId { node_id, hir_id }
= self.next_id();
4988 rules
: hir
::DefaultBlock
,
4990 targeted_by_break
: false,
4994 fn pat_ok(&mut self, span
: Span
, pat
: P
<hir
::Pat
>) -> P
<hir
::Pat
> {
4995 self.pat_std_enum(span
, &["result", "Result", "Ok"], hir_vec
![pat
])
4998 fn pat_err(&mut self, span
: Span
, pat
: P
<hir
::Pat
>) -> P
<hir
::Pat
> {
4999 self.pat_std_enum(span
, &["result", "Result", "Err"], hir_vec
![pat
])
5002 fn pat_some(&mut self, span
: Span
, pat
: P
<hir
::Pat
>) -> P
<hir
::Pat
> {
5003 self.pat_std_enum(span
, &["option", "Option", "Some"], hir_vec
![pat
])
5006 fn pat_none(&mut self, span
: Span
) -> P
<hir
::Pat
> {
5007 self.pat_std_enum(span
, &["option", "Option", "None"], hir_vec
![])
5013 components
: &[&str],
5014 subpats
: hir
::HirVec
<P
<hir
::Pat
>>,
5016 let path
= self.std_path(span
, components
, None
, true);
5017 let qpath
= hir
::QPath
::Resolved(None
, P(path
));
5018 let pt
= if subpats
.is_empty() {
5019 hir
::PatKind
::Path(qpath
)
5021 hir
::PatKind
::TupleStruct(qpath
, subpats
, None
)
5026 fn pat_ident(&mut self, span
: Span
, ident
: Ident
) -> P
<hir
::Pat
> {
5027 self.pat_ident_binding_mode(span
, ident
, hir
::BindingAnnotation
::Unannotated
)
5030 fn pat_ident_binding_mode(
5034 bm
: hir
::BindingAnnotation
,
5036 let LoweredNodeId { node_id, hir_id }
= self.next_id();
5041 node
: hir
::PatKind
::Binding(bm
, node_id
, hir_id
, ident
.with_span_pos(span
), None
),
5046 fn pat_wild(&mut self, span
: Span
) -> P
<hir
::Pat
> {
5047 self.pat(span
, hir
::PatKind
::Wild
)
5050 fn pat(&mut self, span
: Span
, pat
: hir
::PatKind
) -> P
<hir
::Pat
> {
5051 let LoweredNodeId { node_id, hir_id }
= self.next_id();
5060 /// Given suffix ["b","c","d"], returns path `::std::b::c::d` when
5061 /// `fld.cx.use_std`, and `::core::b::c::d` otherwise.
5062 /// The path is also resolved according to `is_value`.
5066 components
: &[&str],
5067 params
: Option
<P
<hir
::GenericArgs
>>,
5070 let mut path
= self.resolver
5071 .resolve_str_path(span
, self.crate_root
, components
, is_value
);
5072 path
.segments
.last_mut().unwrap().args
= params
;
5075 for seg
in path
.segments
.iter_mut() {
5076 if let Some(id
) = seg
.id
{
5077 seg
.id
= Some(self.lower_node_id(id
).node_id
);
5083 fn ty_path(&mut self, id
: LoweredNodeId
, span
: Span
, qpath
: hir
::QPath
) -> hir
::Ty
{
5085 let node
= match qpath
{
5086 hir
::QPath
::Resolved(None
, path
) => {
5087 // Turn trait object paths into `TyKind::TraitObject` instead.
5089 Def
::Trait(_
) | Def
::TraitAlias(_
) => {
5090 let principal
= hir
::PolyTraitRef
{
5091 bound_generic_params
: hir
::HirVec
::new(),
5092 trait_ref
: hir
::TraitRef
{
5093 path
: path
.and_then(|path
| path
),
5095 hir_ref_id
: id
.hir_id
,
5100 // The original ID is taken by the `PolyTraitRef`,
5101 // so the `Ty` itself needs a different one.
5102 id
= self.next_id();
5103 hir
::TyKind
::TraitObject(hir_vec
![principal
], self.elided_dyn_bound(span
))
5105 _
=> hir
::TyKind
::Path(hir
::QPath
::Resolved(None
, path
)),
5108 _
=> hir
::TyKind
::Path(qpath
),
5118 /// Invoked to create the lifetime argument for a type `&T`
5119 /// with no explicit lifetime.
5120 fn elided_ref_lifetime(&mut self, span
: Span
) -> hir
::Lifetime
{
5121 match self.anonymous_lifetime_mode
{
5122 // Intercept when we are in an impl header and introduce an in-band lifetime.
5123 // Hence `impl Foo for &u32` becomes `impl<'f> Foo for &'f u32` for some fresh
5125 AnonymousLifetimeMode
::CreateParameter
=> {
5126 let fresh_name
= self.collect_fresh_in_band_lifetime(span
);
5127 let LoweredNodeId { node_id, hir_id }
= self.next_id();
5132 name
: hir
::LifetimeName
::Param(fresh_name
),
5136 AnonymousLifetimeMode
::ReportError
=> self.new_error_lifetime(None
, span
),
5138 AnonymousLifetimeMode
::PassThrough
=> self.new_implicit_lifetime(span
),
5142 /// Report an error on illegal use of `'_` or a `&T` with no explicit lifetime;
5143 /// return a "error lifetime".
5144 fn new_error_lifetime(&mut self, id
: Option
<NodeId
>, span
: Span
) -> hir
::Lifetime
{
5145 let (id
, msg
, label
) = match id
{
5146 Some(id
) => (id
, "`'_` cannot be used here", "`'_` is a reserved lifetime name"),
5149 self.next_id().node_id
,
5150 "`&` without an explicit lifetime name cannot be used here",
5151 "explicit lifetime name needed here",
5155 let mut err
= struct_span_err
!(
5162 err
.span_label(span
, label
);
5165 self.new_named_lifetime(id
, span
, hir
::LifetimeName
::Error
)
5168 /// Invoked to create the lifetime argument(s) for a path like
5169 /// `std::cell::Ref<T>`; note that implicit lifetimes in these
5170 /// sorts of cases are deprecated. This may therefore report a warning or an
5171 /// error, depending on the mode.
5172 fn elided_path_lifetimes(&mut self, span
: Span
, count
: usize) -> P
<[hir
::Lifetime
]> {
5173 match self.anonymous_lifetime_mode
{
5174 // N.B., We intentionally ignore the create-parameter mode here
5175 // and instead "pass through" to resolve-lifetimes, which will then
5176 // report an error. This is because we don't want to support
5177 // impl elision for deprecated forms like
5179 // impl Foo for std::cell::Ref<u32> // note lack of '_
5180 AnonymousLifetimeMode
::CreateParameter
=> {}
5182 AnonymousLifetimeMode
::ReportError
=> {
5184 .map(|_
| self.new_error_lifetime(None
, span
))
5188 // This is the normal case.
5189 AnonymousLifetimeMode
::PassThrough
=> {}
5193 .map(|_
| self.new_implicit_lifetime(span
))
5197 /// Invoked to create the lifetime argument(s) for an elided trait object
5198 /// bound, like the bound in `Box<dyn Debug>`. This method is not invoked
5199 /// when the bound is written, even if it is written with `'_` like in
5200 /// `Box<dyn Debug + '_>`. In those cases, `lower_lifetime` is invoked.
5201 fn elided_dyn_bound(&mut self, span
: Span
) -> hir
::Lifetime
{
5202 match self.anonymous_lifetime_mode
{
5203 // NB. We intentionally ignore the create-parameter mode here.
5204 // and instead "pass through" to resolve-lifetimes, which will apply
5205 // the object-lifetime-defaulting rules. Elided object lifetime defaults
5206 // do not act like other elided lifetimes. In other words, given this:
5208 // impl Foo for Box<dyn Debug>
5210 // we do not introduce a fresh `'_` to serve as the bound, but instead
5211 // ultimately translate to the equivalent of:
5213 // impl Foo for Box<dyn Debug + 'static>
5215 // `resolve_lifetime` has the code to make that happen.
5216 AnonymousLifetimeMode
::CreateParameter
=> {}
5218 AnonymousLifetimeMode
::ReportError
=> {
5219 // ReportError applies to explicit use of `'_`.
5222 // This is the normal case.
5223 AnonymousLifetimeMode
::PassThrough
=> {}
5226 self.new_implicit_lifetime(span
)
5229 fn new_implicit_lifetime(&mut self, span
: Span
) -> hir
::Lifetime
{
5230 let LoweredNodeId { node_id, hir_id }
= self.next_id();
5236 name
: hir
::LifetimeName
::Implicit
,
5240 fn maybe_lint_bare_trait(&self, span
: Span
, id
: NodeId
, is_global
: bool
) {
5241 self.sess
.buffer_lint_with_diagnostic(
5242 builtin
::BARE_TRAIT_OBJECTS
,
5245 "trait objects without an explicit `dyn` are deprecated",
5246 builtin
::BuiltinLintDiagnostics
::BareTraitObject(span
, is_global
),
5250 fn wrap_in_try_constructor(
5252 method
: &'
static str,
5254 unstable_span
: Span
,
5256 let path
= &["ops", "Try", method
];
5257 let from_err
= P(self.expr_std_path(unstable_span
, path
, None
,
5259 P(self.expr_call(e
.span
, from_err
, hir_vec
![e
]))
5263 fn body_ids(bodies
: &BTreeMap
<hir
::BodyId
, hir
::Body
>) -> Vec
<hir
::BodyId
> {
5264 // Sorting by span ensures that we get things in order within a
5265 // file, and also puts the files in a sensible order.
5266 let mut body_ids
: Vec
<_
> = bodies
.keys().cloned().collect();
5267 body_ids
.sort_by_key(|b
| bodies
[b
].value
.span
);