mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-01 11:31:15 +00:00
Merge pull request #19677 from Veykril/push-xkzwkrpypuqo
refactor: Remove `WherePredicateTypeTarget`
This commit is contained in:
commit
6fce68edb5
@ -37,6 +37,7 @@ use crate::{
|
|||||||
Body, BodySourceMap, ExprPtr, ExpressionStore, ExpressionStoreBuilder,
|
Body, BodySourceMap, ExprPtr, ExpressionStore, ExpressionStoreBuilder,
|
||||||
ExpressionStoreDiagnostics, ExpressionStoreSourceMap, HygieneId, LabelPtr, PatPtr, TypePtr,
|
ExpressionStoreDiagnostics, ExpressionStoreSourceMap, HygieneId, LabelPtr, PatPtr, TypePtr,
|
||||||
expander::Expander,
|
expander::Expander,
|
||||||
|
lower::generics::ImplTraitLowerFn,
|
||||||
path::{AssociatedTypeBinding, GenericArg, GenericArgs, GenericArgsParentheses, Path},
|
path::{AssociatedTypeBinding, GenericArg, GenericArgs, GenericArgsParentheses, Path},
|
||||||
},
|
},
|
||||||
hir::{
|
hir::{
|
||||||
@ -193,7 +194,8 @@ pub(crate) fn lower_type_ref(
|
|||||||
type_ref: InFile<Option<ast::Type>>,
|
type_ref: InFile<Option<ast::Type>>,
|
||||||
) -> (ExpressionStore, ExpressionStoreSourceMap, TypeRefId) {
|
) -> (ExpressionStore, ExpressionStoreSourceMap, TypeRefId) {
|
||||||
let mut expr_collector = ExprCollector::new(db, module, type_ref.file_id);
|
let mut expr_collector = ExprCollector::new(db, module, type_ref.file_id);
|
||||||
let type_ref = expr_collector.lower_type_ref_opt(type_ref.value, &mut TypeRef::ImplTrait);
|
let type_ref =
|
||||||
|
expr_collector.lower_type_ref_opt(type_ref.value, &mut ExprCollector::impl_trait_allocator);
|
||||||
(expr_collector.store.finish(), expr_collector.source_map, type_ref)
|
(expr_collector.store.finish(), expr_collector.source_map, type_ref)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,8 +208,8 @@ pub(crate) fn lower_generic_params(
|
|||||||
where_clause: Option<ast::WhereClause>,
|
where_clause: Option<ast::WhereClause>,
|
||||||
) -> (Arc<ExpressionStore>, Arc<GenericParams>, ExpressionStoreSourceMap) {
|
) -> (Arc<ExpressionStore>, Arc<GenericParams>, ExpressionStoreSourceMap) {
|
||||||
let mut expr_collector = ExprCollector::new(db, module, file_id);
|
let mut expr_collector = ExprCollector::new(db, module, file_id);
|
||||||
let mut collector = generics::GenericParamsCollector::new(&mut expr_collector, def);
|
let mut collector = generics::GenericParamsCollector::new(def);
|
||||||
collector.lower(param_list, where_clause);
|
collector.lower(&mut expr_collector, param_list, where_clause);
|
||||||
let params = collector.finish();
|
let params = collector.finish();
|
||||||
(Arc::new(expr_collector.store.finish()), params, expr_collector.source_map)
|
(Arc::new(expr_collector.store.finish()), params, expr_collector.source_map)
|
||||||
}
|
}
|
||||||
@ -223,13 +225,18 @@ pub(crate) fn lower_impl(
|
|||||||
expr_collector.lower_type_ref_opt_disallow_impl_trait(impl_syntax.value.self_ty());
|
expr_collector.lower_type_ref_opt_disallow_impl_trait(impl_syntax.value.self_ty());
|
||||||
let trait_ = impl_syntax.value.trait_().and_then(|it| match &it {
|
let trait_ = impl_syntax.value.trait_().and_then(|it| match &it {
|
||||||
ast::Type::PathType(path_type) => {
|
ast::Type::PathType(path_type) => {
|
||||||
let path = expr_collector.lower_path_type(path_type, &mut |_| TypeRef::Error)?;
|
let path = expr_collector
|
||||||
|
.lower_path_type(path_type, &mut ExprCollector::impl_trait_allocator)?;
|
||||||
Some(TraitRef { path: expr_collector.alloc_path(path, AstPtr::new(&it)) })
|
Some(TraitRef { path: expr_collector.alloc_path(path, AstPtr::new(&it)) })
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
});
|
});
|
||||||
let mut collector = generics::GenericParamsCollector::new(&mut expr_collector, impl_id.into());
|
let mut collector = generics::GenericParamsCollector::new(impl_id.into());
|
||||||
collector.lower(impl_syntax.value.generic_param_list(), impl_syntax.value.where_clause());
|
collector.lower(
|
||||||
|
&mut expr_collector,
|
||||||
|
impl_syntax.value.generic_param_list(),
|
||||||
|
impl_syntax.value.where_clause(),
|
||||||
|
);
|
||||||
let params = collector.finish();
|
let params = collector.finish();
|
||||||
(expr_collector.store.finish(), expr_collector.source_map, self_ty, trait_, params)
|
(expr_collector.store.finish(), expr_collector.source_map, self_ty, trait_, params)
|
||||||
}
|
}
|
||||||
@ -241,9 +248,16 @@ pub(crate) fn lower_trait(
|
|||||||
trait_id: TraitId,
|
trait_id: TraitId,
|
||||||
) -> (ExpressionStore, ExpressionStoreSourceMap, Arc<GenericParams>) {
|
) -> (ExpressionStore, ExpressionStoreSourceMap, Arc<GenericParams>) {
|
||||||
let mut expr_collector = ExprCollector::new(db, module, trait_syntax.file_id);
|
let mut expr_collector = ExprCollector::new(db, module, trait_syntax.file_id);
|
||||||
let mut collector = generics::GenericParamsCollector::new(&mut expr_collector, trait_id.into());
|
let mut collector = generics::GenericParamsCollector::with_self_param(
|
||||||
collector.fill_self_param(trait_syntax.value.type_bound_list());
|
&mut expr_collector,
|
||||||
collector.lower(trait_syntax.value.generic_param_list(), trait_syntax.value.where_clause());
|
trait_id.into(),
|
||||||
|
trait_syntax.value.type_bound_list(),
|
||||||
|
);
|
||||||
|
collector.lower(
|
||||||
|
&mut expr_collector,
|
||||||
|
trait_syntax.value.generic_param_list(),
|
||||||
|
trait_syntax.value.where_clause(),
|
||||||
|
);
|
||||||
let params = collector.finish();
|
let params = collector.finish();
|
||||||
(expr_collector.store.finish(), expr_collector.source_map, params)
|
(expr_collector.store.finish(), expr_collector.source_map, params)
|
||||||
}
|
}
|
||||||
@ -255,9 +269,16 @@ pub(crate) fn lower_trait_alias(
|
|||||||
trait_id: TraitAliasId,
|
trait_id: TraitAliasId,
|
||||||
) -> (ExpressionStore, ExpressionStoreSourceMap, Arc<GenericParams>) {
|
) -> (ExpressionStore, ExpressionStoreSourceMap, Arc<GenericParams>) {
|
||||||
let mut expr_collector = ExprCollector::new(db, module, trait_syntax.file_id);
|
let mut expr_collector = ExprCollector::new(db, module, trait_syntax.file_id);
|
||||||
let mut collector = generics::GenericParamsCollector::new(&mut expr_collector, trait_id.into());
|
let mut collector = generics::GenericParamsCollector::with_self_param(
|
||||||
collector.fill_self_param(trait_syntax.value.type_bound_list());
|
&mut expr_collector,
|
||||||
collector.lower(trait_syntax.value.generic_param_list(), trait_syntax.value.where_clause());
|
trait_id.into(),
|
||||||
|
trait_syntax.value.type_bound_list(),
|
||||||
|
);
|
||||||
|
collector.lower(
|
||||||
|
&mut expr_collector,
|
||||||
|
trait_syntax.value.generic_param_list(),
|
||||||
|
trait_syntax.value.where_clause(),
|
||||||
|
);
|
||||||
let params = collector.finish();
|
let params = collector.finish();
|
||||||
(expr_collector.store.finish(), expr_collector.source_map, params)
|
(expr_collector.store.finish(), expr_collector.source_map, params)
|
||||||
}
|
}
|
||||||
@ -281,16 +302,23 @@ pub(crate) fn lower_type_alias(
|
|||||||
.map(|bounds| {
|
.map(|bounds| {
|
||||||
bounds
|
bounds
|
||||||
.bounds()
|
.bounds()
|
||||||
.map(|bound| expr_collector.lower_type_bound(bound, &mut TypeRef::ImplTrait))
|
.map(|bound| {
|
||||||
|
expr_collector.lower_type_bound(bound, &mut ExprCollector::impl_trait_allocator)
|
||||||
|
})
|
||||||
.collect()
|
.collect()
|
||||||
})
|
})
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
let mut collector =
|
let mut collector = generics::GenericParamsCollector::new(type_alias_id.into());
|
||||||
generics::GenericParamsCollector::new(&mut expr_collector, type_alias_id.into());
|
collector.lower(
|
||||||
collector.lower(alias.value.generic_param_list(), alias.value.where_clause());
|
&mut expr_collector,
|
||||||
|
alias.value.generic_param_list(),
|
||||||
|
alias.value.where_clause(),
|
||||||
|
);
|
||||||
let params = collector.finish();
|
let params = collector.finish();
|
||||||
let type_ref =
|
let type_ref = alias
|
||||||
alias.value.ty().map(|ty| expr_collector.lower_type_ref(ty, &mut TypeRef::ImplTrait));
|
.value
|
||||||
|
.ty()
|
||||||
|
.map(|ty| expr_collector.lower_type_ref(ty, &mut ExprCollector::impl_trait_allocator));
|
||||||
(expr_collector.store.finish(), expr_collector.source_map, params, bounds, type_ref)
|
(expr_collector.store.finish(), expr_collector.source_map, params, bounds, type_ref)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -309,13 +337,12 @@ pub(crate) fn lower_function(
|
|||||||
bool,
|
bool,
|
||||||
) {
|
) {
|
||||||
let mut expr_collector = ExprCollector::new(db, module, fn_.file_id);
|
let mut expr_collector = ExprCollector::new(db, module, fn_.file_id);
|
||||||
let mut collector =
|
let mut collector = generics::GenericParamsCollector::new(function_id.into());
|
||||||
generics::GenericParamsCollector::new(&mut expr_collector, function_id.into());
|
collector.lower(&mut expr_collector, fn_.value.generic_param_list(), fn_.value.where_clause());
|
||||||
collector.lower(fn_.value.generic_param_list(), fn_.value.where_clause());
|
|
||||||
let mut params = vec![];
|
let mut params = vec![];
|
||||||
let mut has_self_param = false;
|
let mut has_self_param = false;
|
||||||
let mut has_variadic = false;
|
let mut has_variadic = false;
|
||||||
collector.collect_impl_trait(|collector, mut impl_trait_lower_fn| {
|
collector.collect_impl_trait(&mut expr_collector, |collector, mut impl_trait_lower_fn| {
|
||||||
if let Some(param_list) = fn_.value.param_list() {
|
if let Some(param_list) = fn_.value.param_list() {
|
||||||
if let Some(param) = param_list.self_param() {
|
if let Some(param) = param_list.self_param() {
|
||||||
let enabled = collector.expander.is_cfg_enabled(db, module.krate(), ¶m);
|
let enabled = collector.expander.is_cfg_enabled(db, module.krate(), ¶m);
|
||||||
@ -368,10 +395,9 @@ pub(crate) fn lower_function(
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
let generics = collector.finish();
|
let generics = collector.finish();
|
||||||
let return_type = fn_
|
let return_type = fn_.value.ret_type().map(|ret_type| {
|
||||||
.value
|
expr_collector.lower_type_ref_opt(ret_type.ty(), &mut ExprCollector::impl_trait_allocator)
|
||||||
.ret_type()
|
});
|
||||||
.map(|ret_type| expr_collector.lower_type_ref_opt(ret_type.ty(), &mut TypeRef::ImplTrait));
|
|
||||||
|
|
||||||
let return_type = if fn_.value.async_token().is_some() {
|
let return_type = if fn_.value.async_token().is_some() {
|
||||||
let path = hir_expand::mod_path::path![core::future::Future];
|
let path = hir_expand::mod_path::path![core::future::Future];
|
||||||
@ -563,7 +589,7 @@ impl ExprCollector<'_> {
|
|||||||
pub fn lower_type_ref(
|
pub fn lower_type_ref(
|
||||||
&mut self,
|
&mut self,
|
||||||
node: ast::Type,
|
node: ast::Type,
|
||||||
impl_trait_lower_fn: &mut impl FnMut(ThinVec<TypeBound>) -> TypeRef,
|
impl_trait_lower_fn: ImplTraitLowerFn<'_>,
|
||||||
) -> TypeRefId {
|
) -> TypeRefId {
|
||||||
let ty = match &node {
|
let ty = match &node {
|
||||||
ast::Type::ParenType(inner) => {
|
ast::Type::ParenType(inner) => {
|
||||||
@ -653,11 +679,11 @@ impl ExprCollector<'_> {
|
|||||||
// Disallow nested impl traits
|
// Disallow nested impl traits
|
||||||
TypeRef::Error
|
TypeRef::Error
|
||||||
} else {
|
} else {
|
||||||
self.with_outer_impl_trait_scope(true, |this| {
|
return self.with_outer_impl_trait_scope(true, |this| {
|
||||||
let type_bounds =
|
let type_bounds =
|
||||||
this.type_bounds_from_ast(inner.type_bound_list(), impl_trait_lower_fn);
|
this.type_bounds_from_ast(inner.type_bound_list(), impl_trait_lower_fn);
|
||||||
impl_trait_lower_fn(type_bounds)
|
impl_trait_lower_fn(this, AstPtr::new(&node), type_bounds)
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::Type::DynTraitType(inner) => TypeRef::DynTrait(
|
ast::Type::DynTraitType(inner) => TypeRef::DynTrait(
|
||||||
@ -680,13 +706,13 @@ impl ExprCollector<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn lower_type_ref_disallow_impl_trait(&mut self, node: ast::Type) -> TypeRefId {
|
pub(crate) fn lower_type_ref_disallow_impl_trait(&mut self, node: ast::Type) -> TypeRefId {
|
||||||
self.lower_type_ref(node, &mut |_| TypeRef::Error)
|
self.lower_type_ref(node, &mut Self::impl_trait_error_allocator)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn lower_type_ref_opt(
|
pub(crate) fn lower_type_ref_opt(
|
||||||
&mut self,
|
&mut self,
|
||||||
node: Option<ast::Type>,
|
node: Option<ast::Type>,
|
||||||
impl_trait_lower_fn: &mut impl FnMut(ThinVec<TypeBound>) -> TypeRef,
|
impl_trait_lower_fn: ImplTraitLowerFn<'_>,
|
||||||
) -> TypeRefId {
|
) -> TypeRefId {
|
||||||
match node {
|
match node {
|
||||||
Some(node) => self.lower_type_ref(node, impl_trait_lower_fn),
|
Some(node) => self.lower_type_ref(node, impl_trait_lower_fn),
|
||||||
@ -698,7 +724,7 @@ impl ExprCollector<'_> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
node: Option<ast::Type>,
|
node: Option<ast::Type>,
|
||||||
) -> TypeRefId {
|
) -> TypeRefId {
|
||||||
self.lower_type_ref_opt(node, &mut |_| TypeRef::Error)
|
self.lower_type_ref_opt(node, &mut Self::impl_trait_error_allocator)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn alloc_type_ref(&mut self, type_ref: TypeRef, node: TypePtr) -> TypeRefId {
|
fn alloc_type_ref(&mut self, type_ref: TypeRef, node: TypePtr) -> TypeRefId {
|
||||||
@ -712,7 +738,7 @@ impl ExprCollector<'_> {
|
|||||||
pub fn lower_path(
|
pub fn lower_path(
|
||||||
&mut self,
|
&mut self,
|
||||||
ast: ast::Path,
|
ast: ast::Path,
|
||||||
impl_trait_lower_fn: &mut impl FnMut(ThinVec<TypeBound>) -> TypeRef,
|
impl_trait_lower_fn: ImplTraitLowerFn<'_>,
|
||||||
) -> Option<Path> {
|
) -> Option<Path> {
|
||||||
super::lower::path::lower_path(self, ast, impl_trait_lower_fn)
|
super::lower::path::lower_path(self, ast, impl_trait_lower_fn)
|
||||||
}
|
}
|
||||||
@ -736,6 +762,22 @@ impl ExprCollector<'_> {
|
|||||||
self.store.types.alloc(TypeRef::Error)
|
self.store.types.alloc(TypeRef::Error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn impl_trait_error_allocator(
|
||||||
|
ec: &mut ExprCollector<'_>,
|
||||||
|
ptr: TypePtr,
|
||||||
|
_: ThinVec<TypeBound>,
|
||||||
|
) -> TypeRefId {
|
||||||
|
ec.alloc_type_ref(TypeRef::Error, ptr)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn impl_trait_allocator(
|
||||||
|
ec: &mut ExprCollector<'_>,
|
||||||
|
ptr: TypePtr,
|
||||||
|
bounds: ThinVec<TypeBound>,
|
||||||
|
) -> TypeRefId {
|
||||||
|
ec.alloc_type_ref(TypeRef::ImplTrait(bounds), ptr)
|
||||||
|
}
|
||||||
|
|
||||||
fn alloc_path(&mut self, path: Path, node: TypePtr) -> PathId {
|
fn alloc_path(&mut self, path: Path, node: TypePtr) -> PathId {
|
||||||
PathId::from_type_ref_unchecked(self.alloc_type_ref(TypeRef::Path(path), node))
|
PathId::from_type_ref_unchecked(self.alloc_type_ref(TypeRef::Path(path), node))
|
||||||
}
|
}
|
||||||
@ -746,7 +788,7 @@ impl ExprCollector<'_> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
args: Option<ast::ParenthesizedArgList>,
|
args: Option<ast::ParenthesizedArgList>,
|
||||||
ret_type: Option<ast::RetType>,
|
ret_type: Option<ast::RetType>,
|
||||||
impl_trait_lower_fn: &mut impl FnMut(ThinVec<TypeBound>) -> TypeRef,
|
impl_trait_lower_fn: ImplTraitLowerFn<'_>,
|
||||||
) -> Option<GenericArgs> {
|
) -> Option<GenericArgs> {
|
||||||
let params = args?;
|
let params = args?;
|
||||||
let mut param_types = Vec::new();
|
let mut param_types = Vec::new();
|
||||||
@ -786,7 +828,7 @@ impl ExprCollector<'_> {
|
|||||||
pub(super) fn lower_generic_args(
|
pub(super) fn lower_generic_args(
|
||||||
&mut self,
|
&mut self,
|
||||||
node: ast::GenericArgList,
|
node: ast::GenericArgList,
|
||||||
impl_trait_lower_fn: &mut impl FnMut(ThinVec<TypeBound>) -> TypeRef,
|
impl_trait_lower_fn: ImplTraitLowerFn<'_>,
|
||||||
) -> Option<GenericArgs> {
|
) -> Option<GenericArgs> {
|
||||||
// This needs to be kept in sync with `hir_generic_arg_to_ast()`.
|
// This needs to be kept in sync with `hir_generic_arg_to_ast()`.
|
||||||
let mut args = Vec::new();
|
let mut args = Vec::new();
|
||||||
@ -877,7 +919,7 @@ impl ExprCollector<'_> {
|
|||||||
fn type_bounds_from_ast(
|
fn type_bounds_from_ast(
|
||||||
&mut self,
|
&mut self,
|
||||||
type_bounds_opt: Option<ast::TypeBoundList>,
|
type_bounds_opt: Option<ast::TypeBoundList>,
|
||||||
impl_trait_lower_fn: &mut impl FnMut(ThinVec<TypeBound>) -> TypeRef,
|
impl_trait_lower_fn: ImplTraitLowerFn<'_>,
|
||||||
) -> ThinVec<TypeBound> {
|
) -> ThinVec<TypeBound> {
|
||||||
if let Some(type_bounds) = type_bounds_opt {
|
if let Some(type_bounds) = type_bounds_opt {
|
||||||
ThinVec::from_iter(Vec::from_iter(
|
ThinVec::from_iter(Vec::from_iter(
|
||||||
@ -891,7 +933,7 @@ impl ExprCollector<'_> {
|
|||||||
fn lower_path_type(
|
fn lower_path_type(
|
||||||
&mut self,
|
&mut self,
|
||||||
path_type: &ast::PathType,
|
path_type: &ast::PathType,
|
||||||
impl_trait_lower_fn: &mut impl FnMut(ThinVec<TypeBound>) -> TypeRef,
|
impl_trait_lower_fn: ImplTraitLowerFn<'_>,
|
||||||
) -> Option<Path> {
|
) -> Option<Path> {
|
||||||
let path = self.lower_path(path_type.path()?, impl_trait_lower_fn)?;
|
let path = self.lower_path(path_type.path()?, impl_trait_lower_fn)?;
|
||||||
Some(path)
|
Some(path)
|
||||||
@ -900,7 +942,7 @@ impl ExprCollector<'_> {
|
|||||||
fn lower_type_bound(
|
fn lower_type_bound(
|
||||||
&mut self,
|
&mut self,
|
||||||
node: ast::TypeBound,
|
node: ast::TypeBound,
|
||||||
impl_trait_lower_fn: &mut impl FnMut(ThinVec<TypeBound>) -> TypeRef,
|
impl_trait_lower_fn: ImplTraitLowerFn<'_>,
|
||||||
) -> TypeBound {
|
) -> TypeBound {
|
||||||
match node.kind() {
|
match node.kind() {
|
||||||
ast::TypeBoundKind::PathType(path_type) => {
|
ast::TypeBoundKind::PathType(path_type) => {
|
||||||
@ -1081,7 +1123,9 @@ impl ExprCollector<'_> {
|
|||||||
let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
|
let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
|
||||||
let generic_args = e
|
let generic_args = e
|
||||||
.generic_arg_list()
|
.generic_arg_list()
|
||||||
.and_then(|it| self.lower_generic_args(it, &mut |_| TypeRef::Error))
|
.and_then(|it| {
|
||||||
|
self.lower_generic_args(it, &mut Self::impl_trait_error_allocator)
|
||||||
|
})
|
||||||
.map(Box::new);
|
.map(Box::new);
|
||||||
self.alloc_expr(
|
self.alloc_expr(
|
||||||
Expr::MethodCall { receiver, method_name, args, generic_args },
|
Expr::MethodCall { receiver, method_name, args, generic_args },
|
||||||
@ -1162,7 +1206,7 @@ impl ExprCollector<'_> {
|
|||||||
ast::Expr::RecordExpr(e) => {
|
ast::Expr::RecordExpr(e) => {
|
||||||
let path = e
|
let path = e
|
||||||
.path()
|
.path()
|
||||||
.and_then(|path| self.lower_path(path, &mut |_| TypeRef::Error))
|
.and_then(|path| self.lower_path(path, &mut Self::impl_trait_error_allocator))
|
||||||
.map(Box::new);
|
.map(Box::new);
|
||||||
let record_lit = if let Some(nfl) = e.record_expr_field_list() {
|
let record_lit = if let Some(nfl) = e.record_expr_field_list() {
|
||||||
let fields = nfl
|
let fields = nfl
|
||||||
@ -1390,7 +1434,7 @@ impl ExprCollector<'_> {
|
|||||||
|
|
||||||
fn collect_expr_path(&mut self, e: ast::PathExpr) -> Option<(Path, HygieneId)> {
|
fn collect_expr_path(&mut self, e: ast::PathExpr) -> Option<(Path, HygieneId)> {
|
||||||
e.path().and_then(|path| {
|
e.path().and_then(|path| {
|
||||||
let path = self.lower_path(path, &mut |_| TypeRef::Error)?;
|
let path = self.lower_path(path, &mut Self::impl_trait_error_allocator)?;
|
||||||
// Need to enable `mod_path.len() < 1` for `self`.
|
// Need to enable `mod_path.len() < 1` for `self`.
|
||||||
let may_be_variable = matches!(&path, Path::BarePath(mod_path) if mod_path.len() <= 1);
|
let may_be_variable = matches!(&path, Path::BarePath(mod_path) if mod_path.len() <= 1);
|
||||||
let hygiene = if may_be_variable {
|
let hygiene = if may_be_variable {
|
||||||
@ -1459,7 +1503,7 @@ impl ExprCollector<'_> {
|
|||||||
let path = collect_path(self, e.expr()?)?;
|
let path = collect_path(self, e.expr()?)?;
|
||||||
let path = path
|
let path = path
|
||||||
.path()
|
.path()
|
||||||
.and_then(|path| self.lower_path(path, &mut |_| TypeRef::Error))
|
.and_then(|path| self.lower_path(path, &mut Self::impl_trait_error_allocator))
|
||||||
.map(Box::new);
|
.map(Box::new);
|
||||||
let (ellipsis, args) = collect_tuple(self, e.arg_list()?.args());
|
let (ellipsis, args) = collect_tuple(self, e.arg_list()?.args());
|
||||||
self.alloc_pat_from_expr(Pat::TupleStruct { path, args, ellipsis }, syntax_ptr)
|
self.alloc_pat_from_expr(Pat::TupleStruct { path, args, ellipsis }, syntax_ptr)
|
||||||
@ -1488,7 +1532,7 @@ impl ExprCollector<'_> {
|
|||||||
ast::Expr::RecordExpr(e) => {
|
ast::Expr::RecordExpr(e) => {
|
||||||
let path = e
|
let path = e
|
||||||
.path()
|
.path()
|
||||||
.and_then(|path| self.lower_path(path, &mut |_| TypeRef::Error))
|
.and_then(|path| self.lower_path(path, &mut Self::impl_trait_error_allocator))
|
||||||
.map(Box::new);
|
.map(Box::new);
|
||||||
let record_field_list = e.record_expr_field_list()?;
|
let record_field_list = e.record_expr_field_list()?;
|
||||||
let ellipsis = record_field_list.dotdot_token().is_some();
|
let ellipsis = record_field_list.dotdot_token().is_some();
|
||||||
@ -2225,7 +2269,7 @@ impl ExprCollector<'_> {
|
|||||||
ast::Pat::TupleStructPat(p) => {
|
ast::Pat::TupleStructPat(p) => {
|
||||||
let path = p
|
let path = p
|
||||||
.path()
|
.path()
|
||||||
.and_then(|path| self.lower_path(path, &mut |_| TypeRef::Error))
|
.and_then(|path| self.lower_path(path, &mut Self::impl_trait_error_allocator))
|
||||||
.map(Box::new);
|
.map(Box::new);
|
||||||
let (args, ellipsis) = self.collect_tuple_pat(
|
let (args, ellipsis) = self.collect_tuple_pat(
|
||||||
p.fields(),
|
p.fields(),
|
||||||
@ -2240,7 +2284,9 @@ impl ExprCollector<'_> {
|
|||||||
Pat::Ref { pat, mutability }
|
Pat::Ref { pat, mutability }
|
||||||
}
|
}
|
||||||
ast::Pat::PathPat(p) => {
|
ast::Pat::PathPat(p) => {
|
||||||
let path = p.path().and_then(|path| self.lower_path(path, &mut |_| TypeRef::Error));
|
let path = p
|
||||||
|
.path()
|
||||||
|
.and_then(|path| self.lower_path(path, &mut Self::impl_trait_error_allocator));
|
||||||
path.map(Pat::Path).unwrap_or(Pat::Missing)
|
path.map(Pat::Path).unwrap_or(Pat::Missing)
|
||||||
}
|
}
|
||||||
ast::Pat::OrPat(p) => 'b: {
|
ast::Pat::OrPat(p) => 'b: {
|
||||||
@ -2289,7 +2335,7 @@ impl ExprCollector<'_> {
|
|||||||
ast::Pat::RecordPat(p) => {
|
ast::Pat::RecordPat(p) => {
|
||||||
let path = p
|
let path = p
|
||||||
.path()
|
.path()
|
||||||
.and_then(|path| self.lower_path(path, &mut |_| TypeRef::Error))
|
.and_then(|path| self.lower_path(path, &mut Self::impl_trait_error_allocator))
|
||||||
.map(Box::new);
|
.map(Box::new);
|
||||||
let record_pat_field_list =
|
let record_pat_field_list =
|
||||||
&p.record_pat_field_list().expect("every struct should have a field list");
|
&p.record_pat_field_list().expect("every struct should have a field list");
|
||||||
@ -2385,7 +2431,9 @@ impl ExprCollector<'_> {
|
|||||||
.map(|path| self.alloc_expr_from_pat(Expr::Path(path), ptr)),
|
.map(|path| self.alloc_expr_from_pat(Expr::Path(path), ptr)),
|
||||||
ast::Pat::PathPat(p) => p
|
ast::Pat::PathPat(p) => p
|
||||||
.path()
|
.path()
|
||||||
.and_then(|path| self.lower_path(path, &mut |_| TypeRef::Error))
|
.and_then(|path| {
|
||||||
|
self.lower_path(path, &mut Self::impl_trait_error_allocator)
|
||||||
|
})
|
||||||
.map(|parsed| self.alloc_expr_from_pat(Expr::Path(parsed), ptr)),
|
.map(|parsed| self.alloc_expr_from_pat(Expr::Path(parsed), ptr)),
|
||||||
// We only need to handle literal, ident (if bare) and path patterns here,
|
// We only need to handle literal, ident (if bare) and path patterns here,
|
||||||
// as any other pattern as a range pattern operand is semantically invalid.
|
// as any other pattern as a range pattern operand is semantically invalid.
|
||||||
|
@ -11,7 +11,6 @@ use tt::TextRange;
|
|||||||
use crate::{
|
use crate::{
|
||||||
expr_store::lower::{ExprCollector, FxIndexSet},
|
expr_store::lower::{ExprCollector, FxIndexSet},
|
||||||
hir::{AsmOperand, AsmOptions, Expr, ExprId, InlineAsm, InlineAsmRegOrRegClass},
|
hir::{AsmOperand, AsmOptions, Expr, ExprId, InlineAsm, InlineAsmRegOrRegClass},
|
||||||
type_ref::TypeRef,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
impl ExprCollector<'_> {
|
impl ExprCollector<'_> {
|
||||||
@ -159,10 +158,12 @@ impl ExprCollector<'_> {
|
|||||||
AsmOperand::Const(self.collect_expr_opt(c.expr()))
|
AsmOperand::Const(self.collect_expr_opt(c.expr()))
|
||||||
}
|
}
|
||||||
ast::AsmOperand::AsmSym(s) => {
|
ast::AsmOperand::AsmSym(s) => {
|
||||||
let Some(path) = s
|
let Some(path) = s.path().and_then(|p| {
|
||||||
.path()
|
self.lower_path(
|
||||||
.and_then(|p| self.lower_path(p, &mut |_| TypeRef::Error))
|
p,
|
||||||
else {
|
&mut ExprCollector::impl_trait_error_allocator,
|
||||||
|
)
|
||||||
|
}) else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
AsmOperand::Sym(path)
|
AsmOperand::Sym(path)
|
||||||
|
@ -15,205 +15,67 @@ use triomphe::Arc;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
GenericDefId, TypeOrConstParamId, TypeParamId,
|
GenericDefId, TypeOrConstParamId, TypeParamId,
|
||||||
expr_store::lower::ExprCollector,
|
expr_store::{TypePtr, lower::ExprCollector},
|
||||||
hir::generics::{
|
hir::generics::{
|
||||||
ConstParamData, GenericParams, LifetimeParamData, TypeOrConstParamData, TypeParamData,
|
ConstParamData, GenericParams, LifetimeParamData, TypeOrConstParamData, TypeParamData,
|
||||||
TypeParamProvenance, WherePredicate, WherePredicateTypeTarget,
|
TypeParamProvenance, WherePredicate,
|
||||||
},
|
},
|
||||||
type_ref::{LifetimeRef, TypeBound, TypeRef, TypeRefId},
|
type_ref::{LifetimeRef, TypeBound, TypeRef, TypeRefId},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(crate) struct GenericParamsCollector<'db, 'c> {
|
pub(crate) type ImplTraitLowerFn<'l> = &'l mut dyn for<'ec, 'db> FnMut(
|
||||||
expr_collector: &'c mut ExprCollector<'db>,
|
&'ec mut ExprCollector<'db>,
|
||||||
|
TypePtr,
|
||||||
|
ThinVec<TypeBound>,
|
||||||
|
) -> TypeRefId;
|
||||||
|
|
||||||
|
pub(crate) struct GenericParamsCollector {
|
||||||
type_or_consts: Arena<TypeOrConstParamData>,
|
type_or_consts: Arena<TypeOrConstParamData>,
|
||||||
lifetimes: Arena<LifetimeParamData>,
|
lifetimes: Arena<LifetimeParamData>,
|
||||||
where_predicates: Vec<WherePredicate>,
|
where_predicates: Vec<WherePredicate>,
|
||||||
parent: GenericDefId,
|
parent: GenericDefId,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'db, 'c> GenericParamsCollector<'db, 'c> {
|
impl GenericParamsCollector {
|
||||||
pub(crate) fn new(expr_collector: &'c mut ExprCollector<'db>, parent: GenericDefId) -> Self {
|
pub(crate) fn new(parent: GenericDefId) -> Self {
|
||||||
Self {
|
Self {
|
||||||
expr_collector,
|
|
||||||
type_or_consts: Default::default(),
|
type_or_consts: Default::default(),
|
||||||
lifetimes: Default::default(),
|
lifetimes: Default::default(),
|
||||||
where_predicates: Default::default(),
|
where_predicates: Default::default(),
|
||||||
parent,
|
parent,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub(crate) fn with_self_param(
|
||||||
pub(crate) fn fill_self_param(&mut self, bounds: Option<ast::TypeBoundList>) {
|
ec: &mut ExprCollector<'_>,
|
||||||
let self_ = Name::new_symbol_root(sym::Self_);
|
parent: GenericDefId,
|
||||||
let idx = self.type_or_consts.alloc(
|
bounds: Option<ast::TypeBoundList>,
|
||||||
TypeParamData {
|
) -> Self {
|
||||||
name: Some(self_.clone()),
|
let mut this = Self::new(parent);
|
||||||
default: None,
|
this.fill_self_param(ec, bounds);
|
||||||
provenance: TypeParamProvenance::TraitSelf,
|
this
|
||||||
}
|
|
||||||
.into(),
|
|
||||||
);
|
|
||||||
let type_ref = TypeRef::TypeParam(TypeParamId::from_unchecked(TypeOrConstParamId {
|
|
||||||
parent: self.parent,
|
|
||||||
local_id: idx,
|
|
||||||
}));
|
|
||||||
let self_ = self.expr_collector.alloc_type_ref_desugared(type_ref);
|
|
||||||
if let Some(bounds) = bounds {
|
|
||||||
self.lower_bounds(Some(bounds), Either::Left(self_));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn lower(
|
pub(crate) fn lower(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
ec: &mut ExprCollector<'_>,
|
||||||
generic_param_list: Option<ast::GenericParamList>,
|
generic_param_list: Option<ast::GenericParamList>,
|
||||||
where_clause: Option<ast::WhereClause>,
|
where_clause: Option<ast::WhereClause>,
|
||||||
) {
|
) {
|
||||||
if let Some(params) = generic_param_list {
|
if let Some(params) = generic_param_list {
|
||||||
self.lower_param_list(params)
|
self.lower_param_list(ec, params)
|
||||||
}
|
}
|
||||||
if let Some(where_clause) = where_clause {
|
if let Some(where_clause) = where_clause {
|
||||||
self.lower_where_predicates(where_clause);
|
self.lower_where_predicates(ec, where_clause);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_param_list(&mut self, params: ast::GenericParamList) {
|
|
||||||
for generic_param in params.generic_params() {
|
|
||||||
let enabled = self.expr_collector.expander.is_cfg_enabled(
|
|
||||||
self.expr_collector.db,
|
|
||||||
self.expr_collector.module.krate(),
|
|
||||||
&generic_param,
|
|
||||||
);
|
|
||||||
if !enabled {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
match generic_param {
|
|
||||||
ast::GenericParam::TypeParam(type_param) => {
|
|
||||||
let name = type_param.name().map_or_else(Name::missing, |it| it.as_name());
|
|
||||||
let default = type_param
|
|
||||||
.default_type()
|
|
||||||
.map(|it| self.expr_collector.lower_type_ref(it, &mut |_| TypeRef::Error));
|
|
||||||
let param = TypeParamData {
|
|
||||||
name: Some(name.clone()),
|
|
||||||
default,
|
|
||||||
provenance: TypeParamProvenance::TypeParamList,
|
|
||||||
};
|
|
||||||
let idx = self.type_or_consts.alloc(param.into());
|
|
||||||
let type_ref =
|
|
||||||
TypeRef::TypeParam(TypeParamId::from_unchecked(TypeOrConstParamId {
|
|
||||||
parent: self.parent,
|
|
||||||
local_id: idx,
|
|
||||||
}));
|
|
||||||
let type_ref = self.expr_collector.alloc_type_ref_desugared(type_ref);
|
|
||||||
self.lower_bounds(type_param.type_bound_list(), Either::Left(type_ref));
|
|
||||||
}
|
|
||||||
ast::GenericParam::ConstParam(const_param) => {
|
|
||||||
let name = const_param.name().map_or_else(Name::missing, |it| it.as_name());
|
|
||||||
let ty = self
|
|
||||||
.expr_collector
|
|
||||||
.lower_type_ref_opt(const_param.ty(), &mut |_| TypeRef::Error);
|
|
||||||
let param = ConstParamData {
|
|
||||||
name,
|
|
||||||
ty,
|
|
||||||
default: const_param
|
|
||||||
.default_val()
|
|
||||||
.map(|it| self.expr_collector.lower_const_arg(it)),
|
|
||||||
};
|
|
||||||
let _idx = self.type_or_consts.alloc(param.into());
|
|
||||||
}
|
|
||||||
ast::GenericParam::LifetimeParam(lifetime_param) => {
|
|
||||||
let lifetime_ref =
|
|
||||||
self.expr_collector.lower_lifetime_ref_opt(lifetime_param.lifetime());
|
|
||||||
if let LifetimeRef::Named(name) = &lifetime_ref {
|
|
||||||
let param = LifetimeParamData { name: name.clone() };
|
|
||||||
let _idx = self.lifetimes.alloc(param);
|
|
||||||
self.lower_bounds(
|
|
||||||
lifetime_param.type_bound_list(),
|
|
||||||
Either::Right(lifetime_ref),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn lower_where_predicates(&mut self, where_clause: ast::WhereClause) {
|
|
||||||
for pred in where_clause.predicates() {
|
|
||||||
let target = if let Some(type_ref) = pred.ty() {
|
|
||||||
Either::Left(self.expr_collector.lower_type_ref(type_ref, &mut |_| TypeRef::Error))
|
|
||||||
} else if let Some(lifetime) = pred.lifetime() {
|
|
||||||
Either::Right(self.expr_collector.lower_lifetime_ref(lifetime))
|
|
||||||
} else {
|
|
||||||
continue;
|
|
||||||
};
|
|
||||||
|
|
||||||
let lifetimes: Option<Box<_>> = pred.generic_param_list().map(|param_list| {
|
|
||||||
// Higher-Ranked Trait Bounds
|
|
||||||
param_list
|
|
||||||
.lifetime_params()
|
|
||||||
.map(|lifetime_param| {
|
|
||||||
lifetime_param
|
|
||||||
.lifetime()
|
|
||||||
.map_or_else(Name::missing, |lt| Name::new_lifetime(<.text()))
|
|
||||||
})
|
|
||||||
.collect()
|
|
||||||
});
|
|
||||||
for bound in pred.type_bound_list().iter().flat_map(|l| l.bounds()) {
|
|
||||||
self.lower_type_bound_as_predicate(bound, lifetimes.as_deref(), target.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn lower_bounds(
|
|
||||||
&mut self,
|
|
||||||
type_bounds: Option<ast::TypeBoundList>,
|
|
||||||
target: Either<TypeRefId, LifetimeRef>,
|
|
||||||
) {
|
|
||||||
for bound in type_bounds.iter().flat_map(|type_bound_list| type_bound_list.bounds()) {
|
|
||||||
self.lower_type_bound_as_predicate(bound, None, target.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn lower_type_bound_as_predicate(
|
|
||||||
&mut self,
|
|
||||||
bound: ast::TypeBound,
|
|
||||||
hrtb_lifetimes: Option<&[Name]>,
|
|
||||||
target: Either<TypeRefId, LifetimeRef>,
|
|
||||||
) {
|
|
||||||
let bound = self.expr_collector.lower_type_bound(
|
|
||||||
bound,
|
|
||||||
&mut Self::lower_argument_impl_trait(
|
|
||||||
&mut self.type_or_consts,
|
|
||||||
&mut self.where_predicates,
|
|
||||||
self.parent,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
let predicate = match (target, bound) {
|
|
||||||
(_, TypeBound::Error | TypeBound::Use(_)) => return,
|
|
||||||
(Either::Left(type_ref), bound) => match hrtb_lifetimes {
|
|
||||||
Some(hrtb_lifetimes) => WherePredicate::ForLifetime {
|
|
||||||
lifetimes: hrtb_lifetimes.to_vec().into_boxed_slice(),
|
|
||||||
target: WherePredicateTypeTarget::TypeRef(type_ref),
|
|
||||||
bound,
|
|
||||||
},
|
|
||||||
None => WherePredicate::TypeBound {
|
|
||||||
target: WherePredicateTypeTarget::TypeRef(type_ref),
|
|
||||||
bound,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
(Either::Right(lifetime), TypeBound::Lifetime(bound)) => {
|
|
||||||
WherePredicate::Lifetime { target: lifetime, bound }
|
|
||||||
}
|
|
||||||
(Either::Right(_), TypeBound::ForLifetime(..) | TypeBound::Path(..)) => return,
|
|
||||||
};
|
|
||||||
self.where_predicates.push(predicate);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn collect_impl_trait<R>(
|
pub(crate) fn collect_impl_trait<R>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cb: impl FnOnce(&mut ExprCollector<'_>, &mut dyn FnMut(ThinVec<TypeBound>) -> TypeRef) -> R,
|
ec: &mut ExprCollector<'_>,
|
||||||
|
cb: impl FnOnce(&mut ExprCollector<'_>, ImplTraitLowerFn<'_>) -> R,
|
||||||
) -> R {
|
) -> R {
|
||||||
cb(
|
cb(
|
||||||
self.expr_collector,
|
ec,
|
||||||
&mut Self::lower_argument_impl_trait(
|
&mut Self::lower_argument_impl_trait(
|
||||||
&mut self.type_or_consts,
|
&mut self.type_or_consts,
|
||||||
&mut self.where_predicates,
|
&mut self.where_predicates,
|
||||||
@ -222,39 +84,8 @@ impl<'db, 'c> GenericParamsCollector<'db, 'c> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_argument_impl_trait(
|
|
||||||
type_or_consts: &mut Arena<TypeOrConstParamData>,
|
|
||||||
where_predicates: &mut Vec<WherePredicate>,
|
|
||||||
parent: GenericDefId,
|
|
||||||
) -> impl FnMut(ThinVec<TypeBound>) -> TypeRef {
|
|
||||||
move |impl_trait_bounds| {
|
|
||||||
let param = TypeParamData {
|
|
||||||
name: None,
|
|
||||||
default: None,
|
|
||||||
provenance: TypeParamProvenance::ArgumentImplTrait,
|
|
||||||
};
|
|
||||||
let param_id = type_or_consts.alloc(param.into());
|
|
||||||
for bound in impl_trait_bounds {
|
|
||||||
where_predicates.push(WherePredicate::TypeBound {
|
|
||||||
target: WherePredicateTypeTarget::TypeOrConstParam(param_id),
|
|
||||||
bound: bound.clone(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
TypeRef::TypeParam(TypeParamId::from_unchecked(TypeOrConstParamId {
|
|
||||||
parent,
|
|
||||||
local_id: param_id,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn finish(self) -> Arc<GenericParams> {
|
pub(crate) fn finish(self) -> Arc<GenericParams> {
|
||||||
let Self {
|
let Self { mut lifetimes, mut type_or_consts, mut where_predicates, parent: _ } = self;
|
||||||
mut lifetimes,
|
|
||||||
mut type_or_consts,
|
|
||||||
mut where_predicates,
|
|
||||||
expr_collector: _,
|
|
||||||
parent: _,
|
|
||||||
} = self;
|
|
||||||
|
|
||||||
if lifetimes.is_empty() && type_or_consts.is_empty() && where_predicates.is_empty() {
|
if lifetimes.is_empty() && type_or_consts.is_empty() && where_predicates.is_empty() {
|
||||||
static EMPTY: LazyLock<Arc<GenericParams>> = LazyLock::new(|| {
|
static EMPTY: LazyLock<Arc<GenericParams>> = LazyLock::new(|| {
|
||||||
@ -276,4 +107,183 @@ impl<'db, 'c> GenericParamsCollector<'db, 'c> {
|
|||||||
where_predicates: where_predicates.into_boxed_slice(),
|
where_predicates: where_predicates.into_boxed_slice(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn lower_param_list(&mut self, ec: &mut ExprCollector<'_>, params: ast::GenericParamList) {
|
||||||
|
for generic_param in params.generic_params() {
|
||||||
|
let enabled = ec.expander.is_cfg_enabled(ec.db, ec.module.krate(), &generic_param);
|
||||||
|
if !enabled {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
match generic_param {
|
||||||
|
ast::GenericParam::TypeParam(type_param) => {
|
||||||
|
let name = type_param.name().map_or_else(Name::missing, |it| it.as_name());
|
||||||
|
let default = type_param.default_type().map(|it| {
|
||||||
|
ec.lower_type_ref(it, &mut ExprCollector::impl_trait_error_allocator)
|
||||||
|
});
|
||||||
|
let param = TypeParamData {
|
||||||
|
name: Some(name.clone()),
|
||||||
|
default,
|
||||||
|
provenance: TypeParamProvenance::TypeParamList,
|
||||||
|
};
|
||||||
|
let idx = self.type_or_consts.alloc(param.into());
|
||||||
|
let type_ref =
|
||||||
|
TypeRef::TypeParam(TypeParamId::from_unchecked(TypeOrConstParamId {
|
||||||
|
parent: self.parent,
|
||||||
|
local_id: idx,
|
||||||
|
}));
|
||||||
|
let type_ref = ec.alloc_type_ref_desugared(type_ref);
|
||||||
|
self.lower_bounds(ec, type_param.type_bound_list(), Either::Left(type_ref));
|
||||||
|
}
|
||||||
|
ast::GenericParam::ConstParam(const_param) => {
|
||||||
|
let name = const_param.name().map_or_else(Name::missing, |it| it.as_name());
|
||||||
|
let ty = ec.lower_type_ref_opt(
|
||||||
|
const_param.ty(),
|
||||||
|
&mut ExprCollector::impl_trait_error_allocator,
|
||||||
|
);
|
||||||
|
let param = ConstParamData {
|
||||||
|
name,
|
||||||
|
ty,
|
||||||
|
default: const_param.default_val().map(|it| ec.lower_const_arg(it)),
|
||||||
|
};
|
||||||
|
let _idx = self.type_or_consts.alloc(param.into());
|
||||||
|
}
|
||||||
|
ast::GenericParam::LifetimeParam(lifetime_param) => {
|
||||||
|
let lifetime_ref = ec.lower_lifetime_ref_opt(lifetime_param.lifetime());
|
||||||
|
if let LifetimeRef::Named(name) = &lifetime_ref {
|
||||||
|
let param = LifetimeParamData { name: name.clone() };
|
||||||
|
let _idx = self.lifetimes.alloc(param);
|
||||||
|
self.lower_bounds(
|
||||||
|
ec,
|
||||||
|
lifetime_param.type_bound_list(),
|
||||||
|
Either::Right(lifetime_ref),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lower_where_predicates(
|
||||||
|
&mut self,
|
||||||
|
ec: &mut ExprCollector<'_>,
|
||||||
|
where_clause: ast::WhereClause,
|
||||||
|
) {
|
||||||
|
for pred in where_clause.predicates() {
|
||||||
|
let target = if let Some(type_ref) = pred.ty() {
|
||||||
|
Either::Left(
|
||||||
|
ec.lower_type_ref(type_ref, &mut ExprCollector::impl_trait_error_allocator),
|
||||||
|
)
|
||||||
|
} else if let Some(lifetime) = pred.lifetime() {
|
||||||
|
Either::Right(ec.lower_lifetime_ref(lifetime))
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
let lifetimes: Option<Box<_>> = pred.generic_param_list().map(|param_list| {
|
||||||
|
// Higher-Ranked Trait Bounds
|
||||||
|
param_list
|
||||||
|
.lifetime_params()
|
||||||
|
.map(|lifetime_param| {
|
||||||
|
lifetime_param
|
||||||
|
.lifetime()
|
||||||
|
.map_or_else(Name::missing, |lt| Name::new_lifetime(<.text()))
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
});
|
||||||
|
for bound in pred.type_bound_list().iter().flat_map(|l| l.bounds()) {
|
||||||
|
self.lower_type_bound_as_predicate(ec, bound, lifetimes.as_deref(), target.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lower_bounds(
|
||||||
|
&mut self,
|
||||||
|
ec: &mut ExprCollector<'_>,
|
||||||
|
type_bounds: Option<ast::TypeBoundList>,
|
||||||
|
target: Either<TypeRefId, LifetimeRef>,
|
||||||
|
) {
|
||||||
|
for bound in type_bounds.iter().flat_map(|type_bound_list| type_bound_list.bounds()) {
|
||||||
|
self.lower_type_bound_as_predicate(ec, bound, None, target.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lower_type_bound_as_predicate(
|
||||||
|
&mut self,
|
||||||
|
ec: &mut ExprCollector<'_>,
|
||||||
|
bound: ast::TypeBound,
|
||||||
|
hrtb_lifetimes: Option<&[Name]>,
|
||||||
|
target: Either<TypeRefId, LifetimeRef>,
|
||||||
|
) {
|
||||||
|
let bound = ec.lower_type_bound(
|
||||||
|
bound,
|
||||||
|
&mut Self::lower_argument_impl_trait(
|
||||||
|
&mut self.type_or_consts,
|
||||||
|
&mut self.where_predicates,
|
||||||
|
self.parent,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
let predicate = match (target, bound) {
|
||||||
|
(_, TypeBound::Error | TypeBound::Use(_)) => return,
|
||||||
|
(Either::Left(type_ref), bound) => match hrtb_lifetimes {
|
||||||
|
Some(hrtb_lifetimes) => WherePredicate::ForLifetime {
|
||||||
|
lifetimes: ThinVec::from_iter(hrtb_lifetimes.iter().cloned()),
|
||||||
|
target: type_ref,
|
||||||
|
bound,
|
||||||
|
},
|
||||||
|
None => WherePredicate::TypeBound { target: type_ref, bound },
|
||||||
|
},
|
||||||
|
(Either::Right(lifetime), TypeBound::Lifetime(bound)) => {
|
||||||
|
WherePredicate::Lifetime { target: lifetime, bound }
|
||||||
|
}
|
||||||
|
(Either::Right(_), TypeBound::ForLifetime(..) | TypeBound::Path(..)) => return,
|
||||||
|
};
|
||||||
|
self.where_predicates.push(predicate);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lower_argument_impl_trait(
|
||||||
|
type_or_consts: &mut Arena<TypeOrConstParamData>,
|
||||||
|
where_predicates: &mut Vec<WherePredicate>,
|
||||||
|
parent: GenericDefId,
|
||||||
|
) -> impl for<'ec, 'db> FnMut(&'ec mut ExprCollector<'db>, TypePtr, ThinVec<TypeBound>) -> TypeRefId
|
||||||
|
{
|
||||||
|
move |ec, ptr, impl_trait_bounds| {
|
||||||
|
let param = TypeParamData {
|
||||||
|
name: None,
|
||||||
|
default: None,
|
||||||
|
provenance: TypeParamProvenance::ArgumentImplTrait,
|
||||||
|
};
|
||||||
|
let param_id = TypeRef::TypeParam(TypeParamId::from_unchecked(TypeOrConstParamId {
|
||||||
|
parent,
|
||||||
|
local_id: type_or_consts.alloc(param.into()),
|
||||||
|
}));
|
||||||
|
let type_ref = ec.alloc_type_ref(param_id, ptr);
|
||||||
|
for bound in impl_trait_bounds {
|
||||||
|
where_predicates
|
||||||
|
.push(WherePredicate::TypeBound { target: type_ref, bound: bound.clone() });
|
||||||
|
}
|
||||||
|
type_ref
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fill_self_param(&mut self, ec: &mut ExprCollector<'_>, bounds: Option<ast::TypeBoundList>) {
|
||||||
|
let self_ = Name::new_symbol_root(sym::Self_);
|
||||||
|
let idx = self.type_or_consts.alloc(
|
||||||
|
TypeParamData {
|
||||||
|
name: Some(self_.clone()),
|
||||||
|
default: None,
|
||||||
|
provenance: TypeParamProvenance::TraitSelf,
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
);
|
||||||
|
debug_assert_eq!(idx, GenericParams::SELF_PARAM_ID_IN_SELF);
|
||||||
|
let type_ref = TypeRef::TypeParam(TypeParamId::from_unchecked(TypeOrConstParamId {
|
||||||
|
parent: self.parent,
|
||||||
|
local_id: idx,
|
||||||
|
}));
|
||||||
|
let self_ = ec.alloc_type_ref_desugared(type_ref);
|
||||||
|
if let Some(bounds) = bounds {
|
||||||
|
self.lower_bounds(ec, Some(bounds), Either::Left(self_));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,10 @@ mod tests;
|
|||||||
|
|
||||||
use std::iter;
|
use std::iter;
|
||||||
|
|
||||||
use crate::expr_store::{lower::ExprCollector, path::NormalPath};
|
use crate::expr_store::{
|
||||||
|
lower::{ExprCollector, generics::ImplTraitLowerFn},
|
||||||
|
path::NormalPath,
|
||||||
|
};
|
||||||
|
|
||||||
use hir_expand::{
|
use hir_expand::{
|
||||||
mod_path::{ModPath, PathKind, resolve_crate_root},
|
mod_path::{ModPath, PathKind, resolve_crate_root},
|
||||||
@ -16,11 +19,10 @@ use syntax::{
|
|||||||
AstPtr,
|
AstPtr,
|
||||||
ast::{self, AstNode, HasGenericArgs},
|
ast::{self, AstNode, HasGenericArgs},
|
||||||
};
|
};
|
||||||
use thin_vec::ThinVec;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
expr_store::path::{GenericArg, GenericArgs, Path},
|
expr_store::path::{GenericArg, GenericArgs, Path},
|
||||||
type_ref::{TypeBound, TypeRef},
|
type_ref::TypeRef,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@ -36,7 +38,7 @@ thread_local! {
|
|||||||
pub(super) fn lower_path(
|
pub(super) fn lower_path(
|
||||||
collector: &mut ExprCollector<'_>,
|
collector: &mut ExprCollector<'_>,
|
||||||
mut path: ast::Path,
|
mut path: ast::Path,
|
||||||
impl_trait_lower_fn: &mut impl FnMut(ThinVec<TypeBound>) -> TypeRef,
|
impl_trait_lower_fn: ImplTraitLowerFn<'_>,
|
||||||
) -> Option<Path> {
|
) -> Option<Path> {
|
||||||
let mut kind = PathKind::Plain;
|
let mut kind = PathKind::Plain;
|
||||||
let mut type_anchor = None;
|
let mut type_anchor = None;
|
||||||
|
@ -15,14 +15,13 @@ use crate::{
|
|||||||
pretty,
|
pretty,
|
||||||
},
|
},
|
||||||
test_db::TestDB,
|
test_db::TestDB,
|
||||||
type_ref::TypeRef,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
fn lower_path(path: ast::Path) -> (TestDB, ExpressionStore, Option<Path>) {
|
fn lower_path(path: ast::Path) -> (TestDB, ExpressionStore, Option<Path>) {
|
||||||
let (db, file_id) = TestDB::with_single_file("");
|
let (db, file_id) = TestDB::with_single_file("");
|
||||||
let krate = db.fetch_test_crate();
|
let krate = db.fetch_test_crate();
|
||||||
let mut ctx = ExprCollector::new(&db, db.crate_def_map(krate).root_module_id(), file_id.into());
|
let mut ctx = ExprCollector::new(&db, db.crate_def_map(krate).root_module_id(), file_id.into());
|
||||||
let lowered_path = ctx.lower_path(path, &mut TypeRef::ImplTrait);
|
let lowered_path = ctx.lower_path(path, &mut ExprCollector::impl_trait_allocator);
|
||||||
let store = ctx.store.finish();
|
let store = ctx.store.finish();
|
||||||
(db, store, lowered_path)
|
(db, store, lowered_path)
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ use crate::{
|
|||||||
expr_store::path::{GenericArg, GenericArgs},
|
expr_store::path::{GenericArg, GenericArgs},
|
||||||
hir::{
|
hir::{
|
||||||
Array, BindingAnnotation, CaptureBy, ClosureKind, Literal, Movability, Statement,
|
Array, BindingAnnotation, CaptureBy, ClosureKind, Literal, Movability, Statement,
|
||||||
generics::{GenericParams, WherePredicate, WherePredicateTypeTarget},
|
generics::{GenericParams, WherePredicate},
|
||||||
},
|
},
|
||||||
lang_item::LangItemTarget,
|
lang_item::LangItemTarget,
|
||||||
signatures::{FnFlags, FunctionSignature, StructSignature},
|
signatures::{FnFlags, FunctionSignature, StructSignature},
|
||||||
@ -336,21 +336,11 @@ fn print_where_clauses(db: &dyn DefDatabase, generic_params: &GenericParams, p:
|
|||||||
w!(p, ",\n");
|
w!(p, ",\n");
|
||||||
}
|
}
|
||||||
match pred {
|
match pred {
|
||||||
WherePredicate::TypeBound { target, bound } => match target {
|
WherePredicate::TypeBound { target, bound } => {
|
||||||
&WherePredicateTypeTarget::TypeRef(idx) => {
|
p.print_type_ref(*target);
|
||||||
p.print_type_ref(idx);
|
w!(p, ": ");
|
||||||
w!(p, ": ");
|
p.print_type_bounds(std::slice::from_ref(bound));
|
||||||
p.print_type_bounds(std::slice::from_ref(bound));
|
}
|
||||||
}
|
|
||||||
WherePredicateTypeTarget::TypeOrConstParam(idx) => {
|
|
||||||
match generic_params[*idx].name() {
|
|
||||||
Some(name) => w!(p, "{}", name.display(db, p.edition)),
|
|
||||||
None => w!(p, "Param[{}]", idx.into_raw()),
|
|
||||||
}
|
|
||||||
w!(p, ": ");
|
|
||||||
p.print_type_bounds(std::slice::from_ref(bound));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
WherePredicate::Lifetime { target, bound } => {
|
WherePredicate::Lifetime { target, bound } => {
|
||||||
p.print_lifetime_ref(target);
|
p.print_lifetime_ref(target);
|
||||||
w!(p, ": ");
|
w!(p, ": ");
|
||||||
@ -365,21 +355,9 @@ fn print_where_clauses(db: &dyn DefDatabase, generic_params: &GenericParams, p:
|
|||||||
w!(p, "{}", lifetime.display(db, p.edition));
|
w!(p, "{}", lifetime.display(db, p.edition));
|
||||||
}
|
}
|
||||||
w!(p, "> ");
|
w!(p, "> ");
|
||||||
match target {
|
p.print_type_ref(*target);
|
||||||
WherePredicateTypeTarget::TypeRef(idx) => {
|
w!(p, ": ");
|
||||||
p.print_type_ref(*idx);
|
p.print_type_bounds(std::slice::from_ref(bound));
|
||||||
w!(p, ": ");
|
|
||||||
p.print_type_bounds(std::slice::from_ref(bound));
|
|
||||||
}
|
|
||||||
WherePredicateTypeTarget::TypeOrConstParam(idx) => {
|
|
||||||
match generic_params[*idx].name() {
|
|
||||||
Some(name) => w!(p, "{}", name.display(db, p.edition)),
|
|
||||||
None => w!(p, "Param[{}]", idx.into_raw()),
|
|
||||||
}
|
|
||||||
w!(p, ": ");
|
|
||||||
p.print_type_bounds(std::slice::from_ref(bound));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ use std::{ops, sync::LazyLock};
|
|||||||
use hir_expand::name::Name;
|
use hir_expand::name::Name;
|
||||||
use la_arena::{Arena, Idx, RawIdx};
|
use la_arena::{Arena, Idx, RawIdx};
|
||||||
use stdx::impl_from;
|
use stdx::impl_from;
|
||||||
|
use thin_vec::ThinVec;
|
||||||
use triomphe::Arc;
|
use triomphe::Arc;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -13,10 +14,6 @@ use crate::{
|
|||||||
type_ref::{ConstRef, LifetimeRef, TypeBound, TypeRefId},
|
type_ref::{ConstRef, LifetimeRef, TypeBound, TypeRefId},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The index of the self param in the generic of the non-parent definition.
|
|
||||||
const SELF_PARAM_ID_IN_SELF: la_arena::Idx<TypeOrConstParamData> =
|
|
||||||
LocalTypeOrConstParamId::from_raw(RawIdx::from_u32(0));
|
|
||||||
|
|
||||||
pub type LocalTypeOrConstParamId = Idx<TypeOrConstParamData>;
|
pub type LocalTypeOrConstParamId = Idx<TypeOrConstParamData>;
|
||||||
pub type LocalLifetimeParamId = Idx<LifetimeParamData>;
|
pub type LocalLifetimeParamId = Idx<LifetimeParamData>;
|
||||||
|
|
||||||
@ -173,17 +170,9 @@ impl ops::Index<LocalLifetimeParamId> for GenericParams {
|
|||||||
/// associated type bindings like `Iterator<Item = u32>`.
|
/// associated type bindings like `Iterator<Item = u32>`.
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
||||||
pub enum WherePredicate {
|
pub enum WherePredicate {
|
||||||
TypeBound { target: WherePredicateTypeTarget, bound: TypeBound },
|
TypeBound { target: TypeRefId, bound: TypeBound },
|
||||||
Lifetime { target: LifetimeRef, bound: LifetimeRef },
|
Lifetime { target: LifetimeRef, bound: LifetimeRef },
|
||||||
ForLifetime { lifetimes: Box<[Name]>, target: WherePredicateTypeTarget, bound: TypeBound },
|
ForLifetime { lifetimes: ThinVec<Name>, target: TypeRefId, bound: TypeBound },
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
|
||||||
pub enum WherePredicateTypeTarget {
|
|
||||||
TypeRef(TypeRefId),
|
|
||||||
// FIXME: This can be folded into the above now that `TypeRef` can refer to `TypeParam`?
|
|
||||||
/// For desugared where predicates that can directly refer to a type param.
|
|
||||||
TypeOrConstParam(LocalTypeOrConstParamId),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static EMPTY: LazyLock<Arc<GenericParams>> = LazyLock::new(|| {
|
static EMPTY: LazyLock<Arc<GenericParams>> = LazyLock::new(|| {
|
||||||
@ -193,7 +182,12 @@ static EMPTY: LazyLock<Arc<GenericParams>> = LazyLock::new(|| {
|
|||||||
where_predicates: Box::default(),
|
where_predicates: Box::default(),
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
impl GenericParams {
|
impl GenericParams {
|
||||||
|
/// The index of the self param in the generic of the non-parent definition.
|
||||||
|
pub(crate) const SELF_PARAM_ID_IN_SELF: la_arena::Idx<TypeOrConstParamData> =
|
||||||
|
LocalTypeOrConstParamId::from_raw(RawIdx::from_u32(0));
|
||||||
|
|
||||||
pub fn new(db: &dyn DefDatabase, def: GenericDefId) -> Arc<GenericParams> {
|
pub fn new(db: &dyn DefDatabase, def: GenericDefId) -> Arc<GenericParams> {
|
||||||
match def {
|
match def {
|
||||||
GenericDefId::AdtId(AdtId::EnumId(it)) => db.enum_signature(it).generic_params.clone(),
|
GenericDefId::AdtId(AdtId::EnumId(it)) => db.enum_signature(it).generic_params.clone(),
|
||||||
@ -388,13 +382,13 @@ impl GenericParams {
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
matches!(
|
matches!(
|
||||||
self.type_or_consts[SELF_PARAM_ID_IN_SELF],
|
self.type_or_consts[Self::SELF_PARAM_ID_IN_SELF],
|
||||||
TypeOrConstParamData::TypeParamData(TypeParamData {
|
TypeOrConstParamData::TypeParamData(TypeParamData {
|
||||||
provenance: TypeParamProvenance::TraitSelf,
|
provenance: TypeParamProvenance::TraitSelf,
|
||||||
..
|
..
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
.then(|| SELF_PARAM_ID_IN_SELF)
|
.then(|| Self::SELF_PARAM_ID_IN_SELF)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn find_lifetime_by_name(
|
pub fn find_lifetime_by_name(
|
||||||
|
@ -34,7 +34,7 @@ use crate::{
|
|||||||
},
|
},
|
||||||
lang_item::LangItem,
|
lang_item::LangItem,
|
||||||
src::HasSource,
|
src::HasSource,
|
||||||
type_ref::{TraitRef, TypeBound, TypeRef, TypeRefId},
|
type_ref::{TraitRef, TypeBound, TypeRefId},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
@ -877,7 +877,8 @@ fn lower_fields<'a>(
|
|||||||
if attrs.is_cfg_enabled(cfg_options) {
|
if attrs.is_cfg_enabled(cfg_options) {
|
||||||
arena.alloc(FieldData {
|
arena.alloc(FieldData {
|
||||||
name: field.name.clone(),
|
name: field.name.clone(),
|
||||||
type_ref: col.lower_type_ref_opt(ty, &mut |_| TypeRef::Error),
|
type_ref: col
|
||||||
|
.lower_type_ref_opt(ty, &mut ExprCollector::impl_trait_error_allocator),
|
||||||
visibility: item_tree[override_visibility.unwrap_or(field.visibility)].clone(),
|
visibility: item_tree[override_visibility.unwrap_or(field.visibility)].clone(),
|
||||||
is_unsafe: field.is_unsafe,
|
is_unsafe: field.is_unsafe,
|
||||||
});
|
});
|
||||||
|
@ -16,9 +16,7 @@ use hir_def::{
|
|||||||
db::DefDatabase,
|
db::DefDatabase,
|
||||||
expr_store::{ExpressionStore, path::Path},
|
expr_store::{ExpressionStore, path::Path},
|
||||||
find_path::{self, PrefixKind},
|
find_path::{self, PrefixKind},
|
||||||
hir::generics::{
|
hir::generics::{TypeOrConstParamData, TypeParamProvenance, WherePredicate},
|
||||||
TypeOrConstParamData, TypeParamProvenance, WherePredicate, WherePredicateTypeTarget,
|
|
||||||
},
|
|
||||||
item_scope::ItemInNs,
|
item_scope::ItemInNs,
|
||||||
item_tree::FieldsShape,
|
item_tree::FieldsShape,
|
||||||
lang_item::{LangItem, LangItemTarget},
|
lang_item::{LangItem, LangItemTarget},
|
||||||
@ -2119,15 +2117,15 @@ impl HirDisplayWithExpressionStore for TypeRefId {
|
|||||||
generic_params
|
generic_params
|
||||||
.where_predicates()
|
.where_predicates()
|
||||||
.filter_map(|it| match it {
|
.filter_map(|it| match it {
|
||||||
WherePredicate::TypeBound {
|
WherePredicate::TypeBound { target, bound }
|
||||||
target: WherePredicateTypeTarget::TypeOrConstParam(p),
|
| WherePredicate::ForLifetime { lifetimes: _, target, bound }
|
||||||
bound,
|
if matches!(
|
||||||
|
store[*target],
|
||||||
|
TypeRef::TypeParam(t) if t == *param
|
||||||
|
) =>
|
||||||
|
{
|
||||||
|
Some(bound)
|
||||||
}
|
}
|
||||||
| WherePredicate::ForLifetime {
|
|
||||||
lifetimes: _,
|
|
||||||
target: WherePredicateTypeTarget::TypeOrConstParam(p),
|
|
||||||
bound,
|
|
||||||
} if *p == param.local_id() => Some(bound),
|
|
||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
.map(ExpressionStoreAdapter::wrap(store)),
|
.map(ExpressionStoreAdapter::wrap(store)),
|
||||||
|
@ -29,9 +29,7 @@ use hir_def::{
|
|||||||
Lookup, StaticId, StructId, TypeAliasId, TypeOrConstParamId, UnionId, VariantId,
|
Lookup, StaticId, StructId, TypeAliasId, TypeOrConstParamId, UnionId, VariantId,
|
||||||
builtin_type::BuiltinType,
|
builtin_type::BuiltinType,
|
||||||
expr_store::{ExpressionStore, path::Path},
|
expr_store::{ExpressionStore, path::Path},
|
||||||
hir::generics::{
|
hir::generics::{GenericParamDataRef, TypeOrConstParamData, WherePredicate},
|
||||||
GenericParamDataRef, TypeOrConstParamData, WherePredicate, WherePredicateTypeTarget,
|
|
||||||
},
|
|
||||||
item_tree::FieldsShape,
|
item_tree::FieldsShape,
|
||||||
lang_item::LangItem,
|
lang_item::LangItem,
|
||||||
resolver::{HasResolver, LifetimeNs, Resolver, TypeNs},
|
resolver::{HasResolver, LifetimeNs, Resolver, TypeNs},
|
||||||
@ -555,32 +553,12 @@ impl<'a> TyLoweringContext<'a> {
|
|||||||
pub(crate) fn lower_where_predicate<'b>(
|
pub(crate) fn lower_where_predicate<'b>(
|
||||||
&'b mut self,
|
&'b mut self,
|
||||||
where_predicate: &'b WherePredicate,
|
where_predicate: &'b WherePredicate,
|
||||||
generics: &'b Generics,
|
|
||||||
predicate_owner: GenericDefId,
|
|
||||||
ignore_bindings: bool,
|
ignore_bindings: bool,
|
||||||
) -> impl Iterator<Item = QuantifiedWhereClause> + use<'a, 'b> {
|
) -> impl Iterator<Item = QuantifiedWhereClause> + use<'a, 'b> {
|
||||||
match where_predicate {
|
match where_predicate {
|
||||||
WherePredicate::ForLifetime { target, bound, .. }
|
WherePredicate::ForLifetime { target, bound, .. }
|
||||||
| WherePredicate::TypeBound { target, bound } => {
|
| WherePredicate::TypeBound { target, bound } => {
|
||||||
let self_ty = match target {
|
let self_ty = self.lower_ty(*target);
|
||||||
WherePredicateTypeTarget::TypeRef(type_ref) => self.lower_ty(*type_ref),
|
|
||||||
&WherePredicateTypeTarget::TypeOrConstParam(local_id) => {
|
|
||||||
let param_id =
|
|
||||||
hir_def::TypeOrConstParamId { parent: predicate_owner, local_id };
|
|
||||||
match self.type_param_mode {
|
|
||||||
ParamLoweringMode::Placeholder => {
|
|
||||||
TyKind::Placeholder(to_placeholder_idx(self.db, param_id))
|
|
||||||
}
|
|
||||||
ParamLoweringMode::Variable => {
|
|
||||||
let idx = generics
|
|
||||||
.type_or_const_param_idx(param_id)
|
|
||||||
.expect("matching generics");
|
|
||||||
TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, idx))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.intern(Interner)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Either::Left(self.lower_type_bound(bound, self_ty, ignore_bindings))
|
Either::Left(self.lower_type_bound(bound, self_ty, ignore_bindings))
|
||||||
}
|
}
|
||||||
WherePredicate::Lifetime { bound, target } => Either::Right(iter::once(
|
WherePredicate::Lifetime { bound, target } => Either::Right(iter::once(
|
||||||
@ -959,22 +937,14 @@ pub(crate) fn generic_predicates_for_param_query(
|
|||||||
.with_type_param_mode(ParamLoweringMode::Variable);
|
.with_type_param_mode(ParamLoweringMode::Variable);
|
||||||
|
|
||||||
// we have to filter out all other predicates *first*, before attempting to lower them
|
// we have to filter out all other predicates *first*, before attempting to lower them
|
||||||
let predicate = |pred: &_, generics: &Generics, ctx: &mut TyLoweringContext<'_>| match pred {
|
let predicate = |pred: &_, ctx: &mut TyLoweringContext<'_>| match pred {
|
||||||
WherePredicate::ForLifetime { target, bound, .. }
|
WherePredicate::ForLifetime { target, bound, .. }
|
||||||
| WherePredicate::TypeBound { target, bound, .. } => {
|
| WherePredicate::TypeBound { target, bound, .. } => {
|
||||||
let invalid_target = match target {
|
let invalid_target = { ctx.lower_ty_only_param(*target) != Some(param_id) };
|
||||||
WherePredicateTypeTarget::TypeRef(type_ref) => {
|
|
||||||
ctx.lower_ty_only_param(*type_ref) != Some(param_id)
|
|
||||||
}
|
|
||||||
&WherePredicateTypeTarget::TypeOrConstParam(local_id) => {
|
|
||||||
let target_id = TypeOrConstParamId { parent: generics.def(), local_id };
|
|
||||||
target_id != param_id
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if invalid_target {
|
if invalid_target {
|
||||||
// If this is filtered out without lowering, `?Sized` is not gathered into `ctx.unsized_types`
|
// If this is filtered out without lowering, `?Sized` is not gathered into `ctx.unsized_types`
|
||||||
if let TypeBound::Path(_, TraitBoundModifier::Maybe) = bound {
|
if let TypeBound::Path(_, TraitBoundModifier::Maybe) = bound {
|
||||||
ctx.lower_where_predicate(pred, generics, generics.def(), true).for_each(drop);
|
ctx.lower_where_predicate(pred, true).for_each(drop);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1009,10 +979,9 @@ pub(crate) fn generic_predicates_for_param_query(
|
|||||||
{
|
{
|
||||||
ctx.store = maybe_parent_generics.store();
|
ctx.store = maybe_parent_generics.store();
|
||||||
for pred in maybe_parent_generics.where_predicates() {
|
for pred in maybe_parent_generics.where_predicates() {
|
||||||
if predicate(pred, maybe_parent_generics, &mut ctx) {
|
if predicate(pred, &mut ctx) {
|
||||||
predicates.extend(
|
predicates.extend(
|
||||||
ctx.lower_where_predicate(pred, &generics, maybe_parent_generics.def(), true)
|
ctx.lower_where_predicate(pred, true).map(|p| make_binders(db, &generics, p)),
|
||||||
.map(|p| make_binders(db, &generics, p)),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1078,9 +1047,7 @@ pub(crate) fn trait_environment_query(
|
|||||||
{
|
{
|
||||||
ctx.store = maybe_parent_generics.store();
|
ctx.store = maybe_parent_generics.store();
|
||||||
for pred in maybe_parent_generics.where_predicates() {
|
for pred in maybe_parent_generics.where_predicates() {
|
||||||
for pred in
|
for pred in ctx.lower_where_predicate(pred, false) {
|
||||||
ctx.lower_where_predicate(pred, &generics, maybe_parent_generics.def(), false)
|
|
||||||
{
|
|
||||||
if let WhereClause::Implemented(tr) = pred.skip_binders() {
|
if let WhereClause::Implemented(tr) = pred.skip_binders() {
|
||||||
traits_in_scope
|
traits_in_scope
|
||||||
.push((tr.self_type_parameter(Interner).clone(), tr.hir_trait_id()));
|
.push((tr.self_type_parameter(Interner).clone(), tr.hir_trait_id()));
|
||||||
@ -1187,8 +1154,7 @@ where
|
|||||||
// We deliberately use `generics` and not `maybe_parent_generics` here. This is not a mistake!
|
// We deliberately use `generics` and not `maybe_parent_generics` here. This is not a mistake!
|
||||||
// If we use the parent generics
|
// If we use the parent generics
|
||||||
predicates.extend(
|
predicates.extend(
|
||||||
ctx.lower_where_predicate(pred, &generics, maybe_parent_generics.def(), false)
|
ctx.lower_where_predicate(pred, false).map(|p| make_binders(db, &generics, p)),
|
||||||
.map(|p| make_binders(db, &generics, p)),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ use chalk_ir::{
|
|||||||
use hir_def::{
|
use hir_def::{
|
||||||
EnumId, EnumVariantId, FunctionId, Lookup, TraitId, TypeAliasId, TypeOrConstParamId,
|
EnumId, EnumVariantId, FunctionId, Lookup, TraitId, TypeAliasId, TypeOrConstParamId,
|
||||||
db::DefDatabase,
|
db::DefDatabase,
|
||||||
hir::generics::{WherePredicate, WherePredicateTypeTarget},
|
hir::generics::WherePredicate,
|
||||||
lang_item::LangItem,
|
lang_item::LangItem,
|
||||||
resolver::{HasResolver, TypeNs},
|
resolver::{HasResolver, TypeNs},
|
||||||
type_ref::{TraitBoundModifier, TypeRef},
|
type_ref::{TraitBoundModifier, TypeRef},
|
||||||
@ -170,15 +170,10 @@ fn direct_super_traits_cb(db: &dyn DefDatabase, trait_: TraitId, cb: impl FnMut(
|
|||||||
.filter_map(|pred| match pred {
|
.filter_map(|pred| match pred {
|
||||||
WherePredicate::ForLifetime { target, bound, .. }
|
WherePredicate::ForLifetime { target, bound, .. }
|
||||||
| WherePredicate::TypeBound { target, bound } => {
|
| WherePredicate::TypeBound { target, bound } => {
|
||||||
let is_trait = match *target {
|
let is_trait = match &store[*target] {
|
||||||
WherePredicateTypeTarget::TypeRef(type_ref) => match &store[type_ref] {
|
TypeRef::Path(p) => p.is_self_type(),
|
||||||
TypeRef::Path(p) => p.is_self_type(),
|
TypeRef::TypeParam(p) => Some(p.local_id()) == trait_self,
|
||||||
TypeRef::TypeParam(p) => Some(p.local_id()) == trait_self,
|
_ => false,
|
||||||
_ => false,
|
|
||||||
},
|
|
||||||
WherePredicateTypeTarget::TypeOrConstParam(local_id) => {
|
|
||||||
Some(local_id) == trait_self
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
match is_trait {
|
match is_trait {
|
||||||
true => bound.as_path(&store),
|
true => bound.as_path(&store),
|
||||||
|
@ -4,17 +4,15 @@ use either::Either;
|
|||||||
use hir_def::{
|
use hir_def::{
|
||||||
AdtId, GenericDefId,
|
AdtId, GenericDefId,
|
||||||
expr_store::ExpressionStore,
|
expr_store::ExpressionStore,
|
||||||
hir::generics::{
|
hir::generics::{GenericParams, TypeOrConstParamData, TypeParamProvenance, WherePredicate},
|
||||||
GenericParams, TypeOrConstParamData, TypeParamProvenance, WherePredicate,
|
|
||||||
WherePredicateTypeTarget,
|
|
||||||
},
|
|
||||||
item_tree::FieldsShape,
|
item_tree::FieldsShape,
|
||||||
lang_item::LangItem,
|
lang_item::LangItem,
|
||||||
signatures::{StaticFlags, TraitFlags},
|
signatures::{StaticFlags, TraitFlags},
|
||||||
type_ref::{TypeBound, TypeRef},
|
type_ref::{TypeBound, TypeRef, TypeRefId},
|
||||||
};
|
};
|
||||||
use hir_ty::{
|
use hir_ty::{
|
||||||
AliasEq, AliasTy, Interner, ProjectionTyExt, TraitRefExt, TyKind, WhereClause,
|
AliasEq, AliasTy, Interner, ProjectionTyExt, TraitRefExt, TyKind, WhereClause,
|
||||||
|
db::HirDatabase,
|
||||||
display::{
|
display::{
|
||||||
HirDisplay, HirDisplayError, HirDisplayWithExpressionStore, HirFormatter, SizedByDefault,
|
HirDisplay, HirDisplayError, HirDisplayWithExpressionStore, HirFormatter, SizedByDefault,
|
||||||
hir_display_with_store, write_bounds_like_dyn_trait_with_prefix, write_visibility,
|
hir_display_with_store, write_bounds_like_dyn_trait_with_prefix, write_visibility,
|
||||||
@ -43,7 +41,8 @@ impl HirDisplay for Function {
|
|||||||
if f.show_container_bounds() && !params.is_empty() {
|
if f.show_container_bounds() && !params.is_empty() {
|
||||||
write_trait_header(&trait_, f)?;
|
write_trait_header(&trait_, f)?;
|
||||||
f.write_char('\n')?;
|
f.write_char('\n')?;
|
||||||
has_disaplayable_predicates(¶ms).then_some((params, params_store))
|
has_disaplayable_predicates(f.db, ¶ms, ¶ms_store)
|
||||||
|
.then_some((params, params_store))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@ -53,7 +52,8 @@ impl HirDisplay for Function {
|
|||||||
if f.show_container_bounds() && !params.is_empty() {
|
if f.show_container_bounds() && !params.is_empty() {
|
||||||
write_impl_header(&impl_, f)?;
|
write_impl_header(&impl_, f)?;
|
||||||
f.write_char('\n')?;
|
f.write_char('\n')?;
|
||||||
has_disaplayable_predicates(¶ms).then_some((params, params_store))
|
has_disaplayable_predicates(f.db, ¶ms, ¶ms_store)
|
||||||
|
.then_some((params, params_store))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@ -619,7 +619,7 @@ fn write_where_clause(
|
|||||||
f: &mut HirFormatter<'_>,
|
f: &mut HirFormatter<'_>,
|
||||||
) -> Result<bool, HirDisplayError> {
|
) -> Result<bool, HirDisplayError> {
|
||||||
let (params, store) = f.db.generic_params_and_store(def);
|
let (params, store) = f.db.generic_params_and_store(def);
|
||||||
if !has_disaplayable_predicates(¶ms) {
|
if !has_disaplayable_predicates(f.db, ¶ms, &store) {
|
||||||
return Ok(false);
|
return Ok(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -629,12 +629,18 @@ fn write_where_clause(
|
|||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn has_disaplayable_predicates(params: &GenericParams) -> bool {
|
fn has_disaplayable_predicates(
|
||||||
|
db: &dyn HirDatabase,
|
||||||
|
params: &GenericParams,
|
||||||
|
store: &ExpressionStore,
|
||||||
|
) -> bool {
|
||||||
params.where_predicates().any(|pred| {
|
params.where_predicates().any(|pred| {
|
||||||
!matches!(
|
!matches!(
|
||||||
pred,
|
pred,
|
||||||
WherePredicate::TypeBound { target: WherePredicateTypeTarget::TypeOrConstParam(id), .. }
|
WherePredicate::TypeBound { target, .. }
|
||||||
if params[*id].name().is_none()
|
if matches!(store[*target],
|
||||||
|
TypeRef::TypeParam(id) if db.generic_params(id.parent())[id.local_id()].name().is_none()
|
||||||
|
)
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -647,20 +653,12 @@ fn write_where_predicates(
|
|||||||
use WherePredicate::*;
|
use WherePredicate::*;
|
||||||
|
|
||||||
// unnamed type targets are displayed inline with the argument itself, e.g. `f: impl Y`.
|
// unnamed type targets are displayed inline with the argument itself, e.g. `f: impl Y`.
|
||||||
let is_unnamed_type_target = |params: &GenericParams, target: &WherePredicateTypeTarget| {
|
let is_unnamed_type_target = |target: TypeRefId| {
|
||||||
matches!(target,
|
matches!(store[target],
|
||||||
WherePredicateTypeTarget::TypeOrConstParam(id) if params[*id].name().is_none()
|
TypeRef::TypeParam(id) if f.db.generic_params(id.parent())[id.local_id()].name().is_none()
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
let write_target = |target: &WherePredicateTypeTarget, f: &mut HirFormatter<'_>| match target {
|
|
||||||
WherePredicateTypeTarget::TypeRef(ty) => ty.hir_fmt(f, store),
|
|
||||||
WherePredicateTypeTarget::TypeOrConstParam(id) => match params[*id].name() {
|
|
||||||
Some(name) => write!(f, "{}", name.display(f.db, f.edition())),
|
|
||||||
None => f.write_str("{unnamed}"),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
let check_same_target = |pred1: &WherePredicate, pred2: &WherePredicate| match (pred1, pred2) {
|
let check_same_target = |pred1: &WherePredicate, pred2: &WherePredicate| match (pred1, pred2) {
|
||||||
(TypeBound { target: t1, .. }, TypeBound { target: t2, .. }) => t1 == t2,
|
(TypeBound { target: t1, .. }, TypeBound { target: t2, .. }) => t1 == t2,
|
||||||
(Lifetime { target: t1, .. }, Lifetime { target: t2, .. }) => t1 == t2,
|
(Lifetime { target: t1, .. }, Lifetime { target: t2, .. }) => t1 == t2,
|
||||||
@ -673,14 +671,14 @@ fn write_where_predicates(
|
|||||||
|
|
||||||
let mut iter = params.where_predicates().peekable();
|
let mut iter = params.where_predicates().peekable();
|
||||||
while let Some(pred) = iter.next() {
|
while let Some(pred) = iter.next() {
|
||||||
if matches!(pred, TypeBound { target, .. } if is_unnamed_type_target(params, target)) {
|
if matches!(pred, TypeBound { target, .. } if is_unnamed_type_target(*target)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
f.write_str("\n ")?;
|
f.write_str("\n ")?;
|
||||||
match pred {
|
match pred {
|
||||||
TypeBound { target, bound } => {
|
TypeBound { target, bound } => {
|
||||||
write_target(target, f)?;
|
target.hir_fmt(f, store)?;
|
||||||
f.write_str(": ")?;
|
f.write_str(": ")?;
|
||||||
bound.hir_fmt(f, store)?;
|
bound.hir_fmt(f, store)?;
|
||||||
}
|
}
|
||||||
@ -692,7 +690,7 @@ fn write_where_predicates(
|
|||||||
ForLifetime { lifetimes, target, bound } => {
|
ForLifetime { lifetimes, target, bound } => {
|
||||||
let lifetimes = lifetimes.iter().map(|it| it.display(f.db, f.edition())).join(", ");
|
let lifetimes = lifetimes.iter().map(|it| it.display(f.db, f.edition())).join(", ");
|
||||||
write!(f, "for<{lifetimes}> ")?;
|
write!(f, "for<{lifetimes}> ")?;
|
||||||
write_target(target, f)?;
|
target.hir_fmt(f, store)?;
|
||||||
f.write_str(": ")?;
|
f.write_str(": ")?;
|
||||||
bound.hir_fmt(f, store)?;
|
bound.hir_fmt(f, store)?;
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ use hir_def::{
|
|||||||
lang_item::LangItem,
|
lang_item::LangItem,
|
||||||
nameres::MacroSubNs,
|
nameres::MacroSubNs,
|
||||||
resolver::{HasResolver, Resolver, TypeNs, ValueNs, resolver_for_scope},
|
resolver::{HasResolver, Resolver, TypeNs, ValueNs, resolver_for_scope},
|
||||||
type_ref::{Mutability, TypeRef, TypeRefId},
|
type_ref::{Mutability, TypeRefId},
|
||||||
};
|
};
|
||||||
use hir_expand::{
|
use hir_expand::{
|
||||||
HirFileId, InFile, MacroCallId,
|
HirFileId, InFile, MacroCallId,
|
||||||
@ -1004,9 +1004,11 @@ impl SourceAnalyzer {
|
|||||||
|
|
||||||
// FIXME: collectiong here shouldnt be necessary?
|
// FIXME: collectiong here shouldnt be necessary?
|
||||||
let mut collector = ExprCollector::new(db, self.resolver.module(), self.file_id);
|
let mut collector = ExprCollector::new(db, self.resolver.module(), self.file_id);
|
||||||
let hir_path = collector.lower_path(path.clone(), &mut |_| TypeRef::Error)?;
|
let hir_path =
|
||||||
let parent_hir_path =
|
collector.lower_path(path.clone(), &mut ExprCollector::impl_trait_error_allocator)?;
|
||||||
path.parent_path().and_then(|p| collector.lower_path(p, &mut |_| TypeRef::Error));
|
let parent_hir_path = path
|
||||||
|
.parent_path()
|
||||||
|
.and_then(|p| collector.lower_path(p, &mut ExprCollector::impl_trait_error_allocator));
|
||||||
let store = collector.store.finish();
|
let store = collector.store.finish();
|
||||||
|
|
||||||
// Case where path is a qualifier of a use tree, e.g. foo::bar::{Baz, Qux} where we are
|
// Case where path is a qualifier of a use tree, e.g. foo::bar::{Baz, Qux} where we are
|
||||||
|
Loading…
x
Reference in New Issue
Block a user