Introduce LowerCtx for path lowering

This commit is contained in:
Edwin Cheng 2020-04-30 18:20:13 +08:00
parent 1635d22a35
commit bdcf6f5658
14 changed files with 172 additions and 80 deletions

View file

@ -1,12 +1,12 @@
//! This module defines `AssistCtx` -- the API surface that is exposed to assists.
use hir::Semantics;
use ra_db::FileRange;
use ra_db::{FileRange, Upcast};
use ra_fmt::{leading_indent, reindent};
use ra_ide_db::RootDatabase;
use ra_syntax::{
algo::{self, find_covering_element, find_node_at_offset},
AstNode, SourceFile, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken, TextRange, TextSize,
TokenAtOffset,
ast, AstNode, SourceFile, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken, TextRange,
TextSize, TokenAtOffset,
};
use ra_text_edit::TextEditBuilder;
@ -136,6 +136,9 @@ impl<'a> AssistCtx<'a> {
pub(crate) fn covering_node_for_range(&self, range: TextRange) -> SyntaxElement {
find_covering_element(self.source_file.syntax(), range)
}
pub(crate) fn lower_path(&self, path: ast::Path) -> Option<hir::Path> {
hir::Path::from_src(path, &hir::Hygiene::new(self.db.upcast(), self.frange.file_id.into()))
}
}
pub(crate) struct AssistGroup<'a> {

View file

@ -85,6 +85,7 @@ impl<'a> SubstituteTypeParams<'a> {
ast::TypeRef::PathType(path_type) => path_type.path()?,
_ => return None,
};
// FIXME: use `hir::Path::from_src` instead.
let path = hir::Path::from_ast(path)?;
let resolution = self.source_scope.resolve_hir_path(&path)?;
match resolution {
@ -128,6 +129,7 @@ impl<'a> QualifyPaths<'a> {
// don't try to qualify `Fn(Foo) -> Bar` paths, they are in prelude anyway
return None;
}
// FIXME: use `hir::Path::from_src` instead.
let hir_path = hir::Path::from_ast(p.clone());
let resolution = self.source_scope.resolve_hir_path(&hir_path?)?;
match resolution {

View file

@ -27,7 +27,7 @@ pub(crate) fn replace_qualified_name_with_use(ctx: AssistCtx) -> Option<Assist>
return None;
}
let hir_path = hir::Path::from_ast(path.clone())?;
let hir_path = ctx.lower_path(path.clone())?;
let segments = collect_hir_path_segments(&hir_path)?;
if segments.len() < 2 {
return None;

View file

@ -70,6 +70,7 @@ pub use hir_def::{
type_ref::Mutability,
};
pub use hir_expand::{
name::Name, HirFileId, InFile, MacroCallId, MacroCallLoc, MacroDefId, MacroFile, Origin,
hygiene::Hygiene, name::Name, HirFileId, InFile, MacroCallId, MacroCallLoc, MacroDefId,
MacroFile, Origin,
};
pub use hir_ty::{display::HirDisplay, CallableDef};

View file

@ -224,7 +224,8 @@ impl SourceAnalyzer {
}
}
// This must be a normal source file rather than macro file.
let hir_path = crate::Path::from_ast(path.clone())?;
let hir_path =
crate::Path::from_src(path.clone(), &Hygiene::new(db.upcast(), self.file_id))?;
resolve_hir_path(db, &self.resolver, &hir_path)
}

View file

@ -12,9 +12,15 @@ use ra_prof::profile;
use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner, VisibilityOwner};
use crate::{
body::CfgExpander, db::DefDatabase, src::HasChildSource, src::HasSource, trace::Trace,
type_ref::TypeRef, visibility::RawVisibility, EnumId, HasModule, LocalEnumVariantId,
LocalFieldId, Lookup, ModuleId, StructId, UnionId, VariantId,
body::{CfgExpander, LowerCtx},
db::DefDatabase,
src::HasChildSource,
src::HasSource,
trace::Trace,
type_ref::TypeRef,
visibility::RawVisibility,
EnumId, HasModule, LocalEnumVariantId, LocalFieldId, Lookup, ModuleId, StructId, UnionId,
VariantId,
};
/// Note that we use `StructData` for unions as well!
@ -198,6 +204,8 @@ fn lower_struct(
trace: &mut Trace<FieldData, Either<ast::TupleFieldDef, ast::RecordFieldDef>>,
ast: &InFile<ast::StructKind>,
) -> StructKind {
let ctx = LowerCtx::new(db, ast.file_id);
match &ast.value {
ast::StructKind::Tuple(fl) => {
for (i, fd) in fl.fields().enumerate() {
@ -210,7 +218,7 @@ fn lower_struct(
|| Either::Left(fd.clone()),
|| FieldData {
name: Name::new_tuple_field(i),
type_ref: TypeRef::from_ast_opt(fd.type_ref()),
type_ref: TypeRef::from_ast_opt(&ctx, fd.type_ref()),
visibility: RawVisibility::from_ast(db, ast.with_value(fd.visibility())),
},
);
@ -228,7 +236,7 @@ fn lower_struct(
|| Either::Right(fd.clone()),
|| FieldData {
name: fd.name().map(|n| n.as_name()).unwrap_or_else(Name::missing),
type_ref: TypeRef::from_ast_opt(fd.ascribed_type()),
type_ref: TypeRef::from_ast_opt(&ctx, fd.ascribed_type()),
visibility: RawVisibility::from_ast(db, ast.with_value(fd.visibility())),
},
);

View file

@ -15,6 +15,8 @@ use ra_prof::profile;
use ra_syntax::{ast, AstNode, AstPtr};
use rustc_hash::FxHashMap;
pub(crate) use lower::LowerCtx;
use crate::{
attr::Attrs,
db::DefDatabase,

View file

@ -3,8 +3,9 @@
use either::Either;
use hir_expand::{
hygiene::Hygiene,
name::{name, AsName, Name},
MacroDefId, MacroDefKind,
HirFileId, MacroDefId, MacroDefKind,
};
use ra_arena::Arena;
use ra_syntax::{
@ -26,7 +27,7 @@ use crate::{
LogicOp, MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, Statement,
},
item_scope::BuiltinShadowMode,
path::GenericArgs,
path::{GenericArgs, Path},
type_ref::{Mutability, TypeRef},
AdtId, ConstLoc, ContainerId, DefWithBodyId, EnumLoc, FunctionLoc, Intern, ModuleDefId,
StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc,
@ -35,6 +36,23 @@ use crate::{
use super::{ExprSource, PatSource};
use ast::AstChildren;
pub(crate) struct LowerCtx {
hygiene: Hygiene,
}
impl LowerCtx {
pub fn new(db: &dyn DefDatabase, file_id: HirFileId) -> Self {
LowerCtx { hygiene: Hygiene::new(db.upcast(), file_id) }
}
pub fn with_hygiene(hygiene: &Hygiene) -> Self {
LowerCtx { hygiene: hygiene.clone() }
}
pub fn lower_path(&self, ast: ast::Path) -> Option<Path> {
Path::from_src(ast, &self.hygiene)
}
}
pub(super) fn lower(
db: &dyn DefDatabase,
def: DefWithBodyId,
@ -42,10 +60,13 @@ pub(super) fn lower(
params: Option<ast::ParamList>,
body: Option<ast::Expr>,
) -> (Body, BodySourceMap) {
let ctx = LowerCtx::new(db, expander.current_file_id.clone());
ExprCollector {
db,
def,
expander,
ctx,
source_map: BodySourceMap::default(),
body: Body {
exprs: Arena::default(),
@ -62,7 +83,7 @@ struct ExprCollector<'a> {
db: &'a dyn DefDatabase,
def: DefWithBodyId,
expander: Expander,
ctx: LowerCtx,
body: Body,
source_map: BodySourceMap,
}
@ -237,7 +258,8 @@ impl ExprCollector<'_> {
Vec::new()
};
let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
let generic_args = e.type_arg_list().and_then(GenericArgs::from_ast);
let generic_args =
e.type_arg_list().and_then(|it| GenericArgs::from_ast(&self.ctx, it));
self.alloc_expr(
Expr::MethodCall { receiver, method_name, args, generic_args },
syntax_ptr,
@ -343,7 +365,7 @@ impl ExprCollector<'_> {
}
ast::Expr::CastExpr(e) => {
let expr = self.collect_expr_opt(e.expr());
let type_ref = TypeRef::from_ast_opt(e.type_ref());
let type_ref = TypeRef::from_ast_opt(&self.ctx, e.type_ref());
self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr)
}
ast::Expr::RefExpr(e) => {
@ -365,12 +387,16 @@ impl ExprCollector<'_> {
if let Some(pl) = e.param_list() {
for param in pl.params() {
let pat = self.collect_pat_opt(param.pat());
let type_ref = param.ascribed_type().map(TypeRef::from_ast);
let type_ref =
param.ascribed_type().map(|it| TypeRef::from_ast(&self.ctx, it));
args.push(pat);
arg_types.push(type_ref);
}
}
let ret_type = e.ret_type().and_then(|r| r.type_ref()).map(TypeRef::from_ast);
let ret_type = e
.ret_type()
.and_then(|r| r.type_ref())
.map(|it| TypeRef::from_ast(&self.ctx, it));
let body = self.collect_expr_opt(e.body());
self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr)
}
@ -476,7 +502,7 @@ impl ExprCollector<'_> {
.map(|s| match s {
ast::Stmt::LetStmt(stmt) => {
let pat = self.collect_pat_opt(stmt.pat());
let type_ref = stmt.ascribed_type().map(TypeRef::from_ast);
let type_ref = stmt.ascribed_type().map(|it| TypeRef::from_ast(&self.ctx, it));
let initializer = stmt.initializer().map(|e| self.collect_expr(e));
Statement::Let { pat, type_ref, initializer }
}

View file

@ -15,6 +15,7 @@ use ra_syntax::ast::{
use crate::{
attr::Attrs,
body::LowerCtx,
db::DefDatabase,
path::{path, AssociatedTypeBinding, GenericArgs, Path},
src::HasSource,
@ -40,13 +41,14 @@ impl FunctionData {
pub(crate) fn fn_data_query(db: &impl DefDatabase, func: FunctionId) -> Arc<FunctionData> {
let loc = func.lookup(db);
let src = loc.source(db);
let ctx = LowerCtx::new(db, src.file_id);
let name = src.value.name().map(|n| n.as_name()).unwrap_or_else(Name::missing);
let mut params = Vec::new();
let mut has_self_param = false;
if let Some(param_list) = src.value.param_list() {
if let Some(self_param) = param_list.self_param() {
let self_type = if let Some(type_ref) = self_param.ascribed_type() {
TypeRef::from_ast(type_ref)
TypeRef::from_ast(&ctx, type_ref)
} else {
let self_type = TypeRef::Path(name![Self].into());
match self_param.kind() {
@ -63,14 +65,14 @@ impl FunctionData {
has_self_param = true;
}
for param in param_list.params() {
let type_ref = TypeRef::from_ast_opt(param.ascribed_type());
let type_ref = TypeRef::from_ast_opt(&ctx, param.ascribed_type());
params.push(type_ref);
}
}
let attrs = Attrs::new(&src.value, &Hygiene::new(db.upcast(), src.file_id));
let ret_type = if let Some(type_ref) = src.value.ret_type().and_then(|rt| rt.type_ref()) {
TypeRef::from_ast(type_ref)
TypeRef::from_ast(&ctx, type_ref)
} else {
TypeRef::unit()
};
@ -122,7 +124,8 @@ impl TypeAliasData {
let loc = typ.lookup(db);
let node = loc.source(db);
let name = node.value.name().map_or_else(Name::missing, |n| n.as_name());
let type_ref = node.value.type_ref().map(TypeRef::from_ast);
let lower_ctx = LowerCtx::new(db, node.file_id);
let type_ref = node.value.type_ref().map(|it| TypeRef::from_ast(&lower_ctx, it));
let vis_default = RawVisibility::default_for_container(loc.container);
let visibility = RawVisibility::from_ast_with_default(
db,
@ -130,7 +133,7 @@ impl TypeAliasData {
node.as_ref().map(|n| n.visibility()),
);
let bounds = if let Some(bound_list) = node.value.type_bound_list() {
bound_list.bounds().map(TypeBound::from_ast).collect()
bound_list.bounds().map(|it| TypeBound::from_ast(&lower_ctx, it)).collect()
} else {
Vec::new()
};
@ -223,9 +226,10 @@ impl ImplData {
let _p = profile("impl_data_query");
let impl_loc = id.lookup(db);
let src = impl_loc.source(db);
let lower_ctx = LowerCtx::new(db, src.file_id);
let target_trait = src.value.target_trait().map(TypeRef::from_ast);
let target_type = TypeRef::from_ast_opt(src.value.target_type());
let target_trait = src.value.target_trait().map(|it| TypeRef::from_ast(&lower_ctx, it));
let target_type = TypeRef::from_ast_opt(&lower_ctx, src.value.target_type());
let is_negative = src.value.excl_token().is_some();
let module_id = impl_loc.container.module(db);
@ -279,8 +283,9 @@ impl ConstData {
vis_default: RawVisibility,
node: InFile<N>,
) -> ConstData {
let ctx = LowerCtx::new(db, node.file_id);
let name = node.value.name().map(|n| n.as_name());
let type_ref = TypeRef::from_ast_opt(node.value.ascribed_type());
let type_ref = TypeRef::from_ast_opt(&ctx, node.value.ascribed_type());
let visibility =
RawVisibility::from_ast_with_default(db, vis_default, node.map(|n| n.visibility()));
ConstData { name, type_ref, visibility }

View file

@ -15,6 +15,7 @@ use ra_prof::profile;
use ra_syntax::ast::{self, NameOwner, TypeBoundsOwner, TypeParamsOwner};
use crate::{
body::LowerCtx,
child_by_source::ChildBySource,
db::DefDatabase,
dyn_map::DynMap,
@ -80,11 +81,13 @@ impl GenericParams {
fn new(db: &dyn DefDatabase, def: GenericDefId) -> (GenericParams, InFile<SourceMap>) {
let mut generics = GenericParams { types: Arena::default(), where_predicates: Vec::new() };
let mut sm = ArenaMap::default();
// FIXME: add `: Sized` bound for everything except for `Self` in traits
let file_id = match def {
GenericDefId::FunctionId(it) => {
let src = it.lookup(db).source(db);
generics.fill(&mut sm, &src.value);
let lower_ctx = LowerCtx::new(db, src.file_id);
generics.fill(&lower_ctx, &mut sm, &src.value);
// lower `impl Trait` in arguments
let data = db.function_data(it);
for param in &data.params {
@ -94,21 +97,25 @@ impl GenericParams {
}
GenericDefId::AdtId(AdtId::StructId(it)) => {
let src = it.lookup(db).source(db);
generics.fill(&mut sm, &src.value);
let lower_ctx = LowerCtx::new(db, src.file_id);
generics.fill(&lower_ctx, &mut sm, &src.value);
src.file_id
}
GenericDefId::AdtId(AdtId::UnionId(it)) => {
let src = it.lookup(db).source(db);
generics.fill(&mut sm, &src.value);
let lower_ctx = LowerCtx::new(db, src.file_id);
generics.fill(&lower_ctx, &mut sm, &src.value);
src.file_id
}
GenericDefId::AdtId(AdtId::EnumId(it)) => {
let src = it.lookup(db).source(db);
generics.fill(&mut sm, &src.value);
let lower_ctx = LowerCtx::new(db, src.file_id);
generics.fill(&lower_ctx, &mut sm, &src.value);
src.file_id
}
GenericDefId::TraitId(it) => {
let src = it.lookup(db).source(db);
let lower_ctx = LowerCtx::new(db, src.file_id);
// traits get the Self type as an implicit first type parameter
let self_param_id = generics.types.alloc(TypeParamData {
@ -120,14 +127,16 @@ impl GenericParams {
// 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(&src.value, self_param);
generics.fill_bounds(&lower_ctx, &src.value, self_param);
generics.fill(&mut sm, &src.value);
generics.fill(&lower_ctx, &mut sm, &src.value);
src.file_id
}
GenericDefId::TypeAliasId(it) => {
let src = it.lookup(db).source(db);
generics.fill(&mut sm, &src.value);
let lower_ctx = LowerCtx::new(db, src.file_id);
generics.fill(&lower_ctx, &mut sm, &src.value);
src.file_id
}
// Note that we don't add `Self` here: in `impl`s, `Self` is not a
@ -135,7 +144,9 @@ impl GenericParams {
// type, so this is handled by the resolver.
GenericDefId::ImplId(it) => {
let src = it.lookup(db).source(db);
generics.fill(&mut sm, &src.value);
let lower_ctx = LowerCtx::new(db, src.file_id);
generics.fill(&lower_ctx, &mut sm, &src.value);
src.file_id
}
// We won't be using this ID anyway
@ -145,28 +156,38 @@ impl GenericParams {
(generics, InFile::new(file_id, sm))
}
fn fill(&mut self, sm: &mut SourceMap, node: &dyn TypeParamsOwner) {
fn fill(&mut self, lower_ctx: &LowerCtx, sm: &mut SourceMap, node: &dyn TypeParamsOwner) {
if let Some(params) = node.type_param_list() {
self.fill_params(sm, params)
self.fill_params(lower_ctx, sm, params)
}
if let Some(where_clause) = node.where_clause() {
self.fill_where_predicates(where_clause);
self.fill_where_predicates(lower_ctx, where_clause);
}
}
fn fill_bounds(&mut self, node: &dyn ast::TypeBoundsOwner, type_ref: TypeRef) {
fn fill_bounds(
&mut self,
lower_ctx: &LowerCtx,
node: &dyn ast::TypeBoundsOwner,
type_ref: TypeRef,
) {
for bound in
node.type_bound_list().iter().flat_map(|type_bound_list| type_bound_list.bounds())
{
self.add_where_predicate_from_bound(bound, type_ref.clone());
self.add_where_predicate_from_bound(lower_ctx, bound, type_ref.clone());
}
}
fn fill_params(&mut self, sm: &mut SourceMap, params: ast::TypeParamList) {
fn fill_params(
&mut self,
lower_ctx: &LowerCtx,
sm: &mut SourceMap,
params: ast::TypeParamList,
) {
for type_param in params.type_params() {
let name = type_param.name().map_or_else(Name::missing, |it| it.as_name());
// FIXME: Use `Path::from_src`
let default = type_param.default_type().map(TypeRef::from_ast);
let default = type_param.default_type().map(|it| TypeRef::from_ast(lower_ctx, it));
let param = TypeParamData {
name: Some(name.clone()),
default,
@ -176,29 +197,34 @@ impl GenericParams {
sm.insert(param_id, Either::Right(type_param.clone()));
let type_ref = TypeRef::Path(name.into());
self.fill_bounds(&type_param, type_ref);
self.fill_bounds(&lower_ctx, &type_param, type_ref);
}
}
fn fill_where_predicates(&mut self, where_clause: ast::WhereClause) {
fn fill_where_predicates(&mut self, lower_ctx: &LowerCtx, where_clause: ast::WhereClause) {
for pred in where_clause.predicates() {
let type_ref = match pred.type_ref() {
Some(type_ref) => type_ref,
None => continue,
};
let type_ref = TypeRef::from_ast(type_ref);
let type_ref = TypeRef::from_ast(lower_ctx, type_ref);
for bound in pred.type_bound_list().iter().flat_map(|l| l.bounds()) {
self.add_where_predicate_from_bound(bound, type_ref.clone());
self.add_where_predicate_from_bound(lower_ctx, bound, type_ref.clone());
}
}
}
fn add_where_predicate_from_bound(&mut self, bound: ast::TypeBound, type_ref: TypeRef) {
fn add_where_predicate_from_bound(
&mut self,
lower_ctx: &LowerCtx,
bound: ast::TypeBound,
type_ref: TypeRef,
) {
if bound.question_token().is_some() {
// FIXME: remove this bound
return;
}
let bound = TypeBound::from_ast(bound);
let bound = TypeBound::from_ast(lower_ctx, bound);
self.where_predicates
.push(WherePredicate { target: WherePredicateTarget::TypeRef(type_ref), bound });
}

View file

@ -7,6 +7,7 @@ use std::{
sync::Arc,
};
use crate::body::LowerCtx;
use hir_expand::{
hygiene::Hygiene,
name::{AsName, Name},
@ -244,8 +245,8 @@ impl<'a> PathSegments<'a> {
}
impl GenericArgs {
pub(crate) fn from_ast(node: ast::TypeArgList) -> Option<GenericArgs> {
lower::lower_generic_args(node)
pub(crate) fn from_ast(lower_ctx: &LowerCtx, node: ast::TypeArgList) -> Option<GenericArgs> {
lower::lower_generic_args(lower_ctx, node)
}
pub(crate) fn empty() -> GenericArgs {

View file

@ -13,6 +13,7 @@ use ra_syntax::ast::{self, AstNode, TypeAscriptionOwner, TypeBoundsOwner};
use super::AssociatedTypeBinding;
use crate::{
body::LowerCtx,
path::{GenericArg, GenericArgs, ModPath, Path, PathKind},
type_ref::{TypeBound, TypeRef},
};
@ -26,6 +27,7 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path>
let mut type_anchor = None;
let mut segments = Vec::new();
let mut generic_args = Vec::new();
let ctx = LowerCtx::with_hygiene(hygiene);
loop {
let segment = path.segment()?;
@ -40,9 +42,10 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path>
Either::Left(name) => {
let args = segment
.type_arg_list()
.and_then(lower_generic_args)
.and_then(|it| lower_generic_args(&ctx, it))
.or_else(|| {
lower_generic_args_from_fn_path(
&ctx,
segment.param_list(),
segment.ret_type(),
)
@ -60,7 +63,7 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path>
ast::PathSegmentKind::Type { type_ref, trait_ref } => {
assert!(path.qualifier().is_none()); // this can only occur at the first segment
let self_type = TypeRef::from_ast(type_ref?);
let self_type = TypeRef::from_ast(&ctx, type_ref?);
match trait_ref {
// <T>::foo
@ -128,10 +131,13 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path>
}
}
pub(super) fn lower_generic_args(node: ast::TypeArgList) -> Option<GenericArgs> {
pub(super) fn lower_generic_args(
lower_ctx: &LowerCtx,
node: ast::TypeArgList,
) -> Option<GenericArgs> {
let mut args = Vec::new();
for type_arg in node.type_args() {
let type_ref = TypeRef::from_ast_opt(type_arg.type_ref());
let type_ref = TypeRef::from_ast_opt(lower_ctx, type_arg.type_ref());
args.push(GenericArg::Type(type_ref));
}
// lifetimes ignored for now
@ -140,9 +146,9 @@ pub(super) fn lower_generic_args(node: ast::TypeArgList) -> Option<GenericArgs>
let assoc_type_arg: ast::AssocTypeArg = assoc_type_arg;
if let Some(name_ref) = assoc_type_arg.name_ref() {
let name = name_ref.as_name();
let type_ref = assoc_type_arg.type_ref().map(TypeRef::from_ast);
let type_ref = assoc_type_arg.type_ref().map(|it| TypeRef::from_ast(lower_ctx, it));
let bounds = if let Some(l) = assoc_type_arg.type_bound_list() {
l.bounds().map(TypeBound::from_ast).collect()
l.bounds().map(|it| TypeBound::from_ast(lower_ctx, it)).collect()
} else {
Vec::new()
};
@ -159,6 +165,7 @@ pub(super) fn lower_generic_args(node: ast::TypeArgList) -> Option<GenericArgs>
/// 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,
params: Option<ast::ParamList>,
ret_type: Option<ast::RetType>,
) -> Option<GenericArgs> {
@ -167,14 +174,14 @@ fn lower_generic_args_from_fn_path(
if let Some(params) = params {
let mut param_types = Vec::new();
for param in params.params() {
let type_ref = TypeRef::from_ast_opt(param.ascribed_type());
let type_ref = TypeRef::from_ast_opt(&ctx, param.ascribed_type());
param_types.push(type_ref);
}
let arg = GenericArg::Type(TypeRef::Tuple(param_types));
args.push(arg);
}
if let Some(ret_type) = ret_type {
let type_ref = TypeRef::from_ast_opt(ret_type.type_ref());
let type_ref = TypeRef::from_ast_opt(&ctx, ret_type.type_ref());
bindings.push(AssociatedTypeBinding {
name: name![Output],
type_ref: Some(type_ref),

View file

@ -3,7 +3,7 @@
use ra_syntax::ast::{self, TypeAscriptionOwner, TypeBoundsOwner};
use crate::path::Path;
use crate::{body::LowerCtx, path::Path};
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub enum Mutability {
@ -64,30 +64,34 @@ pub enum TypeBound {
impl TypeRef {
/// Converts an `ast::TypeRef` to a `hir::TypeRef`.
pub(crate) fn from_ast(node: ast::TypeRef) -> Self {
pub(crate) fn from_ast(ctx: &LowerCtx, node: ast::TypeRef) -> Self {
match node {
ast::TypeRef::ParenType(inner) => TypeRef::from_ast_opt(inner.type_ref()),
ast::TypeRef::ParenType(inner) => TypeRef::from_ast_opt(&ctx, inner.type_ref()),
ast::TypeRef::TupleType(inner) => {
TypeRef::Tuple(inner.fields().map(TypeRef::from_ast).collect())
TypeRef::Tuple(inner.fields().map(|it| TypeRef::from_ast(ctx, it)).collect())
}
ast::TypeRef::NeverType(..) => TypeRef::Never,
ast::TypeRef::PathType(inner) => {
// FIXME: Use `Path::from_src`
inner.path().and_then(Path::from_ast).map(TypeRef::Path).unwrap_or(TypeRef::Error)
inner
.path()
.and_then(|it| ctx.lower_path(it))
.map(TypeRef::Path)
.unwrap_or(TypeRef::Error)
}
ast::TypeRef::PointerType(inner) => {
let inner_ty = TypeRef::from_ast_opt(inner.type_ref());
let inner_ty = TypeRef::from_ast_opt(&ctx, inner.type_ref());
let mutability = Mutability::from_mutable(inner.mut_token().is_some());
TypeRef::RawPtr(Box::new(inner_ty), mutability)
}
ast::TypeRef::ArrayType(inner) => {
TypeRef::Array(Box::new(TypeRef::from_ast_opt(inner.type_ref())))
TypeRef::Array(Box::new(TypeRef::from_ast_opt(&ctx, inner.type_ref())))
}
ast::TypeRef::SliceType(inner) => {
TypeRef::Slice(Box::new(TypeRef::from_ast_opt(inner.type_ref())))
TypeRef::Slice(Box::new(TypeRef::from_ast_opt(&ctx, inner.type_ref())))
}
ast::TypeRef::ReferenceType(inner) => {
let inner_ty = TypeRef::from_ast_opt(inner.type_ref());
let inner_ty = TypeRef::from_ast_opt(&ctx, inner.type_ref());
let mutability = Mutability::from_mutable(inner.mut_token().is_some());
TypeRef::Reference(Box::new(inner_ty), mutability)
}
@ -96,10 +100,13 @@ impl TypeRef {
let ret_ty = inner
.ret_type()
.and_then(|rt| rt.type_ref())
.map(TypeRef::from_ast)
.map(|it| TypeRef::from_ast(ctx, it))
.unwrap_or_else(|| TypeRef::Tuple(Vec::new()));
let mut params = if let Some(pl) = inner.param_list() {
pl.params().map(|p| p.ascribed_type()).map(TypeRef::from_ast_opt).collect()
pl.params()
.map(|p| p.ascribed_type())
.map(|it| TypeRef::from_ast_opt(&ctx, it))
.collect()
} else {
Vec::new()
};
@ -107,19 +114,19 @@ impl TypeRef {
TypeRef::Fn(params)
}
// for types are close enough for our purposes to the inner type for now...
ast::TypeRef::ForType(inner) => TypeRef::from_ast_opt(inner.type_ref()),
ast::TypeRef::ForType(inner) => TypeRef::from_ast_opt(&ctx, inner.type_ref()),
ast::TypeRef::ImplTraitType(inner) => {
TypeRef::ImplTrait(type_bounds_from_ast(inner.type_bound_list()))
TypeRef::ImplTrait(type_bounds_from_ast(ctx, inner.type_bound_list()))
}
ast::TypeRef::DynTraitType(inner) => {
TypeRef::DynTrait(type_bounds_from_ast(inner.type_bound_list()))
TypeRef::DynTrait(type_bounds_from_ast(ctx, inner.type_bound_list()))
}
}
}
pub(crate) fn from_ast_opt(node: Option<ast::TypeRef>) -> Self {
pub(crate) fn from_ast_opt(ctx: &LowerCtx, node: Option<ast::TypeRef>) -> Self {
if let Some(node) = node {
TypeRef::from_ast(node)
TypeRef::from_ast(ctx, node)
} else {
TypeRef::Error
}
@ -180,24 +187,27 @@ impl TypeRef {
}
}
pub(crate) fn type_bounds_from_ast(type_bounds_opt: Option<ast::TypeBoundList>) -> Vec<TypeBound> {
pub(crate) fn type_bounds_from_ast(
lower_ctx: &LowerCtx,
type_bounds_opt: Option<ast::TypeBoundList>,
) -> Vec<TypeBound> {
if let Some(type_bounds) = type_bounds_opt {
type_bounds.bounds().map(TypeBound::from_ast).collect()
type_bounds.bounds().map(|it| TypeBound::from_ast(lower_ctx, it)).collect()
} else {
vec![]
}
}
impl TypeBound {
pub(crate) fn from_ast(node: ast::TypeBound) -> Self {
pub(crate) fn from_ast(ctx: &LowerCtx, node: ast::TypeBound) -> Self {
match node.kind() {
ast::TypeBoundKind::PathType(path_type) => {
let path = match path_type.path() {
Some(p) => p,
None => return TypeBound::Error,
};
// FIXME: Use `Path::from_src`
let path = match Path::from_ast(path) {
let path = match ctx.lower_path(path) {
Some(p) => p,
None => return TypeBound::Error,
};

View file

@ -12,7 +12,7 @@ use crate::{
HirFileId, HirFileIdRepr, MacroCallId, MacroDefKind,
};
#[derive(Debug)]
#[derive(Clone, Debug)]
pub struct Hygiene {
// This is what `$crate` expands to
def_crate: Option<CrateId>,