mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-11-15 09:27:27 +00:00
Merge #9431
9431: internal: Implement TypeRef::ForLifetime r=flodiebold a=Veykril Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
This commit is contained in:
commit
738dd6ed9f
6 changed files with 64 additions and 19 deletions
|
@ -2,6 +2,8 @@
|
|||
|
||||
use std::fmt::{self, Write};
|
||||
|
||||
use itertools::Itertools;
|
||||
|
||||
use crate::{
|
||||
attr::RawAttrs,
|
||||
generics::{WherePredicate, WherePredicateTypeTarget},
|
||||
|
@ -542,6 +544,10 @@ impl<'a> Printer<'a> {
|
|||
|
||||
match bound.as_ref() {
|
||||
TypeBound::Path(path) => self.print_path(path),
|
||||
TypeBound::ForLifetime(lifetimes, path) => {
|
||||
w!(self, "for<{}> ", lifetimes.iter().format(", "));
|
||||
self.print_path(path);
|
||||
}
|
||||
TypeBound::Lifetime(lt) => w!(self, "{}", lt.name),
|
||||
TypeBound::Error => w!(self, "{{unknown}}"),
|
||||
}
|
||||
|
|
|
@ -282,6 +282,7 @@ struct S {
|
|||
a: Mixed<'a, T, Item=(), OtherItem=u8>,
|
||||
b: <Fully as Qualified>::Syntax,
|
||||
c: <TypeAnchored>::Path::<'a>,
|
||||
d: dyn for<'a> Trait<'a>,
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
|
@ -289,6 +290,7 @@ struct S {
|
|||
pub(self) a: Mixed<'a, T, Item = (), OtherItem = u8>,
|
||||
pub(self) b: Qualified<Self=Fully>::Syntax,
|
||||
pub(self) c: <TypeAnchored>::Path<'a>,
|
||||
pub(self) d: dyn for<'a> Trait<'a>,
|
||||
}
|
||||
"#]],
|
||||
)
|
||||
|
@ -311,7 +313,7 @@ impl<'a, 'b: 'a, T: Copy + 'a + 'b, const K: u8 = 0> S<'a, 'b, T, K> {
|
|||
enum Enum<'a, T, const U: u8> {}
|
||||
union Union<'a, T, const U: u8> {}
|
||||
|
||||
trait Tr<'a, T: 'a>: Super {}
|
||||
trait Tr<'a, T: 'a>: Super where Self: for<'a> Tr<'a, T> {}
|
||||
"#,
|
||||
expect![[r#"
|
||||
pub(self) struct S<'a, 'b, T, const K: u8>
|
||||
|
@ -353,7 +355,8 @@ trait Tr<'a, T: 'a>: Super {}
|
|||
pub(self) trait Tr<'a, Self, T>
|
||||
where
|
||||
Self: Super,
|
||||
T: 'a
|
||||
T: 'a,
|
||||
Self: for<'a> Tr<'a, T>
|
||||
{
|
||||
}
|
||||
"#]],
|
||||
|
|
|
@ -119,7 +119,7 @@ impl LifetimeRef {
|
|||
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
|
||||
pub enum TypeBound {
|
||||
Path(Path),
|
||||
// ForLifetime(Vec<LifetimeRef>, Path), FIXME ForLifetime
|
||||
ForLifetime(Box<[Name]>, Path),
|
||||
Lifetime(LifetimeRef),
|
||||
Error,
|
||||
}
|
||||
|
@ -233,7 +233,9 @@ impl TypeRef {
|
|||
TypeRef::ImplTrait(bounds) | TypeRef::DynTrait(bounds) => {
|
||||
for bound in bounds {
|
||||
match bound.as_ref() {
|
||||
TypeBound::Path(path) => go_path(path, f),
|
||||
TypeBound::Path(path) | TypeBound::ForLifetime(_, path) => {
|
||||
go_path(path, f)
|
||||
}
|
||||
TypeBound::Lifetime(_) | TypeBound::Error => (),
|
||||
}
|
||||
}
|
||||
|
@ -263,7 +265,9 @@ impl TypeRef {
|
|||
}
|
||||
for bound in &binding.bounds {
|
||||
match bound.as_ref() {
|
||||
TypeBound::Path(path) => go_path(path, f),
|
||||
TypeBound::Path(path) | TypeBound::ForLifetime(_, path) => {
|
||||
go_path(path, f)
|
||||
}
|
||||
TypeBound::Lifetime(_) | TypeBound::Error => (),
|
||||
}
|
||||
}
|
||||
|
@ -287,20 +291,29 @@ pub(crate) fn type_bounds_from_ast(
|
|||
|
||||
impl TypeBound {
|
||||
pub(crate) fn from_ast(ctx: &LowerCtx, node: ast::TypeBound) -> Self {
|
||||
let lower_path_type = |path_type: ast::PathType| ctx.lower_path(path_type.path()?);
|
||||
|
||||
match node.kind() {
|
||||
ast::TypeBoundKind::PathType(path_type) => {
|
||||
let path = match path_type.path() {
|
||||
Some(p) => p,
|
||||
None => return TypeBound::Error,
|
||||
};
|
||||
|
||||
let path = match ctx.lower_path(path) {
|
||||
Some(p) => p,
|
||||
None => return TypeBound::Error,
|
||||
};
|
||||
TypeBound::Path(path)
|
||||
lower_path_type(path_type).map(TypeBound::Path).unwrap_or(TypeBound::Error)
|
||||
}
|
||||
ast::TypeBoundKind::ForType(for_type) => {
|
||||
let lt_refs = match for_type.generic_param_list() {
|
||||
Some(gpl) => gpl
|
||||
.lifetime_params()
|
||||
.flat_map(|lp| lp.lifetime().map(|lt| Name::new_lifetime(<)))
|
||||
.collect(),
|
||||
None => Box::default(),
|
||||
};
|
||||
let path = for_type.ty().and_then(|ty| match ty {
|
||||
ast::Type::PathType(path_type) => lower_path_type(path_type),
|
||||
_ => None,
|
||||
});
|
||||
match path {
|
||||
Some(p) => TypeBound::ForLifetime(lt_refs, p),
|
||||
None => TypeBound::Error,
|
||||
}
|
||||
}
|
||||
ast::TypeBoundKind::ForType(_) => TypeBound::Error, // FIXME ForType
|
||||
ast::TypeBoundKind::Lifetime(lifetime) => {
|
||||
TypeBound::Lifetime(LifetimeRef::new(&lifetime))
|
||||
}
|
||||
|
@ -309,8 +322,8 @@ impl TypeBound {
|
|||
|
||||
pub fn as_path(&self) -> Option<&Path> {
|
||||
match self {
|
||||
TypeBound::Path(p) => Some(p),
|
||||
_ => None,
|
||||
TypeBound::Path(p) | TypeBound::ForLifetime(_, p) => Some(p),
|
||||
TypeBound::Lifetime(_) | TypeBound::Error => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ use hir_def::{
|
|||
AssocContainerId, Lookup, ModuleId, TraitId,
|
||||
};
|
||||
use hir_expand::{hygiene::Hygiene, name::Name};
|
||||
use itertools::Itertools;
|
||||
|
||||
use crate::{
|
||||
const_from_placeholder_idx, db::HirDatabase, from_assoc_type_id, from_foreign_def_id,
|
||||
|
@ -1029,6 +1030,10 @@ impl HirDisplay for TypeBound {
|
|||
match self {
|
||||
TypeBound::Path(path) => path.hir_fmt(f),
|
||||
TypeBound::Lifetime(lifetime) => write!(f, "{}", lifetime.name),
|
||||
TypeBound::ForLifetime(lifetimes, path) => {
|
||||
write!(f, "for<{}> ", lifetimes.iter().format(", "))?;
|
||||
path.hir_fmt(f)
|
||||
}
|
||||
TypeBound::Error => write!(f, "{{error}}"),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -786,6 +786,11 @@ impl<'a> TyLoweringContext<'a> {
|
|||
bindings = self.lower_trait_ref_from_path(path, Some(self_ty));
|
||||
bindings.clone().map(WhereClause::Implemented).map(crate::wrap_empty_binders)
|
||||
}
|
||||
TypeBound::ForLifetime(_, path) => {
|
||||
// FIXME Don't silently drop the hrtb lifetimes here
|
||||
bindings = self.lower_trait_ref_from_path(path, Some(self_ty));
|
||||
bindings.clone().map(WhereClause::Implemented).map(crate::wrap_empty_binders)
|
||||
}
|
||||
TypeBound::Lifetime(_) => None,
|
||||
TypeBound::Error => None,
|
||||
};
|
||||
|
@ -803,7 +808,7 @@ impl<'a> TyLoweringContext<'a> {
|
|||
trait_ref: TraitRef,
|
||||
) -> impl Iterator<Item = QuantifiedWhereClause> + 'a {
|
||||
let last_segment = match bound {
|
||||
TypeBound::Path(path) => path.segments().last(),
|
||||
TypeBound::Path(path) | TypeBound::ForLifetime(_, path) => path.segments().last(),
|
||||
TypeBound::Error | TypeBound::Lifetime(_) => None,
|
||||
};
|
||||
last_segment
|
||||
|
|
|
@ -54,3 +54,16 @@ fn main() {
|
|||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn render_dyn_for_ty() {
|
||||
// FIXME
|
||||
check_types_source_code(
|
||||
r#"
|
||||
trait Foo<'a> {}
|
||||
|
||||
fn foo(foo: &dyn for<'a> Foo<'a>) {}
|
||||
// ^^^ &dyn Foo
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue