Skip to content

Commit 4768f5e

Browse files
committed
Improve/fix type bound lowering
1 parent b1a4004 commit 4768f5e

File tree

3 files changed

+64
-30
lines changed

3 files changed

+64
-30
lines changed

crates/ra_hir/src/ty/tests.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3415,6 +3415,39 @@ fn test(x: Trait, y: &Trait) -> u64 {
34153415
);
34163416
}
34173417

3418+
#[test]
3419+
fn weird_bounds() {
3420+
assert_snapshot_matches!(
3421+
infer(r#"
3422+
trait Trait {}
3423+
fn test() {
3424+
let a: impl Trait + 'lifetime = foo;
3425+
let b: impl 'lifetime = foo;
3426+
let b: impl (Trait) = foo;
3427+
let b: impl ('lifetime) = foo;
3428+
let d: impl ?Sized = foo;
3429+
let e: impl Trait + ?Sized = foo;
3430+
}
3431+
"#),
3432+
@r###"
3433+
3434+
⋮[26; 237) '{ ...foo; }': ()
3435+
⋮[36; 37) 'a': impl Trait + {error}
3436+
⋮[64; 67) 'foo': impl Trait + {error}
3437+
⋮[77; 78) 'b': impl {error}
3438+
⋮[97; 100) 'foo': impl {error}
3439+
⋮[110; 111) 'b': impl Trait
3440+
⋮[128; 131) 'foo': impl Trait
3441+
⋮[141; 142) 'b': impl {error}
3442+
⋮[163; 166) 'foo': impl {error}
3443+
⋮[176; 177) 'd': impl {error}
3444+
⋮[193; 196) 'foo': impl {error}
3445+
⋮[206; 207) 'e': impl Trait + {error}
3446+
⋮[231; 234) 'foo': impl Trait + {error}
3447+
"###
3448+
);
3449+
}
3450+
34183451
fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String {
34193452
let file = db.parse(pos.file_id).ok().unwrap();
34203453
let expr = algo::find_node_at_offset::<ast::Expr>(file.syntax(), pos.offset).unwrap();

crates/ra_hir/src/type_ref.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ pub(crate) fn type_bounds_from_ast(type_bounds_opt: Option<ast::TypeBoundList>)
136136
impl TypeBound {
137137
pub(crate) fn from_ast(node: ast::TypeBound) -> Self {
138138
match node.kind() {
139-
Some(ast::TypeBoundKind::PathType(path_type)) => {
139+
ast::TypeBoundKind::PathType(path_type) => {
140140
let path = match path_type.path() {
141141
Some(p) => p,
142142
None => return TypeBound::Error,
@@ -147,9 +147,7 @@ impl TypeBound {
147147
};
148148
TypeBound::Path(path)
149149
}
150-
Some(ast::TypeBoundKind::ForType(_)) | Some(ast::TypeBoundKind::Lifetime(_)) | None => {
151-
TypeBound::Error
152-
}
150+
ast::TypeBoundKind::ForType(_) | ast::TypeBoundKind::Lifetime(_) => TypeBound::Error,
153151
}
154152
}
155153
}

crates/ra_syntax/src/ast/extensions.rs

Lines changed: 29 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,36 @@ impl ast::WherePred {
382382
}
383383
}
384384

385+
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
386+
pub enum TypeBoundKind {
387+
/// Trait
388+
PathType(ast::PathType),
389+
/// for<'a> ...
390+
ForType(ast::ForType),
391+
/// 'a
392+
Lifetime(ast::SyntaxToken),
393+
}
394+
385395
impl ast::TypeBound {
396+
pub fn kind(&self) -> TypeBoundKind {
397+
if let Some(path_type) = children(self).next() {
398+
TypeBoundKind::PathType(path_type)
399+
} else if let Some(for_type) = children(self).next() {
400+
TypeBoundKind::ForType(for_type)
401+
} else if let Some(lifetime) = self.lifetime() {
402+
TypeBoundKind::Lifetime(lifetime)
403+
} else {
404+
unreachable!()
405+
}
406+
}
407+
408+
fn lifetime(&self) -> Option<SyntaxToken> {
409+
self.syntax()
410+
.children_with_tokens()
411+
.filter_map(|it| it.into_token())
412+
.find(|it| it.kind() == LIFETIME)
413+
}
414+
386415
pub fn question_mark_token(&self) -> Option<SyntaxToken> {
387416
self.syntax()
388417
.children_with_tokens()
@@ -399,29 +428,3 @@ impl ast::TraitDef {
399428
self.syntax().children_with_tokens().any(|t| t.kind() == T![auto])
400429
}
401430
}
402-
403-
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
404-
pub enum TypeBoundKind {
405-
/// Trait
406-
PathType(ast::PathType),
407-
/// for<'a> ...
408-
ForType(ast::ForType),
409-
/// 'a
410-
Lifetime(ast::SyntaxToken),
411-
}
412-
413-
impl ast::TypeBound {
414-
pub fn kind(&self) -> Option<TypeBoundKind> {
415-
let child = self.syntax.first_child_or_token()?;
416-
match child.kind() {
417-
PATH_TYPE => Some(TypeBoundKind::PathType(
418-
ast::PathType::cast(child.into_node().unwrap()).unwrap(),
419-
)),
420-
FOR_TYPE => Some(TypeBoundKind::ForType(
421-
ast::ForType::cast(child.into_node().unwrap()).unwrap(),
422-
)),
423-
LIFETIME => Some(TypeBoundKind::Lifetime(child.into_token().unwrap())),
424-
_ => unreachable!(),
425-
}
426-
}
427-
}

0 commit comments

Comments
 (0)