mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-13 13:48:50 +00:00
Merge pull request #18427 from ChayimFriedman2/cleanup-ty
Cleanup TypeRef lowering
This commit is contained in:
commit
3fd6a72556
12 changed files with 151 additions and 170 deletions
|
@ -407,7 +407,7 @@ impl ExprCollector<'_> {
|
|||
let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
|
||||
let generic_args = e
|
||||
.generic_arg_list()
|
||||
.and_then(|it| GenericArgs::from_ast(&self.ctx(), it))
|
||||
.and_then(|it| GenericArgs::from_ast(&mut self.ctx(), it))
|
||||
.map(Box::new);
|
||||
self.alloc_expr(
|
||||
Expr::MethodCall { receiver, method_name, args, generic_args },
|
||||
|
@ -533,7 +533,7 @@ impl ExprCollector<'_> {
|
|||
ast::Expr::TryExpr(e) => self.collect_try_operator(syntax_ptr, e),
|
||||
ast::Expr::CastExpr(e) => {
|
||||
let expr = self.collect_expr_opt(e.expr());
|
||||
let type_ref = TypeRef::from_ast_opt(&self.ctx(), e.ty());
|
||||
let type_ref = TypeRef::from_ast_opt(&mut self.ctx(), e.ty());
|
||||
self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr)
|
||||
}
|
||||
ast::Expr::RefExpr(e) => {
|
||||
|
@ -572,13 +572,15 @@ impl ExprCollector<'_> {
|
|||
arg_types.reserve_exact(num_params);
|
||||
for param in pl.params() {
|
||||
let pat = this.collect_pat_top(param.pat());
|
||||
let type_ref = param.ty().map(|it| TypeRef::from_ast(&this.ctx(), it));
|
||||
let type_ref = param.ty().map(|it| TypeRef::from_ast(&mut this.ctx(), it));
|
||||
args.push(pat);
|
||||
arg_types.push(type_ref);
|
||||
}
|
||||
}
|
||||
let ret_type =
|
||||
e.ret_type().and_then(|r| r.ty()).map(|it| TypeRef::from_ast(&this.ctx(), it));
|
||||
let ret_type = e
|
||||
.ret_type()
|
||||
.and_then(|r| r.ty())
|
||||
.map(|it| TypeRef::from_ast(&mut this.ctx(), it));
|
||||
|
||||
let prev_is_lowering_coroutine = mem::take(&mut this.is_lowering_coroutine);
|
||||
let prev_try_block_label = this.current_try_block_label.take();
|
||||
|
@ -705,7 +707,7 @@ impl ExprCollector<'_> {
|
|||
ast::Expr::UnderscoreExpr(_) => self.alloc_expr(Expr::Underscore, syntax_ptr),
|
||||
ast::Expr::AsmExpr(e) => self.lower_inline_asm(e, syntax_ptr),
|
||||
ast::Expr::OffsetOfExpr(e) => {
|
||||
let container = TypeRef::from_ast_opt(&self.ctx(), e.ty());
|
||||
let container = TypeRef::from_ast_opt(&mut self.ctx(), e.ty());
|
||||
let fields = e.fields().map(|it| it.as_name()).collect();
|
||||
self.alloc_expr(Expr::OffsetOf(OffsetOf { container, fields }), syntax_ptr)
|
||||
}
|
||||
|
@ -1317,7 +1319,7 @@ impl ExprCollector<'_> {
|
|||
return;
|
||||
}
|
||||
let pat = self.collect_pat_top(stmt.pat());
|
||||
let type_ref = stmt.ty().map(|it| TypeRef::from_ast(&self.ctx(), it));
|
||||
let type_ref = stmt.ty().map(|it| TypeRef::from_ast(&mut self.ctx(), it));
|
||||
let initializer = stmt.initializer().map(|e| self.collect_expr(e));
|
||||
let else_branch = stmt
|
||||
.let_else()
|
||||
|
|
|
@ -161,14 +161,14 @@ impl Expander {
|
|||
types_map: &mut TypesMap,
|
||||
types_source_map: &mut TypesSourceMap,
|
||||
) -> Option<Path> {
|
||||
let ctx = LowerCtx::with_span_map_cell(
|
||||
let mut ctx = LowerCtx::with_span_map_cell(
|
||||
db,
|
||||
self.current_file_id,
|
||||
self.span_map.clone(),
|
||||
types_map,
|
||||
types_source_map,
|
||||
);
|
||||
Path::from_src(&ctx, path)
|
||||
Path::from_src(&mut ctx, path)
|
||||
}
|
||||
|
||||
fn within_limit<F, T: ast::AstNode>(
|
||||
|
|
|
@ -451,7 +451,7 @@ pub(crate) struct GenericParamsCollector {
|
|||
impl GenericParamsCollector {
|
||||
pub(crate) fn fill(
|
||||
&mut self,
|
||||
lower_ctx: &LowerCtx<'_>,
|
||||
lower_ctx: &mut LowerCtx<'_>,
|
||||
node: &dyn HasGenericParams,
|
||||
add_param_attrs: impl FnMut(
|
||||
Either<LocalTypeOrConstParamId, LocalLifetimeParamId>,
|
||||
|
@ -468,7 +468,7 @@ impl GenericParamsCollector {
|
|||
|
||||
pub(crate) fn fill_bounds(
|
||||
&mut self,
|
||||
lower_ctx: &LowerCtx<'_>,
|
||||
lower_ctx: &mut LowerCtx<'_>,
|
||||
type_bounds: Option<ast::TypeBoundList>,
|
||||
target: Either<TypeRefId, LifetimeRef>,
|
||||
) {
|
||||
|
@ -479,7 +479,7 @@ impl GenericParamsCollector {
|
|||
|
||||
fn fill_params(
|
||||
&mut self,
|
||||
lower_ctx: &LowerCtx<'_>,
|
||||
lower_ctx: &mut LowerCtx<'_>,
|
||||
params: ast::GenericParamList,
|
||||
mut add_param_attrs: impl FnMut(
|
||||
Either<LocalTypeOrConstParamId, LocalLifetimeParamId>,
|
||||
|
@ -535,7 +535,11 @@ impl GenericParamsCollector {
|
|||
}
|
||||
}
|
||||
|
||||
fn fill_where_predicates(&mut self, lower_ctx: &LowerCtx<'_>, where_clause: ast::WhereClause) {
|
||||
fn fill_where_predicates(
|
||||
&mut self,
|
||||
lower_ctx: &mut LowerCtx<'_>,
|
||||
where_clause: ast::WhereClause,
|
||||
) {
|
||||
for pred in where_clause.predicates() {
|
||||
let target = if let Some(type_ref) = pred.ty() {
|
||||
Either::Left(TypeRef::from_ast(lower_ctx, type_ref))
|
||||
|
@ -569,7 +573,7 @@ impl GenericParamsCollector {
|
|||
|
||||
fn add_where_predicate_from_bound(
|
||||
&mut self,
|
||||
lower_ctx: &LowerCtx<'_>,
|
||||
lower_ctx: &mut LowerCtx<'_>,
|
||||
bound: ast::TypeBound,
|
||||
hrtb_lifetimes: Option<&[Name]>,
|
||||
target: Either<TypeRefId, LifetimeRef>,
|
||||
|
@ -670,8 +674,9 @@ impl GenericParamsCollector {
|
|||
{
|
||||
let (mut macro_types_map, mut macro_types_source_map) =
|
||||
(TypesMap::default(), TypesSourceMap::default());
|
||||
let ctx = expander.ctx(db, &mut macro_types_map, &mut macro_types_source_map);
|
||||
let type_ref = TypeRef::from_ast(&ctx, expanded.tree());
|
||||
let mut ctx =
|
||||
expander.ctx(db, &mut macro_types_map, &mut macro_types_source_map);
|
||||
let type_ref = TypeRef::from_ast(&mut ctx, expanded.tree());
|
||||
self.fill_implicit_impl_trait_args(
|
||||
db,
|
||||
generics_types_map,
|
||||
|
|
|
@ -98,7 +98,7 @@ pub struct TraitRef {
|
|||
|
||||
impl TraitRef {
|
||||
/// Converts an `ast::PathType` to a `hir::TraitRef`.
|
||||
pub(crate) fn from_ast(ctx: &LowerCtx<'_>, node: ast::Type) -> Option<Self> {
|
||||
pub(crate) fn from_ast(ctx: &mut LowerCtx<'_>, node: ast::Type) -> Option<Self> {
|
||||
// FIXME: Use `Path::from_src`
|
||||
match node {
|
||||
ast::Type::PathType(path) => {
|
||||
|
@ -240,7 +240,7 @@ pub enum TraitBoundModifier {
|
|||
|
||||
impl TypeRef {
|
||||
/// Converts an `ast::TypeRef` to a `hir::TypeRef`.
|
||||
pub fn from_ast(ctx: &LowerCtx<'_>, node: ast::Type) -> TypeRefId {
|
||||
pub fn from_ast(ctx: &mut LowerCtx<'_>, node: ast::Type) -> TypeRefId {
|
||||
let ty = match &node {
|
||||
ast::Type::ParenType(inner) => return TypeRef::from_ast_opt(ctx, inner.ty()),
|
||||
ast::Type::TupleType(inner) => TypeRef::Tuple(EmptyOptimizedThinVec::from_iter(
|
||||
|
@ -321,8 +321,9 @@ impl TypeRef {
|
|||
// Disallow nested impl traits
|
||||
TypeRef::Error
|
||||
} else {
|
||||
let _guard = ctx.outer_impl_trait_scope(true);
|
||||
TypeRef::ImplTrait(type_bounds_from_ast(ctx, inner.type_bound_list()))
|
||||
ctx.with_outer_impl_trait_scope(true, |ctx| {
|
||||
TypeRef::ImplTrait(type_bounds_from_ast(ctx, inner.type_bound_list()))
|
||||
})
|
||||
}
|
||||
}
|
||||
ast::Type::DynTraitType(inner) => {
|
||||
|
@ -336,7 +337,7 @@ impl TypeRef {
|
|||
ctx.alloc_type_ref(ty, AstPtr::new(&node))
|
||||
}
|
||||
|
||||
pub(crate) fn from_ast_opt(ctx: &LowerCtx<'_>, node: Option<ast::Type>) -> TypeRefId {
|
||||
pub(crate) fn from_ast_opt(ctx: &mut LowerCtx<'_>, node: Option<ast::Type>) -> TypeRefId {
|
||||
match node {
|
||||
Some(node) => TypeRef::from_ast(ctx, node),
|
||||
None => ctx.alloc_error_type(),
|
||||
|
@ -410,7 +411,7 @@ impl TypeRef {
|
|||
}
|
||||
|
||||
pub(crate) fn type_bounds_from_ast(
|
||||
lower_ctx: &LowerCtx<'_>,
|
||||
lower_ctx: &mut LowerCtx<'_>,
|
||||
type_bounds_opt: Option<ast::TypeBoundList>,
|
||||
) -> ThinVec<TypeBound> {
|
||||
if let Some(type_bounds) = type_bounds_opt {
|
||||
|
@ -423,8 +424,8 @@ pub(crate) fn type_bounds_from_ast(
|
|||
}
|
||||
|
||||
impl TypeBound {
|
||||
pub(crate) fn from_ast(ctx: &LowerCtx<'_>, node: ast::TypeBound) -> Self {
|
||||
let lower_path_type = |path_type: ast::PathType| ctx.lower_path(path_type.path()?);
|
||||
pub(crate) fn from_ast(ctx: &mut LowerCtx<'_>, node: ast::TypeBound) -> Self {
|
||||
let mut lower_path_type = |path_type: ast::PathType| ctx.lower_path(path_type.path()?);
|
||||
|
||||
match node.kind() {
|
||||
ast::TypeBoundKind::PathType(path_type) => {
|
||||
|
|
|
@ -234,11 +234,11 @@ impl<'a> Ctx<'a> {
|
|||
fn lower_struct(&mut self, strukt: &ast::Struct) -> Option<FileItemTreeId<Struct>> {
|
||||
let (mut types_map, mut types_source_map) =
|
||||
(TypesMap::default(), TypesSourceMap::default());
|
||||
let body_ctx = self.body_ctx(&mut types_map, &mut types_source_map);
|
||||
let mut body_ctx = self.body_ctx(&mut types_map, &mut types_source_map);
|
||||
let visibility = self.lower_visibility(strukt);
|
||||
let name = strukt.name()?.as_name();
|
||||
let ast_id = self.source_ast_id_map.ast_id(strukt);
|
||||
let (fields, kind, attrs) = self.lower_fields(&strukt.kind(), &body_ctx);
|
||||
let (fields, kind, attrs) = self.lower_fields(&strukt.kind(), &mut body_ctx);
|
||||
let (generic_params, generics_source_map) =
|
||||
self.lower_generic_params(HasImplicitSelf::No, strukt);
|
||||
types_map.shrink_to_fit();
|
||||
|
@ -273,7 +273,7 @@ impl<'a> Ctx<'a> {
|
|||
fn lower_fields(
|
||||
&mut self,
|
||||
strukt_kind: &ast::StructKind,
|
||||
body_ctx: &LowerCtx<'_>,
|
||||
body_ctx: &mut LowerCtx<'_>,
|
||||
) -> (Box<[Field]>, FieldsShape, Vec<(usize, RawAttrs)>) {
|
||||
match strukt_kind {
|
||||
ast::StructKind::Record(it) => {
|
||||
|
@ -308,7 +308,11 @@ impl<'a> Ctx<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn lower_record_field(&mut self, field: &ast::RecordField, body_ctx: &LowerCtx<'_>) -> Field {
|
||||
fn lower_record_field(
|
||||
&mut self,
|
||||
field: &ast::RecordField,
|
||||
body_ctx: &mut LowerCtx<'_>,
|
||||
) -> Field {
|
||||
let name = match field.name() {
|
||||
Some(name) => name.as_name(),
|
||||
None => Name::missing(),
|
||||
|
@ -323,7 +327,7 @@ impl<'a> Ctx<'a> {
|
|||
&mut self,
|
||||
idx: usize,
|
||||
field: &ast::TupleField,
|
||||
body_ctx: &LowerCtx<'_>,
|
||||
body_ctx: &mut LowerCtx<'_>,
|
||||
) -> Field {
|
||||
let name = Name::new_tuple_field(idx);
|
||||
let visibility = self.lower_visibility(field);
|
||||
|
@ -334,13 +338,13 @@ impl<'a> Ctx<'a> {
|
|||
fn lower_union(&mut self, union: &ast::Union) -> Option<FileItemTreeId<Union>> {
|
||||
let (mut types_map, mut types_source_map) =
|
||||
(TypesMap::default(), TypesSourceMap::default());
|
||||
let body_ctx = self.body_ctx(&mut types_map, &mut types_source_map);
|
||||
let mut body_ctx = self.body_ctx(&mut types_map, &mut types_source_map);
|
||||
let visibility = self.lower_visibility(union);
|
||||
let name = union.name()?.as_name();
|
||||
let ast_id = self.source_ast_id_map.ast_id(union);
|
||||
let (fields, _, attrs) = match union.record_field_list() {
|
||||
Some(record_field_list) => {
|
||||
self.lower_fields(&StructKind::Record(record_field_list), &body_ctx)
|
||||
self.lower_fields(&StructKind::Record(record_field_list), &mut body_ctx)
|
||||
}
|
||||
None => (Box::default(), FieldsShape::Record, Vec::default()),
|
||||
};
|
||||
|
@ -409,12 +413,12 @@ impl<'a> Ctx<'a> {
|
|||
fn lower_variant(&mut self, variant: &ast::Variant) -> Idx<Variant> {
|
||||
let (mut types_map, mut types_source_map) =
|
||||
(TypesMap::default(), TypesSourceMap::default());
|
||||
let body_ctx = self.body_ctx(&mut types_map, &mut types_source_map);
|
||||
let mut body_ctx = self.body_ctx(&mut types_map, &mut types_source_map);
|
||||
let name = match variant.name() {
|
||||
Some(name) => name.as_name(),
|
||||
None => Name::missing(),
|
||||
};
|
||||
let (fields, kind, attrs) = self.lower_fields(&variant.kind(), &body_ctx);
|
||||
let (fields, kind, attrs) = self.lower_fields(&variant.kind(), &mut body_ctx);
|
||||
let ast_id = self.source_ast_id_map.ast_id(variant);
|
||||
types_map.shrink_to_fit();
|
||||
types_source_map.shrink_to_fit();
|
||||
|
@ -436,7 +440,7 @@ impl<'a> Ctx<'a> {
|
|||
fn lower_function(&mut self, func: &ast::Fn) -> Option<FileItemTreeId<Function>> {
|
||||
let (mut types_map, mut types_source_map) =
|
||||
(TypesMap::default(), TypesSourceMap::default());
|
||||
let body_ctx = self.body_ctx(&mut types_map, &mut types_source_map);
|
||||
let mut body_ctx = self.body_ctx(&mut types_map, &mut types_source_map);
|
||||
|
||||
let visibility = self.lower_visibility(func);
|
||||
let name = func.name()?.as_name();
|
||||
|
@ -457,7 +461,7 @@ impl<'a> Ctx<'a> {
|
|||
RawAttrs::new(self.db.upcast(), &self_param, self.span_map()),
|
||||
);
|
||||
let self_type = match self_param.ty() {
|
||||
Some(type_ref) => TypeRef::from_ast(&body_ctx, type_ref),
|
||||
Some(type_ref) => TypeRef::from_ast(&mut body_ctx, type_ref),
|
||||
None => {
|
||||
let self_type = body_ctx.alloc_type_ref_desugared(TypeRef::Path(
|
||||
Name::new_symbol_root(sym::Self_.clone()).into(),
|
||||
|
@ -492,7 +496,7 @@ impl<'a> Ctx<'a> {
|
|||
Param { type_ref: None }
|
||||
}
|
||||
None => {
|
||||
let type_ref = TypeRef::from_ast_opt(&body_ctx, param.ty());
|
||||
let type_ref = TypeRef::from_ast_opt(&mut body_ctx, param.ty());
|
||||
Param { type_ref: Some(type_ref) }
|
||||
}
|
||||
};
|
||||
|
@ -502,7 +506,7 @@ impl<'a> Ctx<'a> {
|
|||
|
||||
let ret_type = match func.ret_type() {
|
||||
Some(rt) => match rt.ty() {
|
||||
Some(type_ref) => TypeRef::from_ast(&body_ctx, type_ref),
|
||||
Some(type_ref) => TypeRef::from_ast(&mut body_ctx, type_ref),
|
||||
None if rt.thin_arrow_token().is_some() => body_ctx.alloc_error_type(),
|
||||
None => body_ctx.alloc_type_ref_desugared(TypeRef::unit()),
|
||||
},
|
||||
|
@ -581,11 +585,11 @@ impl<'a> Ctx<'a> {
|
|||
) -> Option<FileItemTreeId<TypeAlias>> {
|
||||
let (mut types_map, mut types_source_map) =
|
||||
(TypesMap::default(), TypesSourceMap::default());
|
||||
let body_ctx = self.body_ctx(&mut types_map, &mut types_source_map);
|
||||
let mut body_ctx = self.body_ctx(&mut types_map, &mut types_source_map);
|
||||
let name = type_alias.name()?.as_name();
|
||||
let type_ref = type_alias.ty().map(|it| TypeRef::from_ast(&body_ctx, it));
|
||||
let type_ref = type_alias.ty().map(|it| TypeRef::from_ast(&mut body_ctx, it));
|
||||
let visibility = self.lower_visibility(type_alias);
|
||||
let bounds = self.lower_type_bounds(type_alias, &body_ctx);
|
||||
let bounds = self.lower_type_bounds(type_alias, &mut body_ctx);
|
||||
let ast_id = self.source_ast_id_map.ast_id(type_alias);
|
||||
let (generic_params, generics_source_map) =
|
||||
self.lower_generic_params(HasImplicitSelf::No, type_alias);
|
||||
|
@ -612,9 +616,9 @@ impl<'a> Ctx<'a> {
|
|||
fn lower_static(&mut self, static_: &ast::Static) -> Option<FileItemTreeId<Static>> {
|
||||
let (mut types_map, mut types_source_map) =
|
||||
(TypesMap::default(), TypesSourceMap::default());
|
||||
let body_ctx = self.body_ctx(&mut types_map, &mut types_source_map);
|
||||
let mut body_ctx = self.body_ctx(&mut types_map, &mut types_source_map);
|
||||
let name = static_.name()?.as_name();
|
||||
let type_ref = TypeRef::from_ast_opt(&body_ctx, static_.ty());
|
||||
let type_ref = TypeRef::from_ast_opt(&mut body_ctx, static_.ty());
|
||||
let visibility = self.lower_visibility(static_);
|
||||
let mutable = static_.mut_token().is_some();
|
||||
let has_safe_kw = static_.safe_token().is_some();
|
||||
|
@ -639,9 +643,9 @@ impl<'a> Ctx<'a> {
|
|||
fn lower_const(&mut self, konst: &ast::Const) -> FileItemTreeId<Const> {
|
||||
let (mut types_map, mut types_source_map) =
|
||||
(TypesMap::default(), TypesSourceMap::default());
|
||||
let body_ctx = self.body_ctx(&mut types_map, &mut types_source_map);
|
||||
let mut body_ctx = self.body_ctx(&mut types_map, &mut types_source_map);
|
||||
let name = konst.name().map(|it| it.as_name());
|
||||
let type_ref = TypeRef::from_ast_opt(&body_ctx, konst.ty());
|
||||
let type_ref = TypeRef::from_ast_opt(&mut body_ctx, konst.ty());
|
||||
let visibility = self.lower_visibility(konst);
|
||||
let ast_id = self.source_ast_id_map.ast_id(konst);
|
||||
types_map.shrink_to_fit();
|
||||
|
@ -724,14 +728,14 @@ impl<'a> Ctx<'a> {
|
|||
fn lower_impl(&mut self, impl_def: &ast::Impl) -> FileItemTreeId<Impl> {
|
||||
let (mut types_map, mut types_source_map) =
|
||||
(TypesMap::default(), TypesSourceMap::default());
|
||||
let body_ctx = self.body_ctx(&mut types_map, &mut types_source_map);
|
||||
let mut body_ctx = self.body_ctx(&mut types_map, &mut types_source_map);
|
||||
|
||||
let ast_id = self.source_ast_id_map.ast_id(impl_def);
|
||||
// FIXME: If trait lowering fails, due to a non PathType for example, we treat this impl
|
||||
// as if it was an non-trait impl. Ideally we want to create a unique missing ref that only
|
||||
// equals itself.
|
||||
let self_ty = TypeRef::from_ast_opt(&body_ctx, impl_def.self_ty());
|
||||
let target_trait = impl_def.trait_().and_then(|tr| TraitRef::from_ast(&body_ctx, tr));
|
||||
let self_ty = TypeRef::from_ast_opt(&mut body_ctx, impl_def.self_ty());
|
||||
let target_trait = impl_def.trait_().and_then(|tr| TraitRef::from_ast(&mut body_ctx, tr));
|
||||
let is_negative = impl_def.excl_token().is_some();
|
||||
let is_unsafe = impl_def.unsafe_token().is_some();
|
||||
|
||||
|
@ -870,13 +874,8 @@ impl<'a> Ctx<'a> {
|
|||
) -> (Arc<GenericParams>, TypesSourceMap) {
|
||||
let (mut types_map, mut types_source_map) =
|
||||
(TypesMap::default(), TypesSourceMap::default());
|
||||
let body_ctx = self.body_ctx(&mut types_map, &mut types_source_map);
|
||||
let mut body_ctx = self.body_ctx(&mut types_map, &mut types_source_map);
|
||||
debug_assert!(self.generic_param_attr_buffer.is_empty(),);
|
||||
let add_param_attrs = |item: Either<LocalTypeOrConstParamId, LocalLifetimeParamId>,
|
||||
param| {
|
||||
let attrs = RawAttrs::new(self.db.upcast(), ¶m, body_ctx.span_map());
|
||||
debug_assert!(self.generic_param_attr_buffer.insert(item, attrs).is_none());
|
||||
};
|
||||
body_ctx.take_impl_traits_bounds();
|
||||
let mut generics = GenericParamsCollector::default();
|
||||
|
||||
|
@ -892,16 +891,19 @@ impl<'a> Ctx<'a> {
|
|||
);
|
||||
// add super traits as bounds on Self
|
||||
// i.e., `trait Foo: Bar` is equivalent to `trait Foo where Self: Bar`
|
||||
generics.fill_bounds(
|
||||
&body_ctx,
|
||||
bounds,
|
||||
Either::Left(body_ctx.alloc_type_ref_desugared(TypeRef::Path(
|
||||
Name::new_symbol_root(sym::Self_.clone()).into(),
|
||||
))),
|
||||
);
|
||||
let bound_target = Either::Left(body_ctx.alloc_type_ref_desugared(TypeRef::Path(
|
||||
Name::new_symbol_root(sym::Self_.clone()).into(),
|
||||
)));
|
||||
generics.fill_bounds(&mut body_ctx, bounds, bound_target);
|
||||
}
|
||||
|
||||
generics.fill(&body_ctx, node, add_param_attrs);
|
||||
let span_map = body_ctx.span_map().clone();
|
||||
let add_param_attrs = |item: Either<LocalTypeOrConstParamId, LocalLifetimeParamId>,
|
||||
param| {
|
||||
let attrs = RawAttrs::new(self.db.upcast(), ¶m, span_map.as_ref());
|
||||
debug_assert!(self.generic_param_attr_buffer.insert(item, attrs).is_none());
|
||||
};
|
||||
generics.fill(&mut body_ctx, node, add_param_attrs);
|
||||
|
||||
let generics = generics.finish(types_map, &mut types_source_map);
|
||||
(generics, types_source_map)
|
||||
|
@ -910,7 +912,7 @@ impl<'a> Ctx<'a> {
|
|||
fn lower_type_bounds(
|
||||
&mut self,
|
||||
node: &dyn ast::HasTypeBounds,
|
||||
body_ctx: &LowerCtx<'_>,
|
||||
body_ctx: &mut LowerCtx<'_>,
|
||||
) -> Box<[TypeBound]> {
|
||||
match node.type_bound_list() {
|
||||
Some(bound_list) => {
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
//! Context for lowering paths.
|
||||
use std::cell::{OnceCell, RefCell};
|
||||
use std::{cell::OnceCell, mem};
|
||||
|
||||
use hir_expand::{
|
||||
span_map::{SpanMap, SpanMapRef},
|
||||
AstId, HirFileId, InFile,
|
||||
};
|
||||
use hir_expand::{span_map::SpanMap, AstId, HirFileId, InFile};
|
||||
use span::{AstIdMap, AstIdNode};
|
||||
use stdx::thin_vec::ThinVec;
|
||||
use syntax::ast;
|
||||
|
@ -21,28 +18,11 @@ pub struct LowerCtx<'a> {
|
|||
file_id: HirFileId,
|
||||
span_map: OnceCell<SpanMap>,
|
||||
ast_id_map: OnceCell<Arc<AstIdMap>>,
|
||||
impl_trait_bounds: RefCell<Vec<ThinVec<TypeBound>>>,
|
||||
impl_trait_bounds: Vec<ThinVec<TypeBound>>,
|
||||
// Prevent nested impl traits like `impl Foo<impl Bar>`.
|
||||
outer_impl_trait: RefCell<bool>,
|
||||
types_map: RefCell<(&'a mut TypesMap, &'a mut TypesSourceMap)>,
|
||||
}
|
||||
|
||||
pub(crate) struct OuterImplTraitGuard<'a, 'b> {
|
||||
ctx: &'a LowerCtx<'b>,
|
||||
old: bool,
|
||||
}
|
||||
|
||||
impl<'a, 'b> OuterImplTraitGuard<'a, 'b> {
|
||||
fn new(ctx: &'a LowerCtx<'b>, impl_trait: bool) -> Self {
|
||||
let old = ctx.outer_impl_trait.replace(impl_trait);
|
||||
Self { ctx, old }
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for OuterImplTraitGuard<'_, '_> {
|
||||
fn drop(&mut self) {
|
||||
self.ctx.outer_impl_trait.replace(self.old);
|
||||
}
|
||||
outer_impl_trait: bool,
|
||||
types_map: &'a mut TypesMap,
|
||||
types_source_map: &'a mut TypesSourceMap,
|
||||
}
|
||||
|
||||
impl<'a> LowerCtx<'a> {
|
||||
|
@ -57,9 +37,10 @@ impl<'a> LowerCtx<'a> {
|
|||
file_id,
|
||||
span_map: OnceCell::new(),
|
||||
ast_id_map: OnceCell::new(),
|
||||
impl_trait_bounds: RefCell::new(Vec::new()),
|
||||
outer_impl_trait: RefCell::default(),
|
||||
types_map: RefCell::new((types_map, types_source_map)),
|
||||
impl_trait_bounds: Vec::new(),
|
||||
outer_impl_trait: false,
|
||||
types_map,
|
||||
types_source_map,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -75,17 +56,18 @@ impl<'a> LowerCtx<'a> {
|
|||
file_id,
|
||||
span_map,
|
||||
ast_id_map: OnceCell::new(),
|
||||
impl_trait_bounds: RefCell::new(Vec::new()),
|
||||
outer_impl_trait: RefCell::default(),
|
||||
types_map: RefCell::new((types_map, types_source_map)),
|
||||
impl_trait_bounds: Vec::new(),
|
||||
outer_impl_trait: false,
|
||||
types_map,
|
||||
types_source_map,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn span_map(&self) -> SpanMapRef<'_> {
|
||||
self.span_map.get_or_init(|| self.db.span_map(self.file_id)).as_ref()
|
||||
pub(crate) fn span_map(&self) -> &SpanMap {
|
||||
self.span_map.get_or_init(|| self.db.span_map(self.file_id))
|
||||
}
|
||||
|
||||
pub(crate) fn lower_path(&self, ast: ast::Path) -> Option<Path> {
|
||||
pub(crate) fn lower_path(&mut self, ast: ast::Path) -> Option<Path> {
|
||||
Path::from_src(self, ast)
|
||||
}
|
||||
|
||||
|
@ -96,44 +78,44 @@ impl<'a> LowerCtx<'a> {
|
|||
)
|
||||
}
|
||||
|
||||
pub fn update_impl_traits_bounds(&self, bounds: ThinVec<TypeBound>) {
|
||||
self.impl_trait_bounds.borrow_mut().push(bounds);
|
||||
pub fn update_impl_traits_bounds_from_type_ref(&mut self, type_ref: TypeRefId) {
|
||||
TypeRef::walk(type_ref, self.types_map, &mut |tr| {
|
||||
if let TypeRef::ImplTrait(bounds) = tr {
|
||||
self.impl_trait_bounds.push(bounds.clone());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
pub fn take_impl_traits_bounds(&self) -> Vec<ThinVec<TypeBound>> {
|
||||
self.impl_trait_bounds.take()
|
||||
pub fn take_impl_traits_bounds(&mut self) -> Vec<ThinVec<TypeBound>> {
|
||||
mem::take(&mut self.impl_trait_bounds)
|
||||
}
|
||||
|
||||
pub(crate) fn outer_impl_trait(&self) -> bool {
|
||||
*self.outer_impl_trait.borrow()
|
||||
self.outer_impl_trait
|
||||
}
|
||||
|
||||
pub(crate) fn outer_impl_trait_scope<'b>(
|
||||
&'b self,
|
||||
pub(crate) fn with_outer_impl_trait_scope<R>(
|
||||
&mut self,
|
||||
impl_trait: bool,
|
||||
) -> OuterImplTraitGuard<'b, 'a> {
|
||||
OuterImplTraitGuard::new(self, impl_trait)
|
||||
f: impl FnOnce(&mut Self) -> R,
|
||||
) -> R {
|
||||
let old = mem::replace(&mut self.outer_impl_trait, impl_trait);
|
||||
let result = f(self);
|
||||
self.outer_impl_trait = old;
|
||||
result
|
||||
}
|
||||
|
||||
pub(crate) fn alloc_type_ref(&self, type_ref: TypeRef, node: TypePtr) -> TypeRefId {
|
||||
let mut types_map = self.types_map.borrow_mut();
|
||||
let (types_map, types_source_map) = &mut *types_map;
|
||||
let id = types_map.types.alloc(type_ref);
|
||||
types_source_map.types_map_back.insert(id, InFile::new(self.file_id, node));
|
||||
pub(crate) fn alloc_type_ref(&mut self, type_ref: TypeRef, node: TypePtr) -> TypeRefId {
|
||||
let id = self.types_map.types.alloc(type_ref);
|
||||
self.types_source_map.types_map_back.insert(id, InFile::new(self.file_id, node));
|
||||
id
|
||||
}
|
||||
|
||||
pub(crate) fn alloc_type_ref_desugared(&self, type_ref: TypeRef) -> TypeRefId {
|
||||
self.types_map.borrow_mut().0.types.alloc(type_ref)
|
||||
pub(crate) fn alloc_type_ref_desugared(&mut self, type_ref: TypeRef) -> TypeRefId {
|
||||
self.types_map.types.alloc(type_ref)
|
||||
}
|
||||
|
||||
pub(crate) fn alloc_error_type(&self) -> TypeRefId {
|
||||
self.types_map.borrow_mut().0.types.alloc(TypeRef::Error)
|
||||
}
|
||||
|
||||
// FIXME: If we alloc while holding this, well... Bad Things will happen. Need to change this
|
||||
// to use proper mutability instead of interior mutability.
|
||||
pub(crate) fn types_map(&self) -> std::cell::Ref<'_, TypesMap> {
|
||||
std::cell::Ref::map(self.types_map.borrow(), |it| &*it.0)
|
||||
pub(crate) fn alloc_error_type(&mut self) -> TypeRefId {
|
||||
self.types_map.types.alloc(TypeRef::Error)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -121,7 +121,7 @@ pub enum GenericArg {
|
|||
impl Path {
|
||||
/// Converts an `ast::Path` to `Path`. Works with use trees.
|
||||
/// It correctly handles `$crate` based path from macro call.
|
||||
pub fn from_src(ctx: &LowerCtx<'_>, path: ast::Path) -> Option<Path> {
|
||||
pub fn from_src(ctx: &mut LowerCtx<'_>, path: ast::Path) -> Option<Path> {
|
||||
lower::lower_path(ctx, path)
|
||||
}
|
||||
|
||||
|
@ -284,7 +284,7 @@ impl<'a> PathSegments<'a> {
|
|||
|
||||
impl GenericArgs {
|
||||
pub(crate) fn from_ast(
|
||||
lower_ctx: &LowerCtx<'_>,
|
||||
lower_ctx: &mut LowerCtx<'_>,
|
||||
node: ast::GenericArgList,
|
||||
) -> Option<GenericArgs> {
|
||||
lower::lower_generic_args(lower_ctx, node)
|
||||
|
|
|
@ -19,12 +19,11 @@ use crate::{
|
|||
|
||||
/// Converts an `ast::Path` to `Path`. Works with use trees.
|
||||
/// It correctly handles `$crate` based path from macro call.
|
||||
pub(super) fn lower_path(ctx: &LowerCtx<'_>, mut path: ast::Path) -> Option<Path> {
|
||||
pub(super) fn lower_path(ctx: &mut LowerCtx<'_>, mut path: ast::Path) -> Option<Path> {
|
||||
let mut kind = PathKind::Plain;
|
||||
let mut type_anchor = None;
|
||||
let mut segments = Vec::new();
|
||||
let mut generic_args = Vec::new();
|
||||
let span_map = ctx.span_map();
|
||||
loop {
|
||||
let segment = path.segment()?;
|
||||
|
||||
|
@ -37,7 +36,7 @@ pub(super) fn lower_path(ctx: &LowerCtx<'_>, mut path: ast::Path) -> Option<Path
|
|||
if name_ref.text() == "$crate" {
|
||||
break kind = resolve_crate_root(
|
||||
ctx.db.upcast(),
|
||||
span_map.span_for_range(name_ref.syntax().text_range()).ctx,
|
||||
ctx.span_map().span_for_range(name_ref.syntax().text_range()).ctx,
|
||||
)
|
||||
.map(PathKind::DollarCrate)
|
||||
.unwrap_or(PathKind::Crate);
|
||||
|
@ -151,7 +150,7 @@ pub(super) fn lower_path(ctx: &LowerCtx<'_>, mut path: ast::Path) -> Option<Path
|
|||
// We follow what it did anyway :)
|
||||
if segments.len() == 1 && kind == PathKind::Plain {
|
||||
if let Some(_macro_call) = path.syntax().parent().and_then(ast::MacroCall::cast) {
|
||||
let syn_ctxt = span_map.span_for_range(path.segment()?.syntax().text_range()).ctx;
|
||||
let syn_ctxt = ctx.span_map().span_for_range(path.segment()?.syntax().text_range()).ctx;
|
||||
if let Some(macro_call_id) = ctx.db.lookup_intern_syntax_context(syn_ctxt).outer_expn {
|
||||
if ctx.db.lookup_intern_macro_call(macro_call_id).def.local_inner {
|
||||
kind = match resolve_crate_root(ctx.db.upcast(), syn_ctxt) {
|
||||
|
@ -183,7 +182,7 @@ pub(super) fn lower_path(ctx: &LowerCtx<'_>, mut path: ast::Path) -> Option<Path
|
|||
}
|
||||
|
||||
pub(super) fn lower_generic_args(
|
||||
lower_ctx: &LowerCtx<'_>,
|
||||
lower_ctx: &mut LowerCtx<'_>,
|
||||
node: ast::GenericArgList,
|
||||
) -> Option<GenericArgs> {
|
||||
let mut args = Vec::new();
|
||||
|
@ -192,13 +191,7 @@ pub(super) fn lower_generic_args(
|
|||
match generic_arg {
|
||||
ast::GenericArg::TypeArg(type_arg) => {
|
||||
let type_ref = TypeRef::from_ast_opt(lower_ctx, type_arg.ty());
|
||||
let types_map = lower_ctx.types_map();
|
||||
TypeRef::walk(type_ref, &types_map, &mut |tr| {
|
||||
if let TypeRef::ImplTrait(bounds) = tr {
|
||||
lower_ctx.update_impl_traits_bounds(bounds.clone());
|
||||
}
|
||||
});
|
||||
drop(types_map);
|
||||
lower_ctx.update_impl_traits_bounds_from_type_ref(type_ref);
|
||||
args.push(GenericArg::Type(type_ref));
|
||||
}
|
||||
ast::GenericArg::AssocTypeArg(assoc_type_arg) => {
|
||||
|
@ -208,27 +201,22 @@ pub(super) fn lower_generic_args(
|
|||
}
|
||||
if let Some(name_ref) = assoc_type_arg.name_ref() {
|
||||
// Nested impl traits like `impl Foo<Assoc = impl Bar>` are allowed
|
||||
let _guard = lower_ctx.outer_impl_trait_scope(false);
|
||||
let name = name_ref.as_name();
|
||||
let args = assoc_type_arg
|
||||
.generic_arg_list()
|
||||
.and_then(|args| lower_generic_args(lower_ctx, args));
|
||||
let type_ref = assoc_type_arg.ty().map(|it| TypeRef::from_ast(lower_ctx, it));
|
||||
let type_ref = type_ref.inspect(|&tr| {
|
||||
let types_map = lower_ctx.types_map();
|
||||
TypeRef::walk(tr, &types_map, &mut |tr| {
|
||||
if let TypeRef::ImplTrait(bounds) = tr {
|
||||
lower_ctx.update_impl_traits_bounds(bounds.clone());
|
||||
}
|
||||
});
|
||||
drop(types_map);
|
||||
lower_ctx.with_outer_impl_trait_scope(false, |lower_ctx| {
|
||||
let name = name_ref.as_name();
|
||||
let args = assoc_type_arg
|
||||
.generic_arg_list()
|
||||
.and_then(|args| lower_generic_args(lower_ctx, args));
|
||||
let type_ref =
|
||||
assoc_type_arg.ty().map(|it| TypeRef::from_ast(lower_ctx, it));
|
||||
let type_ref = type_ref
|
||||
.inspect(|&tr| lower_ctx.update_impl_traits_bounds_from_type_ref(tr));
|
||||
let bounds = if let Some(l) = assoc_type_arg.type_bound_list() {
|
||||
l.bounds().map(|it| TypeBound::from_ast(lower_ctx, it)).collect()
|
||||
} else {
|
||||
Box::default()
|
||||
};
|
||||
bindings.push(AssociatedTypeBinding { name, args, type_ref, bounds });
|
||||
});
|
||||
let bounds = if let Some(l) = assoc_type_arg.type_bound_list() {
|
||||
l.bounds().map(|it| TypeBound::from_ast(lower_ctx, it)).collect()
|
||||
} else {
|
||||
Box::default()
|
||||
};
|
||||
bindings.push(AssociatedTypeBinding { name, args, type_ref, bounds });
|
||||
}
|
||||
}
|
||||
ast::GenericArg::LifetimeArg(lifetime_arg) => {
|
||||
|
@ -258,7 +246,7 @@ pub(super) fn lower_generic_args(
|
|||
/// Collect `GenericArgs` from the parts of a fn-like path, i.e. `Fn(X, Y)
|
||||
/// -> Z` (which desugars to `Fn<(X, Y), Output=Z>`).
|
||||
fn lower_generic_args_from_fn_path(
|
||||
ctx: &LowerCtx<'_>,
|
||||
ctx: &mut LowerCtx<'_>,
|
||||
params: Option<ast::ParamList>,
|
||||
ret_type: Option<ast::RetType>,
|
||||
) -> Option<GenericArgs> {
|
||||
|
|
|
@ -2033,7 +2033,7 @@ impl HirDisplayWithTypesMap for TypeRefId {
|
|||
TypeRef::Macro(macro_call) => {
|
||||
let (mut types_map, mut types_source_map) =
|
||||
(TypesMap::default(), TypesSourceMap::default());
|
||||
let ctx = hir_def::lower::LowerCtx::new(
|
||||
let mut ctx = hir_def::lower::LowerCtx::new(
|
||||
f.db.upcast(),
|
||||
macro_call.file_id,
|
||||
&mut types_map,
|
||||
|
@ -2041,7 +2041,7 @@ impl HirDisplayWithTypesMap for TypeRefId {
|
|||
);
|
||||
let macro_call = macro_call.to_node(f.db.upcast());
|
||||
match macro_call.path() {
|
||||
Some(path) => match Path::from_src(&ctx, path) {
|
||||
Some(path) => match Path::from_src(&mut ctx, path) {
|
||||
Some(path) => path.hir_fmt(f, &types_map)?,
|
||||
None => write!(f, "{{macro}}")?,
|
||||
},
|
||||
|
|
|
@ -465,13 +465,13 @@ impl<'a> TyLoweringContext<'a> {
|
|||
let (mut types_map, mut types_source_map) =
|
||||
(TypesMap::default(), TypesSourceMap::default());
|
||||
|
||||
let ctx = expander.ctx(
|
||||
let mut ctx = expander.ctx(
|
||||
self.db.upcast(),
|
||||
&mut types_map,
|
||||
&mut types_source_map,
|
||||
);
|
||||
// FIXME: Report syntax errors in expansion here
|
||||
let type_ref = TypeRef::from_ast(&ctx, expanded.tree());
|
||||
let type_ref = TypeRef::from_ast(&mut ctx, expanded.tree());
|
||||
|
||||
drop(expander);
|
||||
|
||||
|
|
|
@ -1271,9 +1271,9 @@ impl<'db> SemanticsImpl<'db> {
|
|||
let analyze = self.analyze(ty.syntax())?;
|
||||
let (mut types_map, mut types_source_map) =
|
||||
(TypesMap::default(), TypesSourceMap::default());
|
||||
let ctx =
|
||||
let mut ctx =
|
||||
LowerCtx::new(self.db.upcast(), analyze.file_id, &mut types_map, &mut types_source_map);
|
||||
let type_ref = crate::TypeRef::from_ast(&ctx, ty.clone());
|
||||
let type_ref = crate::TypeRef::from_ast(&mut ctx, ty.clone());
|
||||
let ty = hir_ty::TyLoweringContext::new_maybe_unowned(
|
||||
self.db,
|
||||
&analyze.resolver,
|
||||
|
@ -1289,9 +1289,9 @@ impl<'db> SemanticsImpl<'db> {
|
|||
let analyze = self.analyze(path.syntax())?;
|
||||
let (mut types_map, mut types_source_map) =
|
||||
(TypesMap::default(), TypesSourceMap::default());
|
||||
let ctx =
|
||||
let mut ctx =
|
||||
LowerCtx::new(self.db.upcast(), analyze.file_id, &mut types_map, &mut types_source_map);
|
||||
let hir_path = Path::from_src(&ctx, path.clone())?;
|
||||
let hir_path = Path::from_src(&mut ctx, path.clone())?;
|
||||
match analyze.resolver.resolve_path_in_type_ns_fully(self.db.upcast(), &hir_path)? {
|
||||
TypeNs::TraitId(id) => Some(Trait { id }),
|
||||
_ => None,
|
||||
|
@ -1974,9 +1974,9 @@ impl SemanticsScope<'_> {
|
|||
pub fn speculative_resolve(&self, ast_path: &ast::Path) -> Option<PathResolution> {
|
||||
let (mut types_map, mut types_source_map) =
|
||||
(TypesMap::default(), TypesSourceMap::default());
|
||||
let ctx =
|
||||
let mut ctx =
|
||||
LowerCtx::new(self.db.upcast(), self.file_id, &mut types_map, &mut types_source_map);
|
||||
let path = Path::from_src(&ctx, ast_path.clone())?;
|
||||
let path = Path::from_src(&mut ctx, ast_path.clone())?;
|
||||
resolve_hir_path(
|
||||
self.db,
|
||||
&self.resolver,
|
||||
|
|
|
@ -616,9 +616,9 @@ impl SourceAnalyzer {
|
|||
) -> Option<Macro> {
|
||||
let (mut types_map, mut types_source_map) =
|
||||
(TypesMap::default(), TypesSourceMap::default());
|
||||
let ctx =
|
||||
let mut ctx =
|
||||
LowerCtx::new(db.upcast(), macro_call.file_id, &mut types_map, &mut types_source_map);
|
||||
let path = macro_call.value.path().and_then(|ast| Path::from_src(&ctx, ast))?;
|
||||
let path = macro_call.value.path().and_then(|ast| Path::from_src(&mut ctx, ast))?;
|
||||
self.resolver
|
||||
.resolve_path_as_macro(db.upcast(), path.mod_path()?, Some(MacroSubNs::Bang))
|
||||
.map(|(it, _)| it.into())
|
||||
|
@ -731,8 +731,9 @@ impl SourceAnalyzer {
|
|||
|
||||
let (mut types_map, mut types_source_map) =
|
||||
(TypesMap::default(), TypesSourceMap::default());
|
||||
let ctx = LowerCtx::new(db.upcast(), self.file_id, &mut types_map, &mut types_source_map);
|
||||
let hir_path = Path::from_src(&ctx, path.clone())?;
|
||||
let mut ctx =
|
||||
LowerCtx::new(db.upcast(), self.file_id, &mut types_map, &mut types_source_map);
|
||||
let hir_path = Path::from_src(&mut ctx, path.clone())?;
|
||||
|
||||
// Case where path is a qualifier of a use tree, e.g. foo::bar::{Baz, Qux} where we are
|
||||
// trying to resolve foo::bar.
|
||||
|
|
Loading…
Reference in a new issue