mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-11-10 23:24:29 +00:00
Auto merge of #14524 - Veykril:hir-pretty, r=Veykril
internal: Render function parameters in hir-def pretty printing
This commit is contained in:
commit
d73161b491
6 changed files with 201 additions and 207 deletions
|
@ -13,11 +13,12 @@ use cfg::{CfgExpr, CfgOptions};
|
|||
use drop_bomb::DropBomb;
|
||||
use either::Either;
|
||||
use hir_expand::{
|
||||
attrs::RawAttrs, hygiene::Hygiene, name::Name, ExpandError, ExpandResult, HirFileId, InFile,
|
||||
MacroCallId,
|
||||
ast_id_map::AstIdMap, attrs::RawAttrs, hygiene::Hygiene, name::Name, AstId, ExpandError,
|
||||
ExpandResult, HirFileId, InFile, MacroCallId,
|
||||
};
|
||||
use la_arena::{Arena, ArenaMap};
|
||||
use limit::Limit;
|
||||
use once_cell::unsync::OnceCell;
|
||||
use profile::Count;
|
||||
use rustc_hash::FxHashMap;
|
||||
use syntax::{ast, AstPtr, SyntaxNode, SyntaxNodePtr};
|
||||
|
@ -37,7 +38,43 @@ use crate::{
|
|||
UnresolvedMacro,
|
||||
};
|
||||
|
||||
pub use lower::LowerCtx;
|
||||
pub struct LowerCtx<'a> {
|
||||
pub db: &'a dyn DefDatabase,
|
||||
hygiene: Hygiene,
|
||||
ast_id_map: Option<(HirFileId, OnceCell<Arc<AstIdMap>>)>,
|
||||
}
|
||||
|
||||
impl<'a> LowerCtx<'a> {
|
||||
pub fn new(db: &'a dyn DefDatabase, hygiene: &Hygiene, file_id: HirFileId) -> Self {
|
||||
LowerCtx { db, hygiene: hygiene.clone(), ast_id_map: Some((file_id, OnceCell::new())) }
|
||||
}
|
||||
|
||||
pub fn with_file_id(db: &'a dyn DefDatabase, file_id: HirFileId) -> Self {
|
||||
LowerCtx {
|
||||
db,
|
||||
hygiene: Hygiene::new(db.upcast(), file_id),
|
||||
ast_id_map: Some((file_id, OnceCell::new())),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_hygiene(db: &'a dyn DefDatabase, hygiene: &Hygiene) -> Self {
|
||||
LowerCtx { db, hygiene: hygiene.clone(), ast_id_map: None }
|
||||
}
|
||||
|
||||
pub(crate) fn hygiene(&self) -> &Hygiene {
|
||||
&self.hygiene
|
||||
}
|
||||
|
||||
pub(crate) fn lower_path(&self, ast: ast::Path) -> Option<Path> {
|
||||
Path::from_src(ast, self)
|
||||
}
|
||||
|
||||
pub(crate) fn ast_id<N: syntax::AstNode>(&self, item: &N) -> Option<AstId<N>> {
|
||||
let &(file_id, ref ast_id_map) = self.ast_id_map.as_ref()?;
|
||||
let ast_id_map = ast_id_map.get_or_init(|| self.db.ast_id_map(file_id));
|
||||
Some(InFile::new(file_id, ast_id_map.ast_id(item)))
|
||||
}
|
||||
}
|
||||
|
||||
/// A subset of Expander that only deals with cfg attributes. We only need it to
|
||||
/// avoid cyclic queries in crate def map during enum processing.
|
||||
|
@ -241,7 +278,7 @@ impl Expander {
|
|||
// The overflow error should have been reported when it occurred (see the next branch),
|
||||
// so don't return overflow error here to avoid diagnostics duplication.
|
||||
cov_mark::hit!(overflow_but_not_me);
|
||||
return ExpandResult::only_err(ExpandError::RecursionOverflowPosioned);
|
||||
return ExpandResult::only_err(ExpandError::RecursionOverflowPoisoned);
|
||||
} else if self.recursion_limit(db).check(self.recursion_depth + 1).is_err() {
|
||||
self.recursion_depth = usize::MAX;
|
||||
cov_mark::hit!(your_stack_belongs_to_me);
|
||||
|
|
|
@ -7,36 +7,30 @@ use base_db::CrateId;
|
|||
use either::Either;
|
||||
use hir_expand::{
|
||||
ast_id_map::AstIdMap,
|
||||
hygiene::Hygiene,
|
||||
name::{name, AsName, Name},
|
||||
AstId, ExpandError, HirFileId, InFile,
|
||||
AstId, ExpandError, InFile,
|
||||
};
|
||||
use intern::Interned;
|
||||
use la_arena::Arena;
|
||||
use once_cell::unsync::OnceCell;
|
||||
use profile::Count;
|
||||
use rustc_hash::FxHashMap;
|
||||
use smallvec::SmallVec;
|
||||
use syntax::{
|
||||
ast::{
|
||||
self, ArrayExprKind, AstChildren, BlockExpr, HasArgList, HasLoopBody, HasName, LiteralKind,
|
||||
self, ArrayExprKind, AstChildren, BlockExpr, HasArgList, HasLoopBody, HasName,
|
||||
SlicePatComponents,
|
||||
},
|
||||
AstNode, AstPtr, SyntaxNodePtr,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
body::{
|
||||
Body, BodyDiagnostic, BodySourceMap, Expander, ExprPtr, ExprSource, LabelPtr, LabelSource,
|
||||
PatPtr, PatSource,
|
||||
},
|
||||
builtin_type::{BuiltinFloat, BuiltinInt, BuiltinUint},
|
||||
body::{Body, BodyDiagnostic, BodySourceMap, Expander, ExprPtr, LabelPtr, LowerCtx, PatPtr},
|
||||
data::adt::StructKind,
|
||||
db::DefDatabase,
|
||||
hir::{
|
||||
dummy_expr_id, Array, Binding, BindingAnnotation, BindingId, ClosureKind, Expr, ExprId,
|
||||
FloatTypeWrapper, Label, LabelId, Literal, MatchArm, Movability, Pat, PatId,
|
||||
RecordFieldPat, RecordLitField, Statement,
|
||||
Label, LabelId, Literal, MatchArm, Movability, Pat, PatId, RecordFieldPat, RecordLitField,
|
||||
Statement,
|
||||
},
|
||||
item_scope::BuiltinShadowMode,
|
||||
lang_item::LangItem,
|
||||
|
@ -45,44 +39,6 @@ use crate::{
|
|||
AdtId, BlockId, BlockLoc, ModuleDefId, UnresolvedMacro,
|
||||
};
|
||||
|
||||
pub struct LowerCtx<'a> {
|
||||
pub db: &'a dyn DefDatabase,
|
||||
hygiene: Hygiene,
|
||||
ast_id_map: Option<(HirFileId, OnceCell<Arc<AstIdMap>>)>,
|
||||
}
|
||||
|
||||
impl<'a> LowerCtx<'a> {
|
||||
pub fn new(db: &'a dyn DefDatabase, hygiene: &Hygiene, file_id: HirFileId) -> Self {
|
||||
LowerCtx { db, hygiene: hygiene.clone(), ast_id_map: Some((file_id, OnceCell::new())) }
|
||||
}
|
||||
|
||||
pub fn with_file_id(db: &'a dyn DefDatabase, file_id: HirFileId) -> Self {
|
||||
LowerCtx {
|
||||
db,
|
||||
hygiene: Hygiene::new(db.upcast(), file_id),
|
||||
ast_id_map: Some((file_id, OnceCell::new())),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_hygiene(db: &'a dyn DefDatabase, hygiene: &Hygiene) -> Self {
|
||||
LowerCtx { db, hygiene: hygiene.clone(), ast_id_map: None }
|
||||
}
|
||||
|
||||
pub(crate) fn hygiene(&self) -> &Hygiene {
|
||||
&self.hygiene
|
||||
}
|
||||
|
||||
pub(crate) fn lower_path(&self, ast: ast::Path) -> Option<Path> {
|
||||
Path::from_src(ast, self)
|
||||
}
|
||||
|
||||
pub(crate) fn ast_id<N: AstNode>(&self, item: &N) -> Option<AstId<N>> {
|
||||
let &(file_id, ref ast_id_map) = self.ast_id_map.as_ref()?;
|
||||
let ast_id_map = ast_id_map.get_or_init(|| self.db.ast_id_map(file_id));
|
||||
Some(InFile::new(file_id, ast_id_map.ast_id(item)))
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn lower(
|
||||
db: &dyn DefDatabase,
|
||||
expander: Expander,
|
||||
|
@ -119,12 +75,22 @@ struct ExprCollector<'a> {
|
|||
db: &'a dyn DefDatabase,
|
||||
expander: Expander,
|
||||
ast_id_map: Arc<AstIdMap>,
|
||||
body: Body,
|
||||
krate: CrateId,
|
||||
body: Body,
|
||||
source_map: BodySourceMap,
|
||||
current_try_block_label: Option<LabelId>,
|
||||
|
||||
is_lowering_assignee_expr: bool,
|
||||
is_lowering_generator: bool,
|
||||
|
||||
current_try_block_label: Option<LabelId>,
|
||||
// points to the expression that a try expression will target (replaces current_try_block_label)
|
||||
// catch_scope: Option<ExprId>,
|
||||
// points to the expression that an unlabeled control flow will target
|
||||
// loop_scope: Option<ExprId>,
|
||||
// needed to diagnose non label control flow in while conditions
|
||||
// is_in_loop_condition: bool,
|
||||
|
||||
// resolution
|
||||
label_ribs: Vec<LabelRib>,
|
||||
}
|
||||
|
||||
|
@ -202,12 +168,9 @@ impl ExprCollector<'_> {
|
|||
self.body.params.push(param_pat);
|
||||
}
|
||||
|
||||
for pat in param_list
|
||||
.params()
|
||||
.zip(attr_enabled)
|
||||
.filter_map(|(param, enabled)| param.pat().filter(|_| enabled))
|
||||
for (param, _) in param_list.params().zip(attr_enabled).filter(|(_, enabled)| *enabled)
|
||||
{
|
||||
let param_pat = self.collect_pat(pat);
|
||||
let param_pat = self.collect_pat_top(param.pat());
|
||||
self.body.params.push(param_pat);
|
||||
}
|
||||
};
|
||||
|
@ -236,63 +199,6 @@ impl ExprCollector<'_> {
|
|||
self.expander.ctx(self.db)
|
||||
}
|
||||
|
||||
fn alloc_expr(&mut self, expr: Expr, ptr: ExprPtr) -> ExprId {
|
||||
let src = self.expander.to_source(ptr);
|
||||
let id = self.make_expr(expr, src.clone());
|
||||
self.source_map.expr_map.insert(src, id);
|
||||
id
|
||||
}
|
||||
// FIXME: desugared exprs don't have ptr, that's wrong and should be fixed somehow.
|
||||
fn alloc_expr_desugared(&mut self, expr: Expr) -> ExprId {
|
||||
self.body.exprs.alloc(expr)
|
||||
}
|
||||
fn missing_expr(&mut self) -> ExprId {
|
||||
self.alloc_expr_desugared(Expr::Missing)
|
||||
}
|
||||
fn make_expr(&mut self, expr: Expr, src: ExprSource) -> ExprId {
|
||||
let id = self.body.exprs.alloc(expr);
|
||||
self.source_map.expr_map_back.insert(id, src);
|
||||
id
|
||||
}
|
||||
|
||||
fn alloc_binding(&mut self, name: Name, mode: BindingAnnotation) -> BindingId {
|
||||
self.body.bindings.alloc(Binding { name, mode, definitions: SmallVec::new() })
|
||||
}
|
||||
fn alloc_pat(&mut self, pat: Pat, ptr: PatPtr) -> PatId {
|
||||
let src = self.expander.to_source(ptr);
|
||||
let id = self.make_pat(pat, src.clone());
|
||||
self.source_map.pat_map.insert(src, id);
|
||||
id
|
||||
}
|
||||
// FIXME: desugared pats don't have ptr, that's wrong and should be fixed somehow.
|
||||
fn alloc_pat_desugared(&mut self, pat: Pat) -> PatId {
|
||||
self.body.pats.alloc(pat)
|
||||
}
|
||||
fn missing_pat(&mut self) -> PatId {
|
||||
self.body.pats.alloc(Pat::Missing)
|
||||
}
|
||||
fn make_pat(&mut self, pat: Pat, src: PatSource) -> PatId {
|
||||
let id = self.body.pats.alloc(pat);
|
||||
self.source_map.pat_map_back.insert(id, src);
|
||||
id
|
||||
}
|
||||
|
||||
fn alloc_label(&mut self, label: Label, ptr: LabelPtr) -> LabelId {
|
||||
let src = self.expander.to_source(ptr);
|
||||
let id = self.make_label(label, src.clone());
|
||||
self.source_map.label_map.insert(src, id);
|
||||
id
|
||||
}
|
||||
// FIXME: desugared labels don't have ptr, that's wrong and should be fixed somehow.
|
||||
fn alloc_label_desugared(&mut self, label: Label) -> LabelId {
|
||||
self.body.labels.alloc(label)
|
||||
}
|
||||
fn make_label(&mut self, label: Label, src: LabelSource) -> LabelId {
|
||||
let id = self.body.labels.alloc(label);
|
||||
self.source_map.label_map_back.insert(id, src);
|
||||
id
|
||||
}
|
||||
|
||||
fn collect_expr(&mut self, expr: ast::Expr) -> ExprId {
|
||||
self.maybe_collect_expr(expr).unwrap_or_else(|| self.missing_expr())
|
||||
}
|
||||
|
@ -320,7 +226,7 @@ impl ExprCollector<'_> {
|
|||
self.alloc_expr(Expr::If { condition, then_branch, else_branch }, syntax_ptr)
|
||||
}
|
||||
ast::Expr::LetExpr(e) => {
|
||||
let pat = self.collect_pat_opt(e.pat());
|
||||
let pat = self.collect_pat_top(e.pat());
|
||||
let expr = self.collect_expr_opt(e.expr());
|
||||
self.alloc_expr(Expr::Let { pat, expr }, syntax_ptr)
|
||||
}
|
||||
|
@ -379,7 +285,7 @@ impl ExprCollector<'_> {
|
|||
ast::Expr::ForExpr(e) => {
|
||||
let label = e.label().map(|label| self.collect_label(label));
|
||||
let iterable = self.collect_expr_opt(e.iterable());
|
||||
let pat = self.collect_pat_opt(e.pat());
|
||||
let pat = self.collect_pat_top(e.pat());
|
||||
let body = self.collect_labelled_block_opt(label, e.loop_body());
|
||||
self.alloc_expr(Expr::For { iterable, pat, body, label }, syntax_ptr)
|
||||
}
|
||||
|
@ -419,7 +325,7 @@ impl ExprCollector<'_> {
|
|||
.arms()
|
||||
.filter_map(|arm| {
|
||||
self.check_cfg(&arm).map(|()| MatchArm {
|
||||
pat: self.collect_pat_opt(arm.pat()),
|
||||
pat: self.collect_pat_top(arm.pat()),
|
||||
expr: self.collect_expr_opt(arm.expr()),
|
||||
guard: arm
|
||||
.guard()
|
||||
|
@ -559,7 +465,7 @@ impl ExprCollector<'_> {
|
|||
let mut arg_types = Vec::new();
|
||||
if let Some(pl) = e.param_list() {
|
||||
for param in pl.params() {
|
||||
let pat = this.collect_pat_opt(param.pat());
|
||||
let pat = this.collect_pat_top(param.pat());
|
||||
let type_ref =
|
||||
param.ty().map(|it| Interned::new(TypeRef::from_ast(&this.ctx(), it)));
|
||||
args.push(pat);
|
||||
|
@ -571,8 +477,7 @@ impl ExprCollector<'_> {
|
|||
.and_then(|r| r.ty())
|
||||
.map(|it| Interned::new(TypeRef::from_ast(&this.ctx(), it)));
|
||||
|
||||
let prev_is_lowering_generator = this.is_lowering_generator;
|
||||
this.is_lowering_generator = false;
|
||||
let prev_is_lowering_generator = mem::take(&mut this.is_lowering_generator);
|
||||
|
||||
let body = this.collect_expr_opt(e.body());
|
||||
|
||||
|
@ -850,7 +755,7 @@ impl ExprCollector<'_> {
|
|||
krate: *krate,
|
||||
});
|
||||
}
|
||||
Some(ExpandError::RecursionOverflowPosioned) => {
|
||||
Some(ExpandError::RecursionOverflowPoisoned) => {
|
||||
// Recursion limit has been reached in the macro expansion tree, but not in
|
||||
// this very macro call. Don't add diagnostics to avoid duplication.
|
||||
}
|
||||
|
@ -931,7 +836,7 @@ impl ExprCollector<'_> {
|
|||
if self.check_cfg(&stmt).is_none() {
|
||||
return;
|
||||
}
|
||||
let pat = self.collect_pat_opt(stmt.pat());
|
||||
let pat = self.collect_pat_top(stmt.pat());
|
||||
let type_ref =
|
||||
stmt.ty().map(|it| Interned::new(TypeRef::from_ast(&self.ctx(), it)));
|
||||
let initializer = stmt.initializer().map(|e| self.collect_expr(e));
|
||||
|
@ -1052,32 +957,23 @@ impl ExprCollector<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
fn collect_label(&mut self, ast_label: ast::Label) -> LabelId {
|
||||
let label = Label {
|
||||
name: ast_label.lifetime().as_ref().map_or_else(Name::missing, Name::new_lifetime),
|
||||
};
|
||||
self.alloc_label(label, AstPtr::new(&ast_label))
|
||||
}
|
||||
// region: patterns
|
||||
|
||||
fn collect_pat(&mut self, pat: ast::Pat) -> PatId {
|
||||
self.collect_pat_(pat, &mut BindingList::default())
|
||||
}
|
||||
|
||||
fn collect_pat_opt(&mut self, pat: Option<ast::Pat>) -> PatId {
|
||||
fn collect_pat_top(&mut self, pat: Option<ast::Pat>) -> PatId {
|
||||
match pat {
|
||||
Some(pat) => self.collect_pat(pat),
|
||||
Some(pat) => self.collect_pat(pat, &mut BindingList::default()),
|
||||
None => self.missing_pat(),
|
||||
}
|
||||
}
|
||||
|
||||
fn collect_pat_(&mut self, pat: ast::Pat, binding_list: &mut BindingList) -> PatId {
|
||||
fn collect_pat(&mut self, pat: ast::Pat, binding_list: &mut BindingList) -> PatId {
|
||||
let pattern = match &pat {
|
||||
ast::Pat::IdentPat(bp) => {
|
||||
let name = bp.name().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
|
||||
|
||||
let annotation =
|
||||
BindingAnnotation::new(bp.mut_token().is_some(), bp.ref_token().is_some());
|
||||
let subpat = bp.pat().map(|subpat| self.collect_pat_(subpat, binding_list));
|
||||
let subpat = bp.pat().map(|subpat| self.collect_pat(subpat, binding_list));
|
||||
|
||||
let is_simple_ident_pat =
|
||||
annotation == BindingAnnotation::Unannotated && subpat.is_none();
|
||||
|
@ -1131,7 +1027,7 @@ impl ExprCollector<'_> {
|
|||
Pat::TupleStruct { path, args, ellipsis }
|
||||
}
|
||||
ast::Pat::RefPat(p) => {
|
||||
let pat = self.collect_pat_opt_(p.pat(), binding_list);
|
||||
let pat = self.collect_pat_opt(p.pat(), binding_list);
|
||||
let mutability = Mutability::from_mutable(p.mut_token().is_some());
|
||||
Pat::Ref { pat, mutability }
|
||||
}
|
||||
|
@ -1141,10 +1037,10 @@ impl ExprCollector<'_> {
|
|||
path.map(Pat::Path).unwrap_or(Pat::Missing)
|
||||
}
|
||||
ast::Pat::OrPat(p) => {
|
||||
let pats = p.pats().map(|p| self.collect_pat_(p, binding_list)).collect();
|
||||
let pats = p.pats().map(|p| self.collect_pat(p, binding_list)).collect();
|
||||
Pat::Or(pats)
|
||||
}
|
||||
ast::Pat::ParenPat(p) => return self.collect_pat_opt_(p.pat(), binding_list),
|
||||
ast::Pat::ParenPat(p) => return self.collect_pat_opt(p.pat(), binding_list),
|
||||
ast::Pat::TuplePat(p) => {
|
||||
let (args, ellipsis) = self.collect_tuple_pat(p.fields(), binding_list);
|
||||
Pat::Tuple { args, ellipsis }
|
||||
|
@ -1159,7 +1055,7 @@ impl ExprCollector<'_> {
|
|||
.fields()
|
||||
.filter_map(|f| {
|
||||
let ast_pat = f.pat()?;
|
||||
let pat = self.collect_pat_(ast_pat, binding_list);
|
||||
let pat = self.collect_pat(ast_pat, binding_list);
|
||||
let name = f.field_name()?.as_name();
|
||||
Some(RecordFieldPat { name, pat })
|
||||
})
|
||||
|
@ -1178,15 +1074,9 @@ impl ExprCollector<'_> {
|
|||
|
||||
// FIXME properly handle `RestPat`
|
||||
Pat::Slice {
|
||||
prefix: prefix
|
||||
.into_iter()
|
||||
.map(|p| self.collect_pat_(p, binding_list))
|
||||
.collect(),
|
||||
slice: slice.map(|p| self.collect_pat_(p, binding_list)),
|
||||
suffix: suffix
|
||||
.into_iter()
|
||||
.map(|p| self.collect_pat_(p, binding_list))
|
||||
.collect(),
|
||||
prefix: prefix.into_iter().map(|p| self.collect_pat(p, binding_list)).collect(),
|
||||
slice: slice.map(|p| self.collect_pat(p, binding_list)),
|
||||
suffix: suffix.into_iter().map(|p| self.collect_pat(p, binding_list)).collect(),
|
||||
}
|
||||
}
|
||||
#[rustfmt::skip] // https://github.com/rust-lang/rustfmt/issues/5676
|
||||
|
@ -1217,7 +1107,7 @@ impl ExprCollector<'_> {
|
|||
Pat::Missing
|
||||
}
|
||||
ast::Pat::BoxPat(boxpat) => {
|
||||
let inner = self.collect_pat_opt_(boxpat.pat(), binding_list);
|
||||
let inner = self.collect_pat_opt(boxpat.pat(), binding_list);
|
||||
Pat::Box { inner }
|
||||
}
|
||||
ast::Pat::ConstBlockPat(const_block_pat) => {
|
||||
|
@ -1235,7 +1125,7 @@ impl ExprCollector<'_> {
|
|||
let src = self.expander.to_source(Either::Left(AstPtr::new(&pat)));
|
||||
let pat =
|
||||
self.collect_macro_call(call, macro_ptr, true, |this, expanded_pat| {
|
||||
this.collect_pat_opt_(expanded_pat, binding_list)
|
||||
this.collect_pat_opt(expanded_pat, binding_list)
|
||||
});
|
||||
self.source_map.pat_map.insert(src, pat);
|
||||
return pat;
|
||||
|
@ -1249,9 +1139,9 @@ impl ExprCollector<'_> {
|
|||
self.alloc_pat(pattern, Either::Left(ptr))
|
||||
}
|
||||
|
||||
fn collect_pat_opt_(&mut self, pat: Option<ast::Pat>, binding_list: &mut BindingList) -> PatId {
|
||||
fn collect_pat_opt(&mut self, pat: Option<ast::Pat>, binding_list: &mut BindingList) -> PatId {
|
||||
match pat {
|
||||
Some(pat) => self.collect_pat_(pat, binding_list),
|
||||
Some(pat) => self.collect_pat(pat, binding_list),
|
||||
None => self.missing_pat(),
|
||||
}
|
||||
}
|
||||
|
@ -1267,12 +1157,14 @@ impl ExprCollector<'_> {
|
|||
// We want to skip the `..` pattern here, since we account for it above.
|
||||
let args = args
|
||||
.filter(|p| !matches!(p, ast::Pat::RestPat(_)))
|
||||
.map(|p| self.collect_pat_(p, binding_list))
|
||||
.map(|p| self.collect_pat(p, binding_list))
|
||||
.collect();
|
||||
|
||||
(args, ellipsis)
|
||||
}
|
||||
|
||||
// endregion: patterns
|
||||
|
||||
/// Returns `None` (and emits diagnostics) when `owner` if `#[cfg]`d out, and `Some(())` when
|
||||
/// not.
|
||||
fn check_cfg(&mut self, owner: &dyn ast::HasAttrs) -> Option<()> {
|
||||
|
@ -1301,6 +1193,15 @@ impl ExprCollector<'_> {
|
|||
self.body.bindings[binding_id].definitions.push(pat_id);
|
||||
}
|
||||
|
||||
// region: labels
|
||||
|
||||
fn collect_label(&mut self, ast_label: ast::Label) -> LabelId {
|
||||
let label = Label {
|
||||
name: ast_label.lifetime().as_ref().map_or_else(Name::missing, Name::new_lifetime),
|
||||
};
|
||||
self.alloc_label(label, AstPtr::new(&ast_label))
|
||||
}
|
||||
|
||||
fn resolve_label(
|
||||
&self,
|
||||
lifetime: Option<ast::Lifetime>,
|
||||
|
@ -1351,42 +1252,53 @@ impl ExprCollector<'_> {
|
|||
self.label_ribs.pop();
|
||||
res
|
||||
}
|
||||
// endregion: labels
|
||||
}
|
||||
|
||||
impl From<ast::LiteralKind> for Literal {
|
||||
fn from(ast_lit_kind: ast::LiteralKind) -> Self {
|
||||
match ast_lit_kind {
|
||||
// FIXME: these should have actual values filled in, but unsure on perf impact
|
||||
LiteralKind::IntNumber(lit) => {
|
||||
if let builtin @ Some(_) = lit.suffix().and_then(BuiltinFloat::from_suffix) {
|
||||
Literal::Float(
|
||||
FloatTypeWrapper::new(lit.float_value().unwrap_or(Default::default())),
|
||||
builtin,
|
||||
)
|
||||
} else if let builtin @ Some(_) = lit.suffix().and_then(BuiltinUint::from_suffix) {
|
||||
Literal::Uint(lit.value().unwrap_or(0), builtin)
|
||||
} else {
|
||||
let builtin = lit.suffix().and_then(BuiltinInt::from_suffix);
|
||||
Literal::Int(lit.value().unwrap_or(0) as i128, builtin)
|
||||
}
|
||||
}
|
||||
LiteralKind::FloatNumber(lit) => {
|
||||
let ty = lit.suffix().and_then(BuiltinFloat::from_suffix);
|
||||
Literal::Float(FloatTypeWrapper::new(lit.value().unwrap_or(Default::default())), ty)
|
||||
}
|
||||
LiteralKind::ByteString(bs) => {
|
||||
let text = bs.value().map(Box::from).unwrap_or_else(Default::default);
|
||||
Literal::ByteString(text)
|
||||
}
|
||||
LiteralKind::String(s) => {
|
||||
let text = s.value().map(Box::from).unwrap_or_else(Default::default);
|
||||
Literal::String(text)
|
||||
}
|
||||
LiteralKind::Byte(b) => {
|
||||
Literal::Uint(b.value().unwrap_or_default() as u128, Some(BuiltinUint::U8))
|
||||
}
|
||||
LiteralKind::Char(c) => Literal::Char(c.value().unwrap_or_default()),
|
||||
LiteralKind::Bool(val) => Literal::Bool(val),
|
||||
}
|
||||
impl ExprCollector<'_> {
|
||||
fn alloc_expr(&mut self, expr: Expr, ptr: ExprPtr) -> ExprId {
|
||||
let src = self.expander.to_source(ptr);
|
||||
let id = self.body.exprs.alloc(expr);
|
||||
self.source_map.expr_map_back.insert(id, src.clone());
|
||||
self.source_map.expr_map.insert(src, id);
|
||||
id
|
||||
}
|
||||
// FIXME: desugared exprs don't have ptr, that's wrong and should be fixed somehow.
|
||||
fn alloc_expr_desugared(&mut self, expr: Expr) -> ExprId {
|
||||
self.body.exprs.alloc(expr)
|
||||
}
|
||||
fn missing_expr(&mut self) -> ExprId {
|
||||
self.alloc_expr_desugared(Expr::Missing)
|
||||
}
|
||||
|
||||
fn alloc_binding(&mut self, name: Name, mode: BindingAnnotation) -> BindingId {
|
||||
self.body.bindings.alloc(Binding { name, mode, definitions: SmallVec::new() })
|
||||
}
|
||||
|
||||
fn alloc_pat(&mut self, pat: Pat, ptr: PatPtr) -> PatId {
|
||||
let src = self.expander.to_source(ptr);
|
||||
let id = self.body.pats.alloc(pat);
|
||||
self.source_map.pat_map_back.insert(id, src.clone());
|
||||
self.source_map.pat_map.insert(src, id);
|
||||
id
|
||||
}
|
||||
// FIXME: desugared pats don't have ptr, that's wrong and should be fixed somehow.
|
||||
fn alloc_pat_desugared(&mut self, pat: Pat) -> PatId {
|
||||
self.body.pats.alloc(pat)
|
||||
}
|
||||
fn missing_pat(&mut self) -> PatId {
|
||||
self.body.pats.alloc(Pat::Missing)
|
||||
}
|
||||
|
||||
fn alloc_label(&mut self, label: Label, ptr: LabelPtr) -> LabelId {
|
||||
let src = self.expander.to_source(ptr);
|
||||
let id = self.body.labels.alloc(label);
|
||||
self.source_map.label_map_back.insert(id, src.clone());
|
||||
self.source_map.label_map.insert(src, id);
|
||||
id
|
||||
}
|
||||
// FIXME: desugared labels don't have ptr, that's wrong and should be fixed somehow.
|
||||
fn alloc_label_desugared(&mut self, label: Label) -> LabelId {
|
||||
self.body.labels.alloc(label)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,20 +13,16 @@ use crate::{
|
|||
use super::*;
|
||||
|
||||
pub(super) fn print_body_hir(db: &dyn DefDatabase, body: &Body, owner: DefWithBodyId) -> String {
|
||||
let needs_semi;
|
||||
let header = match owner {
|
||||
DefWithBodyId::FunctionId(it) => {
|
||||
needs_semi = false;
|
||||
let item_tree_id = it.lookup(db).id;
|
||||
format!("fn {}(…) ", item_tree_id.item_tree(db)[item_tree_id.value].name)
|
||||
format!("fn {}", item_tree_id.item_tree(db)[item_tree_id.value].name)
|
||||
}
|
||||
DefWithBodyId::StaticId(it) => {
|
||||
needs_semi = true;
|
||||
let item_tree_id = it.lookup(db).id;
|
||||
format!("static {} = ", item_tree_id.item_tree(db)[item_tree_id.value].name)
|
||||
}
|
||||
DefWithBodyId::ConstId(it) => {
|
||||
needs_semi = true;
|
||||
let item_tree_id = it.lookup(db).id;
|
||||
let name = match &item_tree_id.item_tree(db)[item_tree_id.value].name {
|
||||
Some(name) => name.to_string(),
|
||||
|
@ -35,7 +31,6 @@ pub(super) fn print_body_hir(db: &dyn DefDatabase, body: &Body, owner: DefWithBo
|
|||
format!("const {name} = ")
|
||||
}
|
||||
DefWithBodyId::VariantId(it) => {
|
||||
needs_semi = false;
|
||||
let src = it.parent.child_source(db);
|
||||
let variant = &src.value[it.local_id];
|
||||
let name = match &variant.name() {
|
||||
|
@ -47,8 +42,18 @@ pub(super) fn print_body_hir(db: &dyn DefDatabase, body: &Body, owner: DefWithBo
|
|||
};
|
||||
|
||||
let mut p = Printer { body, buf: header, indent_level: 0, needs_indent: false };
|
||||
if let DefWithBodyId::FunctionId(it) = owner {
|
||||
p.buf.push('(');
|
||||
body.params.iter().zip(&db.function_data(it).params).for_each(|(¶m, ty)| {
|
||||
p.print_pat(param);
|
||||
p.buf.push(':');
|
||||
p.print_type_ref(ty);
|
||||
});
|
||||
p.buf.push(')');
|
||||
p.buf.push(' ');
|
||||
}
|
||||
p.print_expr(body.body_expr);
|
||||
if needs_semi {
|
||||
if matches!(owner, DefWithBodyId::StaticId(_) | DefWithBodyId::ConstId(_)) {
|
||||
p.buf.push(';');
|
||||
}
|
||||
p.buf
|
||||
|
|
|
@ -20,6 +20,7 @@ use hir_expand::name::Name;
|
|||
use intern::Interned;
|
||||
use la_arena::{Idx, RawIdx};
|
||||
use smallvec::SmallVec;
|
||||
use syntax::ast;
|
||||
|
||||
use crate::{
|
||||
builtin_type::{BuiltinFloat, BuiltinInt, BuiltinUint},
|
||||
|
@ -104,6 +105,45 @@ impl Literal {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<ast::LiteralKind> for Literal {
|
||||
fn from(ast_lit_kind: ast::LiteralKind) -> Self {
|
||||
use ast::LiteralKind;
|
||||
match ast_lit_kind {
|
||||
// FIXME: these should have actual values filled in, but unsure on perf impact
|
||||
LiteralKind::IntNumber(lit) => {
|
||||
if let builtin @ Some(_) = lit.suffix().and_then(BuiltinFloat::from_suffix) {
|
||||
Literal::Float(
|
||||
FloatTypeWrapper::new(lit.float_value().unwrap_or(Default::default())),
|
||||
builtin,
|
||||
)
|
||||
} else if let builtin @ Some(_) = lit.suffix().and_then(BuiltinUint::from_suffix) {
|
||||
Literal::Uint(lit.value().unwrap_or(0), builtin)
|
||||
} else {
|
||||
let builtin = lit.suffix().and_then(BuiltinInt::from_suffix);
|
||||
Literal::Int(lit.value().unwrap_or(0) as i128, builtin)
|
||||
}
|
||||
}
|
||||
LiteralKind::FloatNumber(lit) => {
|
||||
let ty = lit.suffix().and_then(BuiltinFloat::from_suffix);
|
||||
Literal::Float(FloatTypeWrapper::new(lit.value().unwrap_or(Default::default())), ty)
|
||||
}
|
||||
LiteralKind::ByteString(bs) => {
|
||||
let text = bs.value().map(Box::from).unwrap_or_else(Default::default);
|
||||
Literal::ByteString(text)
|
||||
}
|
||||
LiteralKind::String(s) => {
|
||||
let text = s.value().map(Box::from).unwrap_or_else(Default::default);
|
||||
Literal::String(text)
|
||||
}
|
||||
LiteralKind::Byte(b) => {
|
||||
Literal::Uint(b.value().unwrap_or_default() as u128, Some(BuiltinUint::U8))
|
||||
}
|
||||
LiteralKind::Char(c) => Literal::Char(c.value().unwrap_or_default()),
|
||||
LiteralKind::Bool(val) => Literal::Bool(val),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub enum Expr {
|
||||
/// This is produced if the syntax tree does not have a required expression piece.
|
||||
|
|
|
@ -55,7 +55,7 @@ pub type ExpandResult<T> = ValueResult<T, ExpandError>;
|
|||
pub enum ExpandError {
|
||||
UnresolvedProcMacro(CrateId),
|
||||
Mbe(mbe::ExpandError),
|
||||
RecursionOverflowPosioned,
|
||||
RecursionOverflowPoisoned,
|
||||
Other(Box<str>),
|
||||
}
|
||||
|
||||
|
@ -70,7 +70,7 @@ impl fmt::Display for ExpandError {
|
|||
match self {
|
||||
ExpandError::UnresolvedProcMacro(_) => f.write_str("unresolved proc-macro"),
|
||||
ExpandError::Mbe(it) => it.fmt(f),
|
||||
ExpandError::RecursionOverflowPosioned => {
|
||||
ExpandError::RecursionOverflowPoisoned => {
|
||||
f.write_str("overflow expanding the original macro")
|
||||
}
|
||||
ExpandError::Other(it) => f.write_str(it),
|
||||
|
|
|
@ -988,7 +988,7 @@ impl<'a> TyLoweringContext<'a> {
|
|||
// ignore `T: Drop` or `T: Destruct` bounds.
|
||||
// - `T: ~const Drop` has a special meaning in Rust 1.61 that we don't implement.
|
||||
// (So ideally, we'd only ignore `~const Drop` here)
|
||||
// - `Destruct` impls are built-in in 1.62 (current nightlies as of 08-04-2022), so until
|
||||
// - `Destruct` impls are built-in in 1.62 (current nightly as of 08-04-2022), so until
|
||||
// the builtin impls are supported by Chalk, we ignore them here.
|
||||
if let Some(lang) = lang_attr(self.db.upcast(), tr.hir_trait_id()) {
|
||||
if matches!(lang, LangItem::Drop | LangItem::Destruct) {
|
||||
|
@ -1082,23 +1082,23 @@ impl<'a> TyLoweringContext<'a> {
|
|||
associated_ty_id: to_assoc_type_id(associated_ty),
|
||||
substitution,
|
||||
};
|
||||
let mut preds: SmallVec<[_; 1]> = SmallVec::with_capacity(
|
||||
let mut predicates: SmallVec<[_; 1]> = SmallVec::with_capacity(
|
||||
binding.type_ref.as_ref().map_or(0, |_| 1) + binding.bounds.len(),
|
||||
);
|
||||
if let Some(type_ref) = &binding.type_ref {
|
||||
let ty = self.lower_ty(type_ref);
|
||||
let alias_eq =
|
||||
AliasEq { alias: AliasTy::Projection(projection_ty.clone()), ty };
|
||||
preds.push(crate::wrap_empty_binders(WhereClause::AliasEq(alias_eq)));
|
||||
predicates.push(crate::wrap_empty_binders(WhereClause::AliasEq(alias_eq)));
|
||||
}
|
||||
for bound in binding.bounds.iter() {
|
||||
preds.extend(self.lower_type_bound(
|
||||
predicates.extend(self.lower_type_bound(
|
||||
bound,
|
||||
TyKind::Alias(AliasTy::Projection(projection_ty.clone())).intern(Interner),
|
||||
false,
|
||||
));
|
||||
}
|
||||
preds
|
||||
predicates
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -1165,7 +1165,7 @@ impl<'a> TyLoweringContext<'a> {
|
|||
return None;
|
||||
}
|
||||
|
||||
// As multiple occurrences of the same auto traits *are* permitted, we dedulicate the
|
||||
// As multiple occurrences of the same auto traits *are* permitted, we deduplicate the
|
||||
// bounds. We shouldn't have repeated elements besides auto traits at this point.
|
||||
bounds.dedup();
|
||||
|
||||
|
|
Loading…
Reference in a new issue