use hir_expand::{ast_id_map::AstIdMap, hygiene::Hygiene, name::known, HirFileId};
use syntax::{
- ast::{self, ModuleItemOwner},
+ ast::{self, HasModuleItem},
SyntaxNode, WalkEvent,
};
use crate::{
generics::{GenericParams, TypeParamData, TypeParamProvenance},
- type_ref::{LifetimeRef, TraitRef},
+ type_ref::{LifetimeRef, TraitBoundModifier, TraitRef},
};
use super::*;
}
}
- pub(super) fn lower_module_items(mut self, item_owner: &dyn ModuleItemOwner) -> ItemTree {
+ pub(super) fn lower_module_items(mut self, item_owner: &dyn HasModuleItem) -> ItemTree {
self.tree.top_level =
item_owner.items().flat_map(|item| self.lower_mod_item(&item, false)).collect();
self.tree
.statements()
.filter_map(|stmt| match stmt {
ast::Stmt::Item(item) => Some(item),
+ // Macro calls can be both items and expressions. The syntax library always treats
+ // them as expressions here, so we undo that.
+ ast::Stmt::ExprStmt(es) => match es.expr()? {
+ ast::Expr::MacroCall(call) => {
+ cov_mark::hit!(macro_call_in_macro_stmts_is_added_to_item_tree);
+ Some(call.into())
+ }
+ _ => None,
+ },
_ => None,
})
.flat_map(|item| self.lower_mod_item(&item, false))
ast::Item::ExternBlock(ast) => self.lower_extern_block(ast).into(),
};
- self.add_attrs(item.into(), attrs.clone());
+ self.add_attrs(item.into(), attrs);
Some(item)
}
let name = Name::new_tuple_field(idx);
let visibility = self.lower_visibility(field);
let type_ref = self.lower_type_ref_opt(field.ty());
- let res = Field { name, type_ref, visibility };
- res
+ Field { name, type_ref, visibility }
}
fn lower_union(&mut self, union: &ast::Union) -> Option<FileItemTreeId<Union>> {
let visibility = self.lower_visibility(enum_);
let name = enum_.name()?.as_name();
let generic_params = self.lower_generic_params(GenericsOwner::Enum, enum_);
- let variants = match &enum_.variant_list() {
- Some(variant_list) => self.lower_variants(variant_list),
- None => IdRange::new(self.next_variant_idx()..self.next_variant_idx()),
- };
+ let variants =
+ self.with_inherited_visibility(visibility, |this| match &enum_.variant_list() {
+ Some(variant_list) => this.lower_variants(variant_list),
+ None => IdRange::new(this.next_variant_idx()..this.next_variant_idx()),
+ });
let ast_id = self.source_ast_id_map.ast_id(enum_);
let res = Enum { name, visibility, generic_params, variants, ast_id };
Some(id(self.data().enums.alloc(res)))
_ => TypeRef::unit(),
};
- let ret_type = if func.async_token().is_some() {
+ let (ret_type, async_ret_type) = if func.async_token().is_some() {
+ let async_ret_type = ret_type.clone();
let future_impl = desugar_future_path(ret_type);
- let ty_bound = Interned::new(TypeBound::Path(future_impl));
- TypeRef::ImplTrait(vec![ty_bound])
+ let ty_bound = Interned::new(TypeBound::Path(future_impl, TraitBoundModifier::None));
+ (TypeRef::ImplTrait(vec![ty_bound]), Some(async_ret_type))
} else {
- ret_type
+ (ret_type, None)
};
let abi = func.abi().map(lower_abi);
let mut res = Function {
name,
visibility,
- generic_params: Interned::new(GenericParams::default()),
+ explicit_generic_params: Interned::new(GenericParams::default()),
abi,
params,
ret_type: Interned::new(ret_type),
+ async_ret_type: async_ret_type.map(Interned::new),
ast_id,
flags,
};
- res.generic_params = self.lower_generic_params(GenericsOwner::Function(&res), func);
+ res.explicit_generic_params =
+ self.lower_generic_params(GenericsOwner::Function(&res), func);
Some(id(self.data().functions.alloc(res)))
}
}
fn lower_const(&mut self, konst: &ast::Const) -> FileItemTreeId<Const> {
- let name = konst.name().map(|it| it.as_name());
+ let mut name = konst.name().map(|it| it.as_name());
+ if name.as_ref().map_or(false, |n| n.to_string().starts_with("_DERIVE_")) {
+ // FIXME: this is a hack to treat consts generated by synstructure as unnamed
+ // remove this some time in the future
+ name = None;
+ }
let type_ref = self.lower_type_ref_opt(konst.ty());
let visibility = self.lower_visibility(konst);
let ast_id = self.source_ast_id_map.ast_id(konst);
fn lower_macro_call(&mut self, m: &ast::MacroCall) -> Option<FileItemTreeId<MacroCall>> {
let path = Interned::new(ModPath::from_src(self.db, m.path()?, &self.hygiene)?);
let ast_id = self.source_ast_id_map.ast_id(m);
- let fragment = hir_expand::to_fragment_kind(m);
- let res = MacroCall { path, ast_id, fragment };
+ let expand_to = hir_expand::ExpandTo::from_call_site(m);
+ let res = MacroCall { path, ast_id, expand_to };
Some(id(self.data().macro_calls.alloc(res)))
}
fn lower_generic_params_and_inner_items(
&mut self,
owner: GenericsOwner<'_>,
- node: &impl ast::GenericParamsOwner,
+ node: &dyn ast::HasGenericParams,
) -> Interned<GenericParams> {
// Generics are part of item headers and may contain inner items we need to collect.
if let Some(params) = node.generic_param_list() {
fn lower_generic_params(
&mut self,
owner: GenericsOwner<'_>,
- node: &impl ast::GenericParamsOwner,
+ node: &dyn ast::HasGenericParams,
) -> Interned<GenericParams> {
- let mut sm = &mut Default::default();
let mut generics = GenericParams::default();
match owner {
- GenericsOwner::Function(func) => {
- generics.fill(&self.body_ctx, sm, node);
- // lower `impl Trait` in arguments
- for id in func.params.clone() {
- if let Param::Normal(ty) = &self.data().params[id] {
- generics.fill_implicit_impl_trait_args(ty);
- }
- }
- }
- GenericsOwner::Struct
+ GenericsOwner::Function(_)
+ | GenericsOwner::Struct
| GenericsOwner::Enum
| GenericsOwner::Union
| GenericsOwner::TypeAlias => {
- generics.fill(&self.body_ctx, sm, node);
+ generics.fill(&self.body_ctx, node);
}
GenericsOwner::Trait(trait_def) => {
// traits get the Self type as an implicit first type parameter
- let self_param_id = generics.types.alloc(TypeParamData {
+ generics.types.alloc(TypeParamData {
name: Some(name![Self]),
default: None,
provenance: TypeParamProvenance::TraitSelf,
});
- sm.type_params.insert(self_param_id, Either::Left(trait_def.clone()));
// add super traits as bounds on Self
// i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar
let self_param = TypeRef::Path(name![Self].into());
generics.fill_bounds(&self.body_ctx, trait_def, Either::Left(self_param));
- generics.fill(&self.body_ctx, &mut sm, node);
+ generics.fill(&self.body_ctx, node);
}
GenericsOwner::Impl => {
// Note that we don't add `Self` here: in `impl`s, `Self` is not a
// type-parameter, but rather is a type-alias for impl's target
// type, so this is handled by the resolver.
- generics.fill(&self.body_ctx, &mut sm, node);
+ generics.fill(&self.body_ctx, node);
}
}
Interned::new(generics)
}
- fn lower_type_bounds(&mut self, node: &impl ast::TypeBoundsOwner) -> Vec<Interned<TypeBound>> {
+ fn lower_type_bounds(&mut self, node: &dyn ast::HasTypeBounds) -> Vec<Interned<TypeBound>> {
match node.type_bound_list() {
Some(bound_list) => bound_list
.bounds()
}
}
- fn lower_visibility(&mut self, item: &impl ast::VisibilityOwner) -> RawVisibilityId {
+ fn lower_visibility(&mut self, item: &dyn ast::HasVisibility) -> RawVisibilityId {
let vis = match self.forced_visibility {
Some(vis) => return vis,
None => RawVisibility::from_ast_with_hygiene(self.db, item.visibility(), &self.hygiene),
/// Returns `true` if the given intrinsic is unsafe to call, or false otherwise.
fn is_intrinsic_fn_unsafe(name: &Name) -> bool {
- // Should be kept in sync with https://github.com/rust-lang/rust/blob/c6e4db620a7d2f569f11dcab627430921ea8aacf/compiler/rustc_typeck/src/check/intrinsic.rs#L68
+ // Should be kept in sync with https://github.com/rust-lang/rust/blob/0cd0709f19d316c4796fa71c5f52c8612a5f3771/compiler/rustc_typeck/src/check/intrinsic.rs#L72-L105
![
known::abort,
- known::min_align_of,
- known::needs_drop,
- known::caller_location,
- known::size_of_val,
- known::min_align_of_val,
known::add_with_overflow,
- known::sub_with_overflow,
- known::mul_with_overflow,
- known::wrapping_add,
- known::wrapping_sub,
- known::wrapping_mul,
- known::saturating_add,
- known::saturating_sub,
- known::rotate_left,
- known::rotate_right,
- known::ctpop,
+ known::bitreverse,
+ known::bswap,
+ known::caller_location,
known::ctlz,
+ known::ctpop,
known::cttz,
- known::bswap,
- known::bitreverse,
known::discriminant_value,
- known::type_id,
+ known::forget,
known::likely,
- known::unlikely,
- known::ptr_guaranteed_eq,
- known::ptr_guaranteed_ne,
+ known::maxnumf32,
+ known::maxnumf64,
+ known::min_align_of,
known::minnumf32,
known::minnumf64,
- known::maxnumf32,
+ known::mul_with_overflow,
+ known::needs_drop,
+ known::ptr_guaranteed_eq,
+ known::ptr_guaranteed_ne,
+ known::rotate_left,
+ known::rotate_right,
known::rustc_peek,
- known::maxnumf64,
+ known::saturating_add,
+ known::saturating_sub,
+ known::size_of,
+ known::sub_with_overflow,
+ known::type_id,
known::type_name,
+ known::unlikely,
known::variant_count,
+ known::wrapping_add,
+ known::wrapping_mul,
+ known::wrapping_sub,
]
- .contains(&name)
+ .contains(name)
}
fn lower_abi(abi: ast::Abi) -> Interned<str> {
// E.g. `use something::{inner}` (prefix is `None`, path is `something`)
// or `use something::{path::{inner::{innerer}}}` (prefix is `something::path`, path is `inner`)
Some(path) => {
- match ModPath::from_src(self.db, path, &self.hygiene) {
+ match ModPath::from_src(self.db, path, self.hygiene) {
Some(it) => Some(it),
None => return None, // FIXME: report errors somewhere
}
} else {
let is_glob = tree.star_token().is_some();
let path = match tree.path() {
- Some(path) => Some(ModPath::from_src(self.db, path, &self.hygiene)?),
+ Some(path) => Some(ModPath::from_src(self.db, path, self.hygiene)?),
None => None,
};
let alias = tree.rename().map(|a| {