Merge pull request #18427 from ChayimFriedman2/cleanup-ty

Cleanup TypeRef lowering
This commit is contained in:
Lukas Wirth 2024-10-29 10:00:44 +00:00 committed by GitHub
commit 3fd6a72556
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 151 additions and 170 deletions

View file

@ -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()

View file

@ -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>(

View file

@ -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,

View file

@ -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) => {

View file

@ -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(), &param, 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(), &param, 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) => {

View file

@ -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)
}
}

View file

@ -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)

View file

@ -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> {

View file

@ -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}}")?,
},

View file

@ -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);

View file

@ -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,

View file

@ -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.