2020-03-14 00:00:35 +03:00
|
|
|
use rustc_ast::ptr::P;
|
2021-07-15 01:18:39 +02:00
|
|
|
use rustc_ast::visit::AssocCtxt;
|
2020-04-27 23:26:11 +05:30
|
|
|
use rustc_ast::*;
|
2023-02-22 22:40:06 +00:00
|
|
|
use rustc_errors::ErrorGuaranteed;
|
2020-01-05 02:37:57 +01:00
|
|
|
use rustc_hir as hir;
|
2022-05-05 15:50:11 +01:00
|
|
|
use rustc_hir::PredicateOrigin;
|
2020-01-05 02:37:57 +01:00
|
|
|
use rustc_hir::def::{DefKind, Res};
|
2021-07-15 01:18:39 +02:00
|
|
|
use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId};
|
2024-04-03 17:49:59 +03:00
|
|
|
use rustc_index::{IndexSlice, IndexVec};
|
2024-01-07 18:22:47 +01:00
|
|
|
use rustc_middle::span_bug;
|
2023-02-22 19:51:17 +04:00
|
|
|
use rustc_middle::ty::{ResolverAstLowering, TyCtxt};
|
2023-02-19 04:03:56 +00:00
|
|
|
use rustc_span::edit_distance::find_best_match_for_name;
|
2020-04-19 13:00:18 +02:00
|
|
|
use rustc_span::symbol::{Ident, kw, sym};
|
2023-11-02 14:10:12 +11:00
|
|
|
use rustc_span::{DesugaringKind, Span, Symbol};
|
2019-10-27 23:14:35 +01:00
|
|
|
use rustc_target::spec::abi;
|
2019-12-22 18:15:02 +01:00
|
|
|
use smallvec::{SmallVec, smallvec};
|
2022-09-08 17:22:52 +10:00
|
|
|
use thin_vec::ThinVec;
|
2024-04-29 16:24:06 +10:00
|
|
|
use tracing::instrument;
|
2021-02-14 21:14:12 +03:00
|
|
|
|
feat: `riscv-interrupt-{m,s}` calling conventions
Similar to prior support added for the mips430, avr, and x86 targets
this change implements the rough equivalent of clang's
[`__attribute__((interrupt))`][clang-attr] for riscv targets, enabling
e.g.
```rust
static mut CNT: usize = 0;
pub extern "riscv-interrupt-m" fn isr_m() {
unsafe {
CNT += 1;
}
}
```
to produce highly effective assembly like:
```asm
pub extern "riscv-interrupt-m" fn isr_m() {
420003a0: 1141 addi sp,sp,-16
unsafe {
CNT += 1;
420003a2: c62a sw a0,12(sp)
420003a4: c42e sw a1,8(sp)
420003a6: 3fc80537 lui a0,0x3fc80
420003aa: 63c52583 lw a1,1596(a0) # 3fc8063c <_ZN12esp_riscv_rt3CNT17hcec3e3a214887d53E.0>
420003ae: 0585 addi a1,a1,1
420003b0: 62b52e23 sw a1,1596(a0)
}
}
420003b4: 4532 lw a0,12(sp)
420003b6: 45a2 lw a1,8(sp)
420003b8: 0141 addi sp,sp,16
420003ba: 30200073 mret
```
(disassembly via `riscv64-unknown-elf-objdump -C -S --disassemble ./esp32c3-hal/target/riscv32imc-unknown-none-elf/release/examples/gpio_interrupt`)
This outcome is superior to hand-coded interrupt routines which, lacking
visibility into any non-assembly body of the interrupt handler, have to
be very conservative and save the [entire CPU state to the stack
frame][full-frame-save]. By instead asking LLVM to only save the
registers that it uses, we defer the decision to the tool with the best
context: it can more accurately account for the cost of spills if it
knows that every additional register used is already at the cost of an
implicit spill.
At the LLVM level, this is apparently [implemented by] marking every
register as "[callee-save]," matching the semantics of an interrupt
handler nicely (it has to leave the CPU state just as it found it after
its `{m|s}ret`).
This approach is not suitable for every interrupt handler, as it makes
no attempt to e.g. save the state in a user-accessible stack frame. For
a full discussion of those challenges and tradeoffs, please refer to
[the interrupt calling conventions RFC][rfc].
Inside rustc, this implementation differs from prior art because LLVM
does not expose the "all-saved" function flavor as a calling convention
directly, instead preferring to use an attribute that allows for
differentiating between "machine-mode" and "superivsor-mode" interrupts.
Finally, some effort has been made to guide those who may not yet be
aware of the differences between machine-mode and supervisor-mode
interrupts as to why no `riscv-interrupt` calling convention is exposed
through rustc, and similarly for why `riscv-interrupt-u` makes no
appearance (as it would complicate future LLVM upgrades).
[clang-attr]: https://clang.llvm.org/docs/AttributeReference.html#interrupt-risc-v
[full-frame-save]: https://github.com/esp-rs/esp-riscv-rt/blob/9281af2ecffe13e40992917316f36920c26acaf3/src/lib.rs#L440-L469
[implemented by]: https://github.com/llvm/llvm-project/blob/b7fb2a3fec7c187d58a6d338ab512d9173bca987/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp#L61-L67
[callee-save]: https://github.com/llvm/llvm-project/blob/973f1fe7a8591c7af148e573491ab68cc15b6ecf/llvm/lib/Target/RISCV/RISCVCallingConv.td#L30-L37
[rfc]: https://github.com/rust-lang/rfcs/pull/3246
2023-05-23 15:08:23 -07:00
|
|
|
use super::errors::{InvalidAbi, InvalidAbiReason, InvalidAbiSuggestion, MisplacedRelaxTraitBound};
|
2021-07-13 18:45:20 +02:00
|
|
|
use super::{
|
2022-12-18 20:28:59 +01:00
|
|
|
AstOwner, FnDeclKind, ImplTraitContext, ImplTraitPosition, LoweringContext, ParamMode,
|
2023-02-22 19:51:17 +04:00
|
|
|
ResolverAstLoweringExt,
|
2024-07-29 08:13:50 +10:00
|
|
|
};
|
|
|
|
|
|
2021-07-15 16:40:41 +02:00
|
|
|
pub(super) struct ItemLowerer<'a, 'hir> {
|
2021-07-13 18:45:20 +02:00
|
|
|
pub(super) tcx: TyCtxt<'hir>,
|
2022-06-15 19:42:43 +02:00
|
|
|
pub(super) resolver: &'a mut ResolverAstLowering,
|
2023-03-31 00:32:44 -07:00
|
|
|
pub(super) ast_index: &'a IndexSlice<LocalDefId, AstOwner<'a>>,
|
2024-02-03 15:50:14 +03:00
|
|
|
pub(super) owners: &'a mut IndexVec<LocalDefId, hir::MaybeOwner<'hir>>,
|
2019-08-10 20:13:12 +02:00
|
|
|
}
|
|
|
|
|
|
2022-02-07 12:20:09 -05:00
|
|
|
/// When we have a ty alias we *may* have two where clauses. To give the best diagnostics, we set the span
|
2022-03-16 20:12:30 +08:00
|
|
|
/// to the where clause that is preferred, if it exists. Otherwise, it sets the span to the other where
|
2022-02-07 12:20:09 -05:00
|
|
|
/// clause if it exists.
|
|
|
|
|
fn add_ty_alias_where_clause(
|
|
|
|
|
generics: &mut ast::Generics,
|
2024-02-19 14:25:33 +01:00
|
|
|
mut where_clauses: TyAliasWhereClauses,
|
2022-02-07 12:20:09 -05:00
|
|
|
prefer_first: bool,
|
|
|
|
|
) {
|
|
|
|
|
if !prefer_first {
|
2024-02-19 14:25:33 +01:00
|
|
|
(where_clauses.before, where_clauses.after) = (where_clauses.after, where_clauses.before);
|
2022-02-07 12:20:09 -05:00
|
|
|
}
|
2024-02-19 14:25:33 +01:00
|
|
|
let where_clause =
|
|
|
|
|
if where_clauses.before.has_where_token || !where_clauses.after.has_where_token {
|
|
|
|
|
where_clauses.before
|
|
|
|
|
} else {
|
|
|
|
|
where_clauses.after
|
|
|
|
|
};
|
|
|
|
|
generics.where_clause.has_where_token = where_clause.has_where_token;
|
|
|
|
|
generics.where_clause.span = where_clause.span;
|
2022-02-07 12:20:09 -05:00
|
|
|
}
|
|
|
|
|
|
2021-07-15 16:40:41 +02:00
|
|
|
impl<'a, 'hir> ItemLowerer<'a, 'hir> {
|
2021-07-15 17:41:48 +02:00
|
|
|
fn with_lctx(
|
|
|
|
|
&mut self,
|
|
|
|
|
owner: NodeId,
|
|
|
|
|
f: impl FnOnce(&mut LoweringContext<'_, 'hir>) -> hir::OwnerNode<'hir>,
|
|
|
|
|
) {
|
2024-10-20 20:22:11 +00:00
|
|
|
let mut lctx = LoweringContext::new(self.tcx, self.resolver);
|
2021-07-15 17:41:48 +02:00
|
|
|
lctx.with_hir_id_owner(owner, |lctx| f(lctx));
|
|
|
|
|
|
|
|
|
|
for (def_id, info) in lctx.children {
|
2023-04-17 13:14:03 +00:00
|
|
|
let owner = self.owners.ensure_contains_elem(def_id, || hir::MaybeOwner::Phantom);
|
2024-07-16 19:07:36 -07:00
|
|
|
debug_assert!(
|
|
|
|
|
matches!(owner, hir::MaybeOwner::Phantom),
|
|
|
|
|
"duplicate copy of {def_id:?} in lctx.children"
|
|
|
|
|
);
|
2023-04-17 13:14:03 +00:00
|
|
|
*owner = info;
|
2021-07-15 16:40:41 +02:00
|
|
|
}
|
2019-08-10 20:13:12 +02:00
|
|
|
}
|
|
|
|
|
|
2024-02-03 15:50:14 +03:00
|
|
|
pub(super) fn lower_node(&mut self, def_id: LocalDefId) -> hir::MaybeOwner<'hir> {
|
2023-04-17 13:14:03 +00:00
|
|
|
let owner = self.owners.ensure_contains_elem(def_id, || hir::MaybeOwner::Phantom);
|
|
|
|
|
if let hir::MaybeOwner::Phantom = owner {
|
2021-07-15 01:18:39 +02:00
|
|
|
let node = self.ast_index[def_id];
|
|
|
|
|
match node {
|
|
|
|
|
AstOwner::NonOwner => {}
|
|
|
|
|
AstOwner::Crate(c) => self.lower_crate(c),
|
|
|
|
|
AstOwner::Item(item) => self.lower_item(item),
|
|
|
|
|
AstOwner::AssocItem(item, ctxt) => self.lower_assoc_item(item, ctxt),
|
|
|
|
|
AstOwner::ForeignItem(item) => self.lower_foreign_item(item),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-15 16:40:41 +02:00
|
|
|
self.owners[def_id]
|
2021-11-21 16:16:02 +01:00
|
|
|
}
|
|
|
|
|
|
2022-05-20 15:52:56 -03:00
|
|
|
#[instrument(level = "debug", skip(self, c))]
|
2021-07-15 17:41:48 +02:00
|
|
|
fn lower_crate(&mut self, c: &Crate) {
|
2021-07-18 20:09:20 +02:00
|
|
|
debug_assert_eq!(self.resolver.node_id_to_def_id[&CRATE_NODE_ID], CRATE_DEF_ID);
|
2021-07-15 17:41:48 +02:00
|
|
|
self.with_lctx(CRATE_NODE_ID, |lctx| {
|
2022-03-18 17:13:38 -04:00
|
|
|
let module = lctx.lower_mod(&c.items, &c.spans);
|
2021-07-15 01:18:39 +02:00
|
|
|
lctx.lower_attrs(hir::CRATE_HIR_ID, &c.attrs);
|
2022-08-26 16:22:13 +10:00
|
|
|
hir::OwnerNode::Crate(module)
|
2021-07-15 16:40:41 +02:00
|
|
|
})
|
2019-08-10 20:13:12 +02:00
|
|
|
}
|
|
|
|
|
|
2022-05-20 15:52:56 -03:00
|
|
|
#[instrument(level = "debug", skip(self))]
|
2021-07-15 17:41:48 +02:00
|
|
|
fn lower_item(&mut self, item: &Item) {
|
|
|
|
|
self.with_lctx(item.id, |lctx| hir::OwnerNode::Item(lctx.lower_item(item)))
|
2020-07-09 19:03:15 -07:00
|
|
|
}
|
|
|
|
|
|
2021-07-15 17:41:48 +02:00
|
|
|
fn lower_assoc_item(&mut self, item: &AssocItem, ctxt: AssocCtxt) {
|
2021-07-18 20:09:20 +02:00
|
|
|
let def_id = self.resolver.node_id_to_def_id[&item.id];
|
2022-06-02 20:08:38 +02:00
|
|
|
let parent_id = self.tcx.local_parent(def_id);
|
2022-04-07 20:54:13 +02:00
|
|
|
let parent_hir = self.lower_node(parent_id).unwrap();
|
2023-11-28 12:07:05 +11:00
|
|
|
self.with_lctx(item.id, |lctx| lctx.lower_assoc_item(item, ctxt, parent_hir))
|
2019-08-10 20:13:12 +02:00
|
|
|
}
|
2020-11-11 21:57:54 +01:00
|
|
|
|
2021-07-15 17:41:48 +02:00
|
|
|
fn lower_foreign_item(&mut self, item: &ForeignItem) {
|
|
|
|
|
self.with_lctx(item.id, |lctx| hir::OwnerNode::ForeignItem(lctx.lower_foreign_item(item)))
|
2020-11-11 21:57:54 +01:00
|
|
|
}
|
2019-08-10 20:13:12 +02:00
|
|
|
}
|
|
|
|
|
|
2019-11-29 11:09:23 +01:00
|
|
|
impl<'hir> LoweringContext<'_, 'hir> {
|
2022-08-26 16:22:13 +10:00
|
|
|
pub(super) fn lower_mod(
|
|
|
|
|
&mut self,
|
|
|
|
|
items: &[P<Item>],
|
|
|
|
|
spans: &ModSpans,
|
|
|
|
|
) -> &'hir hir::Mod<'hir> {
|
|
|
|
|
self.arena.alloc(hir::Mod {
|
2022-03-18 17:13:38 -04:00
|
|
|
spans: hir::ModSpans {
|
|
|
|
|
inner_span: self.lower_span(spans.inner_span),
|
|
|
|
|
inject_use_span: self.lower_span(spans.inject_use_span),
|
|
|
|
|
},
|
2021-07-14 18:54:56 +02:00
|
|
|
item_ids: self.arena.alloc_from_iter(items.iter().flat_map(|x| self.lower_item_ref(x))),
|
2022-08-26 16:22:13 +10:00
|
|
|
})
|
2019-08-10 20:13:12 +02:00
|
|
|
}
|
|
|
|
|
|
2021-07-14 18:54:56 +02:00
|
|
|
pub(super) fn lower_item_ref(&mut self, i: &Item) -> SmallVec<[hir::ItemId; 1]> {
|
2022-09-20 14:11:23 +09:00
|
|
|
let mut node_ids =
|
2022-10-27 14:02:18 +11:00
|
|
|
smallvec![hir::ItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } }];
|
2022-11-22 15:37:54 +00:00
|
|
|
if let ItemKind::Use(use_tree) = &i.kind {
|
2022-12-01 18:51:20 +03:00
|
|
|
self.lower_item_id_use_tree(use_tree, &mut node_ids);
|
2021-07-14 18:54:56 +02:00
|
|
|
}
|
2019-08-10 20:13:12 +02:00
|
|
|
node_ids
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-01 18:51:20 +03:00
|
|
|
fn lower_item_id_use_tree(&mut self, tree: &UseTree, vec: &mut SmallVec<[hir::ItemId; 1]>) {
|
2022-11-22 15:37:54 +00:00
|
|
|
match &tree.kind {
|
2024-04-02 00:26:10 +02:00
|
|
|
UseTreeKind::Nested { items, .. } => {
|
|
|
|
|
for &(ref nested, id) in items {
|
2022-09-20 14:11:23 +09:00
|
|
|
vec.push(hir::ItemId {
|
2022-10-27 14:02:18 +11:00
|
|
|
owner_id: hir::OwnerId { def_id: self.local_def_id(id) },
|
2022-09-20 14:11:23 +09:00
|
|
|
});
|
2022-12-01 18:51:20 +03:00
|
|
|
self.lower_item_id_use_tree(nested, vec);
|
2019-08-10 20:13:12 +02:00
|
|
|
}
|
|
|
|
|
}
|
2022-12-01 18:51:20 +03:00
|
|
|
UseTreeKind::Simple(..) | UseTreeKind::Glob => {}
|
2019-08-10 20:13:12 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-16 10:16:23 +02:00
|
|
|
fn lower_item(&mut self, i: &Item) -> &'hir hir::Item<'hir> {
|
2019-08-10 20:13:12 +02:00
|
|
|
let mut ident = i.ident;
|
2022-02-13 11:30:48 +01:00
|
|
|
let vis_span = self.lower_span(i.vis.span);
|
2024-09-15 11:10:16 +08:00
|
|
|
let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id);
|
2020-11-24 18:12:42 +01:00
|
|
|
let attrs = self.lower_attrs(hir_id, &i.attrs);
|
2022-02-13 11:30:48 +01:00
|
|
|
let kind = self.lower_item_kind(i.span, i.id, hir_id, &mut ident, attrs, vis_span, &i.kind);
|
2021-07-16 10:16:23 +02:00
|
|
|
let item = hir::Item {
|
2022-10-27 14:02:18 +11:00
|
|
|
owner_id: hir_id.expect_owner(),
|
2021-08-21 00:29:08 +03:00
|
|
|
ident: self.lower_ident(ident),
|
|
|
|
|
kind,
|
2022-02-13 11:30:48 +01:00
|
|
|
vis_span,
|
2021-08-21 00:29:08 +03:00
|
|
|
span: self.lower_span(i.span),
|
2021-07-16 10:16:23 +02:00
|
|
|
};
|
|
|
|
|
self.arena.alloc(item)
|
2019-08-10 20:13:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn lower_item_kind(
|
|
|
|
|
&mut self,
|
2019-12-01 07:24:07 +01:00
|
|
|
span: Span,
|
2019-08-10 20:13:12 +02:00
|
|
|
id: NodeId,
|
2020-11-24 18:12:42 +01:00
|
|
|
hir_id: hir::HirId,
|
2019-08-10 20:13:12 +02:00
|
|
|
ident: &mut Ident,
|
2024-07-26 10:19:31 +00:00
|
|
|
attrs: &'hir [Attribute],
|
2022-02-13 11:30:48 +01:00
|
|
|
vis_span: Span,
|
2019-08-10 20:13:12 +02:00
|
|
|
i: &ItemKind,
|
2019-11-28 19:28:50 +01:00
|
|
|
) -> hir::ItemKind<'hir> {
|
2022-11-22 15:37:54 +00:00
|
|
|
match i {
|
|
|
|
|
ItemKind::ExternCrate(orig_name) => hir::ItemKind::ExternCrate(*orig_name),
|
|
|
|
|
ItemKind::Use(use_tree) => {
|
2019-08-10 20:13:12 +02:00
|
|
|
// Start with an empty prefix.
|
2022-09-08 17:22:52 +10:00
|
|
|
let prefix = Path { segments: ThinVec::new(), span: use_tree.span, tokens: None };
|
2019-08-10 20:13:12 +02:00
|
|
|
|
2022-02-13 11:30:48 +01:00
|
|
|
self.lower_use_tree(use_tree, &prefix, id, vis_span, ident, attrs)
|
2019-08-10 20:13:12 +02:00
|
|
|
}
|
2024-05-07 14:43:23 +02:00
|
|
|
ItemKind::Static(box ast::StaticItem { ty: t, safety: _, mutability: m, expr: e }) => {
|
2024-01-07 17:11:48 +00:00
|
|
|
let (ty, body_id) =
|
|
|
|
|
self.lower_const_item(t, span, e.as_deref(), ImplTraitPosition::StaticTy);
|
2022-11-22 15:37:54 +00:00
|
|
|
hir::ItemKind::Static(ty, *m, body_id)
|
2019-08-10 20:13:12 +02:00
|
|
|
}
|
2023-05-04 16:40:57 +02:00
|
|
|
ItemKind::Const(box ast::ConstItem { generics, ty, expr, .. }) => {
|
|
|
|
|
let (generics, (ty, body_id)) = self.lower_generics(
|
|
|
|
|
generics,
|
|
|
|
|
id,
|
2024-02-07 19:27:44 +00:00
|
|
|
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
2024-01-07 17:11:48 +00:00
|
|
|
|this| {
|
|
|
|
|
this.lower_const_item(ty, span, expr.as_deref(), ImplTraitPosition::ConstTy)
|
|
|
|
|
},
|
2023-05-04 16:40:57 +02:00
|
|
|
);
|
|
|
|
|
hir::ItemKind::Const(ty, generics, body_id)
|
2019-08-10 20:13:12 +02:00
|
|
|
}
|
2021-11-07 16:43:49 +08:00
|
|
|
ItemKind::Fn(box Fn {
|
2022-11-22 15:37:54 +00:00
|
|
|
sig: FnSig { decl, header, span: fn_sig_span },
|
|
|
|
|
generics,
|
|
|
|
|
body,
|
2021-11-07 16:43:49 +08:00
|
|
|
..
|
|
|
|
|
}) => {
|
2024-04-11 13:15:34 +00:00
|
|
|
self.with_new_scopes(*fn_sig_span, |this| {
|
2019-08-10 20:13:12 +02:00
|
|
|
// Note: we don't need to change the return type from `T` to
|
|
|
|
|
// `impl Future<Output = T>` here because lower_body
|
|
|
|
|
// only cares about the input argument patterns in the function
|
|
|
|
|
// declaration (decl), not the return types.
|
2023-12-05 21:39:36 +00:00
|
|
|
let coroutine_kind = header.coroutine_kind;
|
2023-11-29 12:07:43 -08:00
|
|
|
let body_id = this.lower_maybe_coroutine_body(
|
2024-06-27 14:56:57 -04:00
|
|
|
*fn_sig_span,
|
2023-11-29 12:07:43 -08:00
|
|
|
span,
|
|
|
|
|
hir_id,
|
|
|
|
|
decl,
|
2023-12-05 21:39:36 +00:00
|
|
|
coroutine_kind,
|
2023-11-29 12:07:43 -08:00
|
|
|
body.as_deref(),
|
|
|
|
|
);
|
2019-08-10 20:13:12 +02:00
|
|
|
|
2022-12-25 16:42:35 +01:00
|
|
|
let itctx = ImplTraitContext::Universal;
|
2024-10-20 20:22:11 +00:00
|
|
|
let (generics, decl) = this.lower_generics(generics, id, itctx, |this| {
|
|
|
|
|
this.lower_fn_decl(decl, id, *fn_sig_span, FnDeclKind::Fn, coroutine_kind)
|
|
|
|
|
});
|
2020-08-12 17:02:14 -04:00
|
|
|
let sig = hir::FnSig {
|
|
|
|
|
decl,
|
2024-08-07 13:01:34 -04:00
|
|
|
header: this.lower_fn_header(*header, hir::Safety::Safe),
|
2022-11-22 15:37:54 +00:00
|
|
|
span: this.lower_span(*fn_sig_span),
|
2020-08-12 17:02:14 -04:00
|
|
|
};
|
2019-11-07 12:57:52 +01:00
|
|
|
hir::ItemKind::Fn(sig, generics, body_id)
|
2019-08-10 20:13:12 +02:00
|
|
|
})
|
|
|
|
|
}
|
2022-11-22 15:37:54 +00:00
|
|
|
ItemKind::Mod(_, mod_kind) => match mod_kind {
|
2022-03-18 17:13:38 -04:00
|
|
|
ModKind::Loaded(items, _, spans) => {
|
|
|
|
|
hir::ItemKind::Mod(self.lower_mod(items, spans))
|
2021-02-17 00:56:07 +03:00
|
|
|
}
|
|
|
|
|
ModKind::Unloaded => panic!("`mod` items should have been loaded by now"),
|
|
|
|
|
},
|
2022-11-22 15:37:54 +00:00
|
|
|
ItemKind::ForeignMod(fm) => hir::ItemKind::ForeignMod {
|
2021-07-08 21:58:05 +02:00
|
|
|
abi: fm.abi.map_or(abi::Abi::FALLBACK, |abi| self.lower_abi(abi)),
|
|
|
|
|
items: self
|
|
|
|
|
.arena
|
|
|
|
|
.alloc_from_iter(fm.items.iter().map(|x| self.lower_foreign_item_ref(x))),
|
|
|
|
|
},
|
2022-11-22 15:37:54 +00:00
|
|
|
ItemKind::GlobalAsm(asm) => hir::ItemKind::GlobalAsm(self.lower_inline_asm(span, asm)),
|
2023-02-22 21:19:42 +00:00
|
|
|
ItemKind::TyAlias(box TyAlias { generics, where_clauses, ty, .. }) => {
|
2020-06-07 19:42:08 +01:00
|
|
|
// We lower
|
|
|
|
|
//
|
|
|
|
|
// type Foo = impl Trait
|
|
|
|
|
//
|
|
|
|
|
// to
|
|
|
|
|
//
|
|
|
|
|
// type Foo = Foo1
|
|
|
|
|
// opaque type Foo1: Trait
|
2021-10-19 18:45:48 -04:00
|
|
|
let mut generics = generics.clone();
|
2022-11-22 15:37:54 +00:00
|
|
|
add_ty_alias_where_clause(&mut generics, *where_clauses, true);
|
2022-05-31 15:32:05 -03:00
|
|
|
let (generics, ty) = self.lower_generics(
|
2021-10-19 18:45:48 -04:00
|
|
|
&generics,
|
2022-05-31 15:30:14 -03:00
|
|
|
id,
|
2024-02-07 19:27:44 +00:00
|
|
|
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
2023-02-22 21:19:42 +00:00
|
|
|
|this| match ty {
|
|
|
|
|
None => {
|
2023-12-18 22:21:37 +11:00
|
|
|
let guar = this.dcx().span_delayed_bug(
|
2023-02-22 21:19:42 +00:00
|
|
|
span,
|
|
|
|
|
"expected to lower type alias type, but it was missing",
|
|
|
|
|
);
|
|
|
|
|
this.arena.alloc(this.ty(span, hir::TyKind::Err(guar)))
|
|
|
|
|
}
|
2024-03-06 18:44:55 +00:00
|
|
|
Some(ty) => this.lower_ty(ty, ImplTraitContext::OpaqueTy {
|
2024-03-06 17:52:53 +00:00
|
|
|
origin: hir::OpaqueTyOrigin::TyAlias {
|
|
|
|
|
parent: this.local_def_id(id),
|
|
|
|
|
in_assoc_ty: false,
|
|
|
|
|
},
|
2023-04-17 10:19:41 +00:00
|
|
|
}),
|
2023-02-22 21:19:42 +00:00
|
|
|
},
|
2022-01-11 19:00:34 -08:00
|
|
|
);
|
2020-02-21 23:00:27 +01:00
|
|
|
hir::ItemKind::TyAlias(ty, generics)
|
|
|
|
|
}
|
2022-11-22 15:37:54 +00:00
|
|
|
ItemKind::Enum(enum_definition, generics) => {
|
2022-05-31 15:32:05 -03:00
|
|
|
let (generics, variants) = self.lower_generics(
|
2022-01-11 19:00:34 -08:00
|
|
|
generics,
|
2022-05-31 15:30:14 -03:00
|
|
|
id,
|
2024-02-07 19:27:44 +00:00
|
|
|
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
2022-05-31 15:30:14 -03:00
|
|
|
|this| {
|
|
|
|
|
this.arena.alloc_from_iter(
|
|
|
|
|
enum_definition.variants.iter().map(|x| this.lower_variant(x)),
|
|
|
|
|
)
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
hir::ItemKind::Enum(hir::EnumDef { variants }, generics)
|
|
|
|
|
}
|
2022-11-22 15:37:54 +00:00
|
|
|
ItemKind::Struct(struct_def, generics) => {
|
2022-05-31 15:32:05 -03:00
|
|
|
let (generics, struct_def) = self.lower_generics(
|
2022-05-31 15:30:14 -03:00
|
|
|
generics,
|
|
|
|
|
id,
|
2024-02-07 19:27:44 +00:00
|
|
|
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
2022-05-31 15:30:14 -03:00
|
|
|
|this| this.lower_variant_data(hir_id, struct_def),
|
|
|
|
|
);
|
|
|
|
|
hir::ItemKind::Struct(struct_def, generics)
|
2019-08-10 20:13:12 +02:00
|
|
|
}
|
2022-11-22 15:37:54 +00:00
|
|
|
ItemKind::Union(vdata, generics) => {
|
2022-05-31 15:32:05 -03:00
|
|
|
let (generics, vdata) = self.lower_generics(
|
2022-05-31 15:30:14 -03:00
|
|
|
generics,
|
|
|
|
|
id,
|
2024-02-07 19:27:44 +00:00
|
|
|
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
2022-05-31 15:30:14 -03:00
|
|
|
|this| this.lower_variant_data(hir_id, vdata),
|
|
|
|
|
);
|
|
|
|
|
hir::ItemKind::Union(vdata, generics)
|
2019-08-10 20:13:12 +02:00
|
|
|
}
|
2021-11-07 16:43:49 +08:00
|
|
|
ItemKind::Impl(box Impl {
|
2024-05-17 14:17:48 -03:00
|
|
|
safety,
|
2019-08-10 20:13:12 +02:00
|
|
|
polarity,
|
|
|
|
|
defaultness,
|
2020-01-13 20:30:24 -08:00
|
|
|
constness,
|
2022-11-22 15:37:54 +00:00
|
|
|
generics: ast_generics,
|
|
|
|
|
of_trait: trait_ref,
|
|
|
|
|
self_ty: ty,
|
|
|
|
|
items: impl_items,
|
2021-01-29 08:31:08 +01:00
|
|
|
}) => {
|
2019-08-10 20:13:12 +02:00
|
|
|
// Lower the "impl header" first. This ordering is important
|
|
|
|
|
// for in-band lifetimes! Consider `'a` here:
|
|
|
|
|
//
|
|
|
|
|
// impl Foo<'a> for u32 {
|
|
|
|
|
// fn method(&'a self) { .. }
|
|
|
|
|
// }
|
|
|
|
|
//
|
|
|
|
|
// Because we start by lowering the `Foo<'a> for u32`
|
|
|
|
|
// part, we will add `'a` to the list of generics on
|
|
|
|
|
// the impl. When we then encounter it later in the
|
|
|
|
|
// method, it will not be considered an in-band
|
|
|
|
|
// lifetime to be added, but rather a reference to a
|
|
|
|
|
// parent lifetime.
|
2022-12-25 16:42:35 +01:00
|
|
|
let itctx = ImplTraitContext::Universal;
|
2022-04-07 20:54:13 +02:00
|
|
|
let (generics, (trait_ref, lowered_ty)) =
|
2024-10-20 20:22:11 +00:00
|
|
|
self.lower_generics(ast_generics, id, itctx, |this| {
|
2024-01-26 17:00:28 +00:00
|
|
|
let modifiers = TraitBoundModifiers {
|
2024-06-14 12:16:15 +00:00
|
|
|
constness: BoundConstness::Never,
|
2024-01-26 17:00:28 +00:00
|
|
|
asyncness: BoundAsyncness::Normal,
|
|
|
|
|
// we don't use this in bound lowering
|
|
|
|
|
polarity: BoundPolarity::Positive,
|
2023-12-18 17:55:55 +01:00
|
|
|
};
|
|
|
|
|
|
2019-08-10 20:13:12 +02:00
|
|
|
let trait_ref = trait_ref.as_ref().map(|trait_ref| {
|
2022-01-11 19:00:34 -08:00
|
|
|
this.lower_trait_ref(
|
2024-01-26 17:00:28 +00:00
|
|
|
modifiers,
|
2022-01-11 19:00:34 -08:00
|
|
|
trait_ref,
|
2024-02-07 19:27:44 +00:00
|
|
|
ImplTraitContext::Disallowed(ImplTraitPosition::Trait),
|
2022-01-11 19:00:34 -08:00
|
|
|
)
|
2019-08-10 20:13:12 +02:00
|
|
|
});
|
|
|
|
|
|
2023-02-14 22:15:32 +00:00
|
|
|
let lowered_ty = this.lower_ty(
|
|
|
|
|
ty,
|
2024-02-07 19:27:44 +00:00
|
|
|
ImplTraitContext::Disallowed(ImplTraitPosition::ImplSelf),
|
2023-02-14 22:15:32 +00:00
|
|
|
);
|
2019-08-10 20:13:12 +02:00
|
|
|
|
|
|
|
|
(trait_ref, lowered_ty)
|
|
|
|
|
});
|
|
|
|
|
|
2024-03-16 21:03:36 +03:00
|
|
|
self.is_in_trait_impl = trait_ref.is_some();
|
2022-04-24 15:49:00 +02:00
|
|
|
let new_impl_items = self
|
|
|
|
|
.arena
|
|
|
|
|
.alloc_from_iter(impl_items.iter().map(|item| self.lower_impl_item_ref(item)));
|
2019-08-10 20:13:12 +02:00
|
|
|
|
2020-03-02 15:26:00 -08:00
|
|
|
// `defaultness.has_value()` is never called for an `impl`, always `true` in order
|
|
|
|
|
// to not cause an assertion failure inside the `lower_defaultness` function.
|
|
|
|
|
let has_val = true;
|
2022-11-22 15:37:54 +00:00
|
|
|
let (defaultness, defaultness_span) = self.lower_defaultness(*defaultness, has_val);
|
2021-08-21 00:29:08 +03:00
|
|
|
let polarity = match polarity {
|
|
|
|
|
ImplPolarity::Positive => ImplPolarity::Positive,
|
2022-11-22 15:37:54 +00:00
|
|
|
ImplPolarity::Negative(s) => ImplPolarity::Negative(self.lower_span(*s)),
|
2021-08-21 00:29:08 +03:00
|
|
|
};
|
2022-02-05 15:26:49 +01:00
|
|
|
hir::ItemKind::Impl(self.arena.alloc(hir::Impl {
|
2024-06-14 12:16:15 +00:00
|
|
|
constness: self.lower_constness(*constness),
|
2024-05-23 10:01:05 -03:00
|
|
|
safety: self.lower_safety(*safety, hir::Safety::Safe),
|
2019-11-09 18:38:35 +01:00
|
|
|
polarity,
|
2020-03-02 15:26:00 -08:00
|
|
|
defaultness,
|
|
|
|
|
defaultness_span,
|
2019-08-10 20:13:12 +02:00
|
|
|
generics,
|
2020-01-17 16:14:29 -08:00
|
|
|
of_trait: trait_ref,
|
|
|
|
|
self_ty: lowered_ty,
|
|
|
|
|
items: new_impl_items,
|
2022-02-05 15:26:49 +01:00
|
|
|
}))
|
2019-08-10 20:13:12 +02:00
|
|
|
}
|
2024-05-17 14:17:48 -03:00
|
|
|
ItemKind::Trait(box Trait { is_auto, safety, generics, bounds, items }) => {
|
|
|
|
|
let (generics, (safety, items, bounds)) = self.lower_generics(
|
2022-05-31 15:30:14 -03:00
|
|
|
generics,
|
|
|
|
|
id,
|
2024-02-07 19:27:44 +00:00
|
|
|
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
2022-05-31 15:30:14 -03:00
|
|
|
|this| {
|
|
|
|
|
let bounds = this.lower_param_bounds(
|
|
|
|
|
bounds,
|
2024-02-07 19:27:44 +00:00
|
|
|
ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
|
2022-05-31 15:30:14 -03:00
|
|
|
);
|
|
|
|
|
let items = this.arena.alloc_from_iter(
|
|
|
|
|
items.iter().map(|item| this.lower_trait_item_ref(item)),
|
|
|
|
|
);
|
2024-05-23 10:01:05 -03:00
|
|
|
let safety = this.lower_safety(*safety, hir::Safety::Safe);
|
2024-05-17 14:17:48 -03:00
|
|
|
(safety, items, bounds)
|
2022-05-31 15:30:14 -03:00
|
|
|
},
|
2022-01-11 19:00:34 -08:00
|
|
|
);
|
2024-05-17 14:17:48 -03:00
|
|
|
hir::ItemKind::Trait(*is_auto, safety, generics, bounds, items)
|
2019-08-10 20:13:12 +02:00
|
|
|
}
|
2022-11-22 15:37:54 +00:00
|
|
|
ItemKind::TraitAlias(generics, bounds) => {
|
2022-05-31 15:32:05 -03:00
|
|
|
let (generics, bounds) = self.lower_generics(
|
2022-01-11 19:00:34 -08:00
|
|
|
generics,
|
2022-05-31 15:30:14 -03:00
|
|
|
id,
|
2024-02-07 19:27:44 +00:00
|
|
|
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
2022-05-31 15:30:14 -03:00
|
|
|
|this| {
|
|
|
|
|
this.lower_param_bounds(
|
|
|
|
|
bounds,
|
2024-02-07 19:27:44 +00:00
|
|
|
ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
|
2022-05-31 15:30:14 -03:00
|
|
|
)
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
hir::ItemKind::TraitAlias(generics, bounds)
|
|
|
|
|
}
|
2022-11-22 15:37:54 +00:00
|
|
|
ItemKind::MacroDef(MacroDef { body, macro_rules }) => {
|
2022-11-18 11:24:21 +11:00
|
|
|
let body = P(self.lower_delim_args(body));
|
2023-12-15 03:34:37 +00:00
|
|
|
let def_id = self.local_def_id(id);
|
|
|
|
|
let def_kind = self.tcx.def_kind(def_id);
|
|
|
|
|
let DefKind::Macro(macro_kind) = def_kind else {
|
|
|
|
|
unreachable!(
|
|
|
|
|
"expected DefKind::Macro for macro item, found {}",
|
|
|
|
|
def_kind.descr(def_id.to_def_id())
|
|
|
|
|
);
|
2023-11-21 23:40:23 +03:00
|
|
|
};
|
2023-03-25 21:09:11 +01:00
|
|
|
let macro_def = self.arena.alloc(ast::MacroDef { body, macro_rules: *macro_rules });
|
|
|
|
|
hir::ItemKind::Macro(macro_def, macro_kind)
|
2021-07-30 23:50:57 -07:00
|
|
|
}
|
2023-11-26 15:57:31 +03:00
|
|
|
ItemKind::Delegation(box delegation) => {
|
|
|
|
|
let delegation_results = self.lower_delegation(delegation, id);
|
|
|
|
|
hir::ItemKind::Fn(
|
|
|
|
|
delegation_results.sig,
|
|
|
|
|
delegation_results.generics,
|
|
|
|
|
delegation_results.body_id,
|
|
|
|
|
)
|
|
|
|
|
}
|
2024-03-15 14:21:03 +03:00
|
|
|
ItemKind::MacCall(..) | ItemKind::DelegationMac(..) => {
|
|
|
|
|
panic!("macros should have been expanded by now")
|
2019-12-22 17:42:04 -05:00
|
|
|
}
|
2019-08-10 20:13:12 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-14 14:21:02 +01:00
|
|
|
fn lower_const_item(
|
|
|
|
|
&mut self,
|
|
|
|
|
ty: &Ty,
|
|
|
|
|
span: Span,
|
|
|
|
|
body: Option<&Expr>,
|
2024-01-07 17:11:48 +00:00
|
|
|
impl_trait_position: ImplTraitPosition,
|
2020-02-14 14:21:02 +01:00
|
|
|
) -> (&'hir hir::Ty<'hir>, hir::BodyId) {
|
2024-02-07 19:27:44 +00:00
|
|
|
let ty = self.lower_ty(ty, ImplTraitContext::Disallowed(impl_trait_position));
|
2020-02-14 14:21:02 +01:00
|
|
|
(ty, self.lower_const_body(span, body))
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-20 15:52:56 -03:00
|
|
|
#[instrument(level = "debug", skip(self))]
|
2019-08-10 20:13:12 +02:00
|
|
|
fn lower_use_tree(
|
|
|
|
|
&mut self,
|
|
|
|
|
tree: &UseTree,
|
|
|
|
|
prefix: &Path,
|
|
|
|
|
id: NodeId,
|
2022-02-13 11:30:48 +01:00
|
|
|
vis_span: Span,
|
2019-08-10 20:13:12 +02:00
|
|
|
ident: &mut Ident,
|
2024-07-26 10:19:31 +00:00
|
|
|
attrs: &'hir [Attribute],
|
2019-11-28 19:28:50 +01:00
|
|
|
) -> hir::ItemKind<'hir> {
|
2019-08-10 20:13:12 +02:00
|
|
|
let path = &tree.prefix;
|
|
|
|
|
let segments = prefix.segments.iter().chain(path.segments.iter()).cloned().collect();
|
|
|
|
|
|
|
|
|
|
match tree.kind {
|
2022-12-01 18:51:20 +03:00
|
|
|
UseTreeKind::Simple(rename) => {
|
2019-08-10 20:13:12 +02:00
|
|
|
*ident = tree.ident();
|
|
|
|
|
|
|
|
|
|
// First, apply the prefix to the path.
|
2020-08-21 18:51:23 -04:00
|
|
|
let mut path = Path { segments, span: path.span, tokens: None };
|
2019-08-10 20:13:12 +02:00
|
|
|
|
|
|
|
|
// Correctly resolve `self` imports.
|
|
|
|
|
if path.segments.len() > 1
|
|
|
|
|
&& path.segments.last().unwrap().ident.name == kw::SelfLower
|
|
|
|
|
{
|
|
|
|
|
let _ = path.segments.pop();
|
|
|
|
|
if rename.is_none() {
|
|
|
|
|
*ident = path.segments.last().unwrap().ident;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-30 22:03:16 +03:00
|
|
|
let res = self.lower_import_res(id, path.span);
|
2022-12-01 18:51:20 +03:00
|
|
|
let path = self.lower_use_path(res, &path, ParamMode::Explicit);
|
2019-08-10 20:13:12 +02:00
|
|
|
hir::ItemKind::Use(path, hir::UseKind::Single)
|
|
|
|
|
}
|
|
|
|
|
UseTreeKind::Glob => {
|
2022-11-25 17:39:38 +03:00
|
|
|
let res = self.expect_full_res(id);
|
|
|
|
|
let res = smallvec![self.lower_res(res)];
|
|
|
|
|
let path = Path { segments, span: path.span, tokens: None };
|
|
|
|
|
let path = self.lower_use_path(res, &path, ParamMode::Explicit);
|
2019-08-10 20:13:12 +02:00
|
|
|
hir::ItemKind::Use(path, hir::UseKind::Glob)
|
|
|
|
|
}
|
2024-04-02 00:26:10 +02:00
|
|
|
UseTreeKind::Nested { items: ref trees, .. } => {
|
2019-08-10 20:13:12 +02:00
|
|
|
// Nested imports are desugared into simple imports.
|
|
|
|
|
// So, if we start with
|
|
|
|
|
//
|
|
|
|
|
// ```
|
|
|
|
|
// pub(x) use foo::{a, b};
|
|
|
|
|
// ```
|
|
|
|
|
//
|
|
|
|
|
// we will create three items:
|
|
|
|
|
//
|
|
|
|
|
// ```
|
|
|
|
|
// pub(x) use foo::a;
|
|
|
|
|
// pub(x) use foo::b;
|
|
|
|
|
// pub(x) use foo::{}; // <-- this is called the `ListStem`
|
|
|
|
|
// ```
|
|
|
|
|
//
|
|
|
|
|
// The first two are produced by recursively invoking
|
|
|
|
|
// `lower_use_tree` (and indeed there may be things
|
2022-11-16 20:34:16 +00:00
|
|
|
// like `use foo::{a::{b, c}}` and so forth). They
|
2019-08-10 20:13:12 +02:00
|
|
|
// wind up being directly added to
|
|
|
|
|
// `self.items`. However, the structure of this
|
|
|
|
|
// function also requires us to return one item, and
|
|
|
|
|
// for that we return the `{}` import (called the
|
|
|
|
|
// `ListStem`).
|
|
|
|
|
|
2024-01-30 22:03:16 +03:00
|
|
|
let span = prefix.span.to(path.span);
|
|
|
|
|
let prefix = Path { segments, span, tokens: None };
|
2019-08-10 20:13:12 +02:00
|
|
|
|
|
|
|
|
// Add all the nested `PathListItem`s to the HIR.
|
|
|
|
|
for &(ref use_tree, id) in trees {
|
2021-07-18 20:09:20 +02:00
|
|
|
let new_hir_id = self.local_def_id(id);
|
2019-08-10 20:13:12 +02:00
|
|
|
|
|
|
|
|
// Each `use` import is an item and thus are owners of the
|
|
|
|
|
// names in the path. Up to this point the nested import is
|
|
|
|
|
// the current owner, since we want each desugared import to
|
|
|
|
|
// own its own names, we have to adjust the owner before
|
|
|
|
|
// lowering the rest of the import.
|
|
|
|
|
self.with_hir_id_owner(id, |this| {
|
|
|
|
|
let mut ident = *ident;
|
|
|
|
|
|
2023-07-19 16:48:33 +08:00
|
|
|
// `prefix` is lowered multiple times, but in different HIR owners.
|
|
|
|
|
// So each segment gets renewed `HirId` with the same
|
|
|
|
|
// `ItemLocalId` and the new owner. (See `lower_node_id`)
|
2019-09-26 17:51:36 +01:00
|
|
|
let kind =
|
2022-02-13 11:30:48 +01:00
|
|
|
this.lower_use_tree(use_tree, &prefix, id, vis_span, &mut ident, attrs);
|
2024-07-26 10:19:31 +00:00
|
|
|
if !attrs.is_empty() {
|
2024-04-03 17:49:59 +03:00
|
|
|
this.attrs.insert(hir::ItemLocalId::ZERO, attrs);
|
2021-01-24 17:14:17 +01:00
|
|
|
}
|
2019-12-22 17:42:04 -05:00
|
|
|
|
2021-07-16 10:16:23 +02:00
|
|
|
let item = hir::Item {
|
2022-10-27 14:02:18 +11:00
|
|
|
owner_id: hir::OwnerId { def_id: new_hir_id },
|
2021-08-21 00:29:08 +03:00
|
|
|
ident: this.lower_ident(ident),
|
2019-09-26 17:51:36 +01:00
|
|
|
kind,
|
2022-02-13 11:30:48 +01:00
|
|
|
vis_span,
|
2021-08-21 00:29:08 +03:00
|
|
|
span: this.lower_span(use_tree.span),
|
2021-07-16 10:16:23 +02:00
|
|
|
};
|
|
|
|
|
hir::OwnerNode::Item(this.arena.alloc(item))
|
2019-08-10 20:13:12 +02:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-09 19:52:41 +03:00
|
|
|
// Condition should match `build_reduced_graph_for_use_tree`.
|
|
|
|
|
let path = if trees.is_empty()
|
|
|
|
|
&& !(prefix.segments.is_empty()
|
|
|
|
|
|| prefix.segments.len() == 1
|
|
|
|
|
&& prefix.segments[0].ident.name == kw::PathRoot)
|
|
|
|
|
{
|
2024-01-30 22:03:16 +03:00
|
|
|
// For empty lists we need to lower the prefix so it is checked for things
|
|
|
|
|
// like stability later.
|
|
|
|
|
let res = self.lower_import_res(id, span);
|
|
|
|
|
self.lower_use_path(res, &prefix, ParamMode::Explicit)
|
|
|
|
|
} else {
|
|
|
|
|
// For non-empty lists we can just drop all the data, the prefix is already
|
|
|
|
|
// present in HIR as a part of nested imports.
|
|
|
|
|
self.arena.alloc(hir::UsePath { res: smallvec![], segments: &[], span })
|
|
|
|
|
};
|
2019-08-10 20:13:12 +02:00
|
|
|
hir::ItemKind::Use(path, hir::UseKind::ListStem)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-28 12:07:05 +11:00
|
|
|
fn lower_assoc_item(
|
|
|
|
|
&mut self,
|
|
|
|
|
item: &AssocItem,
|
|
|
|
|
ctxt: AssocCtxt,
|
|
|
|
|
parent_hir: &'hir hir::OwnerInfo<'hir>,
|
|
|
|
|
) -> hir::OwnerNode<'hir> {
|
2024-06-14 12:16:15 +00:00
|
|
|
let parent_item = parent_hir.node().expect_item();
|
2024-10-20 20:22:11 +00:00
|
|
|
match parent_item.kind {
|
2023-11-28 12:07:05 +11:00
|
|
|
hir::ItemKind::Impl(impl_) => {
|
|
|
|
|
self.is_in_trait_impl = impl_.of_trait.is_some();
|
|
|
|
|
}
|
2024-10-20 20:22:11 +00:00
|
|
|
hir::ItemKind::Trait(_, _, _, _, _) => {}
|
2024-01-07 18:22:47 +01:00
|
|
|
kind => {
|
|
|
|
|
span_bug!(item.span, "assoc item has unexpected kind of parent: {}", kind.descr())
|
2023-11-28 12:07:05 +11:00
|
|
|
}
|
2024-10-20 20:22:11 +00:00
|
|
|
}
|
2024-01-07 18:22:47 +01:00
|
|
|
|
2024-10-20 20:22:11 +00:00
|
|
|
// Evaluate with the lifetimes in `params` in-scope.
|
|
|
|
|
// This is used to track which lifetimes have already been defined,
|
|
|
|
|
// and which need to be replicated when lowering an async fn.
|
2023-11-28 12:07:05 +11:00
|
|
|
match ctxt {
|
2024-10-20 20:22:11 +00:00
|
|
|
AssocCtxt::Trait => hir::OwnerNode::TraitItem(self.lower_trait_item(item)),
|
|
|
|
|
AssocCtxt::Impl => hir::OwnerNode::ImplItem(self.lower_impl_item(item)),
|
2023-11-28 12:07:05 +11:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-16 10:16:23 +02:00
|
|
|
fn lower_foreign_item(&mut self, i: &ForeignItem) -> &'hir hir::ForeignItem<'hir> {
|
2024-09-15 11:10:16 +08:00
|
|
|
let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id);
|
2022-10-27 14:02:18 +11:00
|
|
|
let owner_id = hir_id.expect_owner();
|
2020-11-27 00:35:22 +01:00
|
|
|
self.lower_attrs(hir_id, &i.attrs);
|
2021-07-16 10:16:23 +02:00
|
|
|
let item = hir::ForeignItem {
|
2022-10-27 14:02:18 +11:00
|
|
|
owner_id,
|
2021-08-21 00:29:08 +03:00
|
|
|
ident: self.lower_ident(i.ident),
|
2022-11-22 15:37:54 +00:00
|
|
|
kind: match &i.kind {
|
|
|
|
|
ForeignItemKind::Fn(box Fn { sig, generics, .. }) => {
|
2020-01-30 00:18:54 +01:00
|
|
|
let fdec = &sig.decl;
|
2022-12-25 16:42:35 +01:00
|
|
|
let itctx = ImplTraitContext::Universal;
|
2024-08-07 13:01:34 -04:00
|
|
|
let (generics, (decl, fn_args)) =
|
2024-10-20 20:22:11 +00:00
|
|
|
self.lower_generics(generics, i.id, itctx, |this| {
|
2019-08-10 20:13:12 +02:00
|
|
|
(
|
2019-09-06 03:57:44 +01:00
|
|
|
// Disallow `impl Trait` in foreign items.
|
2022-09-02 15:57:31 +00:00
|
|
|
this.lower_fn_decl(
|
|
|
|
|
fdec,
|
2022-11-06 09:33:52 +00:00
|
|
|
i.id,
|
2022-09-02 15:57:31 +00:00
|
|
|
sig.span,
|
|
|
|
|
FnDeclKind::ExternFn,
|
2023-11-30 16:39:56 -08:00
|
|
|
None,
|
2022-09-02 15:57:31 +00:00
|
|
|
),
|
2019-08-27 13:24:32 +02:00
|
|
|
this.lower_fn_params_to_names(fdec),
|
2019-08-10 20:13:12 +02:00
|
|
|
)
|
2022-04-07 20:54:13 +02:00
|
|
|
});
|
2019-08-10 20:13:12 +02:00
|
|
|
|
2024-08-07 13:01:34 -04:00
|
|
|
// Unmarked safety in unsafe block defaults to unsafe.
|
|
|
|
|
let header = self.lower_fn_header(sig.header, hir::Safety::Unsafe);
|
|
|
|
|
|
|
|
|
|
hir::ForeignItemKind::Fn(
|
|
|
|
|
hir::FnSig { header, decl, span: self.lower_span(sig.span) },
|
|
|
|
|
fn_args,
|
|
|
|
|
generics,
|
|
|
|
|
)
|
2019-08-10 20:13:12 +02:00
|
|
|
}
|
2024-06-20 19:50:57 -04:00
|
|
|
ForeignItemKind::Static(box StaticItem { ty, mutability, expr: _, safety }) => {
|
2024-04-29 11:27:14 -03:00
|
|
|
let ty = self
|
|
|
|
|
.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::StaticTy));
|
2024-05-23 10:01:05 -03:00
|
|
|
let safety = self.lower_safety(*safety, hir::Safety::Unsafe);
|
|
|
|
|
|
|
|
|
|
hir::ForeignItemKind::Static(ty, *mutability, safety)
|
2019-08-10 20:13:12 +02:00
|
|
|
}
|
2020-02-14 12:55:42 +01:00
|
|
|
ForeignItemKind::TyAlias(..) => hir::ForeignItemKind::Type,
|
2020-02-29 19:32:20 +03:00
|
|
|
ForeignItemKind::MacCall(_) => panic!("macro shouldn't exist here"),
|
2019-08-10 20:13:12 +02:00
|
|
|
},
|
2022-02-13 10:29:46 +01:00
|
|
|
vis_span: self.lower_span(i.vis.span),
|
2021-08-21 00:29:08 +03:00
|
|
|
span: self.lower_span(i.span),
|
2021-07-16 10:16:23 +02:00
|
|
|
};
|
|
|
|
|
self.arena.alloc(item)
|
2019-08-10 20:13:12 +02:00
|
|
|
}
|
|
|
|
|
|
2021-07-15 22:19:39 +02:00
|
|
|
fn lower_foreign_item_ref(&mut self, i: &ForeignItem) -> hir::ForeignItemRef {
|
2020-11-11 21:57:54 +01:00
|
|
|
hir::ForeignItemRef {
|
2022-10-27 14:02:18 +11:00
|
|
|
id: hir::ForeignItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } },
|
2021-08-21 00:29:08 +03:00
|
|
|
ident: self.lower_ident(i.ident),
|
|
|
|
|
span: self.lower_span(i.span),
|
2020-11-11 21:57:54 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-29 09:26:18 +01:00
|
|
|
fn lower_variant(&mut self, v: &Variant) -> hir::Variant<'hir> {
|
2022-11-06 19:46:55 +00:00
|
|
|
let hir_id = self.lower_node_id(v.id);
|
|
|
|
|
self.lower_attrs(hir_id, &v.attrs);
|
2019-08-13 21:40:21 -03:00
|
|
|
hir::Variant {
|
2022-11-06 19:46:55 +00:00
|
|
|
hir_id,
|
|
|
|
|
def_id: self.local_def_id(v.id),
|
|
|
|
|
data: self.lower_variant_data(hir_id, &v.data),
|
2024-07-16 11:29:31 -07:00
|
|
|
disr_expr: v.disr_expr.as_ref().map(|e| self.lower_anon_const_to_anon_const(e)),
|
2021-08-21 00:29:08 +03:00
|
|
|
ident: self.lower_ident(v.ident),
|
|
|
|
|
span: self.lower_span(v.span),
|
2019-08-10 20:13:12 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-24 18:12:42 +01:00
|
|
|
fn lower_variant_data(
|
|
|
|
|
&mut self,
|
|
|
|
|
parent_id: hir::HirId,
|
|
|
|
|
vdata: &VariantData,
|
|
|
|
|
) -> hir::VariantData<'hir> {
|
2022-11-22 15:37:54 +00:00
|
|
|
match vdata {
|
2023-12-19 22:47:30 +00:00
|
|
|
VariantData::Struct { fields, recovered } => hir::VariantData::Struct {
|
|
|
|
|
fields: self
|
|
|
|
|
.arena
|
2021-03-16 00:36:07 +03:00
|
|
|
.alloc_from_iter(fields.iter().enumerate().map(|f| self.lower_field_def(f))),
|
2023-12-19 22:47:30 +00:00
|
|
|
recovered: *recovered,
|
|
|
|
|
},
|
2022-11-22 15:37:54 +00:00
|
|
|
VariantData::Tuple(fields, id) => {
|
|
|
|
|
let ctor_id = self.lower_node_id(*id);
|
2021-01-24 17:14:17 +01:00
|
|
|
self.alias_attrs(ctor_id, parent_id);
|
2020-11-24 18:12:42 +01:00
|
|
|
hir::VariantData::Tuple(
|
|
|
|
|
self.arena.alloc_from_iter(
|
2021-03-16 00:36:07 +03:00
|
|
|
fields.iter().enumerate().map(|f| self.lower_field_def(f)),
|
2020-11-24 18:12:42 +01:00
|
|
|
),
|
|
|
|
|
ctor_id,
|
2022-11-22 15:37:54 +00:00
|
|
|
self.local_def_id(*id),
|
2020-11-24 18:12:42 +01:00
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
VariantData::Unit(id) => {
|
2022-11-22 15:37:54 +00:00
|
|
|
let ctor_id = self.lower_node_id(*id);
|
2021-01-24 17:14:17 +01:00
|
|
|
self.alias_attrs(ctor_id, parent_id);
|
2022-11-22 15:37:54 +00:00
|
|
|
hir::VariantData::Unit(ctor_id, self.local_def_id(*id))
|
2020-11-24 18:12:42 +01:00
|
|
|
}
|
2019-08-10 20:13:12 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-04 21:53:06 +08:00
|
|
|
pub(super) fn lower_field_def(
|
|
|
|
|
&mut self,
|
|
|
|
|
(index, f): (usize, &FieldDef),
|
|
|
|
|
) -> hir::FieldDef<'hir> {
|
2024-08-26 14:41:21 -04:00
|
|
|
let ty = self.lower_ty(&f.ty, ImplTraitContext::Disallowed(ImplTraitPosition::FieldTy));
|
2020-11-24 18:12:42 +01:00
|
|
|
let hir_id = self.lower_node_id(f.id);
|
2020-11-27 00:27:34 +01:00
|
|
|
self.lower_attrs(hir_id, &f.attrs);
|
2021-03-16 00:36:07 +03:00
|
|
|
hir::FieldDef {
|
2021-08-21 00:29:08 +03:00
|
|
|
span: self.lower_span(f.span),
|
2020-11-24 18:12:42 +01:00
|
|
|
hir_id,
|
2022-11-06 19:46:55 +00:00
|
|
|
def_id: self.local_def_id(f.id),
|
2019-08-10 20:13:12 +02:00
|
|
|
ident: match f.ident {
|
2021-08-21 00:29:08 +03:00
|
|
|
Some(ident) => self.lower_ident(ident),
|
2019-08-10 20:13:12 +02:00
|
|
|
// FIXME(jseyfried): positional field hygiene.
|
2021-08-21 00:29:08 +03:00
|
|
|
None => Ident::new(sym::integer(index), self.lower_span(f.span)),
|
2019-08-10 20:13:12 +02:00
|
|
|
},
|
2022-02-13 01:54:13 +01:00
|
|
|
vis_span: self.lower_span(f.vis.span),
|
2019-08-10 20:13:12 +02:00
|
|
|
ty,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-20 20:22:11 +00:00
|
|
|
fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> {
|
2024-09-15 11:10:16 +08:00
|
|
|
let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id);
|
2022-12-02 16:41:25 +00:00
|
|
|
self.lower_attrs(hir_id, &i.attrs);
|
2020-11-24 18:12:42 +01:00
|
|
|
let trait_item_def_id = hir_id.expect_owner();
|
2019-08-10 20:13:12 +02:00
|
|
|
|
2022-11-22 15:37:54 +00:00
|
|
|
let (generics, kind, has_default) = match &i.kind {
|
2023-05-04 16:40:57 +02:00
|
|
|
AssocItemKind::Const(box ConstItem { generics, ty, expr, .. }) => {
|
|
|
|
|
let (generics, kind) = self.lower_generics(
|
2023-11-21 20:07:32 +01:00
|
|
|
generics,
|
2023-05-04 16:40:57 +02:00
|
|
|
i.id,
|
2024-02-07 19:27:44 +00:00
|
|
|
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
2023-05-04 16:40:57 +02:00
|
|
|
|this| {
|
2024-02-07 19:27:44 +00:00
|
|
|
let ty = this
|
|
|
|
|
.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy));
|
2023-05-04 16:40:57 +02:00
|
|
|
let body = expr.as_ref().map(|x| this.lower_const_body(i.span, Some(x)));
|
|
|
|
|
|
|
|
|
|
hir::TraitItemKind::Const(ty, body)
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
(generics, kind, expr.is_some())
|
2019-12-01 12:49:54 +01:00
|
|
|
}
|
2022-11-22 15:37:54 +00:00
|
|
|
AssocItemKind::Fn(box Fn { sig, generics, body: None, .. }) => {
|
2019-08-27 13:24:32 +02:00
|
|
|
let names = self.lower_fn_params_to_names(&sig.decl);
|
2022-09-02 16:45:30 +00:00
|
|
|
let (generics, sig) = self.lower_method_sig(
|
|
|
|
|
generics,
|
|
|
|
|
sig,
|
|
|
|
|
i.id,
|
|
|
|
|
FnDeclKind::Trait,
|
2023-12-05 21:39:36 +00:00
|
|
|
sig.header.coroutine_kind,
|
2022-09-02 16:45:30 +00:00
|
|
|
);
|
2022-03-12 19:36:11 +01:00
|
|
|
(generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)), false)
|
2019-08-10 20:13:12 +02:00
|
|
|
}
|
2022-11-22 15:37:54 +00:00
|
|
|
AssocItemKind::Fn(box Fn { sig, generics, body: Some(body), .. }) => {
|
2023-11-29 12:07:43 -08:00
|
|
|
let body_id = self.lower_maybe_coroutine_body(
|
2024-06-27 14:56:57 -04:00
|
|
|
sig.span,
|
2023-11-29 12:07:43 -08:00
|
|
|
i.span,
|
|
|
|
|
hir_id,
|
|
|
|
|
&sig.decl,
|
2023-12-05 21:39:36 +00:00
|
|
|
sig.header.coroutine_kind,
|
2023-11-29 12:07:43 -08:00
|
|
|
Some(body),
|
|
|
|
|
);
|
2021-04-13 20:57:42 +02:00
|
|
|
let (generics, sig) = self.lower_method_sig(
|
|
|
|
|
generics,
|
|
|
|
|
sig,
|
2022-04-07 20:54:13 +02:00
|
|
|
i.id,
|
2022-01-11 19:00:34 -08:00
|
|
|
FnDeclKind::Trait,
|
2023-12-05 21:39:36 +00:00
|
|
|
sig.header.coroutine_kind,
|
2021-04-13 20:57:42 +02:00
|
|
|
);
|
2022-03-12 19:36:11 +01:00
|
|
|
(generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)), true)
|
2019-08-10 20:13:12 +02:00
|
|
|
}
|
2022-11-22 15:37:54 +00:00
|
|
|
AssocItemKind::Type(box TyAlias { generics, where_clauses, bounds, ty, .. }) => {
|
2021-10-19 18:45:48 -04:00
|
|
|
let mut generics = generics.clone();
|
2022-11-22 15:37:54 +00:00
|
|
|
add_ty_alias_where_clause(&mut generics, *where_clauses, false);
|
2022-03-12 19:36:11 +01:00
|
|
|
let (generics, kind) = self.lower_generics(
|
2021-10-19 18:45:48 -04:00
|
|
|
&generics,
|
2022-05-31 15:30:14 -03:00
|
|
|
i.id,
|
2024-02-07 19:27:44 +00:00
|
|
|
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
2022-05-31 15:30:14 -03:00
|
|
|
|this| {
|
|
|
|
|
let ty = ty.as_ref().map(|x| {
|
2023-02-14 22:15:32 +00:00
|
|
|
this.lower_ty(
|
|
|
|
|
x,
|
2024-02-07 19:27:44 +00:00
|
|
|
ImplTraitContext::Disallowed(ImplTraitPosition::AssocTy),
|
2023-02-14 22:15:32 +00:00
|
|
|
)
|
2022-05-31 15:30:14 -03:00
|
|
|
});
|
|
|
|
|
hir::TraitItemKind::Type(
|
|
|
|
|
this.lower_param_bounds(
|
|
|
|
|
bounds,
|
2024-02-07 19:27:44 +00:00
|
|
|
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
2022-05-31 15:30:14 -03:00
|
|
|
),
|
|
|
|
|
ty,
|
|
|
|
|
)
|
|
|
|
|
},
|
2022-03-12 19:36:11 +01:00
|
|
|
);
|
|
|
|
|
(generics, kind, ty.is_some())
|
2019-08-10 20:13:12 +02:00
|
|
|
}
|
2023-11-26 15:57:31 +03:00
|
|
|
AssocItemKind::Delegation(box delegation) => {
|
|
|
|
|
let delegation_results = self.lower_delegation(delegation, i.id);
|
|
|
|
|
let item_kind = hir::TraitItemKind::Fn(
|
|
|
|
|
delegation_results.sig,
|
|
|
|
|
hir::TraitFn::Provided(delegation_results.body_id),
|
|
|
|
|
);
|
|
|
|
|
(delegation_results.generics, item_kind, true)
|
|
|
|
|
}
|
2024-03-15 14:21:03 +03:00
|
|
|
AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => {
|
|
|
|
|
panic!("macros should have been expanded by now")
|
|
|
|
|
}
|
2019-08-10 20:13:12 +02:00
|
|
|
};
|
|
|
|
|
|
2021-07-16 10:16:23 +02:00
|
|
|
let item = hir::TraitItem {
|
2022-10-27 14:02:18 +11:00
|
|
|
owner_id: trait_item_def_id,
|
2021-08-21 00:29:08 +03:00
|
|
|
ident: self.lower_ident(i.ident),
|
|
|
|
|
generics,
|
|
|
|
|
kind,
|
|
|
|
|
span: self.lower_span(i.span),
|
2022-03-12 19:36:11 +01:00
|
|
|
defaultness: hir::Defaultness::Default { has_value: has_default },
|
2021-07-16 10:16:23 +02:00
|
|
|
};
|
|
|
|
|
self.arena.alloc(item)
|
2019-08-10 20:13:12 +02:00
|
|
|
}
|
|
|
|
|
|
2019-12-08 00:08:09 +01:00
|
|
|
fn lower_trait_item_ref(&mut self, i: &AssocItem) -> hir::TraitItemRef {
|
2022-03-12 19:36:11 +01:00
|
|
|
let kind = match &i.kind {
|
|
|
|
|
AssocItemKind::Const(..) => hir::AssocItemKind::Const,
|
2022-10-10 02:05:24 +00:00
|
|
|
AssocItemKind::Type(..) => hir::AssocItemKind::Type,
|
2022-03-12 19:36:11 +01:00
|
|
|
AssocItemKind::Fn(box Fn { sig, .. }) => {
|
|
|
|
|
hir::AssocItemKind::Fn { has_self: sig.decl.has_self() }
|
2019-08-10 20:13:12 +02:00
|
|
|
}
|
2023-11-26 15:57:31 +03:00
|
|
|
AssocItemKind::Delegation(box delegation) => hir::AssocItemKind::Fn {
|
|
|
|
|
has_self: self.delegation_has_self(i.id, delegation.id, i.span),
|
|
|
|
|
},
|
2024-03-15 14:21:03 +03:00
|
|
|
AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => {
|
|
|
|
|
panic!("macros should have been expanded by now")
|
|
|
|
|
}
|
2019-08-10 20:13:12 +02:00
|
|
|
};
|
2022-10-27 14:02:18 +11:00
|
|
|
let id = hir::TraitItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } };
|
2021-08-21 00:29:08 +03:00
|
|
|
hir::TraitItemRef {
|
|
|
|
|
id,
|
|
|
|
|
ident: self.lower_ident(i.ident),
|
|
|
|
|
span: self.lower_span(i.span),
|
|
|
|
|
kind,
|
|
|
|
|
}
|
2019-08-10 20:13:12 +02:00
|
|
|
}
|
|
|
|
|
|
2019-12-01 07:24:07 +01:00
|
|
|
/// Construct `ExprKind::Err` for the given `span`.
|
2023-02-22 22:40:06 +00:00
|
|
|
pub(crate) fn expr_err(&mut self, span: Span, guar: ErrorGuaranteed) -> hir::Expr<'hir> {
|
|
|
|
|
self.expr(span, hir::ExprKind::Err(guar))
|
2019-12-01 07:24:07 +01:00
|
|
|
}
|
|
|
|
|
|
2024-10-20 20:22:11 +00:00
|
|
|
fn lower_impl_item(&mut self, i: &AssocItem) -> &'hir hir::ImplItem<'hir> {
|
2022-03-12 19:36:11 +01:00
|
|
|
// Since `default impl` is not yet implemented, this is always true in impls.
|
|
|
|
|
let has_value = true;
|
|
|
|
|
let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value);
|
2024-09-15 11:10:16 +08:00
|
|
|
let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id);
|
2022-12-02 16:41:25 +00:00
|
|
|
self.lower_attrs(hir_id, &i.attrs);
|
2022-03-12 19:36:11 +01:00
|
|
|
|
2020-02-23 10:24:30 +01:00
|
|
|
let (generics, kind) = match &i.kind {
|
2023-05-04 16:40:57 +02:00
|
|
|
AssocItemKind::Const(box ConstItem { generics, ty, expr, .. }) => self.lower_generics(
|
2023-11-21 20:07:32 +01:00
|
|
|
generics,
|
2023-05-04 16:40:57 +02:00
|
|
|
i.id,
|
2024-02-07 19:27:44 +00:00
|
|
|
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
2023-05-04 16:40:57 +02:00
|
|
|
|this| {
|
2024-02-07 19:27:44 +00:00
|
|
|
let ty =
|
|
|
|
|
this.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy));
|
2023-05-04 16:40:57 +02:00
|
|
|
let body = this.lower_const_body(i.span, expr.as_deref());
|
|
|
|
|
|
|
|
|
|
hir::ImplItemKind::Const(ty, body)
|
|
|
|
|
},
|
|
|
|
|
),
|
2021-11-07 16:43:49 +08:00
|
|
|
AssocItemKind::Fn(box Fn { sig, generics, body, .. }) => {
|
2023-11-29 12:07:43 -08:00
|
|
|
let body_id = self.lower_maybe_coroutine_body(
|
2024-06-27 14:56:57 -04:00
|
|
|
sig.span,
|
2022-12-02 16:40:57 +00:00
|
|
|
i.span,
|
|
|
|
|
hir_id,
|
|
|
|
|
&sig.decl,
|
2023-12-05 21:39:36 +00:00
|
|
|
sig.header.coroutine_kind,
|
2022-12-02 16:40:57 +00:00
|
|
|
body.as_deref(),
|
|
|
|
|
);
|
2019-08-10 20:13:12 +02:00
|
|
|
let (generics, sig) = self.lower_method_sig(
|
2020-02-13 18:03:38 +01:00
|
|
|
generics,
|
2019-08-10 20:13:12 +02:00
|
|
|
sig,
|
2022-04-07 20:54:13 +02:00
|
|
|
i.id,
|
2022-01-11 19:00:34 -08:00
|
|
|
if self.is_in_trait_impl { FnDeclKind::Impl } else { FnDeclKind::Inherent },
|
2023-12-05 21:39:36 +00:00
|
|
|
sig.header.coroutine_kind,
|
2019-08-10 20:13:12 +02:00
|
|
|
);
|
|
|
|
|
|
2020-03-05 09:57:34 -06:00
|
|
|
(generics, hir::ImplItemKind::Fn(sig, body_id))
|
2019-08-10 20:13:12 +02:00
|
|
|
}
|
2022-10-10 02:05:24 +00:00
|
|
|
AssocItemKind::Type(box TyAlias { generics, where_clauses, ty, .. }) => {
|
2021-10-19 18:45:48 -04:00
|
|
|
let mut generics = generics.clone();
|
2022-02-07 12:20:09 -05:00
|
|
|
add_ty_alias_where_clause(&mut generics, *where_clauses, false);
|
2022-05-31 15:32:05 -03:00
|
|
|
self.lower_generics(
|
2021-10-19 18:45:48 -04:00
|
|
|
&generics,
|
2022-05-31 15:30:14 -03:00
|
|
|
i.id,
|
2024-02-07 19:27:44 +00:00
|
|
|
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
2022-05-31 15:30:14 -03:00
|
|
|
|this| match ty {
|
|
|
|
|
None => {
|
2023-12-18 22:21:37 +11:00
|
|
|
let guar = this.dcx().span_delayed_bug(
|
2023-02-22 21:19:42 +00:00
|
|
|
i.span,
|
|
|
|
|
"expected to lower associated type, but it was missing",
|
|
|
|
|
);
|
|
|
|
|
let ty = this.arena.alloc(this.ty(i.span, hir::TyKind::Err(guar)));
|
2022-10-09 07:09:57 +00:00
|
|
|
hir::ImplItemKind::Type(ty)
|
2022-05-31 15:30:14 -03:00
|
|
|
}
|
|
|
|
|
Some(ty) => {
|
2024-03-06 18:44:55 +00:00
|
|
|
let ty = this.lower_ty(ty, ImplTraitContext::OpaqueTy {
|
2024-03-06 17:52:53 +00:00
|
|
|
origin: hir::OpaqueTyOrigin::TyAlias {
|
|
|
|
|
parent: this.local_def_id(i.id),
|
|
|
|
|
in_assoc_ty: true,
|
|
|
|
|
},
|
2023-04-17 10:19:41 +00:00
|
|
|
});
|
2022-10-09 07:09:57 +00:00
|
|
|
hir::ImplItemKind::Type(ty)
|
2022-05-31 15:30:14 -03:00
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
)
|
2019-11-07 19:13:22 +01:00
|
|
|
}
|
2023-11-26 15:57:31 +03:00
|
|
|
AssocItemKind::Delegation(box delegation) => {
|
|
|
|
|
let delegation_results = self.lower_delegation(delegation, i.id);
|
|
|
|
|
(
|
|
|
|
|
delegation_results.generics,
|
|
|
|
|
hir::ImplItemKind::Fn(delegation_results.sig, delegation_results.body_id),
|
|
|
|
|
)
|
|
|
|
|
}
|
2024-03-15 14:21:03 +03:00
|
|
|
AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => {
|
|
|
|
|
panic!("macros should have been expanded by now")
|
|
|
|
|
}
|
2019-08-10 20:13:12 +02:00
|
|
|
};
|
|
|
|
|
|
2021-07-16 10:16:23 +02:00
|
|
|
let item = hir::ImplItem {
|
2022-10-27 14:02:18 +11:00
|
|
|
owner_id: hir_id.expect_owner(),
|
2021-08-21 00:29:08 +03:00
|
|
|
ident: self.lower_ident(i.ident),
|
2019-08-10 20:13:12 +02:00
|
|
|
generics,
|
2019-09-26 16:38:13 +01:00
|
|
|
kind,
|
2022-02-13 10:54:07 +01:00
|
|
|
vis_span: self.lower_span(i.vis.span),
|
2021-08-21 00:29:08 +03:00
|
|
|
span: self.lower_span(i.span),
|
2022-03-12 19:36:11 +01:00
|
|
|
defaultness,
|
2021-07-16 10:16:23 +02:00
|
|
|
};
|
|
|
|
|
self.arena.alloc(item)
|
2019-08-10 20:13:12 +02:00
|
|
|
}
|
|
|
|
|
|
2021-07-15 22:19:39 +02:00
|
|
|
fn lower_impl_item_ref(&mut self, i: &AssocItem) -> hir::ImplItemRef {
|
2019-08-10 20:13:12 +02:00
|
|
|
hir::ImplItemRef {
|
2022-10-27 14:02:18 +11:00
|
|
|
id: hir::ImplItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } },
|
2021-08-21 00:29:08 +03:00
|
|
|
ident: self.lower_ident(i.ident),
|
|
|
|
|
span: self.lower_span(i.span),
|
2019-11-07 19:13:22 +01:00
|
|
|
kind: match &i.kind {
|
2020-02-29 15:51:08 +03:00
|
|
|
AssocItemKind::Const(..) => hir::AssocItemKind::Const,
|
2022-10-10 02:05:24 +00:00
|
|
|
AssocItemKind::Type(..) => hir::AssocItemKind::Type,
|
2021-11-07 16:43:49 +08:00
|
|
|
AssocItemKind::Fn(box Fn { sig, .. }) => {
|
2020-04-01 10:09:50 +08:00
|
|
|
hir::AssocItemKind::Fn { has_self: sig.decl.has_self() }
|
2019-08-10 20:13:12 +02:00
|
|
|
}
|
2023-11-26 15:57:31 +03:00
|
|
|
AssocItemKind::Delegation(box delegation) => hir::AssocItemKind::Fn {
|
|
|
|
|
has_self: self.delegation_has_self(i.id, delegation.id, i.span),
|
|
|
|
|
},
|
2024-03-15 14:21:03 +03:00
|
|
|
AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => {
|
|
|
|
|
panic!("macros should have been expanded by now")
|
|
|
|
|
}
|
2019-08-10 20:13:12 +02:00
|
|
|
},
|
2024-03-16 21:03:36 +03:00
|
|
|
trait_item_def_id: self
|
|
|
|
|
.resolver
|
|
|
|
|
.get_partial_res(i.id)
|
|
|
|
|
.map(|r| r.expect_full_res().opt_def_id())
|
|
|
|
|
.unwrap_or(None),
|
2019-08-10 20:13:12 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-02 15:26:00 -08:00
|
|
|
fn lower_defaultness(
|
|
|
|
|
&self,
|
|
|
|
|
d: Defaultness,
|
|
|
|
|
has_value: bool,
|
|
|
|
|
) -> (hir::Defaultness, Option<Span>) {
|
2019-08-10 20:13:12 +02:00
|
|
|
match d {
|
2021-08-21 00:29:08 +03:00
|
|
|
Defaultness::Default(sp) => {
|
|
|
|
|
(hir::Defaultness::Default { has_value }, Some(self.lower_span(sp)))
|
|
|
|
|
}
|
2019-08-10 20:13:12 +02:00
|
|
|
Defaultness::Final => {
|
|
|
|
|
assert!(has_value);
|
2020-03-02 15:26:00 -08:00
|
|
|
(hir::Defaultness::Final, None)
|
2019-08-10 20:13:12 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-29 13:43:03 +01:00
|
|
|
fn record_body(
|
|
|
|
|
&mut self,
|
|
|
|
|
params: &'hir [hir::Param<'hir>],
|
|
|
|
|
value: hir::Expr<'hir>,
|
|
|
|
|
) -> hir::BodyId {
|
2023-12-22 21:29:12 +00:00
|
|
|
let body = hir::Body { params, value: self.arena.alloc(value) };
|
2019-08-10 20:13:12 +02:00
|
|
|
let id = body.id();
|
2021-07-16 14:42:26 +02:00
|
|
|
debug_assert_eq!(id.hir_id.owner, self.current_hir_id_owner);
|
2021-10-21 23:08:57 +02:00
|
|
|
self.bodies.push((id.hir_id.local_id, self.arena.alloc(body)));
|
2019-08-10 20:13:12 +02:00
|
|
|
id
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-04 14:53:47 +01:00
|
|
|
pub(super) fn lower_body(
|
2019-08-10 20:13:12 +02:00
|
|
|
&mut self,
|
2019-11-29 13:43:03 +01:00
|
|
|
f: impl FnOnce(&mut Self) -> (&'hir [hir::Param<'hir>], hir::Expr<'hir>),
|
2019-08-10 20:13:12 +02:00
|
|
|
) -> hir::BodyId {
|
2023-10-30 23:35:35 +00:00
|
|
|
let prev_coroutine_kind = self.coroutine_kind.take();
|
2020-04-01 00:41:40 +02:00
|
|
|
let task_context = self.task_context.take();
|
2019-08-27 13:24:32 +02:00
|
|
|
let (parameters, result) = f(self);
|
|
|
|
|
let body_id = self.record_body(parameters, result);
|
2020-04-01 00:41:40 +02:00
|
|
|
self.task_context = task_context;
|
2023-10-30 23:35:35 +00:00
|
|
|
self.coroutine_kind = prev_coroutine_kind;
|
2019-08-10 20:13:12 +02:00
|
|
|
body_id
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-29 13:43:03 +01:00
|
|
|
fn lower_param(&mut self, param: &Param) -> hir::Param<'hir> {
|
2020-11-24 18:12:42 +01:00
|
|
|
let hir_id = self.lower_node_id(param.id);
|
2020-11-26 23:51:27 +01:00
|
|
|
self.lower_attrs(hir_id, ¶m.attrs);
|
2019-08-27 13:24:32 +02:00
|
|
|
hir::Param {
|
2020-11-24 18:12:42 +01:00
|
|
|
hir_id,
|
2019-08-27 13:24:32 +02:00
|
|
|
pat: self.lower_pat(¶m.pat),
|
2021-08-21 00:29:08 +03:00
|
|
|
ty_span: self.lower_span(param.ty.span),
|
|
|
|
|
span: self.lower_span(param.span),
|
2019-08-10 20:23:34 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-10 20:13:12 +02:00
|
|
|
pub(super) fn lower_fn_body(
|
|
|
|
|
&mut self,
|
|
|
|
|
decl: &FnDecl,
|
2019-11-29 13:43:03 +01:00
|
|
|
body: impl FnOnce(&mut Self) -> hir::Expr<'hir>,
|
2019-08-10 20:13:12 +02:00
|
|
|
) -> hir::BodyId {
|
|
|
|
|
self.lower_body(|this| {
|
|
|
|
|
(
|
2019-11-29 11:09:23 +01:00
|
|
|
this.arena.alloc_from_iter(decl.inputs.iter().map(|x| this.lower_param(x))),
|
2019-08-10 20:13:12 +02:00
|
|
|
body(this),
|
|
|
|
|
)
|
2019-12-22 17:42:04 -05:00
|
|
|
})
|
2019-08-10 20:13:12 +02:00
|
|
|
}
|
|
|
|
|
|
2019-12-01 07:24:07 +01:00
|
|
|
fn lower_fn_body_block(
|
|
|
|
|
&mut self,
|
|
|
|
|
span: Span,
|
|
|
|
|
decl: &FnDecl,
|
|
|
|
|
body: Option<&Block>,
|
|
|
|
|
) -> hir::BodyId {
|
|
|
|
|
self.lower_fn_body(decl, |this| this.lower_block_expr_opt(span, body))
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-29 13:43:03 +01:00
|
|
|
fn lower_block_expr_opt(&mut self, span: Span, block: Option<&Block>) -> hir::Expr<'hir> {
|
2019-12-01 07:24:07 +01:00
|
|
|
match block {
|
|
|
|
|
Some(block) => self.lower_block_expr(block),
|
2024-02-14 15:17:15 +11:00
|
|
|
None => self.expr_err(span, self.dcx().has_errors().unwrap()),
|
2019-12-01 07:24:07 +01:00
|
|
|
}
|
2019-08-10 20:13:12 +02:00
|
|
|
}
|
|
|
|
|
|
2019-12-01 07:24:07 +01:00
|
|
|
pub(super) fn lower_const_body(&mut self, span: Span, expr: Option<&Expr>) -> hir::BodyId {
|
2019-11-29 11:09:23 +01:00
|
|
|
self.lower_body(|this| {
|
|
|
|
|
(&[], match expr {
|
2019-12-01 21:10:43 +01:00
|
|
|
Some(expr) => this.lower_expr_mut(expr),
|
2023-12-18 22:21:37 +11:00
|
|
|
None => this.expr_err(span, this.dcx().span_delayed_bug(span, "no block")),
|
2019-12-22 17:42:04 -05:00
|
|
|
})
|
2019-12-01 07:24:07 +01:00
|
|
|
})
|
2019-08-10 20:13:12 +02:00
|
|
|
}
|
|
|
|
|
|
2023-11-29 12:07:43 -08:00
|
|
|
/// Takes what may be the body of an `async fn` or a `gen fn` and wraps it in an `async {}` or
|
|
|
|
|
/// `gen {}` block as appropriate.
|
|
|
|
|
fn lower_maybe_coroutine_body(
|
2019-08-10 20:13:12 +02:00
|
|
|
&mut self,
|
2024-06-27 14:56:57 -04:00
|
|
|
fn_decl_span: Span,
|
2019-12-01 07:24:07 +01:00
|
|
|
span: Span,
|
2022-12-02 16:40:57 +00:00
|
|
|
fn_id: hir::HirId,
|
2019-08-10 20:13:12 +02:00
|
|
|
decl: &FnDecl,
|
2023-12-05 21:39:36 +00:00
|
|
|
coroutine_kind: Option<CoroutineKind>,
|
2019-12-01 07:24:07 +01:00
|
|
|
body: Option<&Block>,
|
2019-08-10 20:13:12 +02:00
|
|
|
) -> hir::BodyId {
|
2023-12-05 21:39:36 +00:00
|
|
|
let (Some(coroutine_kind), Some(body)) = (coroutine_kind, body) else {
|
2023-11-30 16:39:56 -08:00
|
|
|
return self.lower_fn_body_block(span, decl, body);
|
|
|
|
|
};
|
2019-08-10 20:13:12 +02:00
|
|
|
self.lower_body(|this| {
|
2024-01-14 22:14:48 +00:00
|
|
|
let (parameters, expr) = this.lower_coroutine_body_with_moved_arguments(
|
|
|
|
|
decl,
|
2024-01-14 23:12:46 +00:00
|
|
|
|this| this.lower_block_expr(body),
|
2024-06-27 14:56:57 -04:00
|
|
|
fn_decl_span,
|
2024-01-14 23:12:46 +00:00
|
|
|
body.span,
|
2024-01-14 22:14:48 +00:00
|
|
|
coroutine_kind,
|
2024-01-14 23:12:46 +00:00
|
|
|
hir::CoroutineSource::Fn,
|
2024-01-14 22:14:48 +00:00
|
|
|
);
|
2019-08-10 20:13:12 +02:00
|
|
|
|
2024-01-14 22:14:48 +00:00
|
|
|
// FIXME(async_fn_track_caller): Can this be moved above?
|
2024-09-12 11:32:39 +08:00
|
|
|
let hir_id = expr.hir_id;
|
2024-01-14 22:14:48 +00:00
|
|
|
this.maybe_forward_track_caller(body.span, fn_id, hir_id);
|
2019-08-10 20:13:12 +02:00
|
|
|
|
2024-01-14 22:14:48 +00:00
|
|
|
(parameters, expr)
|
|
|
|
|
})
|
|
|
|
|
}
|
2019-08-10 20:13:12 +02:00
|
|
|
|
2024-01-14 22:14:48 +00:00
|
|
|
/// Lowers a desugared coroutine body after moving all of the arguments
|
|
|
|
|
/// into the body. This is to make sure that the future actually owns the
|
|
|
|
|
/// arguments that are passed to the function, and to ensure things like
|
|
|
|
|
/// drop order are stable.
|
2024-06-11 10:46:06 +10:00
|
|
|
pub(crate) fn lower_coroutine_body_with_moved_arguments(
|
2024-01-14 22:14:48 +00:00
|
|
|
&mut self,
|
|
|
|
|
decl: &FnDecl,
|
2024-01-14 23:12:46 +00:00
|
|
|
lower_body: impl FnOnce(&mut LoweringContext<'_, 'hir>) -> hir::Expr<'hir>,
|
2024-06-27 14:56:57 -04:00
|
|
|
fn_decl_span: Span,
|
2024-01-14 23:12:46 +00:00
|
|
|
body_span: Span,
|
2024-01-14 22:14:48 +00:00
|
|
|
coroutine_kind: CoroutineKind,
|
2024-01-14 23:12:46 +00:00
|
|
|
coroutine_source: hir::CoroutineSource,
|
2024-01-14 22:14:48 +00:00
|
|
|
) -> (&'hir [hir::Param<'hir>], hir::Expr<'hir>) {
|
|
|
|
|
let mut parameters: Vec<hir::Param<'_>> = Vec::new();
|
|
|
|
|
let mut statements: Vec<hir::Stmt<'_>> = Vec::new();
|
|
|
|
|
|
|
|
|
|
// Async function parameters are lowered into the closure body so that they are
|
|
|
|
|
// captured and so that the drop order matches the equivalent non-async functions.
|
|
|
|
|
//
|
|
|
|
|
// from:
|
|
|
|
|
//
|
|
|
|
|
// async fn foo(<pattern>: <ty>, <pattern>: <ty>, <pattern>: <ty>) {
|
|
|
|
|
// <body>
|
|
|
|
|
// }
|
|
|
|
|
//
|
|
|
|
|
// into:
|
|
|
|
|
//
|
|
|
|
|
// fn foo(__arg0: <ty>, __arg1: <ty>, __arg2: <ty>) {
|
|
|
|
|
// async move {
|
|
|
|
|
// let __arg2 = __arg2;
|
|
|
|
|
// let <pattern> = __arg2;
|
|
|
|
|
// let __arg1 = __arg1;
|
|
|
|
|
// let <pattern> = __arg1;
|
|
|
|
|
// let __arg0 = __arg0;
|
|
|
|
|
// let <pattern> = __arg0;
|
|
|
|
|
// drop-temps { <body> } // see comments later in fn for details
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
//
|
|
|
|
|
// If `<pattern>` is a simple ident, then it is lowered to a single
|
|
|
|
|
// `let <pattern> = <pattern>;` statement as an optimization.
|
|
|
|
|
//
|
|
|
|
|
// Note that the body is embedded in `drop-temps`; an
|
|
|
|
|
// equivalent desugaring would be `return { <body>
|
|
|
|
|
// };`. The key point is that we wish to drop all the
|
|
|
|
|
// let-bound variables and temporaries created in the body
|
|
|
|
|
// (and its tail expression!) before we drop the
|
|
|
|
|
// parameters (c.f. rust-lang/rust#64512).
|
|
|
|
|
for (index, parameter) in decl.inputs.iter().enumerate() {
|
|
|
|
|
let parameter = self.lower_param(parameter);
|
|
|
|
|
let span = parameter.pat.span;
|
|
|
|
|
|
|
|
|
|
// Check if this is a binding pattern, if so, we can optimize and avoid adding a
|
|
|
|
|
// `let <pat> = __argN;` statement. In this case, we do not rename the parameter.
|
|
|
|
|
let (ident, is_simple_parameter) = match parameter.pat.kind {
|
2024-04-16 19:23:30 -04:00
|
|
|
hir::PatKind::Binding(hir::BindingMode(ByRef::No, _), _, ident, _) => (ident, true),
|
2024-01-14 22:14:48 +00:00
|
|
|
// For `ref mut` or wildcard arguments, we can't reuse the binding, but
|
|
|
|
|
// we can keep the same name for the parameter.
|
|
|
|
|
// This lets rustdoc render it correctly in documentation.
|
|
|
|
|
hir::PatKind::Binding(_, _, ident, _) => (ident, false),
|
|
|
|
|
hir::PatKind::Wild => {
|
|
|
|
|
(Ident::with_dummy_span(rustc_span::symbol::kw::Underscore), false)
|
|
|
|
|
}
|
|
|
|
|
_ => {
|
|
|
|
|
// Replace the ident for bindings that aren't simple.
|
|
|
|
|
let name = format!("__arg{index}");
|
|
|
|
|
let ident = Ident::from_str(&name);
|
2019-08-10 20:13:12 +02:00
|
|
|
|
2024-01-14 22:14:48 +00:00
|
|
|
(ident, false)
|
|
|
|
|
}
|
|
|
|
|
};
|
2019-08-10 20:13:12 +02:00
|
|
|
|
2024-01-14 22:14:48 +00:00
|
|
|
let desugared_span = self.mark_span_with_reason(DesugaringKind::Async, span, None);
|
2019-09-16 16:15:20 -04:00
|
|
|
|
2024-01-14 22:14:48 +00:00
|
|
|
// Construct a parameter representing `__argN: <ty>` to replace the parameter of the
|
|
|
|
|
// async function.
|
|
|
|
|
//
|
|
|
|
|
// If this is the simple case, this parameter will end up being the same as the
|
|
|
|
|
// original parameter, but with a different pattern id.
|
|
|
|
|
let stmt_attrs = self.attrs.get(¶meter.hir_id.local_id).copied();
|
|
|
|
|
let (new_parameter_pat, new_parameter_id) = self.pat_ident(desugared_span, ident);
|
|
|
|
|
let new_parameter = hir::Param {
|
|
|
|
|
hir_id: parameter.hir_id,
|
|
|
|
|
pat: new_parameter_pat,
|
|
|
|
|
ty_span: self.lower_span(parameter.ty_span),
|
|
|
|
|
span: self.lower_span(parameter.span),
|
|
|
|
|
};
|
2019-09-16 16:15:20 -04:00
|
|
|
|
2024-01-14 22:14:48 +00:00
|
|
|
if is_simple_parameter {
|
|
|
|
|
// If this is the simple case, then we only insert one statement that is
|
|
|
|
|
// `let <pat> = <pat>;`. We re-use the original argument's pattern so that
|
|
|
|
|
// `HirId`s are densely assigned.
|
|
|
|
|
let expr = self.expr_ident(desugared_span, ident, new_parameter_id);
|
|
|
|
|
let stmt = self.stmt_let_pat(
|
|
|
|
|
stmt_attrs,
|
|
|
|
|
desugared_span,
|
|
|
|
|
Some(expr),
|
|
|
|
|
parameter.pat,
|
|
|
|
|
hir::LocalSource::AsyncFn,
|
|
|
|
|
);
|
|
|
|
|
statements.push(stmt);
|
|
|
|
|
} else {
|
|
|
|
|
// If this is not the simple case, then we construct two statements:
|
2023-11-29 12:07:43 -08:00
|
|
|
//
|
|
|
|
|
// ```
|
2024-01-14 22:14:48 +00:00
|
|
|
// let __argN = __argN;
|
|
|
|
|
// let <pat> = __argN;
|
2023-11-29 12:07:43 -08:00
|
|
|
// ```
|
2024-01-14 22:14:48 +00:00
|
|
|
//
|
|
|
|
|
// The first statement moves the parameter into the closure and thus ensures
|
|
|
|
|
// that the drop order is correct.
|
|
|
|
|
//
|
|
|
|
|
// The second statement creates the bindings that the user wrote.
|
|
|
|
|
|
|
|
|
|
// Construct the `let mut __argN = __argN;` statement. It must be a mut binding
|
|
|
|
|
// because the user may have specified a `ref mut` binding in the next
|
|
|
|
|
// statement.
|
|
|
|
|
let (move_pat, move_id) =
|
2024-04-16 19:23:30 -04:00
|
|
|
self.pat_ident_binding_mode(desugared_span, ident, hir::BindingMode::MUT);
|
2024-01-14 22:14:48 +00:00
|
|
|
let move_expr = self.expr_ident(desugared_span, ident, new_parameter_id);
|
|
|
|
|
let move_stmt = self.stmt_let_pat(
|
|
|
|
|
None,
|
2023-11-29 12:07:43 -08:00
|
|
|
desugared_span,
|
2024-01-14 22:14:48 +00:00
|
|
|
Some(move_expr),
|
|
|
|
|
move_pat,
|
|
|
|
|
hir::LocalSource::AsyncFn,
|
2023-11-29 12:07:43 -08:00
|
|
|
);
|
2019-11-29 19:01:31 +01:00
|
|
|
|
2024-01-14 22:14:48 +00:00
|
|
|
// Construct the `let <pat> = __argN;` statement. We re-use the original
|
|
|
|
|
// parameter's pattern so that `HirId`s are densely assigned.
|
|
|
|
|
let pattern_expr = self.expr_ident(desugared_span, ident, move_id);
|
|
|
|
|
let pattern_stmt = self.stmt_let_pat(
|
|
|
|
|
stmt_attrs,
|
|
|
|
|
desugared_span,
|
|
|
|
|
Some(pattern_expr),
|
|
|
|
|
parameter.pat,
|
|
|
|
|
hir::LocalSource::AsyncFn,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
statements.push(move_stmt);
|
|
|
|
|
statements.push(pattern_stmt);
|
2023-11-29 12:07:43 -08:00
|
|
|
};
|
2024-01-14 22:14:48 +00:00
|
|
|
|
|
|
|
|
parameters.push(new_parameter);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let mkbody = |this: &mut LoweringContext<'_, 'hir>| {
|
|
|
|
|
// Create a block from the user's function body:
|
2024-01-14 23:12:46 +00:00
|
|
|
let user_body = lower_body(this);
|
2024-01-14 22:14:48 +00:00
|
|
|
|
|
|
|
|
// Transform into `drop-temps { <user-body> }`, an expression:
|
|
|
|
|
let desugared_span =
|
|
|
|
|
this.mark_span_with_reason(DesugaringKind::Async, user_body.span, None);
|
|
|
|
|
let user_body = this.expr_drop_temps(desugared_span, this.arena.alloc(user_body));
|
|
|
|
|
|
|
|
|
|
// As noted above, create the final block like
|
|
|
|
|
//
|
|
|
|
|
// ```
|
|
|
|
|
// {
|
|
|
|
|
// let $param_pattern = $raw_param;
|
|
|
|
|
// ...
|
|
|
|
|
// drop-temps { <user-body> }
|
|
|
|
|
// }
|
|
|
|
|
// ```
|
|
|
|
|
let body = this.block_all(
|
|
|
|
|
desugared_span,
|
|
|
|
|
this.arena.alloc_from_iter(statements),
|
|
|
|
|
Some(user_body),
|
2023-12-28 13:57:43 +01:00
|
|
|
);
|
2019-11-29 11:09:23 +01:00
|
|
|
|
2024-01-14 22:14:48 +00:00
|
|
|
this.expr_block(body)
|
|
|
|
|
};
|
|
|
|
|
let desugaring_kind = match coroutine_kind {
|
|
|
|
|
CoroutineKind::Async { .. } => hir::CoroutineDesugaring::Async,
|
|
|
|
|
CoroutineKind::Gen { .. } => hir::CoroutineDesugaring::Gen,
|
|
|
|
|
CoroutineKind::AsyncGen { .. } => hir::CoroutineDesugaring::AsyncGen,
|
|
|
|
|
};
|
|
|
|
|
let closure_id = coroutine_kind.closure_id();
|
2024-05-13 22:42:18 +08:00
|
|
|
|
2024-01-14 22:14:48 +00:00
|
|
|
let coroutine_expr = self.make_desugared_coroutine_expr(
|
2024-01-24 17:18:08 +00:00
|
|
|
// The default capture mode here is by-ref. Later on during upvar analysis,
|
|
|
|
|
// we will force the captured arguments to by-move, but for async closures,
|
|
|
|
|
// we want to make sure that we avoid unnecessarily moving captures, or else
|
|
|
|
|
// all async closures would default to `FnOnce` as their calling mode.
|
|
|
|
|
CaptureBy::Ref,
|
2024-01-14 22:14:48 +00:00
|
|
|
closure_id,
|
2024-01-24 17:30:02 +00:00
|
|
|
None,
|
2024-06-27 14:56:57 -04:00
|
|
|
fn_decl_span,
|
|
|
|
|
body_span,
|
2024-01-14 22:14:48 +00:00
|
|
|
desugaring_kind,
|
2024-01-14 23:12:46 +00:00
|
|
|
coroutine_source,
|
2024-01-14 22:14:48 +00:00
|
|
|
mkbody,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
let expr = hir::Expr {
|
|
|
|
|
hir_id: self.lower_node_id(closure_id),
|
|
|
|
|
kind: coroutine_expr,
|
2024-01-14 23:12:46 +00:00
|
|
|
span: self.lower_span(body_span),
|
2024-01-14 22:14:48 +00:00
|
|
|
};
|
2023-01-31 22:13:25 +01:00
|
|
|
|
2024-01-14 22:14:48 +00:00
|
|
|
(self.arena.alloc_from_iter(parameters), expr)
|
2019-08-10 20:13:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn lower_method_sig(
|
|
|
|
|
&mut self,
|
|
|
|
|
generics: &Generics,
|
2019-11-07 13:11:59 +01:00
|
|
|
sig: &FnSig,
|
2022-04-07 20:54:13 +02:00
|
|
|
id: NodeId,
|
2022-01-11 19:00:34 -08:00
|
|
|
kind: FnDeclKind,
|
2023-12-05 21:39:36 +00:00
|
|
|
coroutine_kind: Option<CoroutineKind>,
|
2022-02-05 15:26:49 +01:00
|
|
|
) -> (&'hir hir::Generics<'hir>, hir::FnSig<'hir>) {
|
2024-08-07 13:01:34 -04:00
|
|
|
let header = self.lower_fn_header(sig.header, hir::Safety::Safe);
|
2022-12-25 16:42:35 +01:00
|
|
|
let itctx = ImplTraitContext::Universal;
|
2024-10-20 20:22:11 +00:00
|
|
|
let (generics, decl) = self.lower_generics(generics, id, itctx, |this| {
|
|
|
|
|
this.lower_fn_decl(&sig.decl, id, sig.span, kind, coroutine_kind)
|
|
|
|
|
});
|
2021-08-21 00:29:08 +03:00
|
|
|
(generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) })
|
2019-08-10 20:13:12 +02:00
|
|
|
}
|
|
|
|
|
|
2024-08-07 13:01:34 -04:00
|
|
|
pub(super) fn lower_fn_header(
|
|
|
|
|
&mut self,
|
|
|
|
|
h: FnHeader,
|
|
|
|
|
default_safety: hir::Safety,
|
|
|
|
|
) -> hir::FnHeader {
|
2023-12-05 21:39:36 +00:00
|
|
|
let asyncness = if let Some(CoroutineKind::Async { span, .. }) = h.coroutine_kind {
|
2023-11-30 14:54:39 -08:00
|
|
|
hir::IsAsync::Async(span)
|
|
|
|
|
} else {
|
|
|
|
|
hir::IsAsync::NotAsync
|
|
|
|
|
};
|
2019-08-10 20:13:12 +02:00
|
|
|
hir::FnHeader {
|
2024-08-07 13:01:34 -04:00
|
|
|
safety: self.lower_safety(h.safety, default_safety),
|
2024-08-21 01:29:52 -04:00
|
|
|
asyncness,
|
2020-01-30 02:42:33 +01:00
|
|
|
constness: self.lower_constness(h.constness),
|
2021-07-08 21:58:05 +02:00
|
|
|
abi: self.lower_extern(h.ext),
|
2019-08-10 20:13:12 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-10 00:44:59 +03:00
|
|
|
pub(super) fn lower_abi(&mut self, abi: StrLit) -> abi::Abi {
|
feat: `riscv-interrupt-{m,s}` calling conventions
Similar to prior support added for the mips430, avr, and x86 targets
this change implements the rough equivalent of clang's
[`__attribute__((interrupt))`][clang-attr] for riscv targets, enabling
e.g.
```rust
static mut CNT: usize = 0;
pub extern "riscv-interrupt-m" fn isr_m() {
unsafe {
CNT += 1;
}
}
```
to produce highly effective assembly like:
```asm
pub extern "riscv-interrupt-m" fn isr_m() {
420003a0: 1141 addi sp,sp,-16
unsafe {
CNT += 1;
420003a2: c62a sw a0,12(sp)
420003a4: c42e sw a1,8(sp)
420003a6: 3fc80537 lui a0,0x3fc80
420003aa: 63c52583 lw a1,1596(a0) # 3fc8063c <_ZN12esp_riscv_rt3CNT17hcec3e3a214887d53E.0>
420003ae: 0585 addi a1,a1,1
420003b0: 62b52e23 sw a1,1596(a0)
}
}
420003b4: 4532 lw a0,12(sp)
420003b6: 45a2 lw a1,8(sp)
420003b8: 0141 addi sp,sp,16
420003ba: 30200073 mret
```
(disassembly via `riscv64-unknown-elf-objdump -C -S --disassemble ./esp32c3-hal/target/riscv32imc-unknown-none-elf/release/examples/gpio_interrupt`)
This outcome is superior to hand-coded interrupt routines which, lacking
visibility into any non-assembly body of the interrupt handler, have to
be very conservative and save the [entire CPU state to the stack
frame][full-frame-save]. By instead asking LLVM to only save the
registers that it uses, we defer the decision to the tool with the best
context: it can more accurately account for the cost of spills if it
knows that every additional register used is already at the cost of an
implicit spill.
At the LLVM level, this is apparently [implemented by] marking every
register as "[callee-save]," matching the semantics of an interrupt
handler nicely (it has to leave the CPU state just as it found it after
its `{m|s}ret`).
This approach is not suitable for every interrupt handler, as it makes
no attempt to e.g. save the state in a user-accessible stack frame. For
a full discussion of those challenges and tradeoffs, please refer to
[the interrupt calling conventions RFC][rfc].
Inside rustc, this implementation differs from prior art because LLVM
does not expose the "all-saved" function flavor as a calling convention
directly, instead preferring to use an attribute that allows for
differentiating between "machine-mode" and "superivsor-mode" interrupts.
Finally, some effort has been made to guide those who may not yet be
aware of the differences between machine-mode and supervisor-mode
interrupts as to why no `riscv-interrupt` calling convention is exposed
through rustc, and similarly for why `riscv-interrupt-u` makes no
appearance (as it would complicate future LLVM upgrades).
[clang-attr]: https://clang.llvm.org/docs/AttributeReference.html#interrupt-risc-v
[full-frame-save]: https://github.com/esp-rs/esp-riscv-rt/blob/9281af2ecffe13e40992917316f36920c26acaf3/src/lib.rs#L440-L469
[implemented by]: https://github.com/llvm/llvm-project/blob/b7fb2a3fec7c187d58a6d338ab512d9173bca987/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp#L61-L67
[callee-save]: https://github.com/llvm/llvm-project/blob/973f1fe7a8591c7af148e573491ab68cc15b6ecf/llvm/lib/Target/RISCV/RISCVCallingConv.td#L30-L37
[rfc]: https://github.com/rust-lang/rfcs/pull/3246
2023-05-23 15:08:23 -07:00
|
|
|
abi::lookup(abi.symbol_unescaped.as_str()).unwrap_or_else(|err| {
|
|
|
|
|
self.error_on_invalid_abi(abi, err);
|
2019-10-27 23:14:35 +01:00
|
|
|
abi::Abi::Rust
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-08 21:58:05 +02:00
|
|
|
pub(super) fn lower_extern(&mut self, ext: Extern) -> abi::Abi {
|
2019-11-09 22:05:20 +03:00
|
|
|
match ext {
|
|
|
|
|
Extern::None => abi::Abi::Rust,
|
2022-07-02 18:25:55 +01:00
|
|
|
Extern::Implicit(_) => abi::Abi::FALLBACK,
|
|
|
|
|
Extern::Explicit(abi, _) => self.lower_abi(abi),
|
2019-11-09 22:05:20 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
feat: `riscv-interrupt-{m,s}` calling conventions
Similar to prior support added for the mips430, avr, and x86 targets
this change implements the rough equivalent of clang's
[`__attribute__((interrupt))`][clang-attr] for riscv targets, enabling
e.g.
```rust
static mut CNT: usize = 0;
pub extern "riscv-interrupt-m" fn isr_m() {
unsafe {
CNT += 1;
}
}
```
to produce highly effective assembly like:
```asm
pub extern "riscv-interrupt-m" fn isr_m() {
420003a0: 1141 addi sp,sp,-16
unsafe {
CNT += 1;
420003a2: c62a sw a0,12(sp)
420003a4: c42e sw a1,8(sp)
420003a6: 3fc80537 lui a0,0x3fc80
420003aa: 63c52583 lw a1,1596(a0) # 3fc8063c <_ZN12esp_riscv_rt3CNT17hcec3e3a214887d53E.0>
420003ae: 0585 addi a1,a1,1
420003b0: 62b52e23 sw a1,1596(a0)
}
}
420003b4: 4532 lw a0,12(sp)
420003b6: 45a2 lw a1,8(sp)
420003b8: 0141 addi sp,sp,16
420003ba: 30200073 mret
```
(disassembly via `riscv64-unknown-elf-objdump -C -S --disassemble ./esp32c3-hal/target/riscv32imc-unknown-none-elf/release/examples/gpio_interrupt`)
This outcome is superior to hand-coded interrupt routines which, lacking
visibility into any non-assembly body of the interrupt handler, have to
be very conservative and save the [entire CPU state to the stack
frame][full-frame-save]. By instead asking LLVM to only save the
registers that it uses, we defer the decision to the tool with the best
context: it can more accurately account for the cost of spills if it
knows that every additional register used is already at the cost of an
implicit spill.
At the LLVM level, this is apparently [implemented by] marking every
register as "[callee-save]," matching the semantics of an interrupt
handler nicely (it has to leave the CPU state just as it found it after
its `{m|s}ret`).
This approach is not suitable for every interrupt handler, as it makes
no attempt to e.g. save the state in a user-accessible stack frame. For
a full discussion of those challenges and tradeoffs, please refer to
[the interrupt calling conventions RFC][rfc].
Inside rustc, this implementation differs from prior art because LLVM
does not expose the "all-saved" function flavor as a calling convention
directly, instead preferring to use an attribute that allows for
differentiating between "machine-mode" and "superivsor-mode" interrupts.
Finally, some effort has been made to guide those who may not yet be
aware of the differences between machine-mode and supervisor-mode
interrupts as to why no `riscv-interrupt` calling convention is exposed
through rustc, and similarly for why `riscv-interrupt-u` makes no
appearance (as it would complicate future LLVM upgrades).
[clang-attr]: https://clang.llvm.org/docs/AttributeReference.html#interrupt-risc-v
[full-frame-save]: https://github.com/esp-rs/esp-riscv-rt/blob/9281af2ecffe13e40992917316f36920c26acaf3/src/lib.rs#L440-L469
[implemented by]: https://github.com/llvm/llvm-project/blob/b7fb2a3fec7c187d58a6d338ab512d9173bca987/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp#L61-L67
[callee-save]: https://github.com/llvm/llvm-project/blob/973f1fe7a8591c7af148e573491ab68cc15b6ecf/llvm/lib/Target/RISCV/RISCVCallingConv.td#L30-L37
[rfc]: https://github.com/rust-lang/rfcs/pull/3246
2023-05-23 15:08:23 -07:00
|
|
|
fn error_on_invalid_abi(&self, abi: StrLit, err: abi::AbiUnsupported) {
|
2022-09-08 15:37:15 +02:00
|
|
|
let abi_names = abi::enabled_names(self.tcx.features(), abi.span)
|
|
|
|
|
.iter()
|
|
|
|
|
.map(|s| Symbol::intern(s))
|
|
|
|
|
.collect::<Vec<_>>();
|
|
|
|
|
let suggested_name = find_best_match_for_name(&abi_names, abi.symbol_unescaped, None);
|
2023-12-18 22:21:37 +11:00
|
|
|
self.dcx().emit_err(InvalidAbi {
|
2022-09-08 15:37:15 +02:00
|
|
|
abi: abi.symbol_unescaped,
|
2022-08-17 16:58:57 +02:00
|
|
|
span: abi.span,
|
feat: `riscv-interrupt-{m,s}` calling conventions
Similar to prior support added for the mips430, avr, and x86 targets
this change implements the rough equivalent of clang's
[`__attribute__((interrupt))`][clang-attr] for riscv targets, enabling
e.g.
```rust
static mut CNT: usize = 0;
pub extern "riscv-interrupt-m" fn isr_m() {
unsafe {
CNT += 1;
}
}
```
to produce highly effective assembly like:
```asm
pub extern "riscv-interrupt-m" fn isr_m() {
420003a0: 1141 addi sp,sp,-16
unsafe {
CNT += 1;
420003a2: c62a sw a0,12(sp)
420003a4: c42e sw a1,8(sp)
420003a6: 3fc80537 lui a0,0x3fc80
420003aa: 63c52583 lw a1,1596(a0) # 3fc8063c <_ZN12esp_riscv_rt3CNT17hcec3e3a214887d53E.0>
420003ae: 0585 addi a1,a1,1
420003b0: 62b52e23 sw a1,1596(a0)
}
}
420003b4: 4532 lw a0,12(sp)
420003b6: 45a2 lw a1,8(sp)
420003b8: 0141 addi sp,sp,16
420003ba: 30200073 mret
```
(disassembly via `riscv64-unknown-elf-objdump -C -S --disassemble ./esp32c3-hal/target/riscv32imc-unknown-none-elf/release/examples/gpio_interrupt`)
This outcome is superior to hand-coded interrupt routines which, lacking
visibility into any non-assembly body of the interrupt handler, have to
be very conservative and save the [entire CPU state to the stack
frame][full-frame-save]. By instead asking LLVM to only save the
registers that it uses, we defer the decision to the tool with the best
context: it can more accurately account for the cost of spills if it
knows that every additional register used is already at the cost of an
implicit spill.
At the LLVM level, this is apparently [implemented by] marking every
register as "[callee-save]," matching the semantics of an interrupt
handler nicely (it has to leave the CPU state just as it found it after
its `{m|s}ret`).
This approach is not suitable for every interrupt handler, as it makes
no attempt to e.g. save the state in a user-accessible stack frame. For
a full discussion of those challenges and tradeoffs, please refer to
[the interrupt calling conventions RFC][rfc].
Inside rustc, this implementation differs from prior art because LLVM
does not expose the "all-saved" function flavor as a calling convention
directly, instead preferring to use an attribute that allows for
differentiating between "machine-mode" and "superivsor-mode" interrupts.
Finally, some effort has been made to guide those who may not yet be
aware of the differences between machine-mode and supervisor-mode
interrupts as to why no `riscv-interrupt` calling convention is exposed
through rustc, and similarly for why `riscv-interrupt-u` makes no
appearance (as it would complicate future LLVM upgrades).
[clang-attr]: https://clang.llvm.org/docs/AttributeReference.html#interrupt-risc-v
[full-frame-save]: https://github.com/esp-rs/esp-riscv-rt/blob/9281af2ecffe13e40992917316f36920c26acaf3/src/lib.rs#L440-L469
[implemented by]: https://github.com/llvm/llvm-project/blob/b7fb2a3fec7c187d58a6d338ab512d9173bca987/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp#L61-L67
[callee-save]: https://github.com/llvm/llvm-project/blob/973f1fe7a8591c7af148e573491ab68cc15b6ecf/llvm/lib/Target/RISCV/RISCVCallingConv.td#L30-L37
[rfc]: https://github.com/rust-lang/rfcs/pull/3246
2023-05-23 15:08:23 -07:00
|
|
|
explain: match err {
|
|
|
|
|
abi::AbiUnsupported::Reason { explain } => Some(InvalidAbiReason(explain)),
|
|
|
|
|
_ => None,
|
|
|
|
|
},
|
2022-09-08 15:37:15 +02:00
|
|
|
suggestion: suggested_name.map(|suggested_name| InvalidAbiSuggestion {
|
|
|
|
|
span: abi.span,
|
|
|
|
|
suggestion: format!("\"{suggested_name}\""),
|
|
|
|
|
}),
|
|
|
|
|
command: "rustc --print=calling-conventions".to_string(),
|
2022-08-17 16:58:57 +02:00
|
|
|
});
|
2019-10-27 23:14:35 +01:00
|
|
|
}
|
|
|
|
|
|
2022-12-20 16:15:55 +00:00
|
|
|
pub(super) fn lower_constness(&mut self, c: Const) -> hir::Constness {
|
2020-01-30 02:42:33 +01:00
|
|
|
match c {
|
|
|
|
|
Const::Yes(_) => hir::Constness::Const,
|
|
|
|
|
Const::No => hir::Constness::NotConst,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-23 10:01:05 -03:00
|
|
|
pub(super) fn lower_safety(&mut self, s: Safety, default: hir::Safety) -> hir::Safety {
|
2024-05-17 14:17:48 -03:00
|
|
|
match s {
|
|
|
|
|
Safety::Unsafe(_) => hir::Safety::Unsafe,
|
2024-05-23 10:01:05 -03:00
|
|
|
Safety::Default => default,
|
|
|
|
|
Safety::Safe(_) => hir::Safety::Safe,
|
2020-01-30 02:42:33 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-31 17:40:50 -03:00
|
|
|
/// Return the pair of the lowered `generics` as `hir::Generics` and the evaluation of `f` with
|
|
|
|
|
/// the carried impl trait definitions and bounds.
|
2022-05-20 15:52:56 -03:00
|
|
|
#[instrument(level = "debug", skip(self, f))]
|
2022-05-31 15:33:51 -03:00
|
|
|
fn lower_generics<T>(
|
|
|
|
|
&mut self,
|
|
|
|
|
generics: &Generics,
|
|
|
|
|
parent_node_id: NodeId,
|
2024-02-07 19:27:44 +00:00
|
|
|
itctx: ImplTraitContext,
|
2022-05-31 15:33:51 -03:00
|
|
|
f: impl FnOnce(&mut Self) -> T,
|
|
|
|
|
) -> (&'hir hir::Generics<'hir>, T) {
|
2022-06-01 15:38:37 -03:00
|
|
|
debug_assert!(self.impl_trait_defs.is_empty());
|
|
|
|
|
debug_assert!(self.impl_trait_bounds.is_empty());
|
2022-05-31 15:33:51 -03:00
|
|
|
|
2022-03-01 20:02:47 +08:00
|
|
|
// Error if `?Trait` bounds in where clauses don't refer directly to type parameters.
|
2021-08-15 00:53:40 -04:00
|
|
|
// Note: we used to clone these bounds directly onto the type parameter (and avoid lowering
|
|
|
|
|
// these into hir when we lower thee where clauses), but this makes it quite difficult to
|
2024-02-11 09:22:52 +01:00
|
|
|
// keep track of the Span info. Now, `<dyn HirTyLowerer>::add_implicit_sized_bound`
|
|
|
|
|
// checks both param bounds and where clauses for `?Sized`.
|
2019-08-10 20:13:12 +02:00
|
|
|
for pred in &generics.where_clause.predicates {
|
2022-11-22 15:37:54 +00:00
|
|
|
let WherePredicate::BoundPredicate(bound_pred) = pred else {
|
2022-02-19 00:48:49 +01:00
|
|
|
continue;
|
2021-09-28 17:15:28 -04:00
|
|
|
};
|
|
|
|
|
let compute_is_param = || {
|
|
|
|
|
// Check if the where clause type is a plain type parameter.
|
|
|
|
|
match self
|
|
|
|
|
.resolver
|
|
|
|
|
.get_partial_res(bound_pred.bounded_ty.id)
|
2022-10-10 19:21:35 +04:00
|
|
|
.and_then(|r| r.full_res())
|
2021-09-28 17:15:28 -04:00
|
|
|
{
|
2022-10-10 19:21:35 +04:00
|
|
|
Some(Res::Def(DefKind::TyParam, def_id))
|
2021-09-28 17:15:28 -04:00
|
|
|
if bound_pred.bound_generic_params.is_empty() =>
|
|
|
|
|
{
|
|
|
|
|
generics
|
|
|
|
|
.params
|
|
|
|
|
.iter()
|
2021-07-18 20:09:20 +02:00
|
|
|
.any(|p| def_id == self.local_def_id(p.id).to_def_id())
|
2019-08-10 20:13:12 +02:00
|
|
|
}
|
2021-09-28 17:15:28 -04:00
|
|
|
// Either the `bounded_ty` is not a plain type parameter, or
|
|
|
|
|
// it's not found in the generic type parameters list.
|
|
|
|
|
_ => false,
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
// We only need to compute this once per `WherePredicate`, but don't
|
|
|
|
|
// need to compute this at all unless there is a Maybe bound.
|
|
|
|
|
let mut is_param: Option<bool> = None;
|
|
|
|
|
for bound in &bound_pred.bounds {
|
2023-12-20 15:22:06 +01:00
|
|
|
if !matches!(
|
|
|
|
|
*bound,
|
2024-10-13 09:31:22 -04:00
|
|
|
GenericBound::Trait(PolyTraitRef {
|
|
|
|
|
modifiers: TraitBoundModifiers { polarity: BoundPolarity::Maybe(_), .. },
|
2023-12-20 15:22:06 +01:00
|
|
|
..
|
|
|
|
|
})
|
|
|
|
|
) {
|
2021-09-28 17:15:28 -04:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
let is_param = *is_param.get_or_insert_with(compute_is_param);
|
2024-10-09 09:01:57 +02:00
|
|
|
if !is_param && !self.tcx.features().more_maybe_bounds() {
|
2024-02-23 16:39:57 +03:00
|
|
|
self.tcx
|
|
|
|
|
.sess
|
|
|
|
|
.create_feature_err(
|
|
|
|
|
MisplacedRelaxTraitBound { span: bound.span() },
|
|
|
|
|
sym::more_maybe_bounds,
|
|
|
|
|
)
|
|
|
|
|
.emit();
|
2019-08-10 20:13:12 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-31 16:57:16 -03:00
|
|
|
let mut predicates: SmallVec<[hir::WherePredicate<'hir>; 4]> = SmallVec::new();
|
2022-02-07 22:58:30 +01:00
|
|
|
predicates.extend(generics.params.iter().filter_map(|param| {
|
2022-05-05 15:50:11 +01:00
|
|
|
self.lower_generic_bound_predicate(
|
|
|
|
|
param.ident,
|
|
|
|
|
param.id,
|
|
|
|
|
¶m.kind,
|
2022-07-19 18:10:27 -03:00
|
|
|
¶m.bounds,
|
2022-12-25 22:16:04 +01:00
|
|
|
param.colon_span,
|
|
|
|
|
generics.span,
|
2022-07-19 18:10:27 -03:00
|
|
|
itctx,
|
2022-05-05 15:50:11 +01:00
|
|
|
PredicateOrigin::GenericParam,
|
|
|
|
|
)
|
2022-02-07 22:58:30 +01:00
|
|
|
}));
|
|
|
|
|
predicates.extend(
|
2022-02-05 15:48:02 +01:00
|
|
|
generics
|
|
|
|
|
.where_clause
|
|
|
|
|
.predicates
|
|
|
|
|
.iter()
|
|
|
|
|
.map(|predicate| self.lower_where_predicate(predicate)),
|
|
|
|
|
);
|
|
|
|
|
|
2023-02-28 06:26:48 +00:00
|
|
|
let mut params: SmallVec<[hir::GenericParam<'hir>; 4]> = self
|
|
|
|
|
.lower_generic_params_mut(&generics.params, hir::GenericParamSource::Generics)
|
|
|
|
|
.collect();
|
2022-06-06 09:02:24 +02:00
|
|
|
|
|
|
|
|
// Introduce extra lifetimes if late resolution tells us to.
|
2024-10-16 12:17:21 -04:00
|
|
|
let extra_lifetimes = self.resolver.extra_lifetime_params(parent_node_id);
|
2022-06-06 09:02:24 +02:00
|
|
|
params.extend(extra_lifetimes.into_iter().filter_map(|(ident, node_id, res)| {
|
2023-02-28 06:26:48 +00:00
|
|
|
self.lifetime_res_to_generic_param(
|
|
|
|
|
ident,
|
|
|
|
|
node_id,
|
|
|
|
|
res,
|
|
|
|
|
hir::GenericParamSource::Generics,
|
|
|
|
|
)
|
2022-06-06 09:02:24 +02:00
|
|
|
}));
|
|
|
|
|
|
2022-06-05 17:37:45 -07:00
|
|
|
let has_where_clause_predicates = !generics.where_clause.predicates.is_empty();
|
2022-05-31 16:57:16 -03:00
|
|
|
let where_clause_span = self.lower_span(generics.where_clause.span);
|
|
|
|
|
let span = self.lower_span(generics.span);
|
|
|
|
|
let res = f(self);
|
|
|
|
|
|
|
|
|
|
let impl_trait_defs = std::mem::take(&mut self.impl_trait_defs);
|
2022-06-01 14:42:16 -03:00
|
|
|
params.extend(impl_trait_defs.into_iter());
|
|
|
|
|
|
2022-05-31 16:57:16 -03:00
|
|
|
let impl_trait_bounds = std::mem::take(&mut self.impl_trait_bounds);
|
|
|
|
|
predicates.extend(impl_trait_bounds.into_iter());
|
|
|
|
|
|
|
|
|
|
let lowered_generics = self.arena.alloc(hir::Generics {
|
|
|
|
|
params: self.arena.alloc_from_iter(params),
|
|
|
|
|
predicates: self.arena.alloc_from_iter(predicates),
|
2022-06-05 17:37:45 -07:00
|
|
|
has_where_clause_predicates,
|
2022-05-31 16:57:16 -03:00
|
|
|
where_clause_span,
|
|
|
|
|
span,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
(lowered_generics, res)
|
2019-08-10 20:13:12 +02:00
|
|
|
}
|
|
|
|
|
|
2022-02-07 22:58:30 +01:00
|
|
|
pub(super) fn lower_generic_bound_predicate(
|
|
|
|
|
&mut self,
|
|
|
|
|
ident: Ident,
|
|
|
|
|
id: NodeId,
|
|
|
|
|
kind: &GenericParamKind,
|
2022-07-19 18:10:27 -03:00
|
|
|
bounds: &[GenericBound],
|
2022-12-25 22:16:04 +01:00
|
|
|
colon_span: Option<Span>,
|
|
|
|
|
parent_span: Span,
|
2024-02-07 19:27:44 +00:00
|
|
|
itctx: ImplTraitContext,
|
2022-05-05 15:50:11 +01:00
|
|
|
origin: PredicateOrigin,
|
2022-02-07 22:58:30 +01:00
|
|
|
) -> Option<hir::WherePredicate<'hir>> {
|
|
|
|
|
// Do not create a clause if we do not have anything inside it.
|
|
|
|
|
if bounds.is_empty() {
|
|
|
|
|
return None;
|
|
|
|
|
}
|
2022-07-19 18:10:27 -03:00
|
|
|
|
2022-07-26 15:50:25 -03:00
|
|
|
let bounds = self.lower_param_bounds(bounds, itctx);
|
2022-07-19 18:10:27 -03:00
|
|
|
|
2022-02-07 22:58:30 +01:00
|
|
|
let ident = self.lower_ident(ident);
|
|
|
|
|
let param_span = ident.span;
|
2022-12-25 22:16:04 +01:00
|
|
|
|
|
|
|
|
// Reconstruct the span of the entire predicate from the individual generic bounds.
|
|
|
|
|
let span_start = colon_span.unwrap_or_else(|| param_span.shrink_to_hi());
|
|
|
|
|
let span = bounds.iter().fold(span_start, |span_accum, bound| {
|
|
|
|
|
match bound.span().find_ancestor_inside(parent_span) {
|
|
|
|
|
Some(bound_span) => span_accum.to(bound_span),
|
|
|
|
|
None => span_accum,
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
let span = self.lower_span(span);
|
|
|
|
|
|
2022-02-07 22:58:30 +01:00
|
|
|
match kind {
|
|
|
|
|
GenericParamKind::Const { .. } => None,
|
|
|
|
|
GenericParamKind::Type { .. } => {
|
2021-07-18 20:09:20 +02:00
|
|
|
let def_id = self.local_def_id(id).to_def_id();
|
2022-08-30 16:54:42 +10:00
|
|
|
let hir_id = self.next_id();
|
2022-08-30 15:10:28 +10:00
|
|
|
let res = Res::Def(DefKind::TyParam, def_id);
|
2022-02-07 22:58:30 +01:00
|
|
|
let ty_path = self.arena.alloc(hir::Path {
|
|
|
|
|
span: param_span,
|
2022-08-30 15:10:28 +10:00
|
|
|
res,
|
|
|
|
|
segments: self
|
|
|
|
|
.arena
|
2022-09-01 08:44:20 +10:00
|
|
|
.alloc_from_iter([hir::PathSegment::new(ident, hir_id, res)]),
|
2022-02-07 22:58:30 +01:00
|
|
|
});
|
|
|
|
|
let ty_id = self.next_id();
|
|
|
|
|
let bounded_ty =
|
|
|
|
|
self.ty_path(ty_id, param_span, hir::QPath::Resolved(None, ty_path));
|
|
|
|
|
Some(hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
|
2022-09-05 17:21:19 +02:00
|
|
|
hir_id: self.next_id(),
|
2022-02-07 22:58:30 +01:00
|
|
|
bounded_ty: self.arena.alloc(bounded_ty),
|
|
|
|
|
bounds,
|
|
|
|
|
span,
|
|
|
|
|
bound_generic_params: &[],
|
2022-05-05 15:50:11 +01:00
|
|
|
origin,
|
2022-02-07 22:58:30 +01:00
|
|
|
}))
|
|
|
|
|
}
|
|
|
|
|
GenericParamKind::Lifetime => {
|
|
|
|
|
let ident = self.lower_ident(ident);
|
2021-07-18 20:09:20 +02:00
|
|
|
let lt_id = self.next_node_id();
|
2022-11-05 22:41:07 +00:00
|
|
|
let lifetime = self.new_named_lifetime(id, lt_id, ident);
|
2022-02-07 22:58:30 +01:00
|
|
|
Some(hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate {
|
|
|
|
|
lifetime,
|
|
|
|
|
span,
|
|
|
|
|
bounds,
|
|
|
|
|
in_where_clause: false,
|
|
|
|
|
}))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-30 17:46:46 +01:00
|
|
|
fn lower_where_predicate(&mut self, pred: &WherePredicate) -> hir::WherePredicate<'hir> {
|
2022-11-22 15:37:54 +00:00
|
|
|
match pred {
|
2019-08-10 20:13:12 +02:00
|
|
|
WherePredicate::BoundPredicate(WhereBoundPredicate {
|
2022-11-22 15:37:54 +00:00
|
|
|
bound_generic_params,
|
|
|
|
|
bounded_ty,
|
|
|
|
|
bounds,
|
2019-08-10 20:13:12 +02:00
|
|
|
span,
|
2022-04-24 15:49:00 +02:00
|
|
|
}) => hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
|
2022-09-05 17:21:19 +02:00
|
|
|
hir_id: self.next_id(),
|
2023-02-28 06:26:48 +00:00
|
|
|
bound_generic_params: self
|
|
|
|
|
.lower_generic_params(bound_generic_params, hir::GenericParamSource::Binder),
|
2022-09-14 17:39:52 -03:00
|
|
|
bounded_ty: self
|
2024-02-07 19:27:44 +00:00
|
|
|
.lower_ty(bounded_ty, ImplTraitContext::Disallowed(ImplTraitPosition::Bound)),
|
2023-10-11 08:25:08 +00:00
|
|
|
bounds: self.lower_param_bounds(
|
|
|
|
|
bounds,
|
2024-02-07 19:27:44 +00:00
|
|
|
ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
|
2023-10-11 08:25:08 +00:00
|
|
|
),
|
2022-11-22 15:37:54 +00:00
|
|
|
span: self.lower_span(*span),
|
2022-05-05 15:50:11 +01:00
|
|
|
origin: PredicateOrigin::WhereClause,
|
2021-08-15 00:53:40 -04:00
|
|
|
}),
|
2022-11-22 15:37:54 +00:00
|
|
|
WherePredicate::RegionPredicate(WhereRegionPredicate { lifetime, bounds, span }) => {
|
|
|
|
|
hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate {
|
|
|
|
|
span: self.lower_span(*span),
|
|
|
|
|
lifetime: self.lower_lifetime(lifetime),
|
|
|
|
|
bounds: self.lower_param_bounds(
|
|
|
|
|
bounds,
|
2024-02-07 19:27:44 +00:00
|
|
|
ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
|
2022-11-22 15:37:54 +00:00
|
|
|
),
|
|
|
|
|
in_where_clause: true,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
WherePredicate::EqPredicate(WhereEqPredicate { lhs_ty, rhs_ty, span }) => {
|
2019-08-10 20:13:12 +02:00
|
|
|
hir::WherePredicate::EqPredicate(hir::WhereEqPredicate {
|
2022-09-14 17:39:52 -03:00
|
|
|
lhs_ty: self
|
2024-02-07 19:27:44 +00:00
|
|
|
.lower_ty(lhs_ty, ImplTraitContext::Disallowed(ImplTraitPosition::Bound)),
|
2022-09-14 17:39:52 -03:00
|
|
|
rhs_ty: self
|
2024-02-07 19:27:44 +00:00
|
|
|
.lower_ty(rhs_ty, ImplTraitContext::Disallowed(ImplTraitPosition::Bound)),
|
2022-11-22 15:37:54 +00:00
|
|
|
span: self.lower_span(*span),
|
2019-08-10 20:13:12 +02:00
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|