mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-29 21:35:20 +00:00
Improve/fix type bound lowering
This commit is contained in:
parent
b1a40042e8
commit
4768f5e717
3 changed files with 64 additions and 30 deletions
|
@ -3415,6 +3415,39 @@ fn test(x: Trait, y: &Trait) -> u64 {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn weird_bounds() {
|
||||
assert_snapshot_matches!(
|
||||
infer(r#"
|
||||
trait Trait {}
|
||||
fn test() {
|
||||
let a: impl Trait + 'lifetime = foo;
|
||||
let b: impl 'lifetime = foo;
|
||||
let b: impl (Trait) = foo;
|
||||
let b: impl ('lifetime) = foo;
|
||||
let d: impl ?Sized = foo;
|
||||
let e: impl Trait + ?Sized = foo;
|
||||
}
|
||||
"#),
|
||||
@r###"
|
||||
⋮
|
||||
⋮[26; 237) '{ ...foo; }': ()
|
||||
⋮[36; 37) 'a': impl Trait + {error}
|
||||
⋮[64; 67) 'foo': impl Trait + {error}
|
||||
⋮[77; 78) 'b': impl {error}
|
||||
⋮[97; 100) 'foo': impl {error}
|
||||
⋮[110; 111) 'b': impl Trait
|
||||
⋮[128; 131) 'foo': impl Trait
|
||||
⋮[141; 142) 'b': impl {error}
|
||||
⋮[163; 166) 'foo': impl {error}
|
||||
⋮[176; 177) 'd': impl {error}
|
||||
⋮[193; 196) 'foo': impl {error}
|
||||
⋮[206; 207) 'e': impl Trait + {error}
|
||||
⋮[231; 234) 'foo': impl Trait + {error}
|
||||
"###
|
||||
);
|
||||
}
|
||||
|
||||
fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String {
|
||||
let file = db.parse(pos.file_id).ok().unwrap();
|
||||
let expr = algo::find_node_at_offset::<ast::Expr>(file.syntax(), pos.offset).unwrap();
|
||||
|
|
|
@ -136,7 +136,7 @@ pub(crate) fn type_bounds_from_ast(type_bounds_opt: Option<ast::TypeBoundList>)
|
|||
impl TypeBound {
|
||||
pub(crate) fn from_ast(node: ast::TypeBound) -> Self {
|
||||
match node.kind() {
|
||||
Some(ast::TypeBoundKind::PathType(path_type)) => {
|
||||
ast::TypeBoundKind::PathType(path_type) => {
|
||||
let path = match path_type.path() {
|
||||
Some(p) => p,
|
||||
None => return TypeBound::Error,
|
||||
|
@ -147,9 +147,7 @@ impl TypeBound {
|
|||
};
|
||||
TypeBound::Path(path)
|
||||
}
|
||||
Some(ast::TypeBoundKind::ForType(_)) | Some(ast::TypeBoundKind::Lifetime(_)) | None => {
|
||||
TypeBound::Error
|
||||
}
|
||||
ast::TypeBoundKind::ForType(_) | ast::TypeBoundKind::Lifetime(_) => TypeBound::Error,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -382,7 +382,36 @@ impl ast::WherePred {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub enum TypeBoundKind {
|
||||
/// Trait
|
||||
PathType(ast::PathType),
|
||||
/// for<'a> ...
|
||||
ForType(ast::ForType),
|
||||
/// 'a
|
||||
Lifetime(ast::SyntaxToken),
|
||||
}
|
||||
|
||||
impl ast::TypeBound {
|
||||
pub fn kind(&self) -> TypeBoundKind {
|
||||
if let Some(path_type) = children(self).next() {
|
||||
TypeBoundKind::PathType(path_type)
|
||||
} else if let Some(for_type) = children(self).next() {
|
||||
TypeBoundKind::ForType(for_type)
|
||||
} else if let Some(lifetime) = self.lifetime() {
|
||||
TypeBoundKind::Lifetime(lifetime)
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
fn lifetime(&self) -> Option<SyntaxToken> {
|
||||
self.syntax()
|
||||
.children_with_tokens()
|
||||
.filter_map(|it| it.into_token())
|
||||
.find(|it| it.kind() == LIFETIME)
|
||||
}
|
||||
|
||||
pub fn question_mark_token(&self) -> Option<SyntaxToken> {
|
||||
self.syntax()
|
||||
.children_with_tokens()
|
||||
|
@ -399,29 +428,3 @@ impl ast::TraitDef {
|
|||
self.syntax().children_with_tokens().any(|t| t.kind() == T![auto])
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub enum TypeBoundKind {
|
||||
/// Trait
|
||||
PathType(ast::PathType),
|
||||
/// for<'a> ...
|
||||
ForType(ast::ForType),
|
||||
/// 'a
|
||||
Lifetime(ast::SyntaxToken),
|
||||
}
|
||||
|
||||
impl ast::TypeBound {
|
||||
pub fn kind(&self) -> Option<TypeBoundKind> {
|
||||
let child = self.syntax.first_child_or_token()?;
|
||||
match child.kind() {
|
||||
PATH_TYPE => Some(TypeBoundKind::PathType(
|
||||
ast::PathType::cast(child.into_node().unwrap()).unwrap(),
|
||||
)),
|
||||
FOR_TYPE => Some(TypeBoundKind::ForType(
|
||||
ast::ForType::cast(child.into_node().unwrap()).unwrap(),
|
||||
)),
|
||||
LIFETIME => Some(TypeBoundKind::Lifetime(child.into_token().unwrap())),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue